feat(youtube): add options to disable toasts on connection errors (#402)

Co-authored-by: oSumAtrIX <johan.melkonyan1@web.de>
This commit is contained in:
LisoUseInAIKyrios 2023-05-16 10:28:35 +04:00 committed by GitHub
parent 4acbccd947
commit ae18edd047
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 111 additions and 32 deletions

View File

@ -5,11 +5,13 @@ import static app.revanced.integrations.utils.StringRef.str;
import android.util.Base64;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.IOException;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.ProtocolException;
@ -22,6 +24,7 @@ import java.util.Objects;
import app.revanced.integrations.requests.Requester;
import app.revanced.integrations.returnyoutubedislike.ReturnYouTubeDislike;
import app.revanced.integrations.settings.SettingsEnum;
import app.revanced.integrations.utils.LogHelper;
import app.revanced.integrations.utils.ReVancedUtils;
@ -219,6 +222,15 @@ public class ReturnYouTubeDislikeApi {
}
}
private static void handleConnectionError(@NonNull String toastMessage, @Nullable Exception ex) {
if (SettingsEnum.RYD_TOAST_ON_CONNECTION_ERROR.getBoolean()) {
ReVancedUtils.showToastShort(toastMessage);
}
if (ex != null) {
LogHelper.printInfo(() -> toastMessage, ex);
}
}
/**
* @return NULL if fetch failed, or if a rate limit is in effect.
*/
@ -272,12 +284,13 @@ public class ReturnYouTubeDislikeApi {
LogHelper.printDebug(() -> "Video has no like/dislikes (video is a YouTube Story?): " + videoId);
return null; // do not updated connection statistics
} else {
LogHelper.printException(() -> "Failed to fetch votes for video: " + videoId + " response code was: " + responseCode,
null, str("revanced_ryd_failure_connection_status_code", responseCode));
connection.disconnect(); // something went wrong, might as well disconnect
handleConnectionError(str("revanced_ryd_failure_connection_status_code", responseCode), null);
}
connection.disconnect(); // something went wrong, might as well disconnect
} catch (SocketTimeoutException ex) { // connection timed out, response timeout, or some other network error
LogHelper.printException(() -> "Failed to fetch votes", ex, str("revanced_ryd_failure_connection_timeout"));
handleConnectionError((str("revanced_ryd_failure_connection_timeout")), ex);
} catch (IOException ex) {
handleConnectionError((str("revanced_ryd_failure_generic", ex.getMessage())), ex);
} catch (Exception ex) {
// should never happen
LogHelper.printException(() -> "Failed to fetch votes", ex, str("revanced_ryd_failure_generic", ex.getMessage()));
@ -318,11 +331,14 @@ public class ReturnYouTubeDislikeApi {
String solution = solvePuzzle(challenge, difficulty);
return confirmRegistration(userId, solution);
}
LogHelper.printException(() -> "Failed to register new user: " + userId
+ " response code was: " + responseCode); // failed attempt, and ok to log userId
handleConnectionError(str("revanced_ryd_failure_connection_status_code", responseCode), null);
connection.disconnect();
} catch (SocketTimeoutException ex) {
handleConnectionError(str("revanced_ryd_failure_connection_timeout"), ex);
} catch (IOException ex) {
handleConnectionError(str("revanced_ryd_failure_generic", "registration failed"), ex);
} catch (Exception ex) {
LogHelper.printException(() -> "Failed to register user", ex);
LogHelper.printException(() -> "Failed to register user", ex); // should never happen
}
return null;
}
@ -351,19 +367,23 @@ public class ReturnYouTubeDislikeApi {
connection.disconnect(); // disconnect, as no more connections will be made for a little while
return null;
}
String result = null;
if (responseCode == HTTP_STATUS_CODE_SUCCESS) {
String result = Requester.parseJson(connection);
result = Requester.parseJson(connection);
if (result.equalsIgnoreCase("true")) {
LogHelper.printDebug(() -> "Registration confirmation successful");
return userId;
}
LogHelper.printException(() -> "Failed to confirm registration for user: " + userId
+ " solution: " + solution + " response string was: " + result);
} else {
LogHelper.printException(() -> "Failed to confirm registration for user: " + userId
+ " solution: " + solution + " response code was: " + responseCode);
}
final String resultLog = result == null ? "(no response)" : result;
LogHelper.printInfo(() -> "Failed to confirm registration for user: " + userId
+ " solution: " + solution + " responseCode: " + responseCode + " responseString: " + resultLog);
handleConnectionError(str("revanced_ryd_failure_connection_status_code", responseCode), null);
connection.disconnect(); // something went wrong, might as well disconnect
} catch (SocketTimeoutException ex) {
handleConnectionError(str("revanced_ryd_failure_connection_timeout"), ex);
} catch (IOException ex) {
handleConnectionError(str("revanced_ryd_failure_generic", "confirm registration failed"), ex);
} catch (Exception ex) {
LogHelper.printException(() -> "Failed to confirm registration for user: " + userId
+ "solution: " + solution, ex);
@ -405,10 +425,16 @@ public class ReturnYouTubeDislikeApi {
String solution = solvePuzzle(challenge, difficulty);
return confirmVote(videoId, userId, solution);
}
LogHelper.printException(() -> "Failed to send vote for video: " + videoId
+ " vote: " + vote + " response code was: " + responseCode);
LogHelper.printInfo(() -> "Failed to send vote for video: " + videoId + " vote: " + vote
+ " response code was: " + responseCode);
handleConnectionError(str("revanced_ryd_failure_connection_status_code", responseCode), null);
connection.disconnect(); // something went wrong, might as well disconnect
} catch (SocketTimeoutException ex) {
handleConnectionError(str("revanced_ryd_failure_connection_timeout"), ex);
} catch (IOException ex) {
handleConnectionError(str("revanced_ryd_failure_generic", "send vote failed"), ex);
} catch (Exception ex) {
// should never happen
LogHelper.printException(() -> "Failed to send vote for video: " + videoId + " vote: " + vote, ex);
}
return false;
@ -438,23 +464,26 @@ public class ReturnYouTubeDislikeApi {
connection.disconnect(); // disconnect, as no more connections will be made for a little while
return false;
}
String result = null;
if (responseCode == HTTP_STATUS_CODE_SUCCESS) {
String result = Requester.parseJson(connection);
result = Requester.parseJson(connection);
if (result.equalsIgnoreCase("true")) {
LogHelper.printDebug(() -> "Vote confirm successful for video: " + videoId);
return true;
}
LogHelper.printException(() -> "Failed to confirm vote for video: " + videoId
+ " solution: " + solution + " response string was: " + result);
} else {
LogHelper.printException(() -> "Failed to confirm vote for video: " + videoId
+ " solution: " + solution + " response code was: " + responseCode);
}
final String resultLog = result == null ? "(no response)" : result;
LogHelper.printInfo(() -> "Failed to confirm vote for video: " + videoId
+ " solution: " + solution + " responseCode: " + responseCode + " responseString: " + resultLog);
handleConnectionError(str("revanced_ryd_failure_connection_status_code", responseCode), null);
connection.disconnect(); // something went wrong, might as well disconnect
} catch (SocketTimeoutException ex) {
handleConnectionError(str("revanced_ryd_failure_connection_timeout"), ex);
} catch (IOException ex) {
handleConnectionError(str("revanced_ryd_failure_generic", "confirm vote failed"), ex);
} catch (Exception ex) {
LogHelper.printException(() -> "Failed to confirm vote for video: " + videoId
+ " solution: " + solution, ex);
+ " solution: " + solution, ex); // should never happen
}
return false;
}
@ -503,7 +532,7 @@ public class ReturnYouTubeDislikeApi {
}
// should never be reached
throw new IllegalStateException("Failed to solve puzzle challenge: " + challenge + " of difficulty: " + difficulty);
throw new IllegalStateException("Failed to solve puzzle challenge: " + challenge + " difficulty: " + difficulty);
}
// https://stackoverflow.com/a/157202
@ -519,9 +548,8 @@ public class ReturnYouTubeDislikeApi {
private static int countLeadingZeroes(byte[] uInt8View) {
int zeroes = 0;
int value;
for (byte b : uInt8View) {
value = b & 0xFF;
int value = b & 0xFF;
if (value == 0) {
zeroes += 8;
} else {

View File

@ -169,6 +169,7 @@ public enum SettingsEnum {
RYD_SHORTS("ryd_shorts", BOOLEAN, TRUE, RETURN_YOUTUBE_DISLIKE, parents(RYD_ENABLED)),
RYD_DISLIKE_PERCENTAGE("ryd_dislike_percentage", BOOLEAN, FALSE, RETURN_YOUTUBE_DISLIKE, parents(RYD_ENABLED)),
RYD_COMPACT_LAYOUT("ryd_compact_layout", BOOLEAN, FALSE, RETURN_YOUTUBE_DISLIKE, parents(RYD_ENABLED)),
RYD_TOAST_ON_CONNECTION_ERROR("ryd_toast_on_connection_error", BOOLEAN, TRUE, RETURN_YOUTUBE_DISLIKE, parents(RYD_ENABLED)),
// SponsorBlock
SB_ENABLED("sb_enabled", BOOLEAN, TRUE, SPONSOR_BLOCK),
@ -180,6 +181,7 @@ public enum SettingsEnum {
SB_COMPACT_SKIP_BUTTON("sb_compact_skip_button", BOOLEAN, FALSE, SPONSOR_BLOCK, parents(SB_ENABLED)),
SB_AUTO_HIDE_SKIP_BUTTON("sb_auto_hide_skip_button", BOOLEAN, TRUE, SPONSOR_BLOCK, parents(SB_ENABLED)),
SB_TOAST_ON_SKIP("sb_toast_on_skip", BOOLEAN, TRUE, SPONSOR_BLOCK, parents(SB_ENABLED)),
SB_TOAST_ON_CONNECTION_ERROR("sb_toast_on_connection_error", BOOLEAN, TRUE, SPONSOR_BLOCK, parents(SB_ENABLED)),
SB_TRACK_SKIP_COUNT("sb_track_skip_count", BOOLEAN, TRUE, SPONSOR_BLOCK, parents(SB_ENABLED)),
SB_SEGMENT_MIN_DURATION("sb_min_segment_duration", FLOAT, 0F, SPONSOR_BLOCK, parents(SB_ENABLED)),
SB_VIDEO_LENGTH_WITHOUT_SEGMENTS("sb_video_length_without_segments", BOOLEAN, TRUE, SPONSOR_BLOCK, parents(SB_ENABLED)),

View File

@ -34,10 +34,16 @@ public class ReturnYouTubeDislikeSettingsFragment extends PreferenceFragment {
*/
private SwitchPreference compactLayoutPreference;
/**
* If segmented like/dislike button uses smaller compact layout.
*/
private SwitchPreference toastOnRYDNotAvailable;
private void updateUIState() {
shortsPreference.setEnabled(SettingsEnum.RYD_SHORTS.isAvailable());
percentagePreference.setEnabled(SettingsEnum.RYD_DISLIKE_PERCENTAGE.isAvailable());
compactLayoutPreference.setEnabled(SettingsEnum.RYD_COMPACT_LAYOUT.isAvailable());
toastOnRYDNotAvailable.setEnabled(SettingsEnum.RYD_TOAST_ON_CONNECTION_ERROR.isAvailable());
}
@Override
@ -102,6 +108,18 @@ public class ReturnYouTubeDislikeSettingsFragment extends PreferenceFragment {
});
preferenceScreen.addPreference(compactLayoutPreference);
toastOnRYDNotAvailable = new SwitchPreference(context);
toastOnRYDNotAvailable.setChecked(SettingsEnum.RYD_TOAST_ON_CONNECTION_ERROR.getBoolean());
toastOnRYDNotAvailable.setTitle(str("ryd_toast_on_connection_error_title"));
toastOnRYDNotAvailable.setSummaryOn(str("ryd_toast_on_connection_error_summary_on"));
toastOnRYDNotAvailable.setSummaryOff(str("ryd_toast_on_connection_error_summary_off"));
toastOnRYDNotAvailable.setOnPreferenceChangeListener((pref, newValue) -> {
SettingsEnum.RYD_TOAST_ON_CONNECTION_ERROR.saveValue(newValue);
updateUIState();
return true;
});
preferenceScreen.addPreference(toastOnRYDNotAvailable);
updateUIState();

View File

@ -52,6 +52,7 @@ public class SponsorBlockSettingsFragment extends PreferenceFragment {
private SwitchPreference showSkipToast;
private SwitchPreference trackSkips;
private SwitchPreference showTimeWithoutSegments;
private SwitchPreference toastOnConnectionError;
private EditTextPreference newSegmentStep;
private EditTextPreference minSegmentDuration;
@ -90,6 +91,9 @@ public class SponsorBlockSettingsFragment extends PreferenceFragment {
showSkipToast.setChecked(SettingsEnum.SB_TOAST_ON_SKIP.getBoolean());
showSkipToast.setEnabled(enabled);
toastOnConnectionError.setChecked(SettingsEnum.SB_TOAST_ON_CONNECTION_ERROR.getBoolean());
toastOnConnectionError.setEnabled(enabled);
trackSkips.setChecked(SettingsEnum.SB_TRACK_SKIP_COUNT.getBoolean());
trackSkips.setEnabled(enabled);
@ -283,6 +287,17 @@ public class SponsorBlockSettingsFragment extends PreferenceFragment {
screen.addPreference(category);
category.setTitle(str("sb_general"));
toastOnConnectionError = new SwitchPreference(context);
toastOnConnectionError.setTitle(str("sb_toast_on_connection_error_title"));
toastOnConnectionError.setSummaryOn(str("sb_toast_on_connection_error_summary_on"));
toastOnConnectionError.setSummaryOff(str("sb_toast_on_connection_error_summary_off"));
toastOnConnectionError.setOnPreferenceChangeListener((preference1, newValue) -> {
SettingsEnum.SB_TOAST_ON_CONNECTION_ERROR.saveValue(newValue);
updateUI();
return true;
});
category.addPreference(toastOnConnectionError);
trackSkips = new SwitchPreference(context);
trackSkips.setTitle(str("sb_general_skipcount"));
trackSkips.setSummaryOn(str("sb_general_skipcount_sum_on"));

View File

@ -49,6 +49,15 @@ public class SBRequester {
private SBRequester() {
}
private static void handleConnectionError(@NonNull String toastMessage, @Nullable Exception ex) {
if (SettingsEnum.SB_TOAST_ON_CONNECTION_ERROR.getBoolean()) {
ReVancedUtils.showToastShort(toastMessage);
}
if (ex != null) {
LogHelper.printInfo(() -> toastMessage, ex);
}
}
@NonNull
public static SponsorSegment[] getSegments(@NonNull String videoId) {
ReVancedUtils.verifyOffMainThread();
@ -88,14 +97,16 @@ public class SBRequester {
// no segments are found. a normal response
LogHelper.printDebug(() -> "No segments found for video: " + videoId);
} else {
LogHelper.printException(() -> "getSegments failed with response code: " + responseCode,
null, str("sb_sponsorblock_connection_failure_status", responseCode));
handleConnectionError(str("sb_sponsorblock_connection_failure_status", responseCode), null);
connection.disconnect(); // something went wrong, might as well disconnect
}
} catch (SocketTimeoutException ex) {
LogHelper.printException(() -> "Failed to get segments", ex, str("sb_sponsorblock_connection_failure_timeout"));
handleConnectionError(str("sb_sponsorblock_connection_failure_timeout"), ex);
} catch (IOException ex) {
handleConnectionError(str("sb_sponsorblock_connection_failure_generic"), ex);
} catch (Exception ex) {
LogHelper.printException(() -> "Failed to get segments", ex, str("sb_sponsorblock_connection_failure_generic"));
// Should never happen
LogHelper.printException(() -> "getSegments failure", ex);
}
// Crude debug tests to verify random features
@ -162,7 +173,10 @@ public class SBRequester {
}
ReVancedUtils.showToastLong(messageToToast);
} catch (SocketTimeoutException ex) {
// Always show, even if show connection toasts is turned off
ReVancedUtils.showToastLong(str("sb_submit_failed_timeout"));
} catch (IOException ex) {
ReVancedUtils.showToastLong(str("sb_submit_failed_unknown_error", 0, ex.getMessage()));
} catch (Exception ex) {
LogHelper.printException(() -> "failed to submit segments", ex);
}
@ -217,7 +231,9 @@ public class SBRequester {
break;
}
} catch (SocketTimeoutException ex) {
LogHelper.printException(() -> "failed to vote for segment", ex, str("sb_vote_failed_timeout"));
ReVancedUtils.showToastShort(str("sb_vote_failed_timeout"));
} catch (IOException ex) {
ReVancedUtils.showToastShort(str("sb_vote_failed_unknown_error", 0, ex.getMessage()));
} catch (Exception ex) {
LogHelper.printException(() -> "failed to vote for segment", ex); // should never happen
}
@ -264,7 +280,7 @@ public class SBRequester {
public static void runVipCheckInBackgroundIfNeeded() {
if (!SponsorBlockSettings.userHasSBPrivateId()) {
return; // User cannot be a VIP. User has never voted, created any segments, and has not import any SB settings.
return; // User cannot be a VIP. User has never voted, created any segments, or has imported a SB user id.
}
long now = System.currentTimeMillis();
if (now < (SettingsEnum.SB_LAST_VIP_CHECK.getLong() + TimeUnit.DAYS.toMillis(3))) {