fix(YouTube - Return YouTube Dislike): Do not show error toast if API returns 401 status (#5949)

This commit is contained in:
LisoUseInAIKyrios
2025-09-21 17:20:13 +04:00
committed by GitHub
parent ece8076f7c
commit 58d088ab30
3 changed files with 55 additions and 27 deletions

View File

@@ -588,7 +588,13 @@ public class Utils {
showToast(messageToToast, Toast.LENGTH_LONG);
}
private static void showToast(String messageToToast, int toastDuration) {
/**
* Safe to call from any thread.
*
* @param messageToToast Message to show.
* @param toastDuration Either {@link Toast#LENGTH_SHORT} or {@link Toast#LENGTH_LONG}.
*/
public static void showToast(String messageToToast, int toastDuration) {
Objects.requireNonNull(messageToToast);
runOnMainThreadNowOrLater(() -> {
Context currentContext = context;

View File

@@ -21,6 +21,7 @@ import android.text.Spanned;
import android.text.style.ForegroundColorSpan;
import android.text.style.ImageSpan;
import android.text.style.ReplacementSpan;
import android.widget.Toast;
import androidx.annotation.GuardedBy;
import androidx.annotation.NonNull;
@@ -507,6 +508,11 @@ public class ReturnYouTubeDislike {
try {
RYDVoteData votingData = getFetchData(MAX_MILLISECONDS_TO_BLOCK_UI_WAITING_FOR_FETCH);
if (votingData == null) {
// Method automatically prevents showing multiple toasts if the connection failed.
// This call is needed here in case the api call did succeed but took too long.
ReturnYouTubeDislikeApi.handleConnectionError(
str("revanced_ryd_failure_connection_timeout"),
null, null, Toast.LENGTH_SHORT);
Logger.printDebug(() -> "Cannot add dislike to UI (RYD data not available)");
return original;
}

View File

@@ -4,8 +4,8 @@ import static app.revanced.extension.shared.StringRef.str;
import static app.revanced.extension.youtube.returnyoutubedislike.requests.ReturnYouTubeDislikeRoutes.getRYDConnectionFromRoute;
import android.util.Base64;
import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import org.json.JSONException;
@@ -30,15 +30,15 @@ import app.revanced.extension.youtube.settings.Settings;
public class ReturnYouTubeDislikeApi {
/**
* {@link #fetchVotes(String)} TCP connection timeout
* {@link #fetchVotes(String)} TCP connection timeout.
*/
private static final int API_GET_VOTES_TCP_TIMEOUT_MILLISECONDS = 2 * 1000; // 2 Seconds.
private static final int API_GET_VOTES_TCP_TIMEOUT_MILLISECONDS = 3 * 1000; // 3 Seconds.
/**
* {@link #fetchVotes(String)} HTTP read timeout.
* To locally debug and force timeouts, change this to a very small number (ie: 100)
*/
private static final int API_GET_VOTES_HTTP_TIMEOUT_MILLISECONDS = 4 * 1000; // 4 Seconds.
private static final int API_GET_VOTES_HTTP_TIMEOUT_MILLISECONDS = 7 * 1000; // 7 Seconds.
/**
* Default connection and response timeout for voting and registration.
@@ -53,6 +53,15 @@ public class ReturnYouTubeDislikeApi {
*/
private static final int HTTP_STATUS_CODE_SUCCESS = 200;
/**
* RYD API sometimes returns 401 (authorization error), even though the user id is valid.
* There is no known fix for this (resetting to a different user id does not fix it),
* so instead just quietly ignore the error.
*
* See <a href="https://github.com/Anarios/return-youtube-dislike/issues/1153">RYD bug report</a>.
*/
private static final int HTTP_STATUS_CODE_UNAUTHORIZED = 401;
/**
* Indicates a client rate limit has been reached and the client must back off.
*/
@@ -232,14 +241,20 @@ public class ReturnYouTubeDislikeApi {
}
}
private static void handleConnectionError(@NonNull String toastMessage,
/**
* @param toastDuration Either {@link Toast#LENGTH_SHORT} or {@link Toast#LENGTH_LONG}.
*/
public static void handleConnectionError(String toastMessage,
@Nullable Integer responseCode,
@Nullable Exception ex,
boolean showLongToast) {
@Nullable Integer toastDuration) {
if (!lastApiCallFailed && Settings.RYD_TOAST_ON_CONNECTION_ERROR.get()) {
if (showLongToast) {
Utils.showToastLong(toastMessage);
} else {
Utils.showToastShort(toastMessage);
if (responseCode != null && responseCode == HTTP_STATUS_CODE_UNAUTHORIZED) {
Logger.printInfo(() -> "Ignoring status code " + HTTP_STATUS_CODE_UNAUTHORIZED
+ " (API authorization erorr)");
return; // Do not set api failure field.
} else if (toastDuration != null) {
Utils.showToast(toastMessage, toastDuration);
}
}
lastApiCallFailed = true;
@@ -297,13 +312,13 @@ public class ReturnYouTubeDislikeApi {
} else {
// Unexpected response code. Most likely RYD is temporarily broken.
handleConnectionError(str("revanced_ryd_failure_connection_status_code", responseCode),
null, true);
responseCode, null, Toast.LENGTH_LONG);
}
connection.disconnect(); // Something went wrong, might as well disconnect.
} catch (SocketTimeoutException ex) {
handleConnectionError((str("revanced_ryd_failure_connection_timeout")), ex, false);
handleConnectionError((str("revanced_ryd_failure_connection_timeout")), null, ex, Toast.LENGTH_SHORT);
} catch (IOException ex) {
handleConnectionError((str("revanced_ryd_failure_generic", ex.getMessage())), ex, true);
handleConnectionError((str("revanced_ryd_failure_generic", ex.getMessage())), null, ex, Toast.LENGTH_LONG);
} catch (Exception ex) {
// should never happen
Logger.printException(() -> "fetchVotes failure", ex);
@@ -344,13 +359,14 @@ public class ReturnYouTubeDislikeApi {
String solution = solvePuzzle(challenge, difficulty);
return confirmRegistration(userId, solution);
}
handleConnectionError(str("revanced_ryd_failure_connection_status_code", responseCode),
null, true);
responseCode, null, Toast.LENGTH_LONG);
connection.disconnect();
} catch (SocketTimeoutException ex) {
handleConnectionError(str("revanced_ryd_failure_connection_timeout"), ex, false);
handleConnectionError(str("revanced_ryd_failure_connection_timeout"), null, ex, Toast.LENGTH_SHORT);
} catch (IOException ex) {
handleConnectionError(str("revanced_ryd_failure_generic", "registration failed"), ex, true);
handleConnectionError(str("revanced_ryd_failure_generic", "registration failed"), null, ex, Toast.LENGTH_LONG);
} catch (Exception ex) {
Logger.printException(() -> "Failed to register user", ex); // should never happen
}
@@ -393,12 +409,12 @@ public class ReturnYouTubeDislikeApi {
Logger.printInfo(() -> "Failed to confirm registration for user: " + userId
+ " solution: " + solution + " responseCode: " + responseCode + " response: '" + response + "''");
handleConnectionError(str("revanced_ryd_failure_connection_status_code", responseCode),
null, true);
responseCode, null, Toast.LENGTH_LONG);
} catch (SocketTimeoutException ex) {
handleConnectionError(str("revanced_ryd_failure_connection_timeout"), ex, false);
handleConnectionError(str("revanced_ryd_failure_connection_timeout"), null, ex, Toast.LENGTH_SHORT);
} catch (IOException ex) {
handleConnectionError(str("revanced_ryd_failure_generic", "confirm registration failed"),
ex, true);
null, ex, Toast.LENGTH_LONG);
} catch (Exception ex) {
Logger.printException(() -> "Failed to confirm registration for user: " + userId
+ "solution: " + solution, ex);
@@ -469,12 +485,12 @@ public class ReturnYouTubeDislikeApi {
Logger.printInfo(() -> "Failed to send vote for video: " + videoId + " vote: " + vote
+ " response code was: " + responseCode);
handleConnectionError(str("revanced_ryd_failure_connection_status_code", responseCode),
null, true);
responseCode, null, Toast.LENGTH_LONG);
connection.disconnect(); // something went wrong, might as well disconnect
} catch (SocketTimeoutException ex) {
handleConnectionError(str("revanced_ryd_failure_connection_timeout"), ex, false);
handleConnectionError(str("revanced_ryd_failure_connection_timeout"), null, ex, Toast.LENGTH_SHORT);
} catch (IOException ex) {
handleConnectionError(str("revanced_ryd_failure_generic", "send vote failed"), ex, true);
handleConnectionError(str("revanced_ryd_failure_generic", "send vote failed"), null, ex, Toast.LENGTH_LONG);
} catch (Exception ex) {
// should never happen
Logger.printException(() -> "Failed to send vote for video: " + videoId + " vote: " + vote, ex);
@@ -518,12 +534,12 @@ public class ReturnYouTubeDislikeApi {
Logger.printInfo(() -> "Failed to confirm vote for video: " + videoId
+ " solution: " + solution + " responseCode: " + responseCode + " response: '" + response + "'");
handleConnectionError(str("revanced_ryd_failure_connection_status_code", responseCode),
null, true);
responseCode, null, Toast.LENGTH_LONG);
} catch (SocketTimeoutException ex) {
handleConnectionError(str("revanced_ryd_failure_connection_timeout"), ex, false);
handleConnectionError(str("revanced_ryd_failure_connection_timeout"), null, ex, Toast.LENGTH_SHORT);
} catch (IOException ex) {
handleConnectionError(str("revanced_ryd_failure_generic", "confirm vote failed"),
ex, true);
null, ex, Toast.LENGTH_LONG);
} catch (Exception ex) {
Logger.printException(() -> "Failed to confirm vote for video: " + videoId
+ " solution: " + solution, ex); // should never happen