fix(YouTube - Announcements): Only compare ID to not show same announcement after a fix-up (#579)

Previously, the announcement content was hashed and compared with the locally saved hash. Sometimes announcements are fixed up, altering the hash, so instead, compare the ID.
This commit is contained in:
oSumAtrIX 2024-03-03 00:04:38 +01:00 committed by GitHub
parent 67673d089f
commit 5d14f53acd
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 42 additions and 43 deletions

View File

@ -6,12 +6,11 @@ import android.text.Html;
import android.text.method.LinkMovementMethod;
import android.widget.TextView;
import androidx.annotation.RequiresApi;
import app.revanced.integrations.shared.Logger;
import app.revanced.integrations.shared.Utils;
import app.revanced.integrations.youtube.patches.announcements.requests.AnnouncementsRoutes;
import app.revanced.integrations.youtube.requests.Requester;
import app.revanced.integrations.youtube.settings.Settings;
import app.revanced.integrations.shared.Logger;
import app.revanced.integrations.shared.Utils;
import org.json.JSONObject;
import java.io.IOException;
@ -49,9 +48,10 @@ public final class AnnouncementsPatch {
try {
// Do not show the announcement if the request failed.
if (connection.getResponseCode() != 200) {
if (Settings.ANNOUNCEMENT_LAST_HASH.get().isEmpty()) return;
if (Settings.ANNOUNCEMENT_LAST_ID.isSetToDefault())
return;
Settings.ANNOUNCEMENT_LAST_HASH.resetToDefault();
Settings.ANNOUNCEMENT_LAST_ID.resetToDefault();
Utils.showToastLong(str("revanced_announcements_connection_failed"));
return;
@ -65,22 +65,20 @@ public final class AnnouncementsPatch {
var jsonString = Requester.parseInputStreamAndClose(connection.getInputStream(), false);
// Do not show the announcement if it is older or the same as the last one.
final byte[] hashBytes = MessageDigest.getInstance("SHA-256").digest(jsonString.getBytes(StandardCharsets.UTF_8));
final var hash = java.util.Base64.getEncoder().encodeToString(hashBytes);
if (hash.equals(Settings.ANNOUNCEMENT_LAST_HASH.get())) return;
// Parse the announcement. Fall-back to raw string if it fails.
int id = Settings.ANNOUNCEMENT_LAST_ID.defaultValue;
String title;
String message;
Level level = Level.INFO;
try {
final var announcement = new JSONObject(jsonString);
id = announcement.getInt("id");
title = announcement.getString("title");
message = announcement.getJSONObject("content").getString("message");
if (!announcement.isNull("level")) level = Level.fromInt(announcement.getInt("level"));
} catch (Throwable ex) {
Logger.printException(() -> "Failed to parse announcement. Fall-backing to raw string", ex);
@ -88,6 +86,28 @@ public final class AnnouncementsPatch {
message = jsonString;
}
// TODO: Remove this migration code after a few months.
if (!Settings.DEPRECATED_ANNOUNCEMENT_LAST_HASH.isSetToDefault()){
final byte[] hashBytes = MessageDigest
.getInstance("SHA-256")
.digest(jsonString.getBytes(StandardCharsets.UTF_8));
final var hash = java.util.Base64.getEncoder().encodeToString(hashBytes);
// Migrate to saving the id instead of the hash.
if (hash.equals(Settings.DEPRECATED_ANNOUNCEMENT_LAST_HASH.get())) {
Settings.ANNOUNCEMENT_LAST_ID.save(id);
}
Settings.DEPRECATED_ANNOUNCEMENT_LAST_HASH.resetToDefault();
}
// Do not show the announcement, if the last announcement id is the same as the current one.
if (Settings.ANNOUNCEMENT_LAST_ID.get() == id) return;
int finalId = id;
final var finalTitle = title;
final var finalMessage = Html.fromHtml(message, FROM_HTML_MODE_COMPACT);
final Level finalLevel = level;
@ -99,7 +119,7 @@ public final class AnnouncementsPatch {
.setMessage(finalMessage)
.setIcon(finalLevel.icon)
.setPositiveButton("Ok", (dialog, which) -> {
Settings.ANNOUNCEMENT_LAST_HASH.save(hash);
Settings.ANNOUNCEMENT_LAST_ID.save(finalId);
dialog.dismiss();
}).setNegativeButton("Dismiss", (dialog, which) -> {
dialog.dismiss();
@ -119,18 +139,6 @@ public final class AnnouncementsPatch {
});
}
/**
* Clears the last announcement hash if it is not empty.
*
* @return true if the last announcement hash was empty.
*/
private static boolean emptyLastAnnouncementHash() {
if (Settings.ANNOUNCEMENT_LAST_HASH.get().isEmpty()) return true;
Settings.ANNOUNCEMENT_LAST_HASH.resetToDefault();
return false;
}
private static String getOrSetConsumer() {
final var consumer = Settings.ANNOUNCEMENT_CONSUMER.get();
if (!consumer.isEmpty()) return consumer;

View File

@ -1,29 +1,17 @@
package app.revanced.integrations.youtube.settings;
import static java.lang.Boolean.FALSE;
import static java.lang.Boolean.TRUE;
import static app.revanced.integrations.shared.settings.Setting.migrateFromOldPreferences;
import static app.revanced.integrations.shared.settings.Setting.migrateOldSettingToNew;
import static app.revanced.integrations.shared.settings.Setting.parent;
import static app.revanced.integrations.shared.settings.Setting.parentsAny;
import static app.revanced.integrations.youtube.sponsorblock.objects.CategoryBehaviour.IGNORE;
import static app.revanced.integrations.youtube.sponsorblock.objects.CategoryBehaviour.MANUAL_SKIP;
import static app.revanced.integrations.youtube.sponsorblock.objects.CategoryBehaviour.SKIP_AUTOMATICALLY;
import static app.revanced.integrations.youtube.sponsorblock.objects.CategoryBehaviour.SKIP_AUTOMATICALLY_ONCE;
import app.revanced.integrations.shared.settings.*;
import app.revanced.integrations.shared.settings.preference.SharedPrefCategory;
import app.revanced.integrations.youtube.sponsorblock.SponsorBlockSettings;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;
import app.revanced.integrations.shared.settings.BaseSettings;
import app.revanced.integrations.shared.settings.BooleanSetting;
import app.revanced.integrations.shared.settings.FloatSetting;
import app.revanced.integrations.shared.settings.IntegerSetting;
import app.revanced.integrations.shared.settings.LongSetting;
import app.revanced.integrations.shared.settings.Setting;
import app.revanced.integrations.shared.settings.StringSetting;
import app.revanced.integrations.shared.settings.preference.SharedPrefCategory;
import app.revanced.integrations.youtube.sponsorblock.SponsorBlockSettings;
import static app.revanced.integrations.shared.settings.Setting.*;
import static app.revanced.integrations.youtube.sponsorblock.objects.CategoryBehaviour.*;
import static java.lang.Boolean.FALSE;
import static java.lang.Boolean.TRUE;
public class Settings extends BaseSettings {
// External downloader
@ -205,7 +193,9 @@ public class Settings extends BaseSettings {
public static final BooleanSetting BYPASS_URL_REDIRECTS = new BooleanSetting("revanced_bypass_url_redirects", TRUE);
public static final BooleanSetting ANNOUNCEMENTS = new BooleanSetting("revanced_announcements", TRUE);
public static final StringSetting ANNOUNCEMENT_CONSUMER = new StringSetting("revanced_announcement_consumer", "", false, false);
public static final StringSetting ANNOUNCEMENT_LAST_HASH = new StringSetting("revanced_announcement_last_hash", "");
@Deprecated
public static final StringSetting DEPRECATED_ANNOUNCEMENT_LAST_HASH = new StringSetting("revanced_announcement_last_hash", "");
public static final IntegerSetting ANNOUNCEMENT_LAST_ID = new IntegerSetting("revanced_announcement_last_id", -1);
public static final BooleanSetting REMOVE_TRACKING_QUERY_PARAMETER = new BooleanSetting("revanced_remove_tracking_query_parameter", TRUE);
public static final BooleanSetting REMOVE_VIEWER_DISCRETION_DIALOG= new BooleanSetting("revanced_remove_viewer_discretion_dialog", FALSE,
"revanced_remove_viewer_discretion_dialog_user_dialog_message");
@ -245,6 +235,7 @@ public class Settings extends BaseSettings {
* Do not use directly, instead use {@link SponsorBlockSettings}
*/
public static final StringSetting SB_PRIVATE_USER_ID = new StringSetting("sb_private_user_id_Do_Not_Share", "");
@Deprecated
public static final StringSetting DEPRECATED_SB_UUID_OLD_MIGRATION_SETTING = new StringSetting("uuid", ""); // Delete sometime in 2024
public static final IntegerSetting SB_CREATE_NEW_SEGMENT_STEP = new IntegerSetting("sb_create_new_segment_step", 150, parent(SB_ENABLED));
public static final BooleanSetting SB_VOTING_BUTTON = new BooleanSetting("sb_voting_button", FALSE, parent(SB_ENABLED));