mirror of
				https://github.com/KokaKiwi/BarInsta
				synced 2025-10-31 19:45:35 +00:00 
			
		
		
		
	Merge remote-tracking branch 'origin/dm-notifications-enhancements' into dm-notifications-enhancements
This commit is contained in:
		
						commit
						3795ff2420
					
				| @ -10,8 +10,8 @@ android { | ||||
|         minSdkVersion 21 | ||||
|         targetSdkVersion 29 | ||||
| 
 | ||||
|         versionCode 57 | ||||
|         versionName '19.0.5' | ||||
|         versionCode 58 | ||||
|         versionName '19.1.0' | ||||
| 
 | ||||
|         multiDexEnabled true | ||||
| 
 | ||||
|  | ||||
| @ -12,11 +12,13 @@ import com.facebook.imagepipeline.core.ImagePipelineConfig; | ||||
| import java.net.CookieHandler; | ||||
| import java.text.SimpleDateFormat; | ||||
| import java.util.UUID; | ||||
| import java.util.concurrent.ThreadLocalRandom; | ||||
| 
 | ||||
| import awais.instagrabber.utils.Constants; | ||||
| import awais.instagrabber.utils.LocaleUtils; | ||||
| import awais.instagrabber.utils.SettingsHelper; | ||||
| import awais.instagrabber.utils.TextUtils; | ||||
| import awais.instagrabber.utils.UserAgentUtils; | ||||
| import awaisomereport.CrashReporter; | ||||
| import awaisomereport.LogCollector; | ||||
| 
 | ||||
| @ -85,5 +87,15 @@ public final class InstaGrabberApplication extends Application { | ||||
|         if (TextUtils.isEmpty(settingsHelper.getString(Constants.DEVICE_UUID))) { | ||||
|             settingsHelper.putString(Constants.DEVICE_UUID, UUID.randomUUID().toString()); | ||||
|         } | ||||
| 
 | ||||
|         if (settingsHelper.getInteger(Constants.BROWSER_UA_CODE) == -1) { | ||||
|             int randomNum = ThreadLocalRandom.current().nextInt(0, UserAgentUtils.browsers.length); | ||||
|             settingsHelper.putInteger(Constants.BROWSER_UA_CODE, randomNum); | ||||
|         } | ||||
| 
 | ||||
|         if (settingsHelper.getInteger(Constants.APP_UA_CODE) == -1) { | ||||
|             int randomNum = ThreadLocalRandom.current().nextInt(0, UserAgentUtils.devices.length); | ||||
|             settingsHelper.putInteger(Constants.APP_UA_CODE, randomNum); | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @ -0,0 +1,61 @@ | ||||
| package awais.instagrabber.animations; | ||||
| 
 | ||||
| import android.animation.Animator; | ||||
| import android.animation.AnimatorListenerAdapter; | ||||
| import android.view.View; | ||||
| 
 | ||||
| // https://medium.com/better-programming/animated-fab-button-with-more-options-2dcf7118fff6 | ||||
| 
 | ||||
| public class FabAnimation { | ||||
|     public static boolean rotateFab(final View v, boolean rotate) { | ||||
|         v.animate().setDuration(200) | ||||
|                 .setListener(new AnimatorListenerAdapter() { | ||||
|                     @Override | ||||
|                     public void onAnimationEnd(Animator animation) { | ||||
|                         super.onAnimationEnd(animation); | ||||
|                     } | ||||
|                 }) | ||||
|                 .rotation(rotate ? 135f : 0f); | ||||
|         return rotate; | ||||
|     } | ||||
| 
 | ||||
|     public static void showIn(final View v) { | ||||
|         v.setVisibility(View.VISIBLE); | ||||
|         v.setAlpha(0f); | ||||
|         v.setTranslationY(v.getHeight()); | ||||
|         v.animate() | ||||
|                 .setDuration(200) | ||||
|                 .translationY(0) | ||||
|                 .setListener(new AnimatorListenerAdapter() { | ||||
|                     @Override | ||||
|                     public void onAnimationEnd(Animator animation) { | ||||
|                         super.onAnimationEnd(animation); | ||||
|                     } | ||||
|                 }) | ||||
|                 .alpha(1f) | ||||
|                 .start(); | ||||
|     } | ||||
| 
 | ||||
|     public static void showOut(final View v) { | ||||
|         v.setVisibility(View.VISIBLE); | ||||
|         v.setAlpha(1f); | ||||
|         v.setTranslationY(0); | ||||
|         v.animate() | ||||
|                 .setDuration(200) | ||||
|                 .translationY(v.getHeight()) | ||||
|                 .setListener(new AnimatorListenerAdapter() { | ||||
|                     @Override | ||||
|                     public void onAnimationEnd(Animator animation) { | ||||
|                         v.setVisibility(View.GONE); | ||||
|                         super.onAnimationEnd(animation); | ||||
|                     } | ||||
|                 }).alpha(0f) | ||||
|                 .start(); | ||||
|     } | ||||
| 
 | ||||
|     public static void init(final View v) { | ||||
|         v.setVisibility(View.GONE); | ||||
|         v.setTranslationY(v.getHeight()); | ||||
|         v.setAlpha(0f); | ||||
|     } | ||||
| } | ||||
| @ -35,7 +35,7 @@ public class CreateThreadAction extends AsyncTask<Void, Void, String> { | ||||
|         try { | ||||
|             urlConnection = (HttpURLConnection) new URL(url).openConnection(); | ||||
|             urlConnection.setRequestMethod("POST"); | ||||
|             urlConnection.setRequestProperty("User-Agent", Constants.I_USER_AGENT); | ||||
|             urlConnection.setRequestProperty("User-Agent", Utils.settingsHelper.getString(Constants.APP_UA)); | ||||
|             urlConnection.setUseCaches(false); | ||||
|             final String urlParameters = Utils.sign("{\"_csrftoken\":\"" + cookie.split("csrftoken=")[1].split(";")[0] | ||||
|                     + "\",\"_uid\":\"" + CookieUtils.getUserIdFromCookie(cookie) | ||||
|  | ||||
| @ -29,8 +29,9 @@ public class FeedPostFetchService implements PostFetcher.PostFetchService { | ||||
|         final List<Media> feedModels = new ArrayList<>(); | ||||
|         final String cookie = settingsHelper.getString(Constants.COOKIE); | ||||
|         final String csrfToken = CookieUtils.getCsrfTokenFromCookie(cookie); | ||||
|         final String deviceUuid = settingsHelper.getString(Constants.DEVICE_UUID); | ||||
|         feedModels.clear(); | ||||
|         feedService.fetch(csrfToken, nextCursor, new ServiceCallback<PostsFetchResponse>() { | ||||
|         feedService.fetch(csrfToken, deviceUuid, nextCursor, new ServiceCallback<PostsFetchResponse>() { | ||||
|             @Override | ||||
|             public void onSuccess(final PostsFetchResponse result) { | ||||
|                 if (result == null && feedModels.size() > 0) { | ||||
|  | ||||
| @ -14,6 +14,7 @@ import awais.instagrabber.utils.Constants; | ||||
| import awais.instagrabber.utils.CookieUtils; | ||||
| import awais.instagrabber.utils.NetworkUtils; | ||||
| import awais.instagrabber.utils.TextUtils; | ||||
| import awais.instagrabber.utils.Utils; | ||||
| 
 | ||||
| public class GetActivityAsyncTask extends AsyncTask<String, Void, GetActivityAsyncTask.NotificationCounts> { | ||||
|     private static final String TAG = "GetActivityAsyncTask"; | ||||
| @ -44,7 +45,7 @@ public class GetActivityAsyncTask extends AsyncTask<String, Void, GetActivityAsy | ||||
|         try { | ||||
|             urlConnection = (HttpURLConnection) new URL(url).openConnection(); | ||||
|             urlConnection.setUseCaches(false); | ||||
|             urlConnection.setRequestProperty("User-Agent", Constants.USER_AGENT); | ||||
|             urlConnection.setRequestProperty("User-Agent", Utils.settingsHelper.getString(Constants.BROWSER_UA)); | ||||
|             urlConnection.setRequestProperty("x-csrftoken", cookie.split("csrftoken=")[1].split(";")[0]); | ||||
|             urlConnection.connect(); | ||||
|             if (urlConnection.getResponseCode() != HttpURLConnection.HTTP_OK) { | ||||
|  | ||||
| @ -76,8 +76,8 @@ public final class ProfileFetcher extends AsyncTask<Void, Void, User> { | ||||
|                                 userJson.optBoolean("blocked_by_viewer"), | ||||
|                                 false, | ||||
|                                 isPrivate, | ||||
|                                 false, | ||||
|                                 userJson.optBoolean("restricted_by_viewer"), | ||||
|                                 userJson.optBoolean("has_requested_viewer"), | ||||
|                                 userJson.optBoolean("requested_by_viewer"), | ||||
|                                 false, | ||||
|                                 userJson.optBoolean("restricted_by_viewer"), | ||||
|                                 false | ||||
|  | ||||
| @ -14,6 +14,7 @@ import awais.instagrabber.BuildConfig; | ||||
| import awais.instagrabber.interfaces.FetchListener; | ||||
| import awais.instagrabber.utils.Constants; | ||||
| import awais.instagrabber.utils.NetworkUtils; | ||||
| import awais.instagrabber.utils.Utils; | ||||
| 
 | ||||
| public final class UsernameFetcher extends AsyncTask<Void, Void, String> { | ||||
|     private final FetchListener<String> fetchListener; | ||||
| @ -31,7 +32,7 @@ public final class UsernameFetcher extends AsyncTask<Void, Void, String> { | ||||
| 
 | ||||
|         try { | ||||
|             final HttpURLConnection conn = (HttpURLConnection) new URL("https://i.instagram.com/api/v1/users/" + uid + "/info/").openConnection(); | ||||
|             conn.setRequestProperty("User-Agent", Constants.USER_AGENT); | ||||
|             conn.setRequestProperty("User-Agent", Utils.settingsHelper.getString(Constants.BROWSER_UA)); | ||||
|             conn.setUseCaches(true); | ||||
| 
 | ||||
|             final JSONObject user; | ||||
|  | ||||
| @ -64,7 +64,7 @@ public final class CommentsViewerFragment extends BottomSheetDialogFragment impl | ||||
|     private LinearLayoutManager layoutManager; | ||||
|     private RecyclerLazyLoader lazyLoader; | ||||
|     private String shortCode; | ||||
|     private long userId; | ||||
|     private long authorUserId, userIdFromCookie; | ||||
|     private String endCursor = null; | ||||
|     private Resources resources; | ||||
|     private InputMethodManager imm; | ||||
| @ -140,14 +140,13 @@ public final class CommentsViewerFragment extends BottomSheetDialogFragment impl | ||||
|             Toast.makeText(context, R.string.comment_send_empty_comment, Toast.LENGTH_SHORT).show(); | ||||
|             return; | ||||
|         } | ||||
|         final long userId = CookieUtils.getUserIdFromCookie(cookie); | ||||
|         if (userId == 0) return; | ||||
|         if (userIdFromCookie == 0) return; | ||||
|         String replyToId = null; | ||||
|         final CommentModel commentModel = commentsAdapter.getSelected(); | ||||
|         if (commentModel != null) { | ||||
|             replyToId = commentModel.getId(); | ||||
|         } | ||||
|         mediaService.comment(postId, text.toString(), userId, replyToId, CookieUtils.getCsrfTokenFromCookie(cookie), new ServiceCallback<Boolean>() { | ||||
|         mediaService.comment(postId, text.toString(), replyToId, new ServiceCallback<Boolean>() { | ||||
|             @Override | ||||
|             public void onSuccess(final Boolean result) { | ||||
|                 commentsAdapter.clearSelection(); | ||||
| @ -171,7 +170,10 @@ public final class CommentsViewerFragment extends BottomSheetDialogFragment impl | ||||
|     public void onCreate(@Nullable final Bundle savedInstanceState) { | ||||
|         super.onCreate(savedInstanceState); | ||||
|         fragmentActivity = (AppCompatActivity) getActivity(); | ||||
|         mediaService = MediaService.getInstance(); | ||||
|         final String deviceUuid = Utils.settingsHelper.getString(Constants.DEVICE_UUID); | ||||
|         final String csrfToken = CookieUtils.getCsrfTokenFromCookie(cookie); | ||||
|         userIdFromCookie = CookieUtils.getUserIdFromCookie(cookie); | ||||
|         mediaService = MediaService.getInstance(deviceUuid, csrfToken, userIdFromCookie); | ||||
|         // setHasOptionsMenu(true); | ||||
|     } | ||||
| 
 | ||||
| @ -231,7 +233,7 @@ public final class CommentsViewerFragment extends BottomSheetDialogFragment impl | ||||
|         final CommentsViewerFragmentArgs fragmentArgs = CommentsViewerFragmentArgs.fromBundle(getArguments()); | ||||
|         shortCode = fragmentArgs.getShortCode(); | ||||
|         postId = fragmentArgs.getPostId(); | ||||
|         userId = fragmentArgs.getPostUserId(); | ||||
|         authorUserId = fragmentArgs.getPostUserId(); | ||||
|         // setTitle(); | ||||
|         binding.swipeRefreshLayout.setOnRefreshListener(this); | ||||
|         binding.swipeRefreshLayout.setRefreshing(true); | ||||
| @ -289,10 +291,9 @@ public final class CommentsViewerFragment extends BottomSheetDialogFragment impl | ||||
| 
 | ||||
|         String[] commentDialogList; | ||||
| 
 | ||||
|         final long userIdFromCookie = CookieUtils.getUserIdFromCookie(cookie); | ||||
|         if (!TextUtils.isEmpty(cookie) | ||||
|                 && userIdFromCookie != 0 | ||||
|                 && (userIdFromCookie == commentModel.getProfileModel().getPk() || userIdFromCookie == userId)) { | ||||
|                 && (userIdFromCookie == commentModel.getProfileModel().getPk() || userIdFromCookie == authorUserId)) { | ||||
|             commentDialogList = new String[]{ | ||||
|                     resources.getString(R.string.open_profile), | ||||
|                     resources.getString(R.string.comment_viewer_copy_comment), | ||||
| @ -324,7 +325,6 @@ public final class CommentsViewerFragment extends BottomSheetDialogFragment impl | ||||
|         if (context == null) return; | ||||
|         final DialogInterface.OnClickListener profileDialogListener = (dialog, which) -> { | ||||
|             final User profileModel = commentModel.getProfileModel(); | ||||
|             final String csrfToken = CookieUtils.getCsrfTokenFromCookie(cookie); | ||||
|             switch (which) { | ||||
|                 case 0: // open profile | ||||
|                     openProfile("@" + profileModel.getUsername()); | ||||
| @ -354,11 +354,8 @@ public final class CommentsViewerFragment extends BottomSheetDialogFragment impl | ||||
|                     }, 200); | ||||
|                     break; | ||||
|                 case 4: // like/unlike comment | ||||
|                     if (csrfToken == null) { | ||||
|                         return; | ||||
|                     } | ||||
|                     if (!commentModel.getLiked()) { | ||||
|                         mediaService.commentLike(commentModel.getId(), csrfToken, new ServiceCallback<Boolean>() { | ||||
|                         mediaService.commentLike(commentModel.getId(), new ServiceCallback<Boolean>() { | ||||
|                             @Override | ||||
|                             public void onSuccess(final Boolean result) { | ||||
|                                 if (!result) { | ||||
| @ -376,7 +373,7 @@ public final class CommentsViewerFragment extends BottomSheetDialogFragment impl | ||||
|                         }); | ||||
|                         return; | ||||
|                     } | ||||
|                     mediaService.commentUnlike(commentModel.getId(), csrfToken, new ServiceCallback<Boolean>() { | ||||
|                     mediaService.commentUnlike(commentModel.getId(), new ServiceCallback<Boolean>() { | ||||
|                         @Override | ||||
|                         public void onSuccess(final Boolean result) { | ||||
|                             if (!result) { | ||||
| @ -416,10 +413,9 @@ public final class CommentsViewerFragment extends BottomSheetDialogFragment impl | ||||
|                     }); | ||||
|                     break; | ||||
|                 case 6: // delete comment | ||||
|                     final long userId = CookieUtils.getUserIdFromCookie(cookie); | ||||
|                     if (userId == 0) return; | ||||
|                     if (userIdFromCookie == 0) return; | ||||
|                     mediaService.deleteComment( | ||||
|                             postId, userId, commentModel.getId(), csrfToken, | ||||
|                             postId, commentModel.getId(), | ||||
|                             new ServiceCallback<Boolean>() { | ||||
|                                 @Override | ||||
|                                 public void onSuccess(final Boolean result) { | ||||
|  | ||||
| @ -118,7 +118,7 @@ public final class FollowViewerFragment extends Fragment implements SwipeRefresh | ||||
|     @Override | ||||
|     public void onCreate(@Nullable final Bundle savedInstanceState) { | ||||
|         super.onCreate(savedInstanceState); | ||||
|         friendshipService = FriendshipService.getInstance(); | ||||
|         friendshipService = FriendshipService.getInstance(null, null, 0); | ||||
|         fragmentActivity = (AppCompatActivity) getActivity(); | ||||
|         setHasOptionsMenu(true); | ||||
|     } | ||||
|  | ||||
| @ -414,10 +414,11 @@ public class HashTagFragment extends Fragment implements SwipeRefreshLayout.OnRe | ||||
|             hashtagDetailsBinding.btnFollowTag.setOnClickListener(v -> { | ||||
|                 final String cookie = settingsHelper.getString(Constants.COOKIE); | ||||
|                 final String csrfToken = CookieUtils.getCsrfTokenFromCookie(cookie); | ||||
|                 final String ua = settingsHelper.getString(Constants.BROWSER_UA); | ||||
|                 if (csrfToken != null) { | ||||
|                     hashtagDetailsBinding.btnFollowTag.setClickable(false); | ||||
|                     if (!hashtagModel.getFollowing()) { | ||||
|                         tagsService.follow(hashtag.substring(1), csrfToken, new ServiceCallback<Boolean>() { | ||||
|                         tagsService.follow(ua, hashtag.substring(1), csrfToken, new ServiceCallback<Boolean>() { | ||||
|                             @Override | ||||
|                             public void onSuccess(final Boolean result) { | ||||
|                                 hashtagDetailsBinding.btnFollowTag.setClickable(true); | ||||
| @ -445,7 +446,7 @@ public class HashTagFragment extends Fragment implements SwipeRefreshLayout.OnRe | ||||
|                         }); | ||||
|                         return; | ||||
|                     } | ||||
|                     tagsService.unfollow(hashtag.substring(1), csrfToken, new ServiceCallback<Boolean>() { | ||||
|                     tagsService.unfollow(ua, hashtag.substring(1), csrfToken, new ServiceCallback<Boolean>() { | ||||
|                         @Override | ||||
|                         public void onSuccess(final Boolean result) { | ||||
|                             hashtagDetailsBinding.btnFollowTag.setClickable(true); | ||||
|  | ||||
| @ -104,7 +104,7 @@ public final class LikesViewerFragment extends BottomSheetDialogFragment impleme | ||||
|         final String cookie = settingsHelper.getString(Constants.COOKIE); | ||||
|         isLoggedIn = !TextUtils.isEmpty(cookie) && CookieUtils.getUserIdFromCookie(cookie) > 0; | ||||
|         // final AppCompatActivity fragmentActivity = (AppCompatActivity) getActivity(); | ||||
|         mediaService = isLoggedIn ? MediaService.getInstance() : null; | ||||
|         mediaService = isLoggedIn ? MediaService.getInstance(null, null, 0) : null; | ||||
|         graphQLService = isLoggedIn ? null : GraphQLService.getInstance(); | ||||
|         // setHasOptionsMenu(true); | ||||
|     } | ||||
|  | ||||
| @ -60,7 +60,6 @@ public final class NotificationsViewerFragment extends Fragment implements Swipe | ||||
|     private NotificationViewModel notificationViewModel; | ||||
|     private FriendshipService friendshipService; | ||||
|     private MediaService mediaService; | ||||
|     private long userId; | ||||
|     private String csrfToken; | ||||
|     private String type; | ||||
|     private Context context; | ||||
| @ -133,7 +132,7 @@ public final class NotificationsViewerFragment extends Fragment implements Swipe | ||||
|                             break; | ||||
|                         case 1: | ||||
|                             if (model.getType() == NotificationType.REQUEST) { | ||||
|                                 friendshipService.approve(userId, model.getUserId(), csrfToken, new ServiceCallback<FriendshipChangeResponse>() { | ||||
|                                 friendshipService.approve(model.getUserId(), new ServiceCallback<FriendshipChangeResponse>() { | ||||
|                                     @Override | ||||
|                                     public void onSuccess(final FriendshipChangeResponse result) { | ||||
|                                         onRefresh(); | ||||
| @ -175,7 +174,7 @@ public final class NotificationsViewerFragment extends Fragment implements Swipe | ||||
|                             }); | ||||
|                             break; | ||||
|                         case 2: | ||||
|                             friendshipService.ignore(userId, model.getUserId(), csrfToken, new ServiceCallback<FriendshipChangeResponse>() { | ||||
|                             friendshipService.ignore(model.getUserId(), new ServiceCallback<FriendshipChangeResponse>() { | ||||
|                                 @Override | ||||
|                                 public void onSuccess(final FriendshipChangeResponse result) { | ||||
|                                     onRefresh(); | ||||
| @ -218,10 +217,11 @@ public final class NotificationsViewerFragment extends Fragment implements Swipe | ||||
|         if (TextUtils.isEmpty(cookie)) { | ||||
|             Toast.makeText(context, R.string.activity_notloggedin, Toast.LENGTH_SHORT).show(); | ||||
|         } | ||||
|         friendshipService = FriendshipService.getInstance(); | ||||
|         mediaService = MediaService.getInstance(); | ||||
|         userId = CookieUtils.getUserIdFromCookie(cookie); | ||||
|         mediaService = MediaService.getInstance(null, null, 0); | ||||
|         final long userId = CookieUtils.getUserIdFromCookie(cookie); | ||||
|         final String deviceUuid = Utils.settingsHelper.getString(Constants.DEVICE_UUID); | ||||
|         csrfToken = CookieUtils.getCsrfTokenFromCookie(cookie); | ||||
|         friendshipService = FriendshipService.getInstance(deviceUuid, csrfToken, userId); | ||||
|     } | ||||
| 
 | ||||
|     @NonNull | ||||
|  | ||||
| @ -465,16 +465,16 @@ public class PostViewV2Fragment extends SharedElementTransitionDialogFragment im | ||||
|             binding.date.setVisibility(View.VISIBLE); | ||||
|             binding.date.setText(date); | ||||
|         })); | ||||
|         if (viewModel.getMedia().isCommentLikesEnabled()) { | ||||
|             viewModel.getLikeCount().observe(getViewLifecycleOwner(), count -> { | ||||
|                 final long safeCount = getSafeCount(count); | ||||
|                 final String likesString = getResources().getQuantityString(R.plurals.likes_count, (int) safeCount, safeCount); | ||||
|                 binding.likesCount.setText(likesString); | ||||
|             }); | ||||
|         viewModel.getLikeCount().observe(getViewLifecycleOwner(), count -> { | ||||
|             final long safeCount = getSafeCount(count); | ||||
|             final String likesString = getResources().getQuantityString(R.plurals.likes_count, (int) safeCount, safeCount); | ||||
|             binding.likesCount.setText(likesString); | ||||
|         }); | ||||
|         if (!viewModel.getMedia().isCommentsDisabled()) { | ||||
|             viewModel.getCommentCount().observe(getViewLifecycleOwner(), count -> { | ||||
|                 final long safeCount = getSafeCount(count); | ||||
|                 final String likesString = getResources().getQuantityString(R.plurals.comments_count, (int) safeCount, safeCount); | ||||
|                 binding.likesCount.setText(likesString); | ||||
|                 binding.commentsCount.setText(likesString); | ||||
|             }); | ||||
|         } | ||||
|         viewModel.getViewCount().observe(getViewLifecycleOwner(), count -> { | ||||
| @ -538,7 +538,7 @@ public class PostViewV2Fragment extends SharedElementTransitionDialogFragment im | ||||
|     } | ||||
| 
 | ||||
|     private void setupComment() { | ||||
|         if (!viewModel.hasPk() || !viewModel.getMedia().isCommentLikesEnabled()) { | ||||
|         if (!viewModel.hasPk() || viewModel.getMedia().isCommentsDisabled()) { | ||||
|             binding.comment.setVisibility(View.GONE); | ||||
|             binding.commentsCount.setVisibility(View.GONE); | ||||
|             return; | ||||
| @ -577,7 +577,7 @@ public class PostViewV2Fragment extends SharedElementTransitionDialogFragment im | ||||
|     } | ||||
| 
 | ||||
|     private void setupLike() { | ||||
|         final boolean likableMedia = viewModel.hasPk() && viewModel.getMedia().isCommentLikesEnabled(); | ||||
|         final boolean likableMedia = viewModel.hasPk() /*&& viewModel.getMedia().isCommentLikesEnabled()*/; | ||||
|         if (!likableMedia) { | ||||
|             binding.like.setVisibility(View.GONE); | ||||
|             binding.likesCount.setVisibility(View.GONE); | ||||
| @ -1402,20 +1402,24 @@ public class PostViewV2Fragment extends SharedElementTransitionDialogFragment im | ||||
|             if (media.getLocation() != null) { | ||||
|                 binding.location.setVisibility(View.VISIBLE); | ||||
|             } | ||||
|             binding.captionParent.setVisibility(View.VISIBLE); | ||||
|             binding.bottomBg.setVisibility(View.VISIBLE); | ||||
|             binding.likesCount.setVisibility(View.VISIBLE); | ||||
|             binding.commentsCount.setVisibility(View.VISIBLE); | ||||
|             binding.date.setVisibility(View.VISIBLE); | ||||
|             binding.captionToggle.setVisibility(View.VISIBLE); | ||||
|             if (viewModel.hasPk()) { | ||||
|                 binding.likesCount.setVisibility(View.VISIBLE); | ||||
|                 binding.date.setVisibility(View.VISIBLE); | ||||
|                 binding.captionParent.setVisibility(View.VISIBLE); | ||||
|                 binding.captionToggle.setVisibility(View.VISIBLE); | ||||
|                 binding.share.setVisibility(View.VISIBLE); | ||||
|             } | ||||
|             if (viewModel.hasPk() && !viewModel.getMedia().isCommentsDisabled()) { | ||||
|                 binding.comment.setVisibility(View.VISIBLE); | ||||
|                 binding.commentsCount.setVisibility(View.VISIBLE); | ||||
|             } | ||||
|             binding.download.setVisibility(View.VISIBLE); | ||||
|             binding.share.setVisibility(View.VISIBLE); | ||||
|             binding.comment.setVisibility(View.VISIBLE); | ||||
|             final List<Integer> options = viewModel.getOptions().getValue(); | ||||
|             if (options != null && !options.isEmpty()) { | ||||
|                 binding.options.setVisibility(View.VISIBLE); | ||||
|             } | ||||
|             if (viewModel.isLoggedIn()) { | ||||
|             if (viewModel.isLoggedIn() && viewModel.hasPk()) { | ||||
|                 binding.like.setVisibility(View.VISIBLE); | ||||
|                 binding.save.setVisibility(View.VISIBLE); | ||||
|             } | ||||
|  | ||||
| @ -172,6 +172,21 @@ public class DirectMessageThreadFragment extends Fragment { | ||||
| 
 | ||||
|         @Override | ||||
|         public void onMediaClick(final Media media) { | ||||
|             if (media.isReelMedia()) { | ||||
|                 final String pk = media.getPk(); | ||||
|                 try { | ||||
|                     final long mediaId = Long.parseLong(pk); | ||||
|                     final User user = media.getUser(); | ||||
|                     if (user == null) return; | ||||
|                     final String username = user.getUsername(); | ||||
|                     final NavDirections action = DirectMessageThreadFragmentDirections | ||||
|                             .actionThreadToStory(StoryViewerOptions.forStory(mediaId, username)); | ||||
|                     NavHostFragment.findNavController(DirectMessageThreadFragment.this).navigate(action); | ||||
|                 } catch (NumberFormatException e) { | ||||
|                     Log.e(TAG, "onMediaClick (story): ", e); | ||||
|                 } | ||||
|                 return; | ||||
|             } | ||||
|             final PostViewV2Fragment.Builder builder = PostViewV2Fragment.builder(media); | ||||
|             builder.build().show(getChildFragmentManager(), "post_view"); | ||||
|         } | ||||
|  | ||||
| @ -68,6 +68,7 @@ public class FeedFragment extends Fragment implements SwipeRefreshLayout.OnRefre | ||||
|     private FragmentFeedBinding binding; | ||||
|     private StoriesService storiesService; | ||||
|     private boolean shouldRefresh = true; | ||||
|     private final boolean isRotate = false; | ||||
|     private FeedStoriesViewModel feedStoriesViewModel; | ||||
|     private boolean storiesFetching; | ||||
|     private ActionMode actionMode; | ||||
| @ -282,6 +283,24 @@ public class FeedFragment extends Fragment implements SwipeRefreshLayout.OnRefre | ||||
|     public void onViewCreated(@NonNull final View view, @Nullable final Bundle savedInstanceState) { | ||||
|         if (!shouldRefresh) return; | ||||
|         binding.feedSwipeRefreshLayout.setOnRefreshListener(this); | ||||
|         /* | ||||
|         FabAnimation.init(binding.fabCamera); | ||||
|         FabAnimation.init(binding.fabStory); | ||||
|         binding.fabAdd.setOnClickListener(new View.OnClickListener() { | ||||
|             @Override | ||||
|             public void onClick(View v) { | ||||
|                 isRotate = FabAnimation.rotateFab(v, !isRotate); | ||||
|                 if (isRotate) { | ||||
|                     FabAnimation.showIn(binding.fabCamera); | ||||
|                     FabAnimation.showIn(binding.fabStory); | ||||
|                 } | ||||
|                 else { | ||||
|                     FabAnimation.showOut(binding.fabCamera); | ||||
|                     FabAnimation.showOut(binding.fabStory); | ||||
|                 } | ||||
|             } | ||||
|         }); | ||||
|          */ | ||||
|         setupFeedStories(); | ||||
|         setupFeed(); | ||||
|         shouldRefresh = false; | ||||
|  | ||||
| @ -99,7 +99,6 @@ import awais.instagrabber.webservices.StoriesService; | ||||
| import static androidx.core.content.PermissionChecker.checkSelfPermission; | ||||
| import static awais.instagrabber.fragments.HashTagFragment.ARG_HASHTAG; | ||||
| import static awais.instagrabber.utils.DownloadUtils.WRITE_PERMISSION; | ||||
| import static awais.instagrabber.utils.Utils.settingsHelper; | ||||
| 
 | ||||
| public class ProfileFragment extends Fragment implements SwipeRefreshLayout.OnRefreshListener { | ||||
|     private static final String TAG = "ProfileFragment"; | ||||
| @ -300,10 +299,15 @@ public class ProfileFragment extends Fragment implements SwipeRefreshLayout.OnRe | ||||
|     @Override | ||||
|     public void onCreate(@Nullable final Bundle savedInstanceState) { | ||||
|         super.onCreate(savedInstanceState); | ||||
|         cookie = Utils.settingsHelper.getString(Constants.COOKIE); | ||||
|         isLoggedIn = !TextUtils.isEmpty(cookie) && CookieUtils.getUserIdFromCookie(cookie) > 0; | ||||
|         final long userId = CookieUtils.getUserIdFromCookie(cookie); | ||||
|         final String deviceUuid = Utils.settingsHelper.getString(Constants.DEVICE_UUID); | ||||
|         final String csrfToken = CookieUtils.getCsrfTokenFromCookie(cookie); | ||||
|         fragmentActivity = (MainActivity) requireActivity(); | ||||
|         friendshipService = FriendshipService.getInstance(); | ||||
|         friendshipService = FriendshipService.getInstance(deviceUuid, csrfToken, userId); | ||||
|         storiesService = StoriesService.getInstance(); | ||||
|         mediaService = MediaService.getInstance(); | ||||
|         mediaService = MediaService.getInstance(null, null, 0); | ||||
|         accountRepository = AccountRepository.getInstance(AccountDataSource.getInstance(getContext())); | ||||
|         favoriteRepository = FavoriteRepository.getInstance(FavoriteDataSource.getInstance(getContext())); | ||||
|         setHasOptionsMenu(true); | ||||
| @ -313,8 +317,6 @@ public class ProfileFragment extends Fragment implements SwipeRefreshLayout.OnRe | ||||
|     public View onCreateView(@NonNull final LayoutInflater inflater, | ||||
|                              final ViewGroup container, | ||||
|                              final Bundle savedInstanceState) { | ||||
|         cookie = settingsHelper.getString(Constants.COOKIE); | ||||
|         isLoggedIn = !TextUtils.isEmpty(cookie) && CookieUtils.getUserIdFromCookie(cookie) > 0; | ||||
|         if (root != null) { | ||||
|             if (getArguments() != null) { | ||||
|                 final ProfileFragmentArgs fragmentArgs = ProfileFragmentArgs.fromBundle(getArguments()); | ||||
| @ -380,7 +382,6 @@ public class ProfileFragment extends Fragment implements SwipeRefreshLayout.OnRe | ||||
|             friendshipService.toggleRestrict( | ||||
|                     profileModel.getPk(), | ||||
|                     !profileModel.getFriendshipStatus().isRestricted(), | ||||
|                     CookieUtils.getCsrfTokenFromCookie(cookie), | ||||
|                     new ServiceCallback<FriendshipRestrictResponse>() { | ||||
|                         @Override | ||||
|                         public void onSuccess(final FriendshipRestrictResponse result) { | ||||
| @ -396,13 +397,10 @@ public class ProfileFragment extends Fragment implements SwipeRefreshLayout.OnRe | ||||
|             return true; | ||||
|         } | ||||
|         if (item.getItemId() == R.id.block) { | ||||
|             final long userIdFromCookie = CookieUtils.getUserIdFromCookie(cookie); | ||||
|             if (!isLoggedIn) return false; | ||||
|             if (profileModel.getFriendshipStatus().isBlocking()) { | ||||
|                 friendshipService.unblock( | ||||
|                         userIdFromCookie, | ||||
|                         profileModel.getPk(), | ||||
|                         CookieUtils.getCsrfTokenFromCookie(cookie), | ||||
|                         new ServiceCallback<FriendshipChangeResponse>() { | ||||
|                             @Override | ||||
|                             public void onSuccess(final FriendshipChangeResponse result) { | ||||
| @ -418,9 +416,7 @@ public class ProfileFragment extends Fragment implements SwipeRefreshLayout.OnRe | ||||
|                 return true; | ||||
|             } | ||||
|             friendshipService.block( | ||||
|                     userIdFromCookie, | ||||
|                     profileModel.getPk(), | ||||
|                     CookieUtils.getCsrfTokenFromCookie(cookie), | ||||
|                     new ServiceCallback<FriendshipChangeResponse>() { | ||||
|                         @Override | ||||
|                         public void onSuccess(final FriendshipChangeResponse result) { | ||||
| @ -628,9 +624,9 @@ public class ProfileFragment extends Fragment implements SwipeRefreshLayout.OnRe | ||||
|                         ), new RepositoryCallback<Void>() { | ||||
|                             @Override | ||||
|                             public void onSuccess(final Void result) { | ||||
|                                 profileDetailsBinding.favChip.setText(R.string.added_to_favs); | ||||
|                                 profileDetailsBinding.favChip.setText(R.string.added_to_favs_short); | ||||
|                                 profileDetailsBinding.favChip.setChipIconResource(R.drawable.ic_star_check_24); | ||||
|                                 showSnackbar(getString(R.string.added_to_favs)); | ||||
|                                 showSnackbar(getString(R.string.added_to_favs_short)); | ||||
|                             } | ||||
| 
 | ||||
|                             @Override | ||||
| @ -894,7 +890,6 @@ public class ProfileFragment extends Fragment implements SwipeRefreshLayout.OnRe | ||||
| 
 | ||||
|     private void setupCommonListeners() { | ||||
|         final Context context = getContext(); | ||||
|         final long userIdFromCookie = CookieUtils.getUserIdFromCookie(cookie); | ||||
|         profileDetailsBinding.btnFollow.setOnClickListener(v -> { | ||||
|             if (profileModel.getFriendshipStatus().isFollowing() && profileModel.isPrivate()) { | ||||
|                 new AlertDialog.Builder(context) | ||||
| @ -902,9 +897,7 @@ public class ProfileFragment extends Fragment implements SwipeRefreshLayout.OnRe | ||||
|                         .setMessage(R.string.priv_acc_confirm) | ||||
|                         .setPositiveButton(R.string.confirm, (d, w) -> | ||||
|                                 friendshipService.unfollow( | ||||
|                                         userIdFromCookie, | ||||
|                                         profileModel.getPk(), | ||||
|                                         CookieUtils.getCsrfTokenFromCookie(cookie), | ||||
|                                         new ServiceCallback<FriendshipChangeResponse>() { | ||||
|                                             @Override | ||||
|                                             public void onSuccess(final FriendshipChangeResponse result) { | ||||
| @ -919,11 +912,10 @@ public class ProfileFragment extends Fragment implements SwipeRefreshLayout.OnRe | ||||
|                                         })) | ||||
|                         .setNegativeButton(R.string.cancel, null) | ||||
|                         .show(); | ||||
|             } else if (profileModel.getFriendshipStatus().isFollowing() || profileModel.getFriendshipStatus().isOutgoingRequest()) { | ||||
|             } | ||||
|             else if (profileModel.getFriendshipStatus().isFollowing() || profileModel.getFriendshipStatus().isOutgoingRequest()) { | ||||
|                 friendshipService.unfollow( | ||||
|                         userIdFromCookie, | ||||
|                         profileModel.getPk(), | ||||
|                         CookieUtils.getCsrfTokenFromCookie(cookie), | ||||
|                         new ServiceCallback<FriendshipChangeResponse>() { | ||||
|                             @Override | ||||
|                             public void onSuccess(final FriendshipChangeResponse result) { | ||||
| @ -938,9 +930,7 @@ public class ProfileFragment extends Fragment implements SwipeRefreshLayout.OnRe | ||||
|                         }); | ||||
|             } else { | ||||
|                 friendshipService.follow( | ||||
|                         userIdFromCookie, | ||||
|                         profileModel.getPk(), | ||||
|                         CookieUtils.getCsrfTokenFromCookie(cookie), | ||||
|                         new ServiceCallback<FriendshipChangeResponse>() { | ||||
|                             @Override | ||||
|                             public void onSuccess(final FriendshipChangeResponse result) { | ||||
| @ -1102,6 +1092,6 @@ public class ProfileFragment extends Fragment implements SwipeRefreshLayout.OnRe | ||||
|     private boolean isReallyPrivate() { | ||||
|         final long myId = CookieUtils.getUserIdFromCookie(cookie); | ||||
|         final FriendshipStatus friendshipStatus = profileModel.getFriendshipStatus(); | ||||
|         return !friendshipStatus.isFollowedBy() && (profileModel.getPk() != myId) && profileModel.isPrivate(); | ||||
|         return !friendshipStatus.isFollowing() && (profileModel.getPk() != myId) && profileModel.isPrivate(); | ||||
|     } | ||||
| } | ||||
|  | ||||
| @ -8,7 +8,6 @@ import retrofit2.Call; | ||||
| import retrofit2.http.FieldMap; | ||||
| import retrofit2.http.FormUrlEncoded; | ||||
| import retrofit2.http.GET; | ||||
| import retrofit2.http.Header; | ||||
| import retrofit2.http.POST; | ||||
| import retrofit2.http.Path; | ||||
| import retrofit2.http.QueryMap; | ||||
| @ -17,20 +16,17 @@ public interface FriendshipRepository { | ||||
| 
 | ||||
|     @FormUrlEncoded | ||||
|     @POST("/api/v1/friendships/{action}/{id}/") | ||||
|     Call<FriendshipChangeResponse> change(@Header("User-Agent") String userAgent, | ||||
|                                           @Path("action") String action, | ||||
|     Call<FriendshipChangeResponse> change(@Path("action") String action, | ||||
|                                           @Path("id") long id, | ||||
|                                           @FieldMap Map<String, String> form); | ||||
| 
 | ||||
|     @FormUrlEncoded | ||||
|     @POST("/api/v1/restrict_action/{action}/") | ||||
|     Call<FriendshipRestrictResponse> toggleRestrict(@Header("User-Agent") String userAgent, | ||||
|                                                     @Path("action") String action, | ||||
|     Call<FriendshipRestrictResponse> toggleRestrict(@Path("action") String action, | ||||
|                                                     @FieldMap Map<String, String> form); | ||||
| 
 | ||||
|     @GET("/api/v1/friendships/{userId}/{type}/") | ||||
|     Call<String> getList(@Header("User-Agent") String userAgent, | ||||
|                          @Path("userId") long userId, | ||||
|     Call<String> getList(@Path("userId") long userId, | ||||
|                          @Path("type") String type, // following or followers | ||||
|                          @QueryMap(encoded = true) Map<String, String> queryParams); | ||||
| } | ||||
|  | ||||
| @ -2,28 +2,23 @@ package awais.instagrabber.repositories; | ||||
| 
 | ||||
| import java.util.Map; | ||||
| 
 | ||||
| import awais.instagrabber.utils.Constants; | ||||
| import retrofit2.Call; | ||||
| import retrofit2.http.FieldMap; | ||||
| import retrofit2.http.FormUrlEncoded; | ||||
| import retrofit2.http.GET; | ||||
| import retrofit2.http.Header; | ||||
| import retrofit2.http.Headers; | ||||
| import retrofit2.http.POST; | ||||
| import retrofit2.http.Query; | ||||
| 
 | ||||
| public interface NewsRepository { | ||||
| 
 | ||||
|     @Headers("User-Agent: " + Constants.USER_AGENT) | ||||
|     @GET("https://www.instagram.com/accounts/activity/?__a=1") | ||||
|     Call<String> webInbox(); | ||||
|     Call<String> webInbox(@Header("User-Agent") String userAgent); | ||||
| 
 | ||||
|     @Headers("User-Agent: " + Constants.I_USER_AGENT) | ||||
|     @GET("/api/v1/news/inbox/") | ||||
|     Call<String> appInbox(@Query(value = "mark_as_seen", encoded = true) boolean markAsSeen); | ||||
|     Call<String> appInbox(@Header("User-Agent") String userAgent, @Query(value = "mark_as_seen", encoded = true) boolean markAsSeen); | ||||
| 
 | ||||
|     @FormUrlEncoded | ||||
|     @Headers("User-Agent: " + Constants.I_USER_AGENT) | ||||
|     @POST("/api/v1/discover/ayml/") | ||||
|     Call<String> getAyml(@FieldMap final Map<String, String> form); | ||||
|     Call<String> getAyml(@Header("User-Agent") String userAgent, @FieldMap final Map<String, String> form); | ||||
| } | ||||
|  | ||||
| @ -7,7 +7,6 @@ import retrofit2.Call; | ||||
| import retrofit2.http.FieldMap; | ||||
| import retrofit2.http.FormUrlEncoded; | ||||
| import retrofit2.http.GET; | ||||
| import retrofit2.http.Header; | ||||
| import retrofit2.http.POST; | ||||
| import retrofit2.http.Path; | ||||
| import retrofit2.http.QueryMap; | ||||
| @ -28,12 +27,11 @@ public interface StoriesRepository { | ||||
|     Call<String> fetchArchive(@QueryMap Map<String, String> queryParams); | ||||
| 
 | ||||
|     @GET | ||||
|     Call<String> getUserStory(@Header("User-Agent") String userAgent, @Url String url); | ||||
|     Call<String> getUserStory(@Url String url); | ||||
| 
 | ||||
|     @FormUrlEncoded | ||||
|     @POST("/api/v1/media/{storyId}/{stickerId}/{action}/") | ||||
|     Call<StoryStickerResponse> respondToSticker(@Header("User-Agent") String userAgent, | ||||
|                                                 @Path("storyId") String storyId, | ||||
|     Call<StoryStickerResponse> respondToSticker(@Path("storyId") String storyId, | ||||
|                                                 @Path("stickerId") String stickerId, | ||||
|                                                 @Path("action") String action, | ||||
|                                                 // story_poll_vote, story_question_response, story_slider_vote, story_quiz_answer | ||||
|  | ||||
| @ -19,6 +19,7 @@ public class Media implements Serializable { | ||||
|     private final MediaItemType mediaType; | ||||
|     private final boolean canViewerReshare; | ||||
|     private final boolean commentLikesEnabled; | ||||
|     private final boolean commentsDisabled; | ||||
|     private final long nextMaxId; | ||||
|     private final long commentCount; | ||||
|     private final ImageVersions2 imageVersions2; | ||||
| @ -56,6 +57,7 @@ public class Media implements Serializable { | ||||
|                  final int originalHeight, | ||||
|                  final MediaItemType mediaType, | ||||
|                  final boolean commentLikesEnabled, | ||||
|                  final boolean commentsDisabled, | ||||
|                  final long nextMaxId, | ||||
|                  final long commentCount, | ||||
|                  final long likeCount, | ||||
| @ -87,6 +89,7 @@ public class Media implements Serializable { | ||||
|         this.originalHeight = originalHeight; | ||||
|         this.mediaType = mediaType; | ||||
|         this.commentLikesEnabled = commentLikesEnabled; | ||||
|         this.commentsDisabled = commentsDisabled; | ||||
|         this.nextMaxId = nextMaxId; | ||||
|         this.commentCount = commentCount; | ||||
|         this.likeCount = likeCount; | ||||
| @ -182,6 +185,10 @@ public class Media implements Serializable { | ||||
|         return commentLikesEnabled; | ||||
|     } | ||||
| 
 | ||||
|     public boolean isCommentsDisabled() { | ||||
|         return commentsDisabled; | ||||
|     } | ||||
| 
 | ||||
|     public long getNextMaxId() { | ||||
|         return nextMaxId; | ||||
|     } | ||||
|  | ||||
| @ -9,8 +9,10 @@ public final class Constants { | ||||
|     public static final String APP_THEME = "app_theme_v19"; | ||||
|     public static final String APP_LANGUAGE = "app_language_v19"; | ||||
|     public static final String STORY_SORT = "story_sort"; | ||||
|     // int prefs | ||||
|     // int prefs, do not export | ||||
|     public static final String PREV_INSTALL_VERSION = "prevVersion"; | ||||
|     public static final String BROWSER_UA_CODE = "browser_ua_code"; | ||||
|     public static final String APP_UA_CODE = "app_ua_code"; | ||||
|     // boolean prefs | ||||
|     public static final String DOWNLOAD_USER_FOLDER = "download_user_folder"; | ||||
|     // deprecated: public static final String BOTTOM_TOOLBAR = "bottom_toolbar"; | ||||
| @ -31,6 +33,8 @@ public final class Constants { | ||||
|     public static final String COOKIE = "cookie"; | ||||
|     public static final String SHOW_QUICK_ACCESS_DIALOG = "show_quick_dlg"; | ||||
|     public static final String DEVICE_UUID = "device_uuid"; | ||||
|     public static final String BROWSER_UA = "browser_ua"; | ||||
|     public static final String APP_UA = "app_ua"; | ||||
|     //////////////////////// EXTRAS //////////////////////// | ||||
|     public static final String EXTRAS_USER = "user"; | ||||
|     public static final String EXTRAS_HASHTAG = "hashtag"; | ||||
| @ -54,13 +58,6 @@ public final class Constants { | ||||
|     // Notification ids | ||||
|     public static final int ACTIVITY_NOTIFICATION_ID = 10; | ||||
| 
 | ||||
|     // spoof | ||||
|     public static final String USER_AGENT = "Mozilla/5.0 (Linux; Android 8.1.0; motorola one Build/OPKS28.63-18-3; wv) " + | ||||
|             "AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/70.0.3538.80 Mobile Safari/537.36 " + | ||||
|             "Instagram 169.1.0.29.135 Android (27/8.1.0; 320dpi; 720x1362; motorola; motorola one; deen_sprout; qcom; pt_BR; 262886998)"; | ||||
|     public static final String I_USER_AGENT = | ||||
|             "Instagram 169.1.0.29.135 Android (27/8.1.0; 320dpi; 720x1362; motorola; motorola one; deen_sprout; qcom; pt_BR; 262886998)"; | ||||
|     public static final String A_USER_AGENT = "https://Barinsta.AustinHuang.me / mailto:Barinsta@AustinHuang.me"; | ||||
|     // see https://github.com/dilame/instagram-private-api/blob/master/src/core/constants.ts | ||||
|     public static final String SUPPORTED_CAPABILITIES = "[ { \"name\": \"SUPPORTED_SDK_VERSIONS\", \"value\":" + | ||||
|             " \"13.0,14.0,15.0,16.0,17.0,18.0,19.0,20.0,21.0,22.0,23.0,24.0,25.0,26.0,27.0,28.0,29.0,30.0,31.0," + | ||||
|  | ||||
| @ -81,6 +81,7 @@ public class DirectItemFactory { | ||||
|                 height, | ||||
|                 isVideo ? MediaItemType.MEDIA_TYPE_VIDEO : MediaItemType.MEDIA_TYPE_IMAGE, | ||||
|                 false, | ||||
|                 false, | ||||
|                 -1, | ||||
|                 -1, | ||||
|                 -1, | ||||
| @ -156,6 +157,7 @@ public class DirectItemFactory { | ||||
|                 0, | ||||
|                 MediaItemType.MEDIA_TYPE_VOICE, | ||||
|                 false, | ||||
|                 false, | ||||
|                 -1, | ||||
|                 0, | ||||
|                 0, | ||||
|  | ||||
| @ -343,6 +343,10 @@ public final class ExportImportUtils { | ||||
|                 jsonObject.remove(Constants.COOKIE); | ||||
|                 jsonObject.remove(Constants.DEVICE_UUID); | ||||
|                 jsonObject.remove(Constants.PREV_INSTALL_VERSION); | ||||
|                 jsonObject.remove(Constants.BROWSER_UA_CODE); | ||||
|                 jsonObject.remove(Constants.BROWSER_UA); | ||||
|                 jsonObject.remove(Constants.APP_UA_CODE); | ||||
|                 jsonObject.remove(Constants.APP_UA); | ||||
|                 return jsonObject; | ||||
|             } catch (Exception e) { | ||||
|                 Log.e(TAG, "Error exporting settings", e); | ||||
|  | ||||
| @ -102,6 +102,14 @@ public final class FlavorTown { | ||||
| 
 | ||||
|     public static void changelogCheck(@NonNull final Context context) { | ||||
|         if (settingsHelper.getInteger(Constants.PREV_INSTALL_VERSION) < BuildConfig.VERSION_CODE) { | ||||
|             final String langCode = settingsHelper.getString(Constants.APP_LANGUAGE); | ||||
|             final String lang = LocaleUtils.getCorrespondingLanguageCode(langCode); | ||||
|             final int appUaCode = settingsHelper.getInteger(Constants.APP_UA_CODE); | ||||
|             final String appUa = UserAgentUtils.generateAppUA(appUaCode, lang); | ||||
|             settingsHelper.putString(Constants.APP_UA, appUa); | ||||
|             final int browserUaCode = settingsHelper.getInteger(Constants.BROWSER_UA_CODE); | ||||
|             final String browserUa = UserAgentUtils.generateBrowserUA(browserUaCode); | ||||
|             settingsHelper.putString(Constants.BROWSER_UA, browserUa); | ||||
|             Toast.makeText(context, R.string.updated, Toast.LENGTH_SHORT).show(); | ||||
|             settingsHelper.putInteger(Constants.PREV_INSTALL_VERSION, BuildConfig.VERSION_CODE); | ||||
|         } | ||||
|  | ||||
| @ -19,7 +19,11 @@ public final class LocaleUtils { | ||||
|         if (baseContext instanceof ContextThemeWrapper) | ||||
|             baseContext = ((ContextThemeWrapper) baseContext).getBaseContext(); | ||||
| 
 | ||||
|         final String lang = LocaleUtils.getCorrespondingLanguageCode(baseContext); | ||||
|         if (Utils.settingsHelper == null) | ||||
|             Utils.settingsHelper = new SettingsHelper(baseContext); | ||||
| 
 | ||||
|         final String appLanguageSettings = Utils.settingsHelper.getString(Constants.APP_LANGUAGE); | ||||
|         final String lang = TextUtils.isEmpty(appLanguageSettings) ? null : LocaleUtils.getCorrespondingLanguageCode(appLanguageSettings); | ||||
| 
 | ||||
|         currentLocale = TextUtils.isEmpty(lang) ? defaultLocale : | ||||
|                         (lang.contains("_") ? new Locale(lang.split("_")[0], lang.split("_")[1]) : new Locale(lang)); | ||||
| @ -49,13 +53,7 @@ public final class LocaleUtils { | ||||
|     } | ||||
| 
 | ||||
|     @Nullable | ||||
|     private static String getCorrespondingLanguageCode(final Context baseContext) { | ||||
|         if (Utils.settingsHelper == null) | ||||
|             Utils.settingsHelper = new SettingsHelper(baseContext); | ||||
| 
 | ||||
|         final String appLanguageSettings = Utils.settingsHelper.getString(Constants.APP_LANGUAGE); | ||||
|         if (TextUtils.isEmpty(appLanguageSettings)) return null; | ||||
| 
 | ||||
|     public static String getCorrespondingLanguageCode(final String appLanguageSettings) { | ||||
|         final int appLanguageIndex = Integer.parseInt(appLanguageSettings); | ||||
|         if (appLanguageIndex == 1) return "en"; | ||||
|         if (appLanguageIndex == 2) return "fr"; | ||||
|  | ||||
| @ -857,6 +857,7 @@ public final class ResponseBodyUtils { | ||||
|                 height, | ||||
|                 mediaItemType, | ||||
|                 false, | ||||
|                 feedItem.optBoolean("comments_disabled"), | ||||
|                 -1, | ||||
|                 commentsCount, | ||||
|                 likesCount, | ||||
|  | ||||
| @ -10,7 +10,11 @@ import androidx.appcompat.app.AppCompatDelegate; | ||||
| 
 | ||||
| import static awais.instagrabber.utils.Constants.APP_LANGUAGE; | ||||
| import static awais.instagrabber.utils.Constants.APP_THEME; | ||||
| import static awais.instagrabber.utils.Constants.APP_UA; | ||||
| import static awais.instagrabber.utils.Constants.APP_UA_CODE; | ||||
| import static awais.instagrabber.utils.Constants.AUTOPLAY_VIDEOS; | ||||
| import static awais.instagrabber.utils.Constants.BROWSER_UA; | ||||
| import static awais.instagrabber.utils.Constants.BROWSER_UA_CODE; | ||||
| import static awais.instagrabber.utils.Constants.CHECK_ACTIVITY; | ||||
| import static awais.instagrabber.utils.Constants.CHECK_UPDATES; | ||||
| import static awais.instagrabber.utils.Constants.COOKIE; | ||||
| @ -80,7 +84,7 @@ public final class SettingsHelper { | ||||
| 
 | ||||
|     private int getIntegerDefault(@IntegerSettings final String key) { | ||||
|         if (APP_THEME.equals(key)) return getThemeCode(true); | ||||
|         if (PREV_INSTALL_VERSION.equals(key)) return -1; | ||||
|         if (PREV_INSTALL_VERSION.equals(key) || APP_UA_CODE.equals(key) || BROWSER_UA_CODE.equals(key)) return -1; | ||||
|         return 0; | ||||
|     } | ||||
| 
 | ||||
| @ -121,10 +125,11 @@ public final class SettingsHelper { | ||||
|     } | ||||
| 
 | ||||
|     @StringDef( | ||||
|             {APP_LANGUAGE, APP_THEME, COOKIE, FOLDER_PATH, DATE_TIME_FORMAT, DATE_TIME_SELECTION, CUSTOM_DATE_TIME_FORMAT, | ||||
|                     DEVICE_UUID, SKIPPED_VERSION, DEFAULT_TAB, PREF_DARK_THEME, PREF_LIGHT_THEME, PREF_POSTS_LAYOUT, | ||||
|                     PREF_PROFILE_POSTS_LAYOUT, PREF_TOPIC_POSTS_LAYOUT, PREF_HASHTAG_POSTS_LAYOUT, PREF_LOCATION_POSTS_LAYOUT, | ||||
|                     PREF_LIKED_POSTS_LAYOUT, PREF_TAGGED_POSTS_LAYOUT, PREF_SAVED_POSTS_LAYOUT, STORY_SORT, PREF_EMOJI_VARIANTS, PREF_REACTIONS}) | ||||
|             {APP_LANGUAGE, APP_THEME, APP_UA, BROWSER_UA, COOKIE, FOLDER_PATH, DATE_TIME_FORMAT, DATE_TIME_SELECTION, | ||||
|                     CUSTOM_DATE_TIME_FORMAT, DEVICE_UUID, SKIPPED_VERSION, DEFAULT_TAB, PREF_DARK_THEME, PREF_LIGHT_THEME, | ||||
|                     PREF_POSTS_LAYOUT, PREF_PROFILE_POSTS_LAYOUT, PREF_TOPIC_POSTS_LAYOUT, PREF_HASHTAG_POSTS_LAYOUT, | ||||
|                     PREF_LOCATION_POSTS_LAYOUT, PREF_LIKED_POSTS_LAYOUT, PREF_TAGGED_POSTS_LAYOUT, PREF_SAVED_POSTS_LAYOUT, | ||||
|                     STORY_SORT, PREF_EMOJI_VARIANTS, PREF_REACTIONS}) | ||||
|     public @interface StringSettings {} | ||||
| 
 | ||||
|     @StringDef({DOWNLOAD_USER_FOLDER, FOLDER_SAVE_TO, AUTOPLAY_VIDEOS, SHOW_QUICK_ACCESS_DIALOG, MUTED_VIDEOS, | ||||
| @ -132,6 +137,6 @@ public final class SettingsHelper { | ||||
|                        CHECK_UPDATES, SWAP_DATE_TIME_FORMAT_ENABLED}) | ||||
|     public @interface BooleanSettings {} | ||||
| 
 | ||||
|     @StringDef({PREV_INSTALL_VERSION}) | ||||
|     @StringDef({PREV_INSTALL_VERSION, BROWSER_UA_CODE, APP_UA_CODE}) | ||||
|     public @interface IntegerSettings {} | ||||
| } | ||||
| @ -30,7 +30,7 @@ public final class UpdateChecker extends AsyncTask<Void, Void, Boolean> { | ||||
|             HttpURLConnection conn = | ||||
|                     (HttpURLConnection) new URL("https://f-droid.org/api/v1/packages/me.austinhuang.instagrabber").openConnection(); | ||||
|             conn.setUseCaches(false); | ||||
|             conn.setRequestProperty("User-Agent", Constants.A_USER_AGENT); | ||||
|             conn.setRequestProperty("User-Agent", "https://Barinsta.AustinHuang.me / mailto:Barinsta@AustinHuang.me"); | ||||
|             conn.connect(); | ||||
| 
 | ||||
|             final int responseCode = conn.getResponseCode(); | ||||
|  | ||||
| @ -0,0 +1,77 @@ | ||||
| package awais.instagrabber.utils; | ||||
| 
 | ||||
| import androidx.annotation.NonNull; | ||||
| 
 | ||||
| public class UserAgentUtils { | ||||
| 
 | ||||
|     /* GraphQL user agents (which are just standard browser UA's). | ||||
|      * Go to https://www.whatismybrowser.com/guides/the-latest-user-agent/ to update it | ||||
|      * Windows first (Assume win64 not wow64): Chrome, Firefox, Edge | ||||
|      * Then macOS: Chrome, Firefox, Safari | ||||
|      */ | ||||
|     public static final String[] browsers = { | ||||
|             "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.141 Safari/537.36", | ||||
|             "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:84.0) Gecko/20100101 Firefox/84.0", | ||||
|             "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.141 Safari/537.36 Edg/87.0.664.75", | ||||
|             "Mozilla/5.0 (Macintosh; Intel Mac OS X 11_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.141 Safari/537.36", | ||||
|             "Mozilla/5.0 (Macintosh; Intel Mac OS X 11.1; rv:84.0) Gecko/20100101 Firefox/84.0", | ||||
|             "Mozilla/5.0 (Macintosh; Intel Mac OS X 11_1) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.0.2 Safari/605.1.15" | ||||
|     }; | ||||
|     // use APKpure, assume x86 | ||||
|     private static final String igVersion = "169.3.0.30.135"; | ||||
|     private static final String igVersionCode = "264009054"; | ||||
|     // https://github.com/dilame/instagram-private-api/blob/master/src/samples/devices.json | ||||
|     // presumed constant, so no need to update | ||||
|     public static final String[] devices = { | ||||
|             "25/7.1.1; 440dpi; 1080x1920; Xiaomi; Mi Note 3; jason; qcom", | ||||
|             "23/6.0.1; 480dpi; 1080x1920; Xiaomi; Redmi Note 3; kenzo; qcom", | ||||
|             "23/6.0; 480dpi; 1080x1920; Xiaomi; Redmi Note 4; nikel; mt6797", | ||||
|             "24/7.0; 480dpi; 1080x1920; Xiaomi/xiaomi; Redmi Note 4; mido; qcom", | ||||
|             "23/6.0; 480dpi; 1080x1920; Xiaomi; Redmi Note 4X; nikel; mt6797", | ||||
|             "27/8.1.0; 440dpi; 1080x2030; Xiaomi/xiaomi; Redmi Note 5; whyred; qcom", | ||||
|             "23/6.0.1; 480dpi; 1080x1920; Xiaomi; Redmi 4; markw; qcom", | ||||
|             "27/8.1.0; 440dpi; 1080x2030; Xiaomi/xiaomi; Redmi 5 Plus; vince; qcom", | ||||
|             "25/7.1.2; 440dpi; 1080x2030; Xiaomi/xiaomi; Redmi 5 Plus; vince; qcom", | ||||
|             "26/8.0.0; 480dpi; 1080x1920; Xiaomi; MI 5; gemini; qcom", | ||||
|             "27/8.1.0; 480dpi; 1080x1920; Xiaomi/xiaomi; Mi A1; tissot_sprout; qcom", | ||||
|             "26/8.0.0; 480dpi; 1080x1920; Xiaomi; MI 6; sagit; qcom", | ||||
|             "25/7.1.1; 440dpi; 1080x1920; Xiaomi; MI MAX 2; oxygen; qcom", | ||||
|             "24/7.0; 480dpi; 1080x1920; Xiaomi; MI 5s; capricorn; qcom", | ||||
|             "26/8.0.0; 480dpi; 1080x1920; samsung; SM-A520F; a5y17lte; samsungexynos7880", | ||||
|             "26/8.0.0; 480dpi; 1080x2076; samsung; SM-G950F; dreamlte; samsungexynos8895", | ||||
|             "26/8.0.0; 640dpi; 1440x2768; samsung; SM-G950F; dreamlte; samsungexynos8895", | ||||
|             "26/8.0.0; 420dpi; 1080x2094; samsung; SM-G955F; dream2lte; samsungexynos8895", | ||||
|             "26/8.0.0; 560dpi; 1440x2792; samsung; SM-G955F; dream2lte; samsungexynos8895", | ||||
|             "24/7.0; 480dpi; 1080x1920; samsung; SM-A510F; a5xelte; samsungexynos7580", | ||||
|             "26/8.0.0; 480dpi; 1080x1920; samsung; SM-G930F; herolte; samsungexynos8890", | ||||
|             "26/8.0.0; 480dpi; 1080x1920; samsung; SM-G935F; hero2lte; samsungexynos8890", | ||||
|             "26/8.0.0; 420dpi; 1080x2094; samsung; SM-G965F; star2lte; samsungexynos9810", | ||||
|             "26/8.0.0; 480dpi; 1080x2076; samsung; SM-A530F; jackpotlte; samsungexynos7885", | ||||
|             "24/7.0; 640dpi; 1440x2560; samsung; SM-G925F; zerolte; samsungexynos7420", | ||||
|             "26/8.0.0; 420dpi; 1080x1920; samsung; SM-A720F; a7y17lte; samsungexynos7880", | ||||
|             "24/7.0; 640dpi; 1440x2560; samsung; SM-G920F; zeroflte; samsungexynos7420", | ||||
|             "24/7.0; 420dpi; 1080x1920; samsung; SM-J730FM; j7y17lte; samsungexynos7870", | ||||
|             "26/8.0.0; 480dpi; 1080x2076; samsung; SM-G960F; starlte; samsungexynos9810", | ||||
|             "26/8.0.0; 420dpi; 1080x2094; samsung; SM-N950F; greatlte; samsungexynos8895", | ||||
|             "26/8.0.0; 420dpi; 1080x2094; samsung; SM-A730F; jackpot2lte; samsungexynos7885", | ||||
|             "26/8.0.0; 420dpi; 1080x2094; samsung; SM-A605FN; a6plte; qcom", | ||||
|             "26/8.0.0; 480dpi; 1080x1920; HUAWEI/HONOR; STF-L09; HWSTF; hi3660", | ||||
|             "27/8.1.0; 480dpi; 1080x2280; HUAWEI/HONOR; COL-L29; HWCOL; kirin970", | ||||
|             "26/8.0.0; 480dpi; 1080x2032; HUAWEI/HONOR; LLD-L31; HWLLD-H; hi6250", | ||||
|             "26/8.0.0; 480dpi; 1080x2150; HUAWEI; ANE-LX1; HWANE; hi6250", | ||||
|             "26/8.0.0; 480dpi; 1080x2032; HUAWEI; FIG-LX1; HWFIG-H; hi6250", | ||||
|             "27/8.1.0; 480dpi; 1080x2150; HUAWEI/HONOR; COL-L29; HWCOL; kirin970", | ||||
|             "26/8.0.0; 480dpi; 1080x2038; HUAWEI/HONOR; BND-L21; HWBND-H; hi6250", | ||||
|             "23/6.0.1; 420dpi; 1080x1920; LeMobile/LeEco; Le X527; le_s2_ww; qcom" | ||||
|     }; | ||||
| 
 | ||||
|     @NonNull | ||||
|     public static String generateBrowserUA(final int code) { | ||||
|         return browsers[code - 1]; | ||||
|     } | ||||
| 
 | ||||
|     @NonNull | ||||
|     public static String generateAppUA(final int code, final String lang) { | ||||
|         return "Instagram " + igVersion + " Android (" + devices[code] + "; " + lang + "; " + igVersionCode + ")"; | ||||
|     } | ||||
| } | ||||
| @ -79,7 +79,7 @@ public class DirectSettingsViewModel extends AndroidViewModel { | ||||
|             throw new IllegalArgumentException("User is not logged in!"); | ||||
|         } | ||||
|         directMessagesService = DirectMessagesService.getInstance(csrfToken, userId, deviceUuid); | ||||
|         friendshipService = FriendshipService.getInstance(); | ||||
|         friendshipService = FriendshipService.getInstance(deviceUuid, csrfToken, userId); | ||||
|         resources = getApplication().getResources(); | ||||
|     } | ||||
| 
 | ||||
| @ -264,7 +264,7 @@ public class DirectSettingsViewModel extends AndroidViewModel { | ||||
| 
 | ||||
|     private LiveData<Resource<Object>> blockUser(final User user) { | ||||
|         final MutableLiveData<Resource<Object>> data = new MutableLiveData<>(); | ||||
|         friendshipService.block(userId, user.getPk(), csrfToken, new ServiceCallback<FriendshipChangeResponse>() { | ||||
|         friendshipService.block(user.getPk(), new ServiceCallback<FriendshipChangeResponse>() { | ||||
|             @Override | ||||
|             public void onSuccess(final FriendshipChangeResponse result) { | ||||
|                 // refresh thread | ||||
| @ -281,7 +281,7 @@ public class DirectSettingsViewModel extends AndroidViewModel { | ||||
| 
 | ||||
|     private LiveData<Resource<Object>> unblockUser(final User user) { | ||||
|         final MutableLiveData<Resource<Object>> data = new MutableLiveData<>(); | ||||
|         friendshipService.unblock(userId, user.getPk(), csrfToken, new ServiceCallback<FriendshipChangeResponse>() { | ||||
|         friendshipService.unblock(user.getPk(), new ServiceCallback<FriendshipChangeResponse>() { | ||||
|             @Override | ||||
|             public void onSuccess(final FriendshipChangeResponse result) { | ||||
|                 // refresh thread | ||||
| @ -298,7 +298,7 @@ public class DirectSettingsViewModel extends AndroidViewModel { | ||||
| 
 | ||||
|     private LiveData<Resource<Object>> restrictUser(final User user) { | ||||
|         final MutableLiveData<Resource<Object>> data = new MutableLiveData<>(); | ||||
|         friendshipService.toggleRestrict(user.getPk(), true, csrfToken, new ServiceCallback<FriendshipRestrictResponse>() { | ||||
|         friendshipService.toggleRestrict(user.getPk(), true, new ServiceCallback<FriendshipRestrictResponse>() { | ||||
|             @Override | ||||
|             public void onSuccess(final FriendshipRestrictResponse result) { | ||||
|                 // refresh thread | ||||
| @ -315,7 +315,7 @@ public class DirectSettingsViewModel extends AndroidViewModel { | ||||
| 
 | ||||
|     private LiveData<Resource<Object>> unRestrictUser(final User user) { | ||||
|         final MutableLiveData<Resource<Object>> data = new MutableLiveData<>(); | ||||
|         friendshipService.toggleRestrict(user.getPk(), false, csrfToken, new ServiceCallback<FriendshipRestrictResponse>() { | ||||
|         friendshipService.toggleRestrict(user.getPk(), false, new ServiceCallback<FriendshipRestrictResponse>() { | ||||
|             @Override | ||||
|             public void onSuccess(final FriendshipRestrictResponse result) { | ||||
|                 // refresh thread | ||||
|  | ||||
| @ -103,7 +103,7 @@ public class DirectThreadViewModel extends AndroidViewModel { | ||||
|             throw new IllegalArgumentException("User is not logged in!"); | ||||
|         } | ||||
|         service = DirectMessagesService.getInstance(csrfToken, userId, deviceUuid); | ||||
|         mediaService = MediaService.getInstance(); | ||||
|         mediaService = MediaService.getInstance(deviceUuid, csrfToken, userId); | ||||
|         contentResolver = application.getContentResolver(); | ||||
|         recordingsDir = DirectoryUtils.getOutputMediaDirectory(application, "Recordings"); | ||||
|         this.application = application; | ||||
| @ -467,7 +467,7 @@ public class DirectThreadViewModel extends AndroidViewModel { | ||||
|                         .setUploadId(uploadDmVideoOptions.getUploadId()) | ||||
|                         .setSourceType("2") | ||||
|                         .setVideoOptions(new UploadFinishOptions.VideoOptions().setLength(duration / 1000f)); | ||||
|                 final Call<String> uploadFinishRequest = mediaService.uploadFinish(userId, csrfToken, uploadFinishOptions); | ||||
|                 final Call<String> uploadFinishRequest = mediaService.uploadFinish(uploadFinishOptions); | ||||
|                 uploadFinishRequest.enqueue(new Callback<String>() { | ||||
|                     @Override | ||||
|                     public void onResponse(@NonNull final Call<String> call, @NonNull final Response<String> response) { | ||||
| @ -584,7 +584,7 @@ public class DirectThreadViewModel extends AndroidViewModel { | ||||
|                 final UploadFinishOptions uploadFinishOptions = new UploadFinishOptions() | ||||
|                         .setUploadId(uploadDmVoiceOptions.getUploadId()) | ||||
|                         .setSourceType("4"); | ||||
|                 final Call<String> uploadFinishRequest = mediaService.uploadFinish(userId, csrfToken, uploadFinishOptions); | ||||
|                 final Call<String> uploadFinishRequest = mediaService.uploadFinish(uploadFinishOptions); | ||||
|                 uploadFinishRequest.enqueue(new Callback<String>() { | ||||
|                     @Override | ||||
|                     public void onResponse(@NonNull final Call<String> call, @NonNull final Response<String> response) { | ||||
|  | ||||
| @ -43,16 +43,16 @@ public class PostViewV2ViewModel extends ViewModel { | ||||
|     private final MutableLiveData<List<Integer>> options = new MutableLiveData<>(new ArrayList<>()); | ||||
|     private final MediaService mediaService; | ||||
|     private final long viewerId; | ||||
|     private final String csrfToken; | ||||
|     private final boolean isLoggedIn; | ||||
| 
 | ||||
|     private Media media; | ||||
| 
 | ||||
|     public PostViewV2ViewModel() { | ||||
|         mediaService = MediaService.getInstance(); | ||||
|         final String cookie = settingsHelper.getString(Constants.COOKIE); | ||||
|         final String deviceUuid = settingsHelper.getString(Constants.DEVICE_UUID); | ||||
|         final String csrfToken = CookieUtils.getCsrfTokenFromCookie(cookie); | ||||
|         viewerId = CookieUtils.getUserIdFromCookie(cookie); | ||||
|         csrfToken = CookieUtils.getCsrfTokenFromCookie(cookie); | ||||
|         mediaService = MediaService.getInstance(deviceUuid, csrfToken, viewerId); | ||||
|         isLoggedIn = !TextUtils.isEmpty(cookie) && CookieUtils.getUserIdFromCookie(cookie) > 0; | ||||
|     } | ||||
| 
 | ||||
| @ -142,14 +142,14 @@ public class PostViewV2ViewModel extends ViewModel { | ||||
|     public LiveData<Resource<Object>> like() { | ||||
|         final MutableLiveData<Resource<Object>> data = new MutableLiveData<>(); | ||||
|         data.postValue(Resource.loading(null)); | ||||
|         mediaService.like(media.getPk(), viewerId, csrfToken, getLikeUnlikeCallback(data)); | ||||
|         mediaService.like(media.getPk(), getLikeUnlikeCallback(data)); | ||||
|         return data; | ||||
|     } | ||||
| 
 | ||||
|     public LiveData<Resource<Object>> unlike() { | ||||
|         final MutableLiveData<Resource<Object>> data = new MutableLiveData<>(); | ||||
|         data.postValue(Resource.loading(null)); | ||||
|         mediaService.unlike(media.getPk(), viewerId, csrfToken, getLikeUnlikeCallback(data)); | ||||
|         mediaService.unlike(media.getPk(), getLikeUnlikeCallback(data)); | ||||
|         return data; | ||||
|     } | ||||
| 
 | ||||
| @ -196,14 +196,14 @@ public class PostViewV2ViewModel extends ViewModel { | ||||
|     public LiveData<Resource<Object>> save() { | ||||
|         final MutableLiveData<Resource<Object>> data = new MutableLiveData<>(); | ||||
|         data.postValue(Resource.loading(null)); | ||||
|         mediaService.save(media.getPk(), viewerId, csrfToken, getSaveUnsaveCallback(data)); | ||||
|         mediaService.save(media.getPk(), getSaveUnsaveCallback(data)); | ||||
|         return data; | ||||
|     } | ||||
| 
 | ||||
|     public LiveData<Resource<Object>> unsave() { | ||||
|         final MutableLiveData<Resource<Object>> data = new MutableLiveData<>(); | ||||
|         data.postValue(Resource.loading(null)); | ||||
|         mediaService.unsave(media.getPk(), viewerId, csrfToken, getSaveUnsaveCallback(data)); | ||||
|         mediaService.unsave(media.getPk(), getSaveUnsaveCallback(data)); | ||||
|         return data; | ||||
|     } | ||||
| 
 | ||||
| @ -232,7 +232,7 @@ public class PostViewV2ViewModel extends ViewModel { | ||||
|     public LiveData<Resource<Object>> updateCaption(final String caption) { | ||||
|         final MutableLiveData<Resource<Object>> data = new MutableLiveData<>(); | ||||
|         data.postValue(Resource.loading(null)); | ||||
|         mediaService.editCaption(media.getPk(), viewerId, caption, csrfToken, new ServiceCallback<Boolean>() { | ||||
|         mediaService.editCaption(media.getPk(), caption, new ServiceCallback<Boolean>() { | ||||
|             @Override | ||||
|             public void onSuccess(final Boolean result) { | ||||
|                 if (result) { | ||||
|  | ||||
| @ -25,7 +25,7 @@ public class AddCookiesInterceptor implements Interceptor { | ||||
|         } | ||||
|         final String userAgentHeader = "User-Agent"; | ||||
|         if (request.header(userAgentHeader) == null) { | ||||
|             builder.addHeader(userAgentHeader, hasCookie ? Constants.I_USER_AGENT : Constants.USER_AGENT); | ||||
|             builder.addHeader(userAgentHeader, Utils.settingsHelper.getString(hasCookie ? Constants.APP_UA : Constants.BROWSER_UA)); | ||||
|         } | ||||
|         final String languageHeader = "Accept-Language"; | ||||
|         if (request.header(languageHeader) == null) { | ||||
|  | ||||
| @ -9,7 +9,6 @@ import java.util.Collections; | ||||
| import java.util.HashMap; | ||||
| import java.util.List; | ||||
| import java.util.Map; | ||||
| import java.util.TimeZone; | ||||
| import java.util.UUID; | ||||
| 
 | ||||
| import awais.instagrabber.repositories.FeedRepository; | ||||
| @ -47,16 +46,16 @@ public class FeedService extends BaseService { | ||||
|     } | ||||
| 
 | ||||
|     public void fetch(final String csrfToken, | ||||
|                       final String deviceUuid, | ||||
|                       final String cursor, | ||||
|                       final ServiceCallback<PostsFetchResponse> callback) { | ||||
|         final Map<String, String> form = new HashMap<>(); | ||||
|         form.put("_uuid", UUID.randomUUID().toString()); | ||||
|         form.put("_uuid", deviceUuid); | ||||
|         form.put("_csrftoken", csrfToken); | ||||
|         form.put("phone_id", UUID.randomUUID().toString()); | ||||
|         form.put("device_id", UUID.randomUUID().toString()); | ||||
|         form.put("client_session_id", UUID.randomUUID().toString()); | ||||
|         form.put("is_prefetch", "0"); | ||||
|         form.put("timezone_offset", String.valueOf(TimeZone.getDefault().getRawOffset() / 1000)); | ||||
|         if (!TextUtils.isEmpty(cursor)) { | ||||
|             form.put("max_id", cursor); | ||||
|             form.put("reason", "pagination"); | ||||
| @ -110,7 +109,7 @@ public class FeedService extends BaseService { | ||||
|         final List<Media> allPosts = new ArrayList<>(); | ||||
|         final List<Media> items = feedFetchResponse.getItems(); | ||||
|         for (final Media media : items) { | ||||
|             if (media.isInjected() || media.getMediaType() == null) continue; | ||||
|             if (media == null || media.isInjected() || (media.getMediaType() == null && media.getEndOfFeedDemarcator() == null)) continue; | ||||
|             if (needNewMaxId && media.getEndOfFeedDemarcator() != null) { | ||||
|                 final EndOfFeedDemarcator endOfFeedDemarcator = media.getEndOfFeedDemarcator(); | ||||
|                 final EndOfFeedGroupSet groupSet = endOfFeedDemarcator.getGroupSet(); | ||||
| @ -123,7 +122,7 @@ public class FeedService extends BaseService { | ||||
|                     nextMaxId = group.getNextMaxId(); | ||||
|                     final List<Media> feedItems = group.getFeedItems(); | ||||
|                     for (final Media feedItem : feedItems) { | ||||
|                         if (feedItem == null || feedItem.isInjected()) continue; | ||||
|                         if (feedItem == null || feedItem.isInjected() || feedItem.getMediaType() == null) continue; | ||||
|                         allPosts.add(feedItem); | ||||
|                     } | ||||
|                 } | ||||
|  | ||||
| @ -13,14 +13,13 @@ import java.util.Collections; | ||||
| import java.util.HashMap; | ||||
| import java.util.List; | ||||
| import java.util.Map; | ||||
| import java.util.UUID; | ||||
| import java.util.Objects; | ||||
| 
 | ||||
| import awais.instagrabber.models.FollowModel; | ||||
| import awais.instagrabber.repositories.FriendshipRepository; | ||||
| import awais.instagrabber.repositories.responses.FriendshipChangeResponse; | ||||
| import awais.instagrabber.repositories.responses.FriendshipListFetchResponse; | ||||
| import awais.instagrabber.repositories.responses.FriendshipRestrictResponse; | ||||
| import awais.instagrabber.utils.Constants; | ||||
| import awais.instagrabber.utils.TextUtils; | ||||
| import awais.instagrabber.utils.Utils; | ||||
| import retrofit2.Call; | ||||
| @ -32,61 +31,74 @@ public class FriendshipService extends BaseService { | ||||
|     private static final String TAG = "FriendshipService"; | ||||
| 
 | ||||
|     private final FriendshipRepository repository; | ||||
|     private final String deviceUuid, csrfToken; | ||||
|     private final long userId; | ||||
| 
 | ||||
|     private static FriendshipService instance; | ||||
| 
 | ||||
|     private FriendshipService() { | ||||
|     private FriendshipService(final String deviceUuid, | ||||
|                               final String csrfToken, | ||||
|                               final long userId) { | ||||
|         this.deviceUuid = deviceUuid; | ||||
|         this.csrfToken = csrfToken; | ||||
|         this.userId = userId; | ||||
|         final Retrofit retrofit = getRetrofitBuilder() | ||||
|                 .baseUrl("https://i.instagram.com") | ||||
|                 .build(); | ||||
|         repository = retrofit.create(FriendshipRepository.class); | ||||
|     } | ||||
| 
 | ||||
|     public static FriendshipService getInstance() { | ||||
|         if (instance == null) { | ||||
|             instance = new FriendshipService(); | ||||
|     public String getCsrfToken() { | ||||
|         return csrfToken; | ||||
|     } | ||||
| 
 | ||||
|     public String getDeviceUuid() { | ||||
|         return deviceUuid; | ||||
|     } | ||||
| 
 | ||||
|     public long getUserId() { | ||||
|         return userId; | ||||
|     } | ||||
| 
 | ||||
|     public static FriendshipService getInstance(final String deviceUuid, final String csrfToken, final long userId) { | ||||
|         if (instance == null | ||||
|                 || !Objects.equals(instance.getCsrfToken(), csrfToken) | ||||
|                 || !Objects.equals(instance.getDeviceUuid(), deviceUuid) | ||||
|                 || !Objects.equals(instance.getUserId(), userId)) { | ||||
|             instance = new FriendshipService(deviceUuid, csrfToken, userId); | ||||
|         } | ||||
|         return instance; | ||||
|     } | ||||
| 
 | ||||
|     public void follow(final long userId, | ||||
|                        final long targetUserId, | ||||
|                        final String csrfToken, | ||||
|     public void follow(final long targetUserId, | ||||
|                        final ServiceCallback<FriendshipChangeResponse> callback) { | ||||
|         change("create", userId, targetUserId, csrfToken, callback); | ||||
|         change("create", targetUserId, callback); | ||||
|     } | ||||
| 
 | ||||
|     public void unfollow(final long userId, | ||||
|                          final long targetUserId, | ||||
|                          final String csrfToken, | ||||
|     public void unfollow(final long targetUserId, | ||||
|                          final ServiceCallback<FriendshipChangeResponse> callback) { | ||||
|         change("destroy", userId, targetUserId, csrfToken, callback); | ||||
|         change("destroy", targetUserId, callback); | ||||
|     } | ||||
| 
 | ||||
|     public void block(final long userId, | ||||
|                       final long targetUserId, | ||||
|                       final String csrfToken, | ||||
|     public void block(final long targetUserId, | ||||
|                       final ServiceCallback<FriendshipChangeResponse> callback) { | ||||
|         change("block", userId, targetUserId, csrfToken, callback); | ||||
|         change("block", targetUserId, callback); | ||||
|     } | ||||
| 
 | ||||
|     public void unblock(final long userId, | ||||
|                         final long targetUserId, | ||||
|                         final String csrfToken, | ||||
|     public void unblock(final long targetUserId, | ||||
|                         final ServiceCallback<FriendshipChangeResponse> callback) { | ||||
|         change("unblock", userId, targetUserId, csrfToken, callback); | ||||
|         change("unblock", targetUserId, callback); | ||||
|     } | ||||
| 
 | ||||
|     public void toggleRestrict(final long targetUserId, | ||||
|                                final boolean restrict, | ||||
|                                final String csrfToken, | ||||
|                                final ServiceCallback<FriendshipRestrictResponse> callback) { | ||||
|         final Map<String, String> form = new HashMap<>(3); | ||||
|         form.put("_csrftoken", csrfToken); | ||||
|         form.put("_uuid", UUID.randomUUID().toString()); | ||||
|         form.put("_uuid", deviceUuid); | ||||
|         form.put("target_user_id", String.valueOf(targetUserId)); | ||||
|         final String action = restrict ? "restrict" : "unrestrict"; | ||||
|         final Call<FriendshipRestrictResponse> request = repository.toggleRestrict(Constants.I_USER_AGENT, action, form); | ||||
|         final Call<FriendshipRestrictResponse> request = repository.toggleRestrict(action, form); | ||||
|         request.enqueue(new Callback<FriendshipRestrictResponse>() { | ||||
|             @Override | ||||
|             public void onResponse(@NonNull final Call<FriendshipRestrictResponse> call, | ||||
| @ -106,33 +118,27 @@ public class FriendshipService extends BaseService { | ||||
|         }); | ||||
|     } | ||||
| 
 | ||||
|     public void approve(final long userId, | ||||
|                         final long targetUserId, | ||||
|                         final String csrfToken, | ||||
|     public void approve(final long targetUserId, | ||||
|                         final ServiceCallback<FriendshipChangeResponse> callback) { | ||||
|         change("approve", userId, targetUserId, csrfToken, callback); | ||||
|         change("approve", targetUserId, callback); | ||||
|     } | ||||
| 
 | ||||
|     public void ignore(final long userId, | ||||
|                        final long targetUserId, | ||||
|                        final String csrfToken, | ||||
|     public void ignore(final long targetUserId, | ||||
|                        final ServiceCallback<FriendshipChangeResponse> callback) { | ||||
|         change("ignore", userId, targetUserId, csrfToken, callback); | ||||
|         change("ignore", targetUserId, callback); | ||||
|     } | ||||
| 
 | ||||
|     private void change(final String action, | ||||
|                         final long userId, | ||||
|                         final long targetUserId, | ||||
|                         final String csrfToken, | ||||
|                         final ServiceCallback<FriendshipChangeResponse> callback) { | ||||
|         final Map<String, Object> form = new HashMap<>(5); | ||||
|         form.put("_csrftoken", csrfToken); | ||||
|         form.put("_uid", userId); | ||||
|         form.put("_uuid", UUID.randomUUID().toString()); | ||||
|         form.put("_uuid", deviceUuid); | ||||
|         form.put("radio_type", "wifi-none"); | ||||
|         form.put("user_id", targetUserId); | ||||
|         final Map<String, String> signedForm = Utils.sign(form); | ||||
|         final Call<FriendshipChangeResponse> request = repository.change(Constants.I_USER_AGENT, action, targetUserId, signedForm); | ||||
|         final Call<FriendshipChangeResponse> request = repository.change(action, targetUserId, signedForm); | ||||
|         request.enqueue(new Callback<FriendshipChangeResponse>() { | ||||
|             @Override | ||||
|             public void onResponse(@NonNull final Call<FriendshipChangeResponse> call, | ||||
| @ -158,8 +164,8 @@ public class FriendshipService extends BaseService { | ||||
|                         final ServiceCallback<FriendshipListFetchResponse> callback) { | ||||
|         final Map<String, String> queryMap = new HashMap<>(); | ||||
|         if (maxId != null) queryMap.put("max_id", maxId); | ||||
|         final Call<String> request = repository.getList(Constants.I_USER_AGENT, | ||||
|                                                         targetUserId, | ||||
|         final Call<String> request = repository.getList( | ||||
|                 targetUserId, | ||||
|                                                         follower ? "followers" : "following", | ||||
|                                                         queryMap); | ||||
|         request.enqueue(new Callback<String>() { | ||||
|  | ||||
| @ -14,6 +14,7 @@ import java.util.Collections; | ||||
| import java.util.HashMap; | ||||
| import java.util.List; | ||||
| import java.util.Map; | ||||
| import java.util.Objects; | ||||
| import java.util.UUID; | ||||
| 
 | ||||
| import awais.instagrabber.repositories.MediaRepository; | ||||
| @ -34,19 +35,41 @@ public class MediaService extends BaseService { | ||||
|     private static final String TAG = "MediaService"; | ||||
| 
 | ||||
|     private final MediaRepository repository; | ||||
|     private final String deviceUuid, csrfToken; | ||||
|     private final long userId; | ||||
| 
 | ||||
|     private static MediaService instance; | ||||
| 
 | ||||
|     private MediaService() { | ||||
|     private MediaService(final String deviceUuid, | ||||
|                          final String csrfToken, | ||||
|                          final long userId) { | ||||
|         this.deviceUuid = deviceUuid; | ||||
|         this.csrfToken = csrfToken; | ||||
|         this.userId = userId; | ||||
|         final Retrofit retrofit = getRetrofitBuilder() | ||||
|                 .baseUrl("https://i.instagram.com") | ||||
|                 .build(); | ||||
|         repository = retrofit.create(MediaRepository.class); | ||||
|     } | ||||
| 
 | ||||
|     public static MediaService getInstance() { | ||||
|         if (instance == null) { | ||||
|             instance = new MediaService(); | ||||
|     public String getCsrfToken() { | ||||
|         return csrfToken; | ||||
|     } | ||||
| 
 | ||||
|     public String getDeviceUuid() { | ||||
|         return deviceUuid; | ||||
|     } | ||||
| 
 | ||||
|     public long getUserId() { | ||||
|         return userId; | ||||
|     } | ||||
| 
 | ||||
|     public static MediaService getInstance(final String deviceUuid, final String csrfToken, final long userId) { | ||||
|         if (instance == null | ||||
|                 || !Objects.equals(instance.getCsrfToken(), csrfToken) | ||||
|                 || !Objects.equals(instance.getDeviceUuid(), deviceUuid) | ||||
|                 || !Objects.equals(instance.getUserId(), userId)) { | ||||
|             instance = new MediaService(deviceUuid, csrfToken, userId); | ||||
|         } | ||||
|         return instance; | ||||
|     } | ||||
| @ -78,43 +101,33 @@ public class MediaService extends BaseService { | ||||
|     } | ||||
| 
 | ||||
|     public void like(final String mediaId, | ||||
|                      final long userId, | ||||
|                      final String csrfToken, | ||||
|                      final ServiceCallback<Boolean> callback) { | ||||
|         action(mediaId, userId, "like", csrfToken, callback); | ||||
|         action(mediaId, "like", callback); | ||||
|     } | ||||
| 
 | ||||
|     public void unlike(final String mediaId, | ||||
|                        final long userId, | ||||
|                        final String csrfToken, | ||||
|                        final ServiceCallback<Boolean> callback) { | ||||
|         action(mediaId, userId, "unlike", csrfToken, callback); | ||||
|         action(mediaId, "unlike", callback); | ||||
|     } | ||||
| 
 | ||||
|     public void save(final String mediaId, | ||||
|                      final long userId, | ||||
|                      final String csrfToken, | ||||
|                      final ServiceCallback<Boolean> callback) { | ||||
|         action(mediaId, userId, "save", csrfToken, callback); | ||||
|         action(mediaId, "save", callback); | ||||
|     } | ||||
| 
 | ||||
|     public void unsave(final String mediaId, | ||||
|                        final long userId, | ||||
|                        final String csrfToken, | ||||
|                        final ServiceCallback<Boolean> callback) { | ||||
|         action(mediaId, userId, "unsave", csrfToken, callback); | ||||
|         action(mediaId, "unsave", callback); | ||||
|     } | ||||
| 
 | ||||
|     private void action(final String mediaId, | ||||
|                         final long userId, | ||||
|                         final String action, | ||||
|                         final String csrfToken, | ||||
|                         final ServiceCallback<Boolean> callback) { | ||||
|         final Map<String, Object> form = new HashMap<>(4); | ||||
|         form.put("media_id", mediaId); | ||||
|         form.put("_csrftoken", csrfToken); | ||||
|         form.put("_uid", userId); | ||||
|         form.put("_uuid", UUID.randomUUID().toString()); | ||||
|         form.put("_uuid", deviceUuid); | ||||
|         // form.put("radio_type", "wifi-none"); | ||||
|         final Map<String, String> signedForm = Utils.sign(form); | ||||
|         final Call<String> request = repository.action(action, mediaId, signedForm); | ||||
| @ -149,9 +162,7 @@ public class MediaService extends BaseService { | ||||
| 
 | ||||
|     public void comment(@NonNull final String mediaId, | ||||
|                         @NonNull final String comment, | ||||
|                         final long userId, | ||||
|                         final String replyToCommentId, | ||||
|                         final String csrfToken, | ||||
|                         @NonNull final ServiceCallback<Boolean> callback) { | ||||
|         final String module = "self_comments_v2"; | ||||
|         final Map<String, Object> form = new HashMap<>(); | ||||
| @ -159,7 +170,7 @@ public class MediaService extends BaseService { | ||||
|         form.put("idempotence_token", UUID.randomUUID().toString()); | ||||
|         form.put("_csrftoken", csrfToken); | ||||
|         form.put("_uid", userId); | ||||
|         form.put("_uuid", UUID.randomUUID().toString()); | ||||
|         form.put("_uuid", deviceUuid); | ||||
|         form.put("comment_text", comment); | ||||
|         form.put("containermodule", module); | ||||
|         if (!TextUtils.isEmpty(replyToCommentId)) { | ||||
| @ -194,23 +205,19 @@ public class MediaService extends BaseService { | ||||
|     } | ||||
| 
 | ||||
|     public void deleteComment(final String mediaId, | ||||
|                               final long userId, | ||||
|                               final String commentId, | ||||
|                               final String csrfToken, | ||||
|                               @NonNull final ServiceCallback<Boolean> callback) { | ||||
|         deleteComments(mediaId, userId, Collections.singletonList(commentId), csrfToken, callback); | ||||
|         deleteComments(mediaId, Collections.singletonList(commentId), callback); | ||||
|     } | ||||
| 
 | ||||
|     public void deleteComments(final String mediaId, | ||||
|                                final long userId, | ||||
|                                final List<String> commentIds, | ||||
|                                final String csrfToken, | ||||
|                                @NonNull final ServiceCallback<Boolean> callback) { | ||||
|         final Map<String, Object> form = new HashMap<>(); | ||||
|         form.put("comment_ids_to_delete", TextUtils.join(",", commentIds)); | ||||
|         form.put("_csrftoken", csrfToken); | ||||
|         form.put("_uid", userId); | ||||
|         form.put("_uuid", UUID.randomUUID().toString()); | ||||
|         form.put("_uuid", deviceUuid); | ||||
|         final Map<String, String> signedForm = Utils.sign(form); | ||||
|         final Call<String> bulkDeleteRequest = repository.commentsBulkDelete(mediaId, signedForm); | ||||
|         bulkDeleteRequest.enqueue(new Callback<String>() { | ||||
| @ -241,12 +248,11 @@ public class MediaService extends BaseService { | ||||
|     } | ||||
| 
 | ||||
|     public void commentLike(@NonNull final String commentId, | ||||
|                             @NonNull final String csrfToken, | ||||
|                             @NonNull final ServiceCallback<Boolean> callback) { | ||||
|         final Map<String, Object> form = new HashMap<>(); | ||||
|         form.put("_csrftoken", csrfToken); | ||||
|         // form.put("_uid", userId); | ||||
|         // form.put("_uuid", UUID.randomUUID().toString()); | ||||
|         // form.put("_uuid", deviceUuid); | ||||
|         final Map<String, String> signedForm = Utils.sign(form); | ||||
|         final Call<String> commentLikeRequest = repository.commentLike(commentId, signedForm); | ||||
|         commentLikeRequest.enqueue(new Callback<String>() { | ||||
| @ -277,12 +283,11 @@ public class MediaService extends BaseService { | ||||
|     } | ||||
| 
 | ||||
|     public void commentUnlike(final String commentId, | ||||
|                               @NonNull final String csrfToken, | ||||
|                               @NonNull final ServiceCallback<Boolean> callback) { | ||||
|         final Map<String, Object> form = new HashMap<>(); | ||||
|         form.put("_csrftoken", csrfToken); | ||||
|         // form.put("_uid", userId); | ||||
|         // form.put("_uuid", UUID.randomUUID().toString()); | ||||
|         // form.put("_uuid", deviceUuid); | ||||
|         final Map<String, String> signedForm = Utils.sign(form); | ||||
|         final Call<String> commentUnlikeRequest = repository.commentUnlike(commentId, signedForm); | ||||
|         commentUnlikeRequest.enqueue(new Callback<String>() { | ||||
| @ -313,14 +318,12 @@ public class MediaService extends BaseService { | ||||
|     } | ||||
| 
 | ||||
|     public void editCaption(final String postId, | ||||
|                             final long userId, | ||||
|                             final String newCaption, | ||||
|                             @NonNull final String csrfToken, | ||||
|                             @NonNull final ServiceCallback<Boolean> callback) { | ||||
|         final Map<String, Object> form = new HashMap<>(); | ||||
|         form.put("_csrftoken", csrfToken); | ||||
|         form.put("_uid", userId); | ||||
|         form.put("_uuid", UUID.randomUUID().toString()); | ||||
|         form.put("_uuid", deviceUuid); | ||||
|         form.put("igtv_feed_preview", "false"); | ||||
|         form.put("media_id", postId); | ||||
|         form.put("caption_text", newCaption); | ||||
| @ -411,9 +414,7 @@ public class MediaService extends BaseService { | ||||
|         }); | ||||
|     } | ||||
| 
 | ||||
|     public Call<String> uploadFinish(final long userId, | ||||
|                                      @NonNull final String csrfToken, | ||||
|                                      @NonNull final UploadFinishOptions options) { | ||||
|     public Call<String> uploadFinish(@NonNull final UploadFinishOptions options) { | ||||
|         if (options.getVideoOptions() != null) { | ||||
|             final UploadFinishOptions.VideoOptions videoOptions = options.getVideoOptions(); | ||||
|             if (videoOptions.getClips() == null) { | ||||
| @ -430,7 +431,7 @@ public class MediaService extends BaseService { | ||||
|                 .put("_csrftoken", csrfToken) | ||||
|                 .put("source_type", options.getSourceType()) | ||||
|                 .put("_uid", String.valueOf(userId)) | ||||
|                 .put("_uuid", UUID.randomUUID().toString()) | ||||
|                 .put("_uuid", deviceUuid) | ||||
|                 .put("upload_id", options.getUploadId()); | ||||
|         if (options.getVideoOptions() != null) { | ||||
|             formBuilder.putAll(options.getVideoOptions().getMap()); | ||||
|  | ||||
| @ -21,6 +21,7 @@ import awais.instagrabber.models.NotificationModel; | ||||
| import awais.instagrabber.models.enums.NotificationType; | ||||
| import awais.instagrabber.repositories.NewsRepository; | ||||
| import awais.instagrabber.utils.Constants; | ||||
| import awais.instagrabber.utils.Utils; | ||||
| import retrofit2.Call; | ||||
| import retrofit2.Callback; | ||||
| import retrofit2.Response; | ||||
| @ -32,6 +33,7 @@ public class NewsService extends BaseService { | ||||
|     private final NewsRepository repository; | ||||
| 
 | ||||
|     private static NewsService instance; | ||||
|     private static String browserUa, appUa; | ||||
| 
 | ||||
|     private NewsService() { | ||||
|         final Retrofit retrofit = getRetrofitBuilder() | ||||
| @ -44,13 +46,15 @@ public class NewsService extends BaseService { | ||||
|         if (instance == null) { | ||||
|             instance = new NewsService(); | ||||
|         } | ||||
|         appUa = Utils.settingsHelper.getString(Constants.APP_UA); | ||||
|         browserUa = Utils.settingsHelper.getString(Constants.BROWSER_UA); | ||||
|         return instance; | ||||
|     } | ||||
| 
 | ||||
|     public void fetchAppInbox(final boolean markAsSeen, | ||||
|                               final ServiceCallback<List<NotificationModel>> callback) { | ||||
|         final List<NotificationModel> result = new ArrayList<>(); | ||||
|         final Call<String> request = repository.appInbox(markAsSeen); | ||||
|         final Call<String> request = repository.appInbox(appUa, markAsSeen); | ||||
|         request.enqueue(new Callback<String>() { | ||||
|             @Override | ||||
|             public void onResponse(@NonNull final Call<String> call, @NonNull final Response<String> response) { | ||||
| @ -90,7 +94,7 @@ public class NewsService extends BaseService { | ||||
| 
 | ||||
|     public void fetchWebInbox(final boolean markAsSeen, | ||||
|                               final ServiceCallback<List<NotificationModel>> callback) { | ||||
|         final Call<String> request = repository.webInbox(); | ||||
|         final Call<String> request = repository.webInbox(browserUa); | ||||
|         request.enqueue(new Callback<String>() { | ||||
|             @Override | ||||
|             public void onResponse(@NonNull final Call<String> call, @NonNull final Response<String> response) { | ||||
| @ -181,7 +185,7 @@ public class NewsService extends BaseService { | ||||
|                 data.getLong("profile_id"), | ||||
|                 data.getString("profile_name"), | ||||
|                 data.getString("profile_image"), | ||||
|                 !data.isNull("media") ? data.getJSONArray("media").getJSONObject(0).getLong("id") : 0, | ||||
|                 !data.isNull("media") ? Long.valueOf(data.getJSONArray("media").getJSONObject(0).getString("id").split("_")[0]) : 0, | ||||
|                 !data.isNull("media") ? data.getJSONArray("media").getJSONObject(0).getString("image") : null, | ||||
|                 notificationType); | ||||
|     } | ||||
| @ -206,7 +210,7 @@ public class NewsService extends BaseService { | ||||
|         form.put("device_id", UUID.randomUUID().toString()); | ||||
|         form.put("module", "discover_people"); | ||||
|         form.put("paginate", "false"); | ||||
|         final Call<String> request = repository.getAyml(form); | ||||
|         final Call<String> request = repository.getAyml(appUa, form); | ||||
|         request.enqueue(new Callback<String>() { | ||||
|             @Override | ||||
|             public void onResponse(@NonNull final Call<String> call, @NonNull final Response<String> response) { | ||||
|  | ||||
| @ -325,7 +325,7 @@ public class StoriesService extends BaseService { | ||||
|     public void getUserStory(final StoryViewerOptions options, | ||||
|                              final ServiceCallback<List<StoryModel>> callback) { | ||||
|         final String url = buildUrl(options); | ||||
|         final Call<String> userStoryCall = repository.getUserStory(Constants.I_USER_AGENT, url); | ||||
|         final Call<String> userStoryCall = repository.getUserStory(url); | ||||
|         final boolean isLoc = options.getType() == StoryViewerOptions.Type.LOCATION; | ||||
|         final boolean isHashtag = options.getType() == StoryViewerOptions.Type.HASHTAG; | ||||
|         final boolean isHighlight = options.getType() == StoryViewerOptions.Type.HIGHLIGHT; | ||||
| @ -400,7 +400,7 @@ public class StoriesService extends BaseService { | ||||
|         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); | ||||
|                 repository.respondToSticker(storyId, stickerId, action, signedForm); | ||||
|         request.enqueue(new Callback<StoryStickerResponse>() { | ||||
|             @Override | ||||
|             public void onResponse(@NonNull final Call<StoryStickerResponse> call, | ||||
|  | ||||
| @ -12,7 +12,6 @@ import org.json.JSONObject; | ||||
| import awais.instagrabber.repositories.TagsRepository; | ||||
| import awais.instagrabber.repositories.responses.PostsFetchResponse; | ||||
| import awais.instagrabber.repositories.responses.TagFeedResponse; | ||||
| import awais.instagrabber.utils.Constants; | ||||
| import awais.instagrabber.utils.TextUtils; | ||||
| import retrofit2.Call; | ||||
| import retrofit2.Callback; | ||||
| @ -46,12 +45,11 @@ public class TagsService extends BaseService { | ||||
|         return instance; | ||||
|     } | ||||
| 
 | ||||
|     public void follow(@NonNull final String tag, | ||||
|     public void follow(@NonNull final String ua, | ||||
|                        @NonNull final String tag, | ||||
|                        @NonNull final String csrfToken, | ||||
|                        final ServiceCallback<Boolean> callback) { | ||||
|         final Call<String> request = webRepository.follow(Constants.USER_AGENT, | ||||
|                                                           csrfToken, | ||||
|                                                           tag); | ||||
|         final Call<String> request = webRepository.follow(ua, csrfToken, tag); | ||||
|         request.enqueue(new Callback<String>() { | ||||
|             @Override | ||||
|             public void onResponse(@NonNull final Call<String> call, @NonNull final Response<String> response) { | ||||
| @ -77,12 +75,11 @@ public class TagsService extends BaseService { | ||||
|         }); | ||||
|     } | ||||
| 
 | ||||
|     public void unfollow(@NonNull final String tag, | ||||
|     public void unfollow(@NonNull final String ua, | ||||
|                          @NonNull final String tag, | ||||
|                          @NonNull final String csrfToken, | ||||
|                          final ServiceCallback<Boolean> callback) { | ||||
|         final Call<String> request = webRepository.unfollow(Constants.USER_AGENT, | ||||
|                                                             csrfToken, | ||||
|                                                             tag); | ||||
|         final Call<String> request = webRepository.unfollow(ua, csrfToken, tag); | ||||
|         request.enqueue(new Callback<String>() { | ||||
|             @Override | ||||
|             public void onResponse(@NonNull final Call<String> call, @NonNull final Response<String> response) { | ||||
|  | ||||
| @ -72,6 +72,7 @@ | ||||
|                     android:layout_height="wrap_content" | ||||
|                     android:paddingStart="0dp" | ||||
|                     android:paddingEnd="8dp" | ||||
|                     android:layout_margin="8dp" | ||||
|                     app:layout_constraintBottom_toTopOf="@id/mute_mentions" | ||||
|                     app:layout_constraintEnd_toEndOf="parent" | ||||
|                     app:layout_constraintTop_toBottomOf="@id/title_edit_input_layout" /> | ||||
| @ -98,6 +99,7 @@ | ||||
|                     android:layout_height="wrap_content" | ||||
|                     android:paddingStart="0dp" | ||||
|                     android:paddingEnd="8dp" | ||||
|                     android:layout_margin="8dp" | ||||
|                     app:layout_constraintBottom_toTopOf="@id/leave" | ||||
|                     app:layout_constraintEnd_toEndOf="parent" | ||||
|                     app:layout_constraintTop_toBottomOf="@id/mute_messages" /> | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user