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); 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); Objects.requireNonNull(messageToToast);
runOnMainThreadNowOrLater(() -> { runOnMainThreadNowOrLater(() -> {
Context currentContext = context; Context currentContext = context;

View File

@@ -21,6 +21,7 @@ import android.text.Spanned;
import android.text.style.ForegroundColorSpan; import android.text.style.ForegroundColorSpan;
import android.text.style.ImageSpan; import android.text.style.ImageSpan;
import android.text.style.ReplacementSpan; import android.text.style.ReplacementSpan;
import android.widget.Toast;
import androidx.annotation.GuardedBy; import androidx.annotation.GuardedBy;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
@@ -507,6 +508,11 @@ public class ReturnYouTubeDislike {
try { try {
RYDVoteData votingData = getFetchData(MAX_MILLISECONDS_TO_BLOCK_UI_WAITING_FOR_FETCH); RYDVoteData votingData = getFetchData(MAX_MILLISECONDS_TO_BLOCK_UI_WAITING_FOR_FETCH);
if (votingData == null) { 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)"); Logger.printDebug(() -> "Cannot add dislike to UI (RYD data not available)");
return original; 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 static app.revanced.extension.youtube.returnyoutubedislike.requests.ReturnYouTubeDislikeRoutes.getRYDConnectionFromRoute;
import android.util.Base64; import android.util.Base64;
import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import org.json.JSONException; import org.json.JSONException;
@@ -30,15 +30,15 @@ import app.revanced.extension.youtube.settings.Settings;
public class ReturnYouTubeDislikeApi { 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. * {@link #fetchVotes(String)} HTTP read timeout.
* To locally debug and force timeouts, change this to a very small number (ie: 100) * 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. * 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; 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. * 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, @Nullable Exception ex,
boolean showLongToast) { @Nullable Integer toastDuration) {
if (!lastApiCallFailed && Settings.RYD_TOAST_ON_CONNECTION_ERROR.get()) { if (!lastApiCallFailed && Settings.RYD_TOAST_ON_CONNECTION_ERROR.get()) {
if (showLongToast) { if (responseCode != null && responseCode == HTTP_STATUS_CODE_UNAUTHORIZED) {
Utils.showToastLong(toastMessage); Logger.printInfo(() -> "Ignoring status code " + HTTP_STATUS_CODE_UNAUTHORIZED
} else { + " (API authorization erorr)");
Utils.showToastShort(toastMessage); return; // Do not set api failure field.
} else if (toastDuration != null) {
Utils.showToast(toastMessage, toastDuration);
} }
} }
lastApiCallFailed = true; lastApiCallFailed = true;
@@ -297,13 +312,13 @@ public class ReturnYouTubeDislikeApi {
} else { } else {
// Unexpected response code. Most likely RYD is temporarily broken. // Unexpected response code. Most likely RYD is temporarily broken.
handleConnectionError(str("revanced_ryd_failure_connection_status_code", 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. connection.disconnect(); // Something went wrong, might as well disconnect.
} catch (SocketTimeoutException ex) { } 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) { } 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) { } catch (Exception ex) {
// should never happen // should never happen
Logger.printException(() -> "fetchVotes failure", ex); Logger.printException(() -> "fetchVotes failure", ex);
@@ -344,13 +359,14 @@ public class ReturnYouTubeDislikeApi {
String solution = solvePuzzle(challenge, difficulty); String solution = solvePuzzle(challenge, difficulty);
return confirmRegistration(userId, solution); return confirmRegistration(userId, solution);
} }
handleConnectionError(str("revanced_ryd_failure_connection_status_code", responseCode), handleConnectionError(str("revanced_ryd_failure_connection_status_code", responseCode),
null, true); responseCode, null, Toast.LENGTH_LONG);
connection.disconnect(); connection.disconnect();
} catch (SocketTimeoutException ex) { } 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) { } 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) { } catch (Exception ex) {
Logger.printException(() -> "Failed to register user", ex); // should never happen 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 Logger.printInfo(() -> "Failed to confirm registration for user: " + userId
+ " solution: " + solution + " responseCode: " + responseCode + " response: '" + response + "''"); + " solution: " + solution + " responseCode: " + responseCode + " response: '" + response + "''");
handleConnectionError(str("revanced_ryd_failure_connection_status_code", responseCode), handleConnectionError(str("revanced_ryd_failure_connection_status_code", responseCode),
null, true); responseCode, null, Toast.LENGTH_LONG);
} catch (SocketTimeoutException ex) { } 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) { } catch (IOException ex) {
handleConnectionError(str("revanced_ryd_failure_generic", "confirm registration failed"), handleConnectionError(str("revanced_ryd_failure_generic", "confirm registration failed"),
ex, true); null, ex, Toast.LENGTH_LONG);
} catch (Exception ex) { } catch (Exception ex) {
Logger.printException(() -> "Failed to confirm registration for user: " + userId Logger.printException(() -> "Failed to confirm registration for user: " + userId
+ "solution: " + solution, ex); + "solution: " + solution, ex);
@@ -469,12 +485,12 @@ public class ReturnYouTubeDislikeApi {
Logger.printInfo(() -> "Failed to send vote for video: " + videoId + " vote: " + vote Logger.printInfo(() -> "Failed to send vote for video: " + videoId + " vote: " + vote
+ " response code was: " + responseCode); + " response code was: " + responseCode);
handleConnectionError(str("revanced_ryd_failure_connection_status_code", 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 connection.disconnect(); // something went wrong, might as well disconnect
} catch (SocketTimeoutException ex) { } 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) { } 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) { } catch (Exception ex) {
// should never happen // should never happen
Logger.printException(() -> "Failed to send vote for video: " + videoId + " vote: " + vote, ex); 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 Logger.printInfo(() -> "Failed to confirm vote for video: " + videoId
+ " solution: " + solution + " responseCode: " + responseCode + " response: '" + response + "'"); + " solution: " + solution + " responseCode: " + responseCode + " response: '" + response + "'");
handleConnectionError(str("revanced_ryd_failure_connection_status_code", responseCode), handleConnectionError(str("revanced_ryd_failure_connection_status_code", responseCode),
null, true); responseCode, null, Toast.LENGTH_LONG);
} catch (SocketTimeoutException ex) { } 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) { } catch (IOException ex) {
handleConnectionError(str("revanced_ryd_failure_generic", "confirm vote failed"), handleConnectionError(str("revanced_ryd_failure_generic", "confirm vote failed"),
ex, true); null, ex, Toast.LENGTH_LONG);
} catch (Exception ex) { } catch (Exception ex) {
Logger.printException(() -> "Failed to confirm vote for video: " + videoId Logger.printException(() -> "Failed to confirm vote for video: " + videoId
+ " solution: " + solution, ex); // should never happen + " solution: " + solution, ex); // should never happen