From 91e13a23ad288243a17ca59776063cbd5212d996 Mon Sep 17 00:00:00 2001 From: Ammar Githam Date: Mon, 22 Mar 2021 22:02:48 +0900 Subject: [PATCH] Add ig error interceptor --- .../instagrabber/InstaGrabberApplication.java | 3 - .../instagrabber/activities/MainActivity.java | 2 + .../awais/instagrabber/utils/Constants.java | 1 + .../webservices/RetrofitFactory.java | 17 +-- .../interceptors/IgErrorsInterceptor.java | 108 ++++++++++++++++++ app/src/main/res/values/strings.xml | 6 + 6 files changed, 126 insertions(+), 11 deletions(-) create mode 100644 app/src/main/java/awais/instagrabber/webservices/interceptors/IgErrorsInterceptor.java diff --git a/app/src/main/java/awais/instagrabber/InstaGrabberApplication.java b/app/src/main/java/awais/instagrabber/InstaGrabberApplication.java index de555f94..36807a6c 100644 --- a/app/src/main/java/awais/instagrabber/InstaGrabberApplication.java +++ b/app/src/main/java/awais/instagrabber/InstaGrabberApplication.java @@ -17,7 +17,6 @@ import awais.instagrabber.utils.Constants; import awais.instagrabber.utils.LocaleUtils; import awais.instagrabber.utils.SettingsHelper; import awais.instagrabber.utils.TextUtils; -import awais.instagrabber.webservices.RetrofitFactory; import awaisomereport.CrashReporter; import static awais.instagrabber.utils.CookieUtils.NET_COOKIE_MANAGER; @@ -87,7 +86,5 @@ public final class InstaGrabberApplication extends Application { if (TextUtils.isEmpty(settingsHelper.getString(Constants.DEVICE_UUID))) { settingsHelper.putString(Constants.DEVICE_UUID, UUID.randomUUID().toString()); } - - RetrofitFactory.setup(this); } } \ No newline at end of file diff --git a/app/src/main/java/awais/instagrabber/activities/MainActivity.java b/app/src/main/java/awais/instagrabber/activities/MainActivity.java index df2369cc..66670534 100644 --- a/app/src/main/java/awais/instagrabber/activities/MainActivity.java +++ b/app/src/main/java/awais/instagrabber/activities/MainActivity.java @@ -83,6 +83,7 @@ import awais.instagrabber.utils.TextUtils; import awais.instagrabber.utils.Utils; import awais.instagrabber.utils.emoji.EmojiParser; import awais.instagrabber.viewmodels.AppStateViewModel; +import awais.instagrabber.webservices.RetrofitFactory; import static awais.instagrabber.utils.NavigationExtensions.setupWithNavController; import static awais.instagrabber.utils.Utils.settingsHelper; @@ -138,6 +139,7 @@ public class MainActivity extends BaseLanguageActivity implements FragmentManage @Override protected void onCreate(@Nullable final Bundle savedInstanceState) { super.onCreate(savedInstanceState); + RetrofitFactory.setup(this); binding = ActivityMainBinding.inflate(getLayoutInflater()); final String cookie = settingsHelper.getString(Constants.COOKIE); CookieUtils.setupCookies(cookie); diff --git a/app/src/main/java/awais/instagrabber/utils/Constants.java b/app/src/main/java/awais/instagrabber/utils/Constants.java index 0c92f0fd..4c064e81 100644 --- a/app/src/main/java/awais/instagrabber/utils/Constants.java +++ b/app/src/main/java/awais/instagrabber/utils/Constants.java @@ -111,6 +111,7 @@ public final class Constants { public static final int SHOW_ACTIVITY_REQUEST_CODE = 1738; public static final int SHOW_DM_THREAD = 2000; public static final int DM_SYNC_SERVICE_REQUEST_CODE = 3000; + public static final int GLOBAL_NETWORK_ERROR_DIALOG_REQUEST_CODE = 7777; public static final String ACTION_SHOW_ACTIVITY = "show_activity"; public static final String ACTION_SHOW_DM_THREAD = "show_dm_thread"; diff --git a/app/src/main/java/awais/instagrabber/webservices/RetrofitFactory.java b/app/src/main/java/awais/instagrabber/webservices/RetrofitFactory.java index ce8cbfa7..71c78a4e 100644 --- a/app/src/main/java/awais/instagrabber/webservices/RetrofitFactory.java +++ b/app/src/main/java/awais/instagrabber/webservices/RetrofitFactory.java @@ -1,7 +1,5 @@ package awais.instagrabber.webservices; -import android.app.Application; - import androidx.annotation.NonNull; import com.google.gson.FieldNamingPolicy; @@ -11,9 +9,11 @@ import com.google.gson.GsonBuilder; import java.io.File; import awais.instagrabber.BuildConfig; +import awais.instagrabber.activities.MainActivity; import awais.instagrabber.repositories.responses.Caption; import awais.instagrabber.utils.Utils; import awais.instagrabber.webservices.interceptors.AddCookiesInterceptor; +import awais.instagrabber.webservices.interceptors.IgErrorsInterceptor; import okhttp3.Cache; import okhttp3.OkHttpClient; import retrofit2.Retrofit; @@ -25,7 +25,7 @@ public final class RetrofitFactory { private static RetrofitFactory instance; - private final Application application; + private final MainActivity mainActivity; private final int cacheSize = 10 * 1024 * 1024; // 10 MB private final Cache cache = new Cache(new File(Utils.cacheDir), cacheSize); @@ -33,11 +33,11 @@ public final class RetrofitFactory { private Retrofit retrofit; private Retrofit retrofitWeb; - public static void setup(@NonNull final Application application) { + public static void setup(@NonNull final MainActivity mainActivity) { if (instance == null) { synchronized (LOCK) { if (instance == null) { - instance = new RetrofitFactory(application); + instance = new RetrofitFactory(mainActivity); } } } @@ -50,20 +50,21 @@ public final class RetrofitFactory { return instance; } - private RetrofitFactory(@NonNull final Application application) { - this.application = application; + private RetrofitFactory(@NonNull final MainActivity mainActivity) { + this.mainActivity = mainActivity; } private Retrofit.Builder getRetrofitBuilder() { if (builder == null) { final OkHttpClient.Builder clientBuilder = new OkHttpClient.Builder() - .addInterceptor(new AddCookiesInterceptor()) .followRedirects(false) .followSslRedirects(false) .cache(cache); if (BuildConfig.DEBUG) { // clientBuilder.addInterceptor(new LoggingInterceptor()); } + clientBuilder.addInterceptor(new AddCookiesInterceptor()) + .addInterceptor(new IgErrorsInterceptor(mainActivity)); final Gson gson = new GsonBuilder() .setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES) .registerTypeAdapter(Caption.class, new Caption.CaptionDeserializer()) diff --git a/app/src/main/java/awais/instagrabber/webservices/interceptors/IgErrorsInterceptor.java b/app/src/main/java/awais/instagrabber/webservices/interceptors/IgErrorsInterceptor.java new file mode 100644 index 00000000..413f0e03 --- /dev/null +++ b/app/src/main/java/awais/instagrabber/webservices/interceptors/IgErrorsInterceptor.java @@ -0,0 +1,108 @@ +package awais.instagrabber.webservices.interceptors; + +import android.util.Log; + +import androidx.annotation.NonNull; +import androidx.annotation.StringRes; + +import org.json.JSONObject; + +import java.io.IOException; + +import awais.instagrabber.R; +import awais.instagrabber.activities.MainActivity; +import awais.instagrabber.dialogs.ConfirmDialogFragment; +import awais.instagrabber.utils.Constants; +import awais.instagrabber.utils.TextUtils; +import okhttp3.Interceptor; +import okhttp3.Request; +import okhttp3.Response; +import okhttp3.ResponseBody; + +public class IgErrorsInterceptor implements Interceptor { + private static final String TAG = IgErrorsInterceptor.class.getSimpleName(); + + private final MainActivity mainActivity; + + public IgErrorsInterceptor(@NonNull final MainActivity mainActivity) { + this.mainActivity = mainActivity; + } + + @NonNull + @Override + public Response intercept(@NonNull final Chain chain) throws IOException { + final Request request = chain.request(); + final Response response = chain.proceed(request); + if (response.isSuccessful()) { + return response; + } + checkError(response); + return response; + } + + private void checkError(@NonNull final Response response) { + final int errorCode = response.code(); + switch (errorCode) { + case 429: // "429 Too Many Requests" + // ('Throttled by Instagram because of too many API requests.'); + showErrorDialog(R.string.throttle_error); + return; + case 431: // "431 Request Header Fields Too Large" + // show dialog? + Log.e(TAG, "Network error: " + getMessage(errorCode, "The request start-line and/or headers are too large to process.")); + return; + } + final ResponseBody body = response.body(); + if (body == null) return; + try { + final String bodyString = body.string(); + final JSONObject jsonObject = new JSONObject(bodyString); + String message = jsonObject.optString("message", null); + if (!TextUtils.isEmpty(message)) { + message = message.toLowerCase(); + switch (message) { + case "user_has_logged_out": + showErrorDialog(R.string.account_logged_out); + return; + case "login_required": + showErrorDialog(R.string.login_required); + return; + case "not authorized to view user": // Do we handle this in profile view fragment? + case "challenge_required": // Since we make users login using browser, we should not be getting this error in api requests + default: + Log.e(TAG, "checkError: " + bodyString); + return; + } + } + final String errorType = jsonObject.optString("error_type", null); + if (TextUtils.isEmpty(errorType)) return; + if (errorType.equals("sentry_block")) { + showErrorDialog(R.string.sentry_block); + return; + } + if (errorType.equals("inactive user")) { + showErrorDialog(R.string.inactive_user); + } + } catch (Exception e) { + Log.e(TAG, "checkError: ", e); + } + } + + @NonNull + private String getMessage(final int errorCode, final String message) { + return String.format("code: %s, internalMessage: %s", errorCode, message); + } + + private void showErrorDialog(@StringRes final int messageResId) { + if (messageResId == 0) return; + final ConfirmDialogFragment dialogFragment = ConfirmDialogFragment.newInstance( + Constants.GLOBAL_NETWORK_ERROR_DIALOG_REQUEST_CODE, + R.string.error, + messageResId, + R.string.ok, + 0, + 0 + ); + dialogFragment.show(mainActivity.getSupportFragmentManager(), "network_error_dialog"); + } +} \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index f65ff8c9..af62d980 100755 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -473,4 +473,10 @@ Removed keyword: %s from filter list Marked as seen Delete unsuccessful + Throttled by Instagram because of too many API requests. Wait for some time before retrying. + Error + This account has been logged out. + Login required! + Sentry block. + User is inactive!