feat(YouTube Music): Add Announcements patch

This commit is contained in:
oSumAtrIX 2024-12-07 23:47:10 +01:00
parent 6a44e75203
commit 470feb6967
No known key found for this signature in database
GPG Key ID: A9B3094ACDB604B4
11 changed files with 649 additions and 255 deletions

View File

@ -1,9 +1,9 @@
package app.revanced.extension.youtube.patches.announcements; package app.revanced.extension.shared.announcements;
import static android.text.Html.FROM_HTML_MODE_COMPACT; import static android.text.Html.FROM_HTML_MODE_COMPACT;
import static app.revanced.extension.shared.StringRef.str; import static app.revanced.extension.shared.StringRef.str;
import static app.revanced.extension.youtube.patches.announcements.requests.AnnouncementsRoutes.GET_LATEST_ANNOUNCEMENTS; import static app.revanced.extension.shared.announcements.requests.AnnouncementsRoutes.GET_LATEST_ANNOUNCEMENTS;
import static app.revanced.extension.youtube.patches.announcements.requests.AnnouncementsRoutes.GET_LATEST_ANNOUNCEMENT_IDS; import static app.revanced.extension.shared.announcements.requests.AnnouncementsRoutes.GET_LATEST_ANNOUNCEMENT_IDS;
import android.app.Activity; import android.app.Activity;
import android.app.AlertDialog; import android.app.AlertDialog;
@ -23,8 +23,8 @@ import java.time.LocalDateTime;
import app.revanced.extension.shared.Logger; import app.revanced.extension.shared.Logger;
import app.revanced.extension.shared.Utils; import app.revanced.extension.shared.Utils;
import app.revanced.extension.shared.requests.Requester; import app.revanced.extension.shared.requests.Requester;
import app.revanced.extension.youtube.patches.announcements.requests.AnnouncementsRoutes; import app.revanced.extension.shared.announcements.requests.AnnouncementsRoutes;
import app.revanced.extension.youtube.settings.Settings; import app.revanced.extension.shared.settings.BaseSettings;
@SuppressWarnings("unused") @SuppressWarnings("unused")
public final class AnnouncementsPatch { public final class AnnouncementsPatch {
@ -41,10 +41,10 @@ public final class AnnouncementsPatch {
try { try {
// Do not show the announcement if the request failed. // Do not show the announcement if the request failed.
if (connection.getResponseCode() != 200) { if (connection.getResponseCode() != 200) {
if (Settings.ANNOUNCEMENT_LAST_ID.isSetToDefault()) if (BaseSettings.ANNOUNCEMENT_LAST_ID.isSetToDefault())
return true; return true;
Settings.ANNOUNCEMENT_LAST_ID.resetToDefault(); BaseSettings.ANNOUNCEMENT_LAST_ID.resetToDefault();
Utils.showToastLong(str("revanced_announcements_connection_failed")); Utils.showToastLong(str("revanced_announcements_connection_failed"));
return true; return true;
@ -57,7 +57,7 @@ public final class AnnouncementsPatch {
var jsonString = Requester.parseStringAndDisconnect(connection); var jsonString = Requester.parseStringAndDisconnect(connection);
// Parse the ID. Fall-back to raw string if it fails. // Parse the ID. Fall-back to raw string if it fails.
int id = Settings.ANNOUNCEMENT_LAST_ID.defaultValue; int id = BaseSettings.ANNOUNCEMENT_LAST_ID.defaultValue;
try { try {
final var announcementIds = new JSONArray(jsonString); final var announcementIds = new JSONArray(jsonString);
id = announcementIds.getJSONObject(0).getInt("id"); id = announcementIds.getJSONObject(0).getInt("id");
@ -67,12 +67,12 @@ public final class AnnouncementsPatch {
} }
// Do not show the announcement, if the last announcement id is the same as the current one. // 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 BaseSettings.ANNOUNCEMENT_LAST_ID.get() == id;
} }
@RequiresApi(api = Build.VERSION_CODES.O) @RequiresApi(api = Build.VERSION_CODES.O)
public static void showAnnouncement(final Activity context) { public static void showAnnouncement(final Activity context) {
if (!Settings.ANNOUNCEMENTS.get()) return; if (!BaseSettings.ANNOUNCEMENTS.get()) return;
// Check if there is internet connection // Check if there is internet connection
if (!Utils.isNetworkConnected()) return; if (!Utils.isNetworkConnected()) return;
@ -89,7 +89,7 @@ public final class AnnouncementsPatch {
var jsonString = Requester.parseStringAndDisconnect(connection); var jsonString = Requester.parseStringAndDisconnect(connection);
// Parse the announcement. Fall-back to raw string if it fails. // Parse the announcement. Fall-back to raw string if it fails.
int id = Settings.ANNOUNCEMENT_LAST_ID.defaultValue; int id = BaseSettings.ANNOUNCEMENT_LAST_ID.defaultValue;
String title; String title;
String message; String message;
LocalDateTime archivedAt = LocalDateTime.MAX; LocalDateTime archivedAt = LocalDateTime.MAX;
@ -115,7 +115,7 @@ public final class AnnouncementsPatch {
// If the announcement is archived, do not show it. // If the announcement is archived, do not show it.
if (archivedAt.isBefore(LocalDateTime.now())) { if (archivedAt.isBefore(LocalDateTime.now())) {
Settings.ANNOUNCEMENT_LAST_ID.save(id); BaseSettings.ANNOUNCEMENT_LAST_ID.save(id);
return; return;
} }
@ -131,7 +131,7 @@ public final class AnnouncementsPatch {
.setMessage(finalMessage) .setMessage(finalMessage)
.setIcon(finalLevel.icon) .setIcon(finalLevel.icon)
.setPositiveButton(android.R.string.ok, (dialog, which) -> { .setPositiveButton(android.R.string.ok, (dialog, which) -> {
Settings.ANNOUNCEMENT_LAST_ID.save(finalId); BaseSettings.ANNOUNCEMENT_LAST_ID.save(finalId);
dialog.dismiss(); dialog.dismiss();
}).setNegativeButton(str("revanced_announcements_dialog_dismiss"), (dialog, which) -> { }).setNegativeButton(str("revanced_announcements_dialog_dismiss"), (dialog, which) -> {
dialog.dismiss(); dialog.dismiss();

View File

@ -1,4 +1,4 @@
package app.revanced.extension.youtube.patches.announcements.requests; package app.revanced.extension.shared.announcements.requests;
import app.revanced.extension.shared.requests.Requester; import app.revanced.extension.shared.requests.Requester;
import app.revanced.extension.shared.requests.Route; import app.revanced.extension.shared.requests.Route;
@ -9,9 +9,9 @@ import java.net.HttpURLConnection;
import static app.revanced.extension.shared.requests.Route.Method.GET; import static app.revanced.extension.shared.requests.Route.Method.GET;
public class AnnouncementsRoutes { 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=youtube"); public static final Route GET_LATEST_ANNOUNCEMENT_IDS = new Route(GET, "/announcements/latest/id?tag=youtube");
public static final Route GET_LATEST_ANNOUNCEMENTS = new Route(GET, "/announcements/latest?tag=youtube"); public static final Route GET_LATEST_ANNOUNCEMENTS = new Route(GET, "/announcements/latest?tag=youtube");
private static final String ANNOUNCEMENTS_PROVIDER = "https://api.revanced.app/v4";
private AnnouncementsRoutes() { private AnnouncementsRoutes() {
} }

View File

@ -16,4 +16,7 @@ public class BaseSettings {
public static final BooleanSetting DEBUG_TOAST_ON_ERROR = new BooleanSetting("revanced_debug_toast_on_error", TRUE, "revanced_debug_toast_on_error_user_dialog_message"); public static final BooleanSetting DEBUG_TOAST_ON_ERROR = new BooleanSetting("revanced_debug_toast_on_error", TRUE, "revanced_debug_toast_on_error_user_dialog_message");
public static final IntegerSetting CHECK_ENVIRONMENT_WARNINGS_ISSUED = new IntegerSetting("revanced_check_environment_warnings_issued", 0, true, false); public static final IntegerSetting CHECK_ENVIRONMENT_WARNINGS_ISSUED = new IntegerSetting("revanced_check_environment_warnings_issued", 0, true, false);
public static final BooleanSetting ANNOUNCEMENTS = new BooleanSetting("revanced_announcements", TRUE);
public static final IntegerSetting ANNOUNCEMENT_LAST_ID = new IntegerSetting("revanced_announcement_last_id", -1, false, false);
} }

View File

@ -271,12 +271,10 @@ public class Settings extends BaseSettings {
public static final BooleanSetting SPOOF_DEVICE_DIMENSIONS = new BooleanSetting("revanced_spoof_device_dimensions", FALSE, true, public static final BooleanSetting SPOOF_DEVICE_DIMENSIONS = new BooleanSetting("revanced_spoof_device_dimensions", FALSE, true,
"revanced_spoof_device_dimensions_user_dialog_message"); "revanced_spoof_device_dimensions_user_dialog_message");
public static final BooleanSetting BYPASS_URL_REDIRECTS = new BooleanSetting("revanced_bypass_url_redirects", TRUE); 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 BooleanSetting SPOOF_VIDEO_STREAMS = new BooleanSetting("revanced_spoof_video_streams", TRUE, true,"revanced_spoof_video_streams_user_dialog_message"); public static final BooleanSetting SPOOF_VIDEO_STREAMS = new BooleanSetting("revanced_spoof_video_streams", TRUE, true,"revanced_spoof_video_streams_user_dialog_message");
public static final BooleanSetting SPOOF_VIDEO_STREAMS_IOS_FORCE_AVC = new BooleanSetting("revanced_spoof_video_streams_ios_force_avc", FALSE, true, public static final BooleanSetting SPOOF_VIDEO_STREAMS_IOS_FORCE_AVC = new BooleanSetting("revanced_spoof_video_streams_ios_force_avc", FALSE, true,
"revanced_spoof_video_streams_ios_force_avc_user_dialog_message", new SpoofVideoStreamsPatch.ForceiOSAVCAvailability()); "revanced_spoof_video_streams_ios_force_avc_user_dialog_message", new SpoofVideoStreamsPatch.ForceiOSAVCAvailability());
public static final EnumSetting<ClientType> SPOOF_VIDEO_STREAMS_CLIENT_TYPE = new EnumSetting<>("revanced_spoof_video_streams_client", ClientType.ANDROID_VR, true, parent(SPOOF_VIDEO_STREAMS)); public static final EnumSetting<ClientType> SPOOF_VIDEO_STREAMS_CLIENT_TYPE = new EnumSetting<>("revanced_spoof_video_streams_client", ClientType.ANDROID_VR, true, parent(SPOOF_VIDEO_STREAMS));
public static final IntegerSetting ANNOUNCEMENT_LAST_ID = new IntegerSetting("revanced_announcement_last_id", -1, false, false);
public static final BooleanSetting CHECK_WATCH_HISTORY_DOMAIN_NAME = new BooleanSetting("revanced_check_watch_history_domain_name", TRUE, false, false); public static final BooleanSetting CHECK_WATCH_HISTORY_DOMAIN_NAME = new BooleanSetting("revanced_check_watch_history_domain_name", TRUE, false, false);
public static final BooleanSetting REMOVE_TRACKING_QUERY_PARAMETER = new BooleanSetting("revanced_remove_tracking_query_parameter", TRUE); public static final BooleanSetting REMOVE_TRACKING_QUERY_PARAMETER = new BooleanSetting("revanced_remove_tracking_query_parameter", TRUE);

View File

@ -2,6 +2,11 @@ public final class app/revanced/patches/all/misc/activity/exportall/ExportAllAct
public static final fun getExportAllActivitiesPatch ()Lapp/revanced/patcher/patch/ResourcePatch; public static final fun getExportAllActivitiesPatch ()Lapp/revanced/patcher/patch/ResourcePatch;
} }
public final class app/revanced/patches/all/misc/announcements/AnnouncementsPatchKt {
public static final fun announcementsPatch (Lapp/revanced/patcher/Fingerprint;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;)Lapp/revanced/patcher/patch/BytecodePatch;
public static synthetic fun announcementsPatch$default (Lapp/revanced/patcher/Fingerprint;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lapp/revanced/patcher/patch/BytecodePatch;
}
public final class app/revanced/patches/all/misc/build/BaseSpoofBuildInfoPatchKt { public final class app/revanced/patches/all/misc/build/BaseSpoofBuildInfoPatchKt {
public static final fun baseSpoofBuildInfoPatch (Lkotlin/jvm/functions/Function0;)Lapp/revanced/patcher/patch/BytecodePatch; public static final fun baseSpoofBuildInfoPatch (Lkotlin/jvm/functions/Function0;)Lapp/revanced/patcher/patch/BytecodePatch;
} }
@ -304,6 +309,10 @@ public final class app/revanced/patches/music/misc/androidauto/BypassCertificate
public static final fun getBypassCertificateChecksPatch ()Lapp/revanced/patcher/patch/BytecodePatch; public static final fun getBypassCertificateChecksPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
} }
public final class app/revanced/patches/music/misc/announcements/AnnouncementsPatchKt {
public static final fun getAnnouncementsPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
}
public final class app/revanced/patches/music/misc/backgroundplayback/BackgroundPlaybackPatchKt { public final class app/revanced/patches/music/misc/backgroundplayback/BackgroundPlaybackPatchKt {
public static final fun getBackgroundPlaybackPatch ()Lapp/revanced/patcher/patch/BytecodePatch; public static final fun getBackgroundPlaybackPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
} }

View File

@ -0,0 +1,36 @@
package app.revanced.patches.all.misc.announcements
import app.revanced.patcher.Fingerprint
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
import app.revanced.patcher.patch.BytecodePatchBuilder
import app.revanced.patcher.patch.BytecodePatchContext
import app.revanced.patcher.patch.bytecodePatch
import app.revanced.patches.all.misc.resources.addResources
import app.revanced.patches.all.misc.resources.addResourcesPatch
private const val EXTENSION_CLASS_DESCRIPTOR =
"Lapp/revanced/extension/shared/announcements/AnnouncementsPatch;"
fun announcementsPatch(
mainActivityOnCreateFingerprint: Fingerprint,
block: BytecodePatchBuilder.() -> Unit = {},
executeBlock: BytecodePatchContext.() -> Unit = {},
) = bytecodePatch(
name = "Announcements",
description = "Adds an option to show announcements from ReVanced on app startup.",
) {
block()
dependsOn(addResourcesPatch)
execute {
addResources("shared", "misc.announcements.announcementsPatch")
mainActivityOnCreateFingerprint.method.addInstructions(
0,
"invoke-static/range { p0 .. p0 }, $EXTENSION_CLASS_DESCRIPTOR->showAnnouncement(Landroid/app/Activity;)V",
)
executeBlock()
}
}

View File

@ -0,0 +1,11 @@
package app.revanced.patches.music.misc.announcements
import app.revanced.patches.all.misc.announcements.announcementsPatch
import app.revanced.patches.music.shared.musicActivityOnCreateFingerprint
val announcementsPatch = announcementsPatch(
musicActivityOnCreateFingerprint,
{
compatibleWith("com.google.android.apps.music")
},
)

View File

@ -4,6 +4,7 @@ import app.revanced.patcher.patch.Option
import app.revanced.patches.music.misc.extension.sharedExtensionPatch import app.revanced.patches.music.misc.extension.sharedExtensionPatch
import app.revanced.patches.music.misc.gms.Constants.MUSIC_PACKAGE_NAME import app.revanced.patches.music.misc.gms.Constants.MUSIC_PACKAGE_NAME
import app.revanced.patches.music.misc.gms.Constants.REVANCED_MUSIC_PACKAGE_NAME import app.revanced.patches.music.misc.gms.Constants.REVANCED_MUSIC_PACKAGE_NAME
import app.revanced.patches.music.shared.musicActivityOnCreateFingerprint
import app.revanced.patches.shared.castContextFetchFingerprint import app.revanced.patches.shared.castContextFetchFingerprint
import app.revanced.patches.shared.misc.gms.gmsCoreSupportPatch import app.revanced.patches.shared.misc.gms.gmsCoreSupportPatch
import app.revanced.patches.shared.primeMethodFingerprint import app.revanced.patches.shared.primeMethodFingerprint

View File

@ -1,4 +1,4 @@
package app.revanced.patches.music.misc.gms package app.revanced.patches.music.shared
import app.revanced.patcher.fingerprint import app.revanced.patcher.fingerprint

View File

@ -1,51 +1,24 @@
package app.revanced.patches.youtube.misc.announcements package app.revanced.patches.youtube.misc.announcements
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions import app.revanced.patches.all.misc.announcements.announcementsPatch
import app.revanced.patcher.patch.bytecodePatch
import app.revanced.patches.all.misc.resources.addResources import app.revanced.patches.all.misc.resources.addResources
import app.revanced.patches.all.misc.resources.addResourcesPatch
import app.revanced.patches.shared.misc.settings.preference.SwitchPreference import app.revanced.patches.shared.misc.settings.preference.SwitchPreference
import app.revanced.patches.youtube.misc.settings.PreferenceScreen import app.revanced.patches.youtube.misc.settings.PreferenceScreen
import app.revanced.patches.youtube.misc.settings.settingsPatch import app.revanced.patches.youtube.misc.settings.settingsPatch
import app.revanced.patches.youtube.shared.mainActivityOnCreateFingerprint import app.revanced.patches.youtube.shared.mainActivityOnCreateFingerprint
private const val EXTENSION_CLASS_DESCRIPTOR = val announcementsPatch = announcementsPatch(
"Lapp/revanced/extension/youtube/patches/announcements/AnnouncementsPatch;" mainActivityOnCreateFingerprint,
{
dependsOn(settingsPatch)
val announcementsPatch = bytecodePatch( compatibleWith("com.google.android.youtube")
name = "Announcements", },
description = "Adds an option to show announcements from ReVanced on app startup.", {
) {
dependsOn(
settingsPatch,
addResourcesPatch,
)
compatibleWith(
"com.google.android.youtube"(
"18.38.44",
"18.49.37",
"19.16.39",
"19.25.37",
"19.34.42",
"19.43.41",
"19.45.38",
"19.46.42",
),
)
execute {
addResources("youtube", "misc.announcements.announcementsPatch") addResources("youtube", "misc.announcements.announcementsPatch")
PreferenceScreen.MISC.addPreferences( PreferenceScreen.MISC.addPreferences(
SwitchPreference("revanced_announcements"), SwitchPreference("revanced_announcements"),
) )
},
mainActivityOnCreateFingerprint.method.addInstructions( )
// Insert index must be greater than the insert index used by GmsCoreSupport,
// as both patch the same method and GmsCore check should be first.
1,
"invoke-static/range { p0 .. p0 }, $EXTENSION_CLASS_DESCRIPTOR->showAnnouncement(Landroid/app/Activity;)V",
)
}
}

File diff suppressed because it is too large Load Diff