mirror of
				https://github.com/KokaKiwi/BarInsta
				synced 2025-10-31 03:25:34 +00:00 
			
		
		
		
	the great user agent change
This commit is contained in:
		
							parent
							
								
									c9f891e4e1
								
							
						
					
					
						commit
						e8711379d0
					
				| @ -10,8 +10,8 @@ android { | ||||
|         minSdkVersion 21 | ||||
|         targetSdkVersion 29 | ||||
| 
 | ||||
|         versionCode 57 | ||||
|         versionName '19.0.5' | ||||
|         versionCode 58 | ||||
|         versionName '19.1.0' | ||||
| 
 | ||||
|         multiDexEnabled true | ||||
| 
 | ||||
|  | ||||
| @ -11,12 +11,14 @@ import com.facebook.imagepipeline.core.ImagePipelineConfig; | ||||
| 
 | ||||
| import java.net.CookieHandler; | ||||
| import java.text.SimpleDateFormat; | ||||
| import java.util.concurrent.ThreadLocalRandom; | ||||
| import java.util.UUID; | ||||
| 
 | ||||
| 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); | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @ -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) | ||||
|  | ||||
| @ -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) { | ||||
|  | ||||
| @ -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; | ||||
|  | ||||
| @ -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); | ||||
|  | ||||
| @ -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); | ||||
| } | ||||
|  | ||||
| @ -3,6 +3,7 @@ package awais.instagrabber.repositories; | ||||
| import java.util.Map; | ||||
| 
 | ||||
| import awais.instagrabber.utils.Constants; | ||||
| import awais.instagrabber.utils.Utils; | ||||
| import retrofit2.Call; | ||||
| import retrofit2.http.FieldMap; | ||||
| import retrofit2.http.FormUrlEncoded; | ||||
| @ -14,16 +15,13 @@ 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); | ||||
| } | ||||
|  | ||||
| @ -28,12 +28,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 | ||||
|  | ||||
| @ -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,12 +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"; | ||||
|     public static final String I_USER_AGENT = | ||||
|             "Instagram 169.3.0.30.135 Android (27/8.1.0; 320dpi; 720x1362; motorola; motorola one; deen_sprout; qcom; pt_BR; 264009054)"; | ||||
|     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," + | ||||
|  | ||||
| @ -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"; | ||||
|  | ||||
| @ -9,8 +9,12 @@ import androidx.annotation.StringDef; | ||||
| import androidx.appcompat.app.AppCompatDelegate; | ||||
| 
 | ||||
| import static awais.instagrabber.utils.Constants.APP_LANGUAGE; | ||||
| import static awais.instagrabber.utils.Constants.APP_UA; | ||||
| import static awais.instagrabber.utils.Constants.APP_UA_CODE; | ||||
| import static awais.instagrabber.utils.Constants.APP_THEME; | ||||
| 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; | ||||
| @ -79,7 +83,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; | ||||
|     } | ||||
| 
 | ||||
| @ -120,10 +124,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}) | ||||
|             {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}) | ||||
|     public @interface StringSettings {} | ||||
| 
 | ||||
|     @StringDef({DOWNLOAD_USER_FOLDER, FOLDER_SAVE_TO, AUTOPLAY_VIDEOS, SHOW_QUICK_ACCESS_DIALOG, MUTED_VIDEOS, | ||||
| @ -131,6 +136,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 + ")"; | ||||
|     } | ||||
| } | ||||
| @ -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) { | ||||
|  | ||||
| @ -14,14 +14,12 @@ import java.util.HashMap; | ||||
| import java.util.List; | ||||
| import java.util.Map; | ||||
| import java.util.Objects; | ||||
| import java.util.UUID; | ||||
| 
 | ||||
| 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; | ||||
| @ -100,7 +98,7 @@ public class FriendshipService extends BaseService { | ||||
|         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, | ||||
| @ -140,7 +138,7 @@ public class FriendshipService extends BaseService { | ||||
|         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, | ||||
| @ -166,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>() { | ||||
|  | ||||
| @ -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) { | ||||
| @ -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) { | ||||
|  | ||||
| @ -326,7 +326,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; | ||||
| @ -401,7 +401,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, | ||||
|  | ||||
| @ -46,12 +46,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 +76,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) { | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user