mirror of
				https://github.com/KokaKiwi/BarInsta
				synced 2025-10-31 11:35:34 +00:00 
			
		
		
		
	
							parent
							
								
									e39c129b61
								
							
						
					
					
						commit
						c24fd016b1
					
				| @ -1,89 +0,0 @@ | |||||||
| package awais.instagrabber.asyncs; |  | ||||||
| 
 |  | ||||||
| import android.os.AsyncTask; |  | ||||||
| import android.util.Log; |  | ||||||
| 
 |  | ||||||
| import org.json.JSONObject; |  | ||||||
| 
 |  | ||||||
| import java.io.DataOutputStream; |  | ||||||
| import java.net.HttpURLConnection; |  | ||||||
| import java.net.URL; |  | ||||||
| import java.util.UUID; |  | ||||||
| 
 |  | ||||||
| import awais.instagrabber.models.StoryModel; |  | ||||||
| import awais.instagrabber.models.stickers.QuizModel; |  | ||||||
| import awais.instagrabber.utils.Constants; |  | ||||||
| import awais.instagrabber.utils.CookieUtils; |  | ||||||
| import awais.instagrabber.utils.Utils; |  | ||||||
| 
 |  | ||||||
| import static awais.instagrabber.utils.Utils.settingsHelper; |  | ||||||
| 
 |  | ||||||
