From a05386e8bc24c085b5c74f3674c402c5dd5ad468 Mon Sep 17 00:00:00 2001 From: oSumAtrIX Date: Tue, 17 Mar 2026 13:16:40 +0100 Subject: [PATCH] feat(Announcements): Support ReVanced API v5 announcements --- .../announcements/AnnouncementsPatch.java | 55 ++++++++++++++++--- .../requests/AnnouncementsRoutes.java | 6 +- 2 files changed, 50 insertions(+), 11 deletions(-) diff --git a/extensions/youtube/src/main/java/app/revanced/extension/youtube/patches/announcements/AnnouncementsPatch.java b/extensions/youtube/src/main/java/app/revanced/extension/youtube/patches/announcements/AnnouncementsPatch.java index 1212416069..8e24d65ec5 100644 --- a/extensions/youtube/src/main/java/app/revanced/extension/youtube/patches/announcements/AnnouncementsPatch.java +++ b/extensions/youtube/src/main/java/app/revanced/extension/youtube/patches/announcements/AnnouncementsPatch.java @@ -14,7 +14,9 @@ import android.widget.LinearLayout; import android.widget.TextView; import app.revanced.extension.shared.ui.CustomDialog; + import org.json.JSONArray; +import org.json.JSONObject; import java.io.IOException; import java.net.HttpURLConnection; @@ -29,9 +31,20 @@ import app.revanced.extension.youtube.settings.Settings; @SuppressWarnings("unused") public final class AnnouncementsPatch { + private static final String[] ANNOUNCEMENT_TAGS = { + "\uD83C\uDF9E\uFE0F YouTube", + }; + private AnnouncementsPatch() { } + private static boolean hasSupportedTag(String wrapperTag) { + if (wrapperTag == null) return false; + for (var tag : ANNOUNCEMENT_TAGS) if (tag.equals(wrapperTag)) return true; + + return false; + } + private static boolean isLatestAlready() throws IOException { HttpURLConnection connection = AnnouncementsRoutes.getAnnouncementsConnectionFromRoute(GET_LATEST_ANNOUNCEMENT_IDS); @@ -56,19 +69,30 @@ public final class AnnouncementsPatch { var jsonString = Requester.parseStringAndDisconnect(connection); - // Parse the ID. Fall-back to raw string if it fails. - int id = Settings.ANNOUNCEMENT_LAST_ID.defaultValue; + var id = -1; try { - final var announcementIDs = new JSONArray(jsonString); - if (announcementIDs.length() == 0) return true; - - id = announcementIDs.getJSONObject(0).getInt("id"); + final var announcementIDTagPairs = new JSONArray(jsonString); + if (announcementIDTagPairs.length() == 0) return true; + + JSONObject latest = null; + for (int i = 0, entryCount = announcementIDTagPairs.length(); i < entryCount; i++) { + var pair = announcementIDTagPairs.optJSONObject(i); + if (pair != null && hasSupportedTag(pair.optString("tag", null))) { + latest = pair; + break; + } + } + + if (latest == null || latest.isNull("id")) return true; + + id = latest.getInt("id"); } catch (Throwable ex) { Logger.printException(() -> "Failed to parse announcement ID", ex); + return true; } // Do not show the announcement, if the last announcement id is the same as the current one. - return Settings.ANNOUNCEMENT_LAST_ID.get() == id; + return Settings.ANNOUNCEMENT_LAST_ID.get().equals(id); } public static void showAnnouncement(final Activity context) { @@ -95,7 +119,22 @@ public final class AnnouncementsPatch { LocalDateTime archivedAt = LocalDateTime.MAX; Level level = Level.INFO; try { - final var announcement = new JSONArray(jsonString).getJSONObject(0); + final var announcements = new JSONArray(jsonString); + JSONObject latestAnnouncement = null; + for (int i = 0, entryCount = announcements.length(); i < entryCount; i++) { + var announcementTagPair = announcements.optJSONObject(i); + if (announcementTagPair != null && hasSupportedTag(announcementTagPair.optString("tag", null))) { + latestAnnouncement = announcementTagPair; + break; + } + } + + if (latestAnnouncement == null || latestAnnouncement.isNull("announcement")) { + Logger.printDebug(() -> "No YouTube announcement found in latest announcements response"); + return; + } + + final var announcement = latestAnnouncement.getJSONObject("announcement"); id = announcement.getInt("id"); title = announcement.getString("title"); diff --git a/extensions/youtube/src/main/java/app/revanced/extension/youtube/patches/announcements/requests/AnnouncementsRoutes.java b/extensions/youtube/src/main/java/app/revanced/extension/youtube/patches/announcements/requests/AnnouncementsRoutes.java index d89a2d3403..aa63ae864c 100644 --- a/extensions/youtube/src/main/java/app/revanced/extension/youtube/patches/announcements/requests/AnnouncementsRoutes.java +++ b/extensions/youtube/src/main/java/app/revanced/extension/youtube/patches/announcements/requests/AnnouncementsRoutes.java @@ -9,9 +9,9 @@ import java.net.HttpURLConnection; import static app.revanced.extension.shared.requests.Route.Method.GET; public class AnnouncementsRoutes { - private static final String ANNOUNCEMENTS_PROVIDER = "https://api.revanced.app/v4"; - public static final Route GET_LATEST_ANNOUNCEMENT_IDS = new Route(GET, "/announcements/latest/id?tag=\uD83C\uDF9E\uFE0F%20YouTube"); - public static final Route GET_LATEST_ANNOUNCEMENTS = new Route(GET, "/announcements/latest?tag=\uD83C\uDF9E\uFE0F%20YouTube"); + private static final String ANNOUNCEMENTS_PROVIDER = "https://api.revanced.app/v5"; + public static final Route GET_LATEST_ANNOUNCEMENT_IDS = new Route(GET, "/announcements/latest/id"); + public static final Route GET_LATEST_ANNOUNCEMENTS = new Route(GET, "/announcements/latest"); private AnnouncementsRoutes() { }