| public class QuizAction extends AsyncTask<Integer, Void, Integer> { |  | ||||||
|     private static final String TAG = "QuizAction"; |  | ||||||
| 
 |  | ||||||
|     private final StoryModel storyModel; |  | ||||||
|     private final QuizModel quizModel; |  | ||||||
|     private final String cookie; |  | ||||||
|     private final OnTaskCompleteListener onTaskCompleteListener; |  | ||||||
| 
 |  | ||||||
|     public QuizAction(final StoryModel storyModel, |  | ||||||
|                       final QuizModel quizModel, |  | ||||||
|                       final String cookie, |  | ||||||
|                       final OnTaskCompleteListener onTaskCompleteListener) { |  | ||||||
|         this.storyModel = storyModel; |  | ||||||
|         this.quizModel = quizModel; |  | ||||||
|         this.cookie = cookie; |  | ||||||
|         this.onTaskCompleteListener = onTaskCompleteListener; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     protected Integer doInBackground(Integer... rawChoice) { |  | ||||||
|         int choice = rawChoice[0]; |  | ||||||
|         final String url = "https://i.instagram.com/api/v1/media/" + storyModel.getStoryMediaId().split("_")[0] + "/" + quizModel.getId() + "/story_quiz_answer/"; |  | ||||||
|         HttpURLConnection urlConnection = null; |  | ||||||
|         try { |  | ||||||
|             JSONObject ogBody = new JSONObject("{\"client_context\":\"" + UUID.randomUUID().toString() |  | ||||||
|                     + "\",\"mutation_token\":\"" + UUID.randomUUID().toString() |  | ||||||
|                     + "\",\"_csrftoken\":\"" + cookie.split("csrftoken=")[1].split(";")[0] |  | ||||||
|                     + "\",\"_uid\":\"" + CookieUtils.getUserIdFromCookie(cookie) |  | ||||||
|                     + "\",\"__uuid\":\"" + settingsHelper.getString(Constants.DEVICE_UUID) |  | ||||||
|                     + "\"}"); |  | ||||||
|             ogBody.put("answer", String.valueOf(choice)); |  | ||||||
|             String urlParameters = Utils.sign(ogBody.toString()); |  | ||||||
|             urlConnection = (HttpURLConnection) new URL(url).openConnection(); |  | ||||||
|             urlConnection.setRequestMethod("POST"); |  | ||||||
|             urlConnection.setUseCaches(false); |  | ||||||
|             urlConnection.setRequestProperty("User-Agent", Constants.I_USER_AGENT); |  | ||||||
|             urlConnection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded"); |  | ||||||
|             if (urlParameters != null) { |  | ||||||
|                 urlConnection.setRequestProperty("Content-Length", Integer.toString(urlParameters.getBytes().length)); |  | ||||||
|             } |  | ||||||
|             urlConnection.setDoOutput(true); |  | ||||||
|             DataOutputStream wr = new DataOutputStream(urlConnection.getOutputStream()); |  | ||||||
|             wr.writeBytes(urlParameters); |  | ||||||
|             wr.flush(); |  | ||||||
|             wr.close(); |  | ||||||
|             Log.d(TAG, "quiz: " + url + " " + cookie + " " + urlParameters); |  | ||||||
|             urlConnection.connect(); |  | ||||||
|             if (urlConnection.getResponseCode() == HttpURLConnection.HTTP_OK) { |  | ||||||
|                 return choice; |  | ||||||
|             } |  | ||||||
|         } catch (Throwable ex) { |  | ||||||
|             Log.e(TAG, "quiz: " + ex); |  | ||||||
|         } finally { |  | ||||||
|             if (urlConnection != null) { |  | ||||||
|                 urlConnection.disconnect(); |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
|         return -1; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     @Override |  | ||||||
|     protected void onPostExecute(final Integer choice) { |  | ||||||
|         if (onTaskCompleteListener == null || choice == null) return; |  | ||||||
|         onTaskCompleteListener.onTaskComplete(choice); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     public interface OnTaskCompleteListener { |  | ||||||
|         void onTaskComplete(final int choice); |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| @ -1,88 +0,0 @@ | |||||||
| package awais.instagrabber.asyncs; |  | ||||||
| 
 |  | ||||||
| import android.os.AsyncTask; |  | ||||||
| import android.util.Log; |  | ||||||
| 
 |  | ||||||
| import org.json.JSONObject; |  | ||||||
| 
 |  | ||||||
| import java.io.DataOutputStream; |  | ||||||
| import java.net.HttpURLConnection; |  | ||||||
| import java.net.URL; |  | ||||||
| import java.util.UUID; |  | ||||||
| 
 |  | ||||||
| import awais.instagrabber.models.StoryModel; |  | ||||||
| import awais.instagrabber.models.stickers.QuestionModel; |  | ||||||
| import awais.instagrabber.utils.Constants; |  | ||||||
| import awais.instagrabber.utils.CookieUtils; |  | ||||||
| import awais.instagrabber.utils.Utils; |  | ||||||
| 
 |  | ||||||
| import static awais.instagrabber.utils.Utils.settingsHelper; |  | ||||||
| 
 |  | ||||||
| public class RespondAction extends AsyncTask<String, Void, Boolean> { |  | ||||||
| 
 |  | ||||||
|     private final StoryModel storyModel; |  | ||||||
|     private final QuestionModel questionModel; |  | ||||||
|     private final String cookie; |  | ||||||
|     private final OnTaskCompleteListener onTaskCompleteListener; |  | ||||||
| 
 |  | ||||||
|     public RespondAction(final StoryModel storyModel, |  | ||||||
|                          final QuestionModel questionModel, |  | ||||||
|                          final String cookie, |  | ||||||
|                          final OnTaskCompleteListener onTaskCompleteListener) { |  | ||||||
|         this.storyModel = storyModel; |  | ||||||
|         this.questionModel = questionModel; |  | ||||||
|         this.cookie = cookie; |  | ||||||
|         this.onTaskCompleteListener = onTaskCompleteListener; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     protected Boolean doInBackground(String... rawChoice) { |  | ||||||
|         final String url = "https://i.instagram.com/api/v1/media/" |  | ||||||
|                 + storyModel.getStoryMediaId().split("_")[0] + "/" + questionModel.getId() + "/story_question_response/"; |  | ||||||
|         HttpURLConnection urlConnection = null; |  | ||||||
|         try { |  | ||||||
|             final JSONObject ogbody = new JSONObject("{\"client_context\":\"" + UUID.randomUUID().toString() |  | ||||||
|                     + "\",\"mutation_token\":\"" + UUID.randomUUID().toString() |  | ||||||
|                     + "\",\"_csrftoken\":\"" + cookie.split("csrftoken=")[1].split(";")[0] |  | ||||||
|                     + "\",\"_uid\":\"" + CookieUtils.getUserIdFromCookie(cookie) |  | ||||||
|                     + "\",\"__uuid\":\"" + settingsHelper.getString(Constants.DEVICE_UUID) |  | ||||||
|                     + "\"}"); |  | ||||||
|             String choice = rawChoice[0].replaceAll("\"", ("\\\"")); |  | ||||||
|             ogbody.put("response", choice); |  | ||||||
|             String urlParameters = Utils.sign(ogbody.toString()); |  | ||||||
|             urlConnection = (HttpURLConnection) new URL(url).openConnection(); |  | ||||||
|             urlConnection.setRequestMethod("POST"); |  | ||||||
|             urlConnection.setUseCaches(false); |  | ||||||
|             urlConnection.setRequestProperty("User-Agent", Constants.I_USER_AGENT); |  | ||||||
|             urlConnection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded"); |  | ||||||
|             urlConnection.setRequestProperty("Content-Length", Integer.toString(urlParameters.getBytes().length)); |  | ||||||
|             urlConnection.setDoOutput(true); |  | ||||||
|             DataOutputStream wr = new DataOutputStream(urlConnection.getOutputStream()); |  | ||||||
|             wr.writeBytes(urlParameters); |  | ||||||
|             wr.flush(); |  | ||||||
|             wr.close(); |  | ||||||
|             urlConnection.connect(); |  | ||||||
|             if (urlConnection.getResponseCode() == HttpURLConnection.HTTP_OK) { |  | ||||||
|                 return true; |  | ||||||
|             } |  | ||||||
| 
 |  | ||||||
|         } catch (Throwable ex) { |  | ||||||
|             Log.e("austin_debug", "respond: " + ex); |  | ||||||
|         } finally { |  | ||||||
|             if (urlConnection != null) { |  | ||||||
|                 urlConnection.disconnect(); |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
|         return null; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     @Override |  | ||||||
|     protected void onPostExecute(final Boolean ok) { |  | ||||||
|         if (onTaskCompleteListener == null) return; |  | ||||||
|         onTaskCompleteListener.onTaskComplete(ok); |  | ||||||
| 
 |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     public interface OnTaskCompleteListener { |  | ||||||
|         void onTaskComplete(final boolean result); |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| @ -1,69 +0,0 @@ | |||||||
| package awais.instagrabber.asyncs; |  | ||||||
| 
 |  | ||||||
| import android.os.AsyncTask; |  | ||||||
| import android.util.Log; |  | ||||||
| 
 |  | ||||||
| import java.io.DataOutputStream; |  | ||||||
| import java.net.HttpURLConnection; |  | ||||||
| import java.net.URL; |  | ||||||
| 
 |  | ||||||
| import awais.instagrabber.models.StoryModel; |  | ||||||
| import awais.instagrabber.models.stickers.PollModel; |  | ||||||
| import awais.instagrabber.utils.Constants; |  | ||||||
| 
 |  | ||||||
| public class VoteAction extends AsyncTask<Integer, Void, Integer> { |  | ||||||
| 
 |  | ||||||
|     private static final String TAG = "VoteAction"; |  | ||||||
| 
 |  | ||||||
|     private final StoryModel storyModel; |  | ||||||
|     private final PollModel pollModel; |  | ||||||
|     private final String cookie; |  | ||||||
|     private final OnTaskCompleteListener onTaskCompleteListener; |  | ||||||
| 
 |  | ||||||
|     public VoteAction(final StoryModel storyModel, |  | ||||||
|                       final PollModel pollModel, |  | ||||||
|                       final String cookie, |  | ||||||
|                       final OnTaskCompleteListener onTaskCompleteListener) { |  | ||||||
|         this.storyModel = storyModel; |  | ||||||
|         this.pollModel = pollModel; |  | ||||||
|         this.cookie = cookie; |  | ||||||
|         this.onTaskCompleteListener = onTaskCompleteListener; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     protected Integer doInBackground(Integer... rawChoice) { |  | ||||||
|         int choice = rawChoice[0]; |  | ||||||
|         final String url = "https://www.instagram.com/media/" + storyModel.getStoryMediaId().split("_")[0] + "/" + pollModel.getId() + "/story_poll_vote/"; |  | ||||||
|         try { |  | ||||||
|             final HttpURLConnection urlConnection = (HttpURLConnection) new URL(url).openConnection(); |  | ||||||
|             urlConnection.setRequestMethod("POST"); |  | ||||||
|             urlConnection.setUseCaches(false); |  | ||||||
|             urlConnection.setRequestProperty("User-Agent", Constants.USER_AGENT); |  | ||||||
|             urlConnection.setRequestProperty("x-csrftoken", cookie.split("csrftoken=")[1].split(";")[0]); |  | ||||||
|             urlConnection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded"); |  | ||||||
|             urlConnection.setRequestProperty("Content-Length", "6"); |  | ||||||
|             urlConnection.setDoOutput(true); |  | ||||||
|             DataOutputStream wr = new DataOutputStream(urlConnection.getOutputStream()); |  | ||||||
|             wr.writeBytes("vote=" + choice); |  | ||||||
|             wr.flush(); |  | ||||||
|             wr.close(); |  | ||||||
|             urlConnection.connect(); |  | ||||||
|             if (urlConnection.getResponseCode() == HttpURLConnection.HTTP_OK) { |  | ||||||
|                 return choice; |  | ||||||
|             } |  | ||||||
|             urlConnection.disconnect(); |  | ||||||
|         } catch (Exception ex) { |  | ||||||
|             Log.e(TAG, "Error", ex); |  | ||||||
|         } |  | ||||||
|         return -1; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     @Override |  | ||||||
|     protected void onPostExecute(final Integer result) { |  | ||||||
|         if (result == null || onTaskCompleteListener == null) return; |  | ||||||
|         onTaskCompleteListener.onTaskComplete(result); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     public interface OnTaskCompleteListener { |  | ||||||
|         void onTaskComplete(final int choice); |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| @ -11,6 +11,7 @@ import android.os.Handler; | |||||||
| import android.util.Log; | import android.util.Log; | ||||||
| import android.util.Pair; | import android.util.Pair; | ||||||
| import android.view.GestureDetector; | import android.view.GestureDetector; | ||||||
|  | import android.view.Gravity; | ||||||
| import android.view.LayoutInflater; | import android.view.LayoutInflater; | ||||||
| import android.view.Menu; | import android.view.Menu; | ||||||
| import android.view.MenuInflater; | import android.view.MenuInflater; | ||||||
| @ -20,6 +21,9 @@ import android.view.View; | |||||||
| import android.view.ViewGroup; | import android.view.ViewGroup; | ||||||
| import android.widget.ArrayAdapter; | import android.widget.ArrayAdapter; | ||||||
| import android.widget.EditText; | import android.widget.EditText; | ||||||
|  | import android.widget.LinearLayout; | ||||||
|  | import android.widget.SeekBar; | ||||||
|  | import android.widget.TextView; | ||||||
| import android.widget.Toast; | import android.widget.Toast; | ||||||
| 
 | 
 | ||||||
| import androidx.annotation.NonNull; | import androidx.annotation.NonNull; | ||||||
| @ -55,6 +59,7 @@ import com.google.android.exoplayer2.upstream.DefaultDataSourceFactory; | |||||||
| 
 | 
 | ||||||
| import java.io.IOException; | import java.io.IOException; | ||||||
| import java.io.UnsupportedEncodingException; | import java.io.UnsupportedEncodingException; | ||||||
|  | import java.text.NumberFormat; | ||||||
| import java.util.Collections; | import java.util.Collections; | ||||||
| import java.util.Date; | import java.util.Date; | ||||||
| import java.util.List; | import java.util.List; | ||||||
| @ -63,10 +68,7 @@ import awais.instagrabber.BuildConfig; | |||||||
| import awais.instagrabber.R; | import awais.instagrabber.R; | ||||||
| import awais.instagrabber.adapters.StoriesAdapter; | import awais.instagrabber.adapters.StoriesAdapter; | ||||||
| import awais.instagrabber.asyncs.PostFetcher; | import awais.instagrabber.asyncs.PostFetcher; | ||||||
| import awais.instagrabber.asyncs.QuizAction; |  | ||||||
| import awais.instagrabber.asyncs.RespondAction; |  | ||||||
| import awais.instagrabber.asyncs.SeenAction; | import awais.instagrabber.asyncs.SeenAction; | ||||||
| import awais.instagrabber.asyncs.VoteAction; |  | ||||||
| import awais.instagrabber.asyncs.direct_messages.CreateThreadAction; | import awais.instagrabber.asyncs.direct_messages.CreateThreadAction; | ||||||
| import awais.instagrabber.asyncs.direct_messages.DirectThreadBroadcaster; | import awais.instagrabber.asyncs.direct_messages.DirectThreadBroadcaster; | ||||||
| import awais.instagrabber.customviews.helpers.SwipeGestureListener; | import awais.instagrabber.customviews.helpers.SwipeGestureListener; | ||||||
| @ -80,7 +82,10 @@ import awais.instagrabber.models.enums.MediaItemType; | |||||||
| import awais.instagrabber.models.stickers.PollModel; | import awais.instagrabber.models.stickers.PollModel; | ||||||
| import awais.instagrabber.models.stickers.QuestionModel; | import awais.instagrabber.models.stickers.QuestionModel; | ||||||
| import awais.instagrabber.models.stickers.QuizModel; | import awais.instagrabber.models.stickers.QuizModel; | ||||||
|  | import awais.instagrabber.models.stickers.SliderModel; | ||||||
|  | import awais.instagrabber.repositories.responses.StoryStickerResponse; | ||||||
| import awais.instagrabber.utils.Constants; | import awais.instagrabber.utils.Constants; | ||||||
|  | import awais.instagrabber.utils.CookieUtils; | ||||||
| import awais.instagrabber.utils.DownloadUtils; | import awais.instagrabber.utils.DownloadUtils; | ||||||
| import awais.instagrabber.utils.TextUtils; | import awais.instagrabber.utils.TextUtils; | ||||||
| import awais.instagrabber.utils.Utils; | import awais.instagrabber.utils.Utils; | ||||||
| @ -117,13 +122,15 @@ public class StoryViewerFragment extends Fragment { | |||||||
|     private QuestionModel question; |     private QuestionModel question; | ||||||
|     private String[] mentions; |     private String[] mentions; | ||||||
|     private QuizModel quiz; |     private QuizModel quiz; | ||||||
|  |     private SliderModel slider; | ||||||
|     private MenuItem menuDownload; |     private MenuItem menuDownload; | ||||||
|     private MenuItem menuDm; |     private MenuItem menuDm; | ||||||
|     private SimpleExoPlayer player; |     private SimpleExoPlayer player; | ||||||
|     private boolean isHashtag, isLoc; |     private boolean isHashtag, isLoc; | ||||||
|     private String highlight; |     private String highlight; | ||||||
|     private boolean fetching = false; |     private boolean fetching = false, sticking = false; | ||||||
|     private int currentFeedStoryIndex; |     private int currentFeedStoryIndex; | ||||||
|  |     private double sliderValue; | ||||||
|     private StoriesViewModel storiesViewModel; |     private StoriesViewModel storiesViewModel; | ||||||
|     private boolean shouldRefresh = true; |     private boolean shouldRefresh = true; | ||||||
|     private StoryViewerFragmentArgs fragmentArgs; |     private StoryViewerFragmentArgs fragmentArgs; | ||||||
| @ -190,7 +197,7 @@ public class StoryViewerFragment extends Fragment { | |||||||
|                 new AlertDialog.Builder(context) |                 new AlertDialog.Builder(context) | ||||||
|                         .setTitle(R.string.reply_story) |                         .setTitle(R.string.reply_story) | ||||||
|                         .setView(input) |                         .setView(input) | ||||||
|                         .setPositiveButton(R.string.ok, (d, w) -> new CreateThreadAction(cookie, currentStory.getUserId(), threadId -> { |                         .setPositiveButton(R.string.confirm, (d, w) -> new CreateThreadAction(cookie, currentStory.getUserId(), threadId -> { | ||||||
|                             try { |                             try { | ||||||
|                                 final DirectThreadBroadcaster.StoryReplyBroadcastOptions options = new DirectThreadBroadcaster.StoryReplyBroadcastOptions( |                                 final DirectThreadBroadcaster.StoryReplyBroadcastOptions options = new DirectThreadBroadcaster.StoryReplyBroadcastOptions( | ||||||
|                                         input.getText().toString(), |                                         input.getText().toString(), | ||||||
| @ -273,6 +280,7 @@ public class StoryViewerFragment extends Fragment { | |||||||
| 
 | 
 | ||||||
|     @SuppressLint("ClickableViewAccessibility") |     @SuppressLint("ClickableViewAccessibility") | ||||||
|     private void setupListeners() { |     private void setupListeners() { | ||||||
|  |         final String userIdFromCookie = CookieUtils.getUserIdFromCookie(cookie); | ||||||
|         final boolean hasFeedStories; |         final boolean hasFeedStories; | ||||||
|         List<?> models = null; |         List<?> models = null; | ||||||
|         if (currentFeedStoryIndex >= 0) { |         if (currentFeedStoryIndex >= 0) { | ||||||
| @ -297,6 +305,10 @@ public class StoryViewerFragment extends Fragment { | |||||||
|         swipeEvent = isRightSwipe -> { |         swipeEvent = isRightSwipe -> { | ||||||
|             final List<StoryModel> storyModels = storiesViewModel.getList().getValue(); |             final List<StoryModel> storyModels = storiesViewModel.getList().getValue(); | ||||||
|             final int storiesLen = storyModels == null ? 0 : storyModels.size(); |             final int storiesLen = storyModels == null ? 0 : storyModels.size(); | ||||||
|  |             if (sticking) { | ||||||
|  |                 Toast.makeText(context, R.string.follower_wait_to_load, Toast.LENGTH_SHORT).show(); | ||||||
|  |                 return; | ||||||
|  |             } | ||||||
|             if (storiesLen <= 0) return; |             if (storiesLen <= 0) return; | ||||||
|             final boolean isLeftSwipe = !isRightSwipe; |             final boolean isLeftSwipe = !isRightSwipe; | ||||||
|             final boolean endOfCurrentStories = slidePos + 1 >= storiesLen; |             final boolean endOfCurrentStories = slidePos + 1 >= storiesLen; | ||||||
| @ -407,15 +419,30 @@ public class StoryViewerFragment extends Fragment { | |||||||
|                                     poll.getLeftChoice() + " (" + poll.getLeftCount() + ")", |                                     poll.getLeftChoice() + " (" + poll.getLeftCount() + ")", | ||||||
|                                     poll.getRightChoice() + " (" + poll.getRightCount() + ")" |                                     poll.getRightChoice() + " (" + poll.getRightCount() + ")" | ||||||
|                             }), (d, w) -> { |                             }), (d, w) -> { | ||||||
|                                 if (!TextUtils.isEmpty(cookie)) |                                 if (!TextUtils.isEmpty(cookie)) { | ||||||
|                                     new VoteAction(currentStory, poll, cookie, choice -> { |                                     sticking = true; | ||||||
|                                         if (choice > -1) { |                                     storiesService.respondToPoll( | ||||||
|                                             poll.setMyChoice(choice); |                                             currentStory.getStoryMediaId().split("_")[0], | ||||||
|                                             Toast.makeText(context, R.string.votef_story_poll, Toast.LENGTH_SHORT).show(); |                                             poll.getId(), | ||||||
|                                             return; |                                             w, | ||||||
|                                         } |                                             userIdFromCookie, | ||||||
|                                         Toast.makeText(context, R.string.downloader_unknown_error, Toast.LENGTH_SHORT).show(); |                                             CookieUtils.getCsrfTokenFromCookie(cookie), | ||||||
|                                     }).execute(w); |                                             new ServiceCallback<StoryStickerResponse>() { | ||||||
|  |                                                 @Override | ||||||
|  |                                                 public void onSuccess(final StoryStickerResponse result) { | ||||||
|  |                                                     sticking = false; | ||||||
|  |                                                     poll.setMyChoice(w); | ||||||
|  |                                                     Toast.makeText(context, R.string.votef_story_poll, Toast.LENGTH_SHORT).show(); | ||||||
|  |                                                 } | ||||||
|  | 
 | ||||||
|  |                                                 @Override | ||||||
|  |                                                 public void onFailure(final Throwable t) { | ||||||
|  |                                                     sticking = false; | ||||||
|  |                                                     Log.e(TAG, "Error responding", t); | ||||||
|  |                                                     Toast.makeText(context, R.string.downloader_unknown_error, Toast.LENGTH_SHORT).show(); | ||||||
|  |                                                 } | ||||||
|  |                                             }); | ||||||
|  |                                 } | ||||||
|                             }) |                             }) | ||||||
|                             .setPositiveButton(R.string.cancel, null) |                             .setPositiveButton(R.string.cancel, null) | ||||||
|                             .show(); |                             .show(); | ||||||
| @ -427,12 +454,29 @@ public class StoryViewerFragment extends Fragment { | |||||||
|                 new AlertDialog.Builder(context) |                 new AlertDialog.Builder(context) | ||||||
|                         .setTitle(question.getQuestion()) |                         .setTitle(question.getQuestion()) | ||||||
|                         .setView(input) |                         .setView(input) | ||||||
|                         .setPositiveButton(R.string.ok, (d, w) -> new RespondAction(currentStory, question, cookie, result -> { |                         .setPositiveButton(R.string.confirm, (d, w) -> { | ||||||
|                             if (result) { |                                 sticking = true; | ||||||
|                                 Toast.makeText(context, R.string.answered_story, Toast.LENGTH_SHORT).show(); |                                 storiesService.respondToQuestion( | ||||||
|                             } else |                                         currentStory.getStoryMediaId().split("_")[0], | ||||||
|                                 Toast.makeText(context, R.string.downloader_unknown_error, Toast.LENGTH_SHORT).show(); |                                         question.getId(), | ||||||
|                         }).execute(input.getText().toString())) |                                         input.getText().toString(), | ||||||
|  |                                         userIdFromCookie, | ||||||
|  |                                         CookieUtils.getCsrfTokenFromCookie(cookie), | ||||||
|  |                                         new ServiceCallback<StoryStickerResponse>() { | ||||||
|  |                                             @Override | ||||||
|  |                                             public void onSuccess(final StoryStickerResponse result) { | ||||||
|  |                                                 sticking = false; | ||||||
|  |                                                 Toast.makeText(context, R.string.answered_story, Toast.LENGTH_SHORT).show(); | ||||||
|  |                                             } | ||||||
|  | 
 | ||||||
|  |                                             @Override | ||||||
|  |                                             public void onFailure(final Throwable t) { | ||||||
|  |                                                 sticking = false; | ||||||
|  |                                                 Log.e(TAG, "Error responding", t); | ||||||
|  |                                                 Toast.makeText(context, R.string.downloader_unknown_error, Toast.LENGTH_SHORT).show(); | ||||||
|  |                                             } | ||||||
|  |                                         }); | ||||||
|  |                         }) | ||||||
|                         .setNegativeButton(R.string.cancel, null) |                         .setNegativeButton(R.string.cancel, null) | ||||||
|                         .show(); |                         .show(); | ||||||
|             } else if (tag instanceof String[]) { |             } else if (tag instanceof String[]) { | ||||||
| @ -452,24 +496,119 @@ public class StoryViewerFragment extends Fragment { | |||||||
|                 new AlertDialog.Builder(context) |                 new AlertDialog.Builder(context) | ||||||
|                         .setTitle(quiz.getMyChoice() > -1 ? getString(R.string.story_quizzed) : quiz.getQuestion()) |                         .setTitle(quiz.getMyChoice() > -1 ? getString(R.string.story_quizzed) : quiz.getQuestion()) | ||||||
|                         .setAdapter(new ArrayAdapter<>(context, android.R.layout.simple_list_item_1, choices), (d, w) -> { |                         .setAdapter(new ArrayAdapter<>(context, android.R.layout.simple_list_item_1, choices), (d, w) -> { | ||||||
|                             if (quiz.getMyChoice() == -1 && !TextUtils.isEmpty(cookie)) |                             if (quiz.getMyChoice() == -1 && !TextUtils.isEmpty(cookie)) { | ||||||
|                                 new QuizAction(currentStory, quiz, cookie, choice -> { |                                 sticking = true; | ||||||
|                                     if (choice > -1) { |                                 storiesService.respondToQuiz( | ||||||
|                                         quiz.setMyChoice(choice); |                                         currentStory.getStoryMediaId().split("_")[0], | ||||||
|                                         Toast.makeText(context, R.string.answered_story, Toast.LENGTH_SHORT).show(); |                                         quiz.getId(), | ||||||
|                                         return; |                                         w, | ||||||
|                                     } |                                         userIdFromCookie, | ||||||
|                                     Toast.makeText(context, R.string.downloader_unknown_error, Toast.LENGTH_SHORT).show(); |                                         CookieUtils.getCsrfTokenFromCookie(cookie), | ||||||
|                                 }).execute(w); |                                         new ServiceCallback<StoryStickerResponse>() { | ||||||
|  |                                             @Override | ||||||
|  |                                             public void onSuccess(final StoryStickerResponse result) { | ||||||
|  |                                                 sticking = false; | ||||||
|  |                                                 quiz.setMyChoice(w); | ||||||
|  |                                                 Toast.makeText(context, R.string.answered_story, Toast.LENGTH_SHORT).show(); | ||||||
|  |                                             } | ||||||
|  | 
 | ||||||
|  |                                             @Override | ||||||
|  |                                             public void onFailure(final Throwable t) { | ||||||
|  |                                                 sticking = false; | ||||||
|  |                                                 Log.e(TAG, "Error responding", t); | ||||||
|  |                                                 Toast.makeText(context, R.string.downloader_unknown_error, Toast.LENGTH_SHORT).show(); | ||||||
|  |                                             } | ||||||
|  |                                         }); | ||||||
|  |                             } | ||||||
|                         }) |                         }) | ||||||
|                         .setPositiveButton(R.string.cancel, null) |                         .setPositiveButton(R.string.cancel, null) | ||||||
|                         .show(); |                         .show(); | ||||||
|  |             } else if (tag instanceof SliderModel) { | ||||||
|  |                 slider = (SliderModel) tag; | ||||||
|  |                 NumberFormat percentage = NumberFormat.getPercentInstance(); | ||||||
|  |                 percentage.setMaximumFractionDigits(2); | ||||||
|  |                 LinearLayout sliderView = new LinearLayout(context); | ||||||
|  |                 sliderView.setLayoutParams(new LinearLayout.LayoutParams( | ||||||
|  |                         LinearLayout.LayoutParams.MATCH_PARENT, | ||||||
|  |                         LinearLayout.LayoutParams.WRAP_CONTENT)); | ||||||
|  |                 sliderView.setOrientation(LinearLayout.VERTICAL); | ||||||
|  |                 TextView tv = new TextView(context); | ||||||
|  |                 tv.setGravity(Gravity.CENTER_HORIZONTAL); | ||||||
|  |                 final SeekBar input = new SeekBar(context); | ||||||
|  |                 Double avg = slider.getAverage() * 100; | ||||||
|  |                 input.setProgress(avg.intValue()); | ||||||
|  |                 sliderView.addView(input); | ||||||
|  |                 sliderView.addView(tv); | ||||||
|  |                 if (slider.getMyChoice().isNaN() && slider.canVote()) { | ||||||
|  |                     input.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() { | ||||||
|  |                         @Override | ||||||
|  |                         public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { | ||||||
|  |                             sliderValue = progress / 100.0; | ||||||
|  |                             tv.setText(percentage.format(sliderValue)); | ||||||
|  |                         } | ||||||
|  | 
 | ||||||
|  |                         @Override | ||||||
|  |                         public void onStartTrackingTouch(SeekBar seekBar) { | ||||||
|  |                         } | ||||||
|  | 
 | ||||||
|  |                         @Override | ||||||
|  |                         public void onStopTrackingTouch(SeekBar seekBar) { | ||||||
|  |                         } | ||||||
|  |                     }); | ||||||
|  |                     new AlertDialog.Builder(context) | ||||||
|  |                             .setTitle(TextUtils.isEmpty(slider.getQuestion()) ? slider.getEmoji() : slider.getQuestion()) | ||||||
|  |                             .setMessage(getResources().getQuantityString(R.plurals.slider_info, | ||||||
|  |                                     slider.getVoteCount(), | ||||||
|  |                                     slider.getVoteCount(), | ||||||
|  |                                     percentage.format(slider.getAverage()))) | ||||||
|  |                             .setView(sliderView) | ||||||
|  |                             .setPositiveButton(R.string.confirm, (d, w) -> { | ||||||
|  |                                 sticking = true; | ||||||
|  |                                 storiesService.respondToSlider( | ||||||
|  |                                         currentStory.getStoryMediaId().split("_")[0], | ||||||
|  |                                         slider.getId(), | ||||||
|  |                                         sliderValue, | ||||||
|  |                                         userIdFromCookie, | ||||||
|  |                                         CookieUtils.getCsrfTokenFromCookie(cookie), | ||||||
|  |                                         new ServiceCallback<StoryStickerResponse>() { | ||||||
|  |                                             @Override | ||||||
|  |                                             public void onSuccess(final StoryStickerResponse result) { | ||||||
|  |                                                 sticking = false; | ||||||
|  |                                                 slider.setMyChoice(sliderValue); | ||||||
|  |                                                 Toast.makeText(context, R.string.answered_story, Toast.LENGTH_SHORT).show(); | ||||||
|  |                                             } | ||||||
|  | 
 | ||||||
|  |                                             @Override | ||||||
|  |                                             public void onFailure(final Throwable t) { | ||||||
|  |                                                 sticking = false; | ||||||
|  |                                                 Log.e(TAG, "Error responding", t); | ||||||
|  |                                                 Toast.makeText(context, R.string.downloader_unknown_error, Toast.LENGTH_SHORT).show(); | ||||||
|  |                                             } | ||||||
|  |                                         }); | ||||||
|  |                             }) | ||||||
|  |                             .setNegativeButton(R.string.cancel, null) | ||||||
|  |                             .show(); | ||||||
|  |                 } | ||||||
|  |                 else { | ||||||
|  |                     input.setEnabled(false); | ||||||
|  |                     tv.setText(getString(R.string.slider_answer, percentage.format(slider.getMyChoice()))); | ||||||
|  |                     new AlertDialog.Builder(context) | ||||||
|  |                             .setTitle(TextUtils.isEmpty(slider.getQuestion()) ? slider.getEmoji() : slider.getQuestion()) | ||||||
|  |                             .setMessage(getResources().getQuantityString(R.plurals.slider_info, | ||||||
|  |                                     slider.getVoteCount(), | ||||||
|  |                                     slider.getVoteCount(), | ||||||
|  |                                     percentage.format(slider.getAverage()))) | ||||||
|  |                             .setView(sliderView) | ||||||
|  |                             .setPositiveButton(R.string.ok, null) | ||||||
|  |                             .show(); | ||||||
|  |                 } | ||||||
|             } |             } | ||||||
|         }; |         }; | ||||||
|         binding.poll.setOnClickListener(storyActionListener); |         binding.poll.setOnClickListener(storyActionListener); | ||||||
|         binding.answer.setOnClickListener(storyActionListener); |         binding.answer.setOnClickListener(storyActionListener); | ||||||
|         binding.mention.setOnClickListener(storyActionListener); |         binding.mention.setOnClickListener(storyActionListener); | ||||||
|         binding.quiz.setOnClickListener(storyActionListener); |         binding.quiz.setOnClickListener(storyActionListener); | ||||||
|  |         binding.slider.setOnClickListener(storyActionListener); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     private void resetView() { |     private void resetView() { | ||||||
| @ -588,6 +727,10 @@ public class StoryViewerFragment extends Fragment { | |||||||
|         binding.quiz.setVisibility(quiz != null ? View.VISIBLE : View.GONE); |         binding.quiz.setVisibility(quiz != null ? View.VISIBLE : View.GONE); | ||||||
|         binding.quiz.setTag(quiz); |         binding.quiz.setTag(quiz); | ||||||
| 
 | 
 | ||||||
|  |         slider = currentStory.getSlider(); | ||||||
|  |         binding.slider.setVisibility(slider != null ? View.VISIBLE : View.GONE); | ||||||
|  |         binding.slider.setTag(slider); | ||||||
|  | 
 | ||||||
|         releasePlayer(); |         releasePlayer(); | ||||||
|         if (isHashtag || isLoc) { |         if (isHashtag || isLoc) { | ||||||
|             final ActionBar actionBar = fragmentActivity.getSupportActionBar(); |             final ActionBar actionBar = fragmentActivity.getSupportActionBar(); | ||||||
|  | |||||||
| @ -47,6 +47,7 @@ import awais.instagrabber.models.FeedModel; | |||||||
| import awais.instagrabber.models.FeedStoryModel; | import awais.instagrabber.models.FeedStoryModel; | ||||||
| import awais.instagrabber.models.PostsLayoutPreferences; | import awais.instagrabber.models.PostsLayoutPreferences; | ||||||
| import awais.instagrabber.utils.Constants; | import awais.instagrabber.utils.Constants; | ||||||
|  | import awais.instagrabber.utils.CookieUtils; | ||||||
| import awais.instagrabber.utils.DownloadUtils; | import awais.instagrabber.utils.DownloadUtils; | ||||||
| import awais.instagrabber.utils.Utils; | import awais.instagrabber.utils.Utils; | ||||||
| import awais.instagrabber.viewmodels.FeedStoriesViewModel; | import awais.instagrabber.viewmodels.FeedStoriesViewModel; | ||||||
| @ -55,6 +56,7 @@ import awais.instagrabber.webservices.StoriesService; | |||||||
| 
 | 
 | ||||||
| import static androidx.core.content.PermissionChecker.checkSelfPermission; | import static androidx.core.content.PermissionChecker.checkSelfPermission; | ||||||
| import static awais.instagrabber.utils.DownloadUtils.WRITE_PERMISSION; | import static awais.instagrabber.utils.DownloadUtils.WRITE_PERMISSION; | ||||||
|  | import static awais.instagrabber.utils.Utils.settingsHelper; | ||||||
| 
 | 
 | ||||||
| public class FeedFragment extends Fragment implements SwipeRefreshLayout.OnRefreshListener { | public class FeedFragment extends Fragment implements SwipeRefreshLayout.OnRefreshListener { | ||||||
|     private static final String TAG = "FeedFragment"; |     private static final String TAG = "FeedFragment"; | ||||||
| @ -367,9 +369,10 @@ public class FeedFragment extends Fragment implements SwipeRefreshLayout.OnRefre | |||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     private void fetchStories() { |     private void fetchStories() { | ||||||
|  |         final String cookie = settingsHelper.getString(Constants.COOKIE); | ||||||
|         storiesFetching = true; |         storiesFetching = true; | ||||||
|         updateSwipeRefreshState(); |         updateSwipeRefreshState(); | ||||||
|         storiesService.getFeedStories(new ServiceCallback<List<FeedStoryModel>>() { |         storiesService.getFeedStories(CookieUtils.getCsrfTokenFromCookie(cookie), new ServiceCallback<List<FeedStoryModel>>() { | ||||||
|             @Override |             @Override | ||||||
|             public void onSuccess(final List<FeedStoryModel> result) { |             public void onSuccess(final List<FeedStoryModel> result) { | ||||||
|                 feedStoriesViewModel.getList().postValue(result); |                 feedStoriesViewModel.getList().postValue(result); | ||||||
|  | |||||||
| @ -6,6 +6,7 @@ import awais.instagrabber.models.enums.MediaItemType; | |||||||
| import awais.instagrabber.models.stickers.PollModel; | import awais.instagrabber.models.stickers.PollModel; | ||||||
| import awais.instagrabber.models.stickers.QuestionModel; | import awais.instagrabber.models.stickers.QuestionModel; | ||||||
| import awais.instagrabber.models.stickers.QuizModel; | import awais.instagrabber.models.stickers.QuizModel; | ||||||
|  | import awais.instagrabber.models.stickers.SliderModel; | ||||||
| import awais.instagrabber.models.stickers.SwipeUpModel; | import awais.instagrabber.models.stickers.SwipeUpModel; | ||||||
| 
 | 
 | ||||||
| public final class StoryModel implements Serializable { | public final class StoryModel implements Serializable { | ||||||
| @ -21,6 +22,7 @@ public final class StoryModel implements Serializable { | |||||||
|     private String spotify; |     private String spotify; | ||||||
|     private PollModel poll; |     private PollModel poll; | ||||||
|     private QuestionModel question; |     private QuestionModel question; | ||||||
|  |     private SliderModel slider; | ||||||
|     private QuizModel quiz; |     private QuizModel quiz; | ||||||
|     private SwipeUpModel swipeUp; |     private SwipeUpModel swipeUp; | ||||||
|     private String[] mentions; |     private String[] mentions; | ||||||
| @ -71,6 +73,10 @@ public final class StoryModel implements Serializable { | |||||||
|         return question; |         return question; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     public SliderModel getSlider() { | ||||||
|  |         return slider; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|     public QuizModel getQuiz() { |     public QuizModel getQuiz() { | ||||||
|         return quiz; |         return quiz; | ||||||
|     } |     } | ||||||
| @ -109,6 +115,10 @@ public final class StoryModel implements Serializable { | |||||||
|         this.question = question; |         this.question = question; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     public void setSlider(final SliderModel slider) { | ||||||
|  |         this.slider = slider; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|     public void setQuiz(final QuizModel quiz) { |     public void setQuiz(final QuizModel quiz) { | ||||||
|         this.quiz = quiz; |         this.quiz = quiz; | ||||||
|     } |     } | ||||||
|  | |||||||
							
								
								
									
										53
									
								
								app/src/main/java/awais/instagrabber/models/stickers/SliderModel.java
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										53
									
								
								app/src/main/java/awais/instagrabber/models/stickers/SliderModel.java
									
									
									
									
									
										Executable file
									
								
							| @ -0,0 +1,53 @@ | |||||||
|  | package awais.instagrabber.models.stickers; | ||||||
|  | 
 | ||||||
|  | import java.io.Serializable; | ||||||
|  | 
 | ||||||
|  | public final class SliderModel implements Serializable { | ||||||
|  |     private final int voteCount; | ||||||
|  |     private final Double average; | ||||||
|  |     private Double myChoice; | ||||||
|  |     private final boolean canVote; | ||||||
|  |     private final String id, question, emoji; | ||||||
|  | 
 | ||||||
|  |     public SliderModel(final String id, final String question, final String emoji, final boolean canVote, | ||||||
|  |                        final Double average, final int voteCount, final Double myChoice) { | ||||||
|  |         this.id = id; | ||||||
|  |         this.question = question; | ||||||
|  |         this.emoji = emoji; | ||||||
|  |         this.canVote = canVote; | ||||||
|  |         this.average = average; | ||||||
|  |         this.voteCount = voteCount; | ||||||
|  |         this.myChoice = myChoice; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public String getId() { | ||||||
|  |         return id; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public String getQuestion() { | ||||||
|  |         return question; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public String getEmoji() { | ||||||
|  |         return emoji; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public boolean canVote() { | ||||||
|  |         return canVote; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public int getVoteCount() { | ||||||
|  |         return voteCount; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public Double getAverage() { | ||||||
|  |         return average; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public Double getMyChoice() { return myChoice; } | ||||||
|  | 
 | ||||||
|  |     public Double setMyChoice(final Double choice) { | ||||||
|  |         this.myChoice = choice; | ||||||
|  |         return choice; | ||||||
|  |     } | ||||||
|  | } | ||||||
| @ -2,17 +2,33 @@ package awais.instagrabber.repositories; | |||||||
| 
 | 
 | ||||||
| import java.util.Map; | import java.util.Map; | ||||||
| 
 | 
 | ||||||
|  | import awais.instagrabber.repositories.responses.StoryStickerResponse; | ||||||
| import retrofit2.Call; | import retrofit2.Call; | ||||||
|  | import retrofit2.http.FieldMap; | ||||||
|  | import retrofit2.http.FormUrlEncoded; | ||||||
| import retrofit2.http.GET; | import retrofit2.http.GET; | ||||||
| import retrofit2.http.Header; | import retrofit2.http.Header; | ||||||
|  | import retrofit2.http.Path; | ||||||
|  | import retrofit2.http.POST; | ||||||
| import retrofit2.http.QueryMap; | import retrofit2.http.QueryMap; | ||||||
| import retrofit2.http.Url; | import retrofit2.http.Url; | ||||||
| 
 | 
 | ||||||
| public interface StoriesRepository { | public interface StoriesRepository { | ||||||
| 
 | 
 | ||||||
|     @GET("graphql/query/") |     @FormUrlEncoded | ||||||
|     Call<String> getStories(@QueryMap(encoded = true) Map<String, String> variables); |     @POST("/api/v1/feed/reels_tray/") | ||||||
|  |     Call<String> getStories(@Header("User-Agent") String userAgent, | ||||||
|  |                             @FieldMap Map<String, String> form); | ||||||
| 
 | 
 | ||||||
|     @GET |     @GET | ||||||
|     Call<String> getUserStory(@Header("User-Agent") String userAgent, @Url String url); |     Call<String> getUserStory(@Header("User-Agent") String userAgent, @Url String url); | ||||||
|  | 
 | ||||||
|  |     @FormUrlEncoded | ||||||
|  |     @POST("/api/v1/media/{storyId}/{stickerId}/{action}/") | ||||||
|  |     Call<StoryStickerResponse> respondToSticker(@Header("User-Agent") String userAgent, | ||||||
|  |                                                 @Path("storyId") String storyId, | ||||||
|  |                                                 @Path("stickerId") String stickerId, | ||||||
|  |                                                 @Path("action") String action, | ||||||
|  |                                                 // story_poll_vote, story_question_response, story_slider_vote, story_quiz_answer | ||||||
|  |                                                 @FieldMap Map<String, String> form); | ||||||
| } | } | ||||||
|  | |||||||
| @ -0,0 +1,20 @@ | |||||||
|  | package awais.instagrabber.repositories.responses; | ||||||
|  | 
 | ||||||
|  | public class StoryStickerResponse { | ||||||
|  |     private final String status; | ||||||
|  | 
 | ||||||
|  |     public StoryStickerResponse(final String status) { | ||||||
|  |         this.status = status; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public String getStatus() { | ||||||
|  |         return status; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     public String toString() { | ||||||
|  |         return "StoryStickerResponse{" + | ||||||
|  |                 "status='" + status + '\'' + | ||||||
|  |                 '}'; | ||||||
|  |     } | ||||||
|  | } | ||||||
| @ -18,6 +18,7 @@ import java.util.ArrayList; | |||||||
| import java.util.HashMap; | import java.util.HashMap; | ||||||
| import java.util.List; | import java.util.List; | ||||||
| import java.util.Map; | import java.util.Map; | ||||||
|  | import java.util.UUID; | ||||||
| 
 | 
 | ||||||
| import awais.instagrabber.models.FeedStoryModel; | import awais.instagrabber.models.FeedStoryModel; | ||||||
| import awais.instagrabber.models.ProfileModel; | import awais.instagrabber.models.ProfileModel; | ||||||
| @ -26,9 +27,13 @@ import awais.instagrabber.models.enums.MediaItemType; | |||||||
| import awais.instagrabber.models.stickers.PollModel; | import awais.instagrabber.models.stickers.PollModel; | ||||||
| import awais.instagrabber.models.stickers.QuestionModel; | import awais.instagrabber.models.stickers.QuestionModel; | ||||||
| import awais.instagrabber.models.stickers.QuizModel; | import awais.instagrabber.models.stickers.QuizModel; | ||||||
|  | import awais.instagrabber.models.stickers.SliderModel; | ||||||
|  | import awais.instagrabber.models.stickers.SwipeUpModel; | ||||||
| import awais.instagrabber.repositories.StoriesRepository; | import awais.instagrabber.repositories.StoriesRepository; | ||||||
|  | import awais.instagrabber.repositories.responses.StoryStickerResponse; | ||||||
| import awais.instagrabber.utils.Constants; | import awais.instagrabber.utils.Constants; | ||||||
| import awais.instagrabber.utils.ResponseBodyUtils; | import awais.instagrabber.utils.ResponseBodyUtils; | ||||||
|  | import awais.instagrabber.utils.Utils; | ||||||
| import retrofit2.Call; | import retrofit2.Call; | ||||||
| import retrofit2.Callback; | import retrofit2.Callback; | ||||||
| import retrofit2.Response; | import retrofit2.Response; | ||||||
| @ -44,7 +49,7 @@ public class StoriesService extends BaseService { | |||||||
| 
 | 
 | ||||||
|     private StoriesService() { |     private StoriesService() { | ||||||
|         final Retrofit retrofit = getRetrofitBuilder() |         final Retrofit retrofit = getRetrofitBuilder() | ||||||
|                 .baseUrl("https://www.instagram.com") |                 .baseUrl("https://i.instagram.com") | ||||||
|                 .build(); |                 .build(); | ||||||
|         repository = retrofit.create(StoriesRepository.class); |         repository = retrofit.create(StoriesRepository.class); | ||||||
|     } |     } | ||||||
| @ -56,7 +61,7 @@ public class StoriesService extends BaseService { | |||||||
|         return instance; |         return instance; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     public void getFeedStories(final ServiceCallback<List<FeedStoryModel>> callback) { |     public void getFeedStories(final String csrfToken, final ServiceCallback<List<FeedStoryModel>> callback) { | ||||||
|         if (loadFromMock) { |         if (loadFromMock) { | ||||||
|             final Handler handler = new Handler(); |             final Handler handler = new Handler(); | ||||||
|             handler.postDelayed(() -> { |             handler.postDelayed(() -> { | ||||||
| @ -81,10 +86,13 @@ public class StoriesService extends BaseService { | |||||||
|             }, 1000); |             }, 1000); | ||||||
|             return; |             return; | ||||||
|         } |         } | ||||||
|         final Map<String, String> queryMap = new HashMap<>(); |         final Map<String, Object> form = new HashMap<>(4); | ||||||
|         queryMap.put("query_hash", "b7b84d884400bc5aa7cfe12ae843a091"); |         form.put("reason", "cold_start"); | ||||||
|         queryMap.put("variables", "{\"only_stories\":true,\"stories_prefetch\":false,\"stories_video_dash_manifest\":false}"); |         form.put("_csrftoken", csrfToken); | ||||||
|         final Call<String> response = repository.getStories(queryMap); |         form.put("_uuid", UUID.randomUUID().toString()); | ||||||
|  |         form.put("supported_capabilities_new", Constants.SUPPORTED_CAPABILITIES); | ||||||
|  |         final Map<String, String> signedForm = Utils.sign(form); | ||||||
|  |         final Call<String> response = repository.getStories(Constants.I_USER_AGENT, signedForm); | ||||||
|         response.enqueue(new Callback<String>() { |         response.enqueue(new Callback<String>() { | ||||||
|             @Override |             @Override | ||||||
|             public void onResponse(@NonNull final Call<String> call, @NonNull final Response<String> response) { |             public void onResponse(@NonNull final Call<String> call, @NonNull final Response<String> response) { | ||||||
| @ -106,17 +114,12 @@ public class StoriesService extends BaseService { | |||||||
|     private void parseStoriesBody(final String body, final ServiceCallback<List<FeedStoryModel>> callback) { |     private void parseStoriesBody(final String body, final ServiceCallback<List<FeedStoryModel>> callback) { | ||||||
|         try { |         try { | ||||||
|             final List<FeedStoryModel> feedStoryModels = new ArrayList<>(); |             final List<FeedStoryModel> feedStoryModels = new ArrayList<>(); | ||||||
|             final JSONArray feedStoriesReel = new JSONObject(body) |             final JSONArray feedStoriesReel = new JSONObject(body).getJSONArray("tray"); | ||||||
|                     .getJSONObject("data") |  | ||||||
|                     .getJSONObject(Constants.EXTRAS_USER) |  | ||||||
|                     .getJSONObject("feed_reels_tray") |  | ||||||
|                     .getJSONObject("edge_reels_tray_to_reel") |  | ||||||
|                     .getJSONArray("edges"); |  | ||||||
|             for (int i = 0; i < feedStoriesReel.length(); ++i) { |             for (int i = 0; i < feedStoriesReel.length(); ++i) { | ||||||
|                 final JSONObject node = feedStoriesReel.getJSONObject(i).getJSONObject("node"); |                 final JSONObject node = feedStoriesReel.getJSONObject(i); | ||||||
|                 final JSONObject user = node.getJSONObject(node.has("user") ? "user" : "owner"); |                 final JSONObject user = node.getJSONObject(node.has("user") ? "user" : "owner"); | ||||||
|                 final ProfileModel profileModel = new ProfileModel(false, false, false, |                 final ProfileModel profileModel = new ProfileModel(false, false, false, | ||||||
|                                                                    user.getString("id"), |                                                                    user.getString("pk"), | ||||||
|                                                                    user.getString("username"), |                                                                    user.getString("username"), | ||||||
|                                                                    null, null, null, |                                                                    null, null, null, | ||||||
|                                                                    user.getString("profile_pic_url"), |                                                                    user.getString("profile_pic_url"), | ||||||
| @ -240,6 +243,27 @@ public class StoriesService extends BaseService { | |||||||
|                                     )); |                                     )); | ||||||
|                                 } |                                 } | ||||||
|                             } |                             } | ||||||
|  |                             if (data.has("story_cta") && data.has("link_text")) { | ||||||
|  |                                 JSONObject tappableObject = data.getJSONArray("story_cta").getJSONObject(0).getJSONArray("links").getJSONObject(0); | ||||||
|  |                                 String swipeUpUrl = tappableObject.getString("webUri"); | ||||||
|  |                                 if (swipeUpUrl.startsWith("http")) { | ||||||
|  |                                     model.setSwipeUp(new SwipeUpModel(swipeUpUrl, data.getString("link_text"))); | ||||||
|  |                                 } | ||||||
|  |                             } | ||||||
|  |                             if (data.has("story_sliders")) { | ||||||
|  |                                 final JSONObject tappableObject = data.getJSONArray("story_sliders").getJSONObject(0) | ||||||
|  |                                         .optJSONObject("slider_sticker"); | ||||||
|  |                                 if (tappableObject != null) | ||||||
|  |                                     model.setSlider(new SliderModel( | ||||||
|  |                                             String.valueOf(tappableObject.getLong("slider_id")), | ||||||
|  |                                             tappableObject.getString("question"), | ||||||
|  |                                             tappableObject.getString("emoji"), | ||||||
|  |                                             tappableObject.getBoolean("viewer_can_vote"), | ||||||
|  |                                             tappableObject.getDouble("slider_vote_average"), | ||||||
|  |                                             tappableObject.getInt("slider_vote_count"), | ||||||
|  |                                             tappableObject.optDouble("viewer_vote") | ||||||
|  |                                     )); | ||||||
|  |                             } | ||||||
|                             JSONArray hashtags = data.optJSONArray("story_hashtags"); |                             JSONArray hashtags = data.optJSONArray("story_hashtags"); | ||||||
|                             JSONArray locations = data.optJSONArray("story_locations"); |                             JSONArray locations = data.optJSONArray("story_locations"); | ||||||
|                             JSONArray atmarks = data.optJSONArray("reel_mentions"); |                             JSONArray atmarks = data.optJSONArray("reel_mentions"); | ||||||
| @ -283,6 +307,83 @@ public class StoriesService extends BaseService { | |||||||
|         }); |         }); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     private void respondToSticker(final String storyId, | ||||||
|  |                                   final String stickerId, | ||||||
|  |                                   final String action, | ||||||
|  |                                   final String arg1, | ||||||
|  |                                   final String arg2, | ||||||
|  |                                   final String userId, | ||||||
|  |                                   final String csrfToken, | ||||||
|  |                                   final ServiceCallback<StoryStickerResponse> callback) { | ||||||
|  |         final Map<String, Object> form = new HashMap<>(); | ||||||
|  |         form.put("_csrftoken", csrfToken); | ||||||
|  |         form.put("_uid", userId); | ||||||
|  |         form.put("_uuid", UUID.randomUUID().toString()); | ||||||
|  |         form.put("mutation_token", UUID.randomUUID().toString()); | ||||||
|  |         form.put("client_context", UUID.randomUUID().toString()); | ||||||
|  |         form.put("radio_type", "wifi-none"); | ||||||
|  |         form.put(arg1, arg2); | ||||||
|  |         final Map<String, String> signedForm = Utils.sign(form); | ||||||
|  |         final Call<StoryStickerResponse> request = | ||||||
|  |                 repository.respondToSticker(Constants.I_USER_AGENT, storyId, stickerId, action, signedForm); | ||||||
|  |         request.enqueue(new Callback<StoryStickerResponse>() { | ||||||
|  |             @Override | ||||||
|  |             public void onResponse(@NonNull final Call<StoryStickerResponse> call, | ||||||
|  |                                    @NonNull final Response<StoryStickerResponse> response) { | ||||||
|  |                 if (callback != null) { | ||||||
|  |                     callback.onSuccess(response.body()); | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |             @Override | ||||||
|  |             public void onFailure(@NonNull final Call<StoryStickerResponse> call, | ||||||
|  |                                   @NonNull final Throwable t) { | ||||||
|  |                 if (callback != null) { | ||||||
|  |                     callback.onFailure(t); | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |         }); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     // RespondAction.java | ||||||
|  |     public void respondToQuestion(final String storyId, | ||||||
|  |                                    final String stickerId, | ||||||
|  |                                    final String answer, | ||||||
|  |                                    final String userId, | ||||||
|  |                                    final String csrfToken, | ||||||
|  |                                    final ServiceCallback<StoryStickerResponse> callback) { | ||||||
|  |         respondToSticker(storyId, stickerId, "story_question_response", "response", answer, userId, csrfToken, callback); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     // QuizAction.java | ||||||
|  |     public void respondToQuiz(final String storyId, | ||||||
|  |                                final String stickerId, | ||||||
|  |                                final int answer, | ||||||
|  |                                final String userId, | ||||||
|  |                                final String csrfToken, | ||||||
|  |                                final ServiceCallback<StoryStickerResponse> callback) { | ||||||
|  |         respondToSticker(storyId, stickerId, "story_quiz_answer", "answer", String.valueOf(answer), userId, csrfToken, callback); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     // VoteAction.java | ||||||
|  |     public void respondToPoll(final String storyId, | ||||||
|  |                                final String stickerId, | ||||||
|  |                                final int answer, | ||||||
|  |                                final String userId, | ||||||
|  |                                final String csrfToken, | ||||||
|  |                                final ServiceCallback<StoryStickerResponse> callback) { | ||||||
|  |         respondToSticker(storyId, stickerId, "story_poll_vote", "vote", String.valueOf(answer), userId, csrfToken, callback); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public void respondToSlider(final String storyId, | ||||||
|  |                               final String stickerId, | ||||||
|  |                               final double answer, | ||||||
|  |                               final String userId, | ||||||
|  |                               final String csrfToken, | ||||||
|  |                               final ServiceCallback<StoryStickerResponse> callback) { | ||||||
|  |         respondToSticker(storyId, stickerId, "story_slider_vote", "vote", String.valueOf(answer), userId, csrfToken, callback); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|     private String buildUrl(final String id, final boolean isLoc, final boolean isHashtag, final boolean highlight) { |     private String buildUrl(final String id, final boolean isLoc, final boolean isHashtag, final boolean highlight) { | ||||||
|         final String userId = id.replace(":", "%3A"); |         final String userId = id.replace(":", "%3A"); | ||||||
|         final StringBuilder builder = new StringBuilder(); |         final StringBuilder builder = new StringBuilder(); | ||||||
|  | |||||||
| @ -85,6 +85,16 @@ | |||||||
|                 android:visibility="gone" |                 android:visibility="gone" | ||||||
|                 app:backgroundTint="@color/btn_blue_background" /> |                 app:backgroundTint="@color/btn_blue_background" /> | ||||||
| 
 | 
 | ||||||
|  |             <androidx.appcompat.widget.AppCompatButton | ||||||
|  |                 android:id="@+id/slider" | ||||||
|  |                 android:layout_width="match_parent" | ||||||
|  |                 android:layout_height="wrap_content" | ||||||
|  |                 android:layout_weight="1" | ||||||
|  |                 android:text="@string/story_slider" | ||||||
|  |                 android:textColor="@color/btn_blue_text_color" | ||||||
|  |                 android:visibility="gone" | ||||||
|  |                 app:backgroundTint="@color/btn_blue_background" /> | ||||||
|  | 
 | ||||||
|             <androidx.appcompat.widget.AppCompatButton |             <androidx.appcompat.widget.AppCompatButton | ||||||
|                 android:id="@+id/swipeUp" |                 android:id="@+id/swipeUp" | ||||||
|                 android:layout_width="match_parent" |                 android:layout_width="match_parent" | ||||||
|  | |||||||
| @ -66,9 +66,15 @@ | |||||||
|     <string name="respond_story">Respond</string> |     <string name="respond_story">Respond</string> | ||||||
|     <string name="answer_hint">Answer…</string> |     <string name="answer_hint">Answer…</string> | ||||||
|     <string name="answered_story">Answer successful!</string> |     <string name="answered_story">Answer successful!</string> | ||||||
|  |     <plurals name="slider_info" comment="For slider stickers in stories, eg. 3 responses averaging 17.38%"> | ||||||
|  |         <item quantity="one">%d response averaging %s</item> | ||||||
|  |         <item quantity="other">%d responses averaging %s</item> | ||||||
|  |     </plurals> | ||||||
|  |     <string name="slider_answer">Your answer: %s</string> | ||||||
|     <string name="reply_story">Reply to story</string> |     <string name="reply_story">Reply to story</string> | ||||||
|     <string name="reply_hint">Reply…</string> |     <string name="reply_hint">Reply…</string> | ||||||
|     <string name="story_quiz">Quiz</string> |     <string name="story_quiz">Quiz</string> | ||||||
|  |     <string name="story_slider">Slider</string> | ||||||
|     <string name="story_quizzed">You have already answered!</string> |     <string name="story_quizzed">You have already answered!</string> | ||||||
|     <string name="story_mentions">Mentions</string> |     <string name="story_mentions">Mentions</string> | ||||||
|     <string name="priv_acc">This Account is Private</string> |     <string name="priv_acc">This Account is Private</string> | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user