diff --git a/extensions/shared/src/main/java/app/revanced/extension/music/patches/misc/SpoofClientPatch.java b/extensions/shared/src/main/java/app/revanced/extension/music/patches/misc/SpoofClientPatch.java index 19c5b6935..e3e651a36 100644 --- a/extensions/shared/src/main/java/app/revanced/extension/music/patches/misc/SpoofClientPatch.java +++ b/extensions/shared/src/main/java/app/revanced/extension/music/patches/misc/SpoofClientPatch.java @@ -2,11 +2,11 @@ package app.revanced.extension.music.patches.misc; import app.revanced.extension.music.patches.misc.client.AppClient.ClientType; import app.revanced.extension.music.settings.Settings; -import app.revanced.extension.shared.patches.BlockRequestPatch; @SuppressWarnings("unused") -public class SpoofClientPatch extends BlockRequestPatch { +public class SpoofClientPatch { private static final ClientType CLIENT_TYPE = Settings.SPOOF_CLIENT_TYPE.get(); + public static final boolean SPOOF_CLIENT = Settings.SPOOF_CLIENT.get(); /** * Injection point. diff --git a/extensions/shared/src/main/java/app/revanced/extension/music/patches/misc/client/AppClient.java b/extensions/shared/src/main/java/app/revanced/extension/music/patches/misc/client/AppClient.java index 0a21f6196..487ef08c4 100644 --- a/extensions/shared/src/main/java/app/revanced/extension/music/patches/misc/client/AppClient.java +++ b/extensions/shared/src/main/java/app/revanced/extension/music/patches/misc/client/AppClient.java @@ -2,49 +2,78 @@ package app.revanced.extension.music.patches.misc.client; import android.os.Build; -import app.revanced.extension.music.settings.Settings; - public class AppClient { - private static final String CLIENT_VERSION_ANDROID_MUSIC = Settings.SPOOF_CLIENT_LEGACY.get() - ? "4.27.53" // Audio codec is MP4A. - : "5.29.53"; // Audio codec is OPUS. - private static final String OS_VERSION_ANDROID_MUSIC = Build.VERSION.RELEASE; - private static final String USER_AGENT_ANDROID_MUSIC = "com.google.android.apps.youtube.music/" + - CLIENT_VERSION_ANDROID_MUSIC + - " (Linux; U; Android " + - OS_VERSION_ANDROID_MUSIC + - "; GB) gzip"; - private static final String CLIENT_VERSION_IOS_MUSIC = Settings.SPOOF_CLIENT_LEGACY.get() - ? "4.27" // Audio codec is MP4A. - : "7.31.2"; // Audio codec is OPUS. + // Audio codec is MP4A. + private static final String CLIENT_VERSION_ANDROID_MUSIC_4_27 = "4.27.53"; + + // Audio codec is OPUS. + private static final String CLIENT_VERSION_ANDROID_MUSIC_5_29 = "5.29.53"; + + private static final String PACKAGE_NAME_ANDROID_MUSIC = "com.google.android.apps.youtube.music"; + private static final String DEVICE_MODEL_ANDROID_MUSIC = Build.MODEL; + private static final String OS_VERSION_ANDROID_MUSIC = Build.VERSION.RELEASE; + + // Audio codec is MP4A. + private static final String CLIENT_VERSION_IOS_MUSIC_6_21 = "6.21"; + + // Audio codec is OPUS. + private static final String CLIENT_VERSION_IOS_MUSIC_7_04 = "7.04"; + + private static final String PACKAGE_NAME_IOS_MUSIC = "com.google.ios.youtubemusic"; private static final String DEVICE_MODEL_IOS_MUSIC = "iPhone14,3"; private static final String OS_VERSION_IOS_MUSIC = "15.7.1.19H117"; private static final String USER_AGENT_VERSION_IOS_MUSIC = "15_7_1"; - private static final String USER_AGENT_IOS_MUSIC = "com.google.ios.youtubemusic/" + - CLIENT_VERSION_IOS_MUSIC + - "(" + - DEVICE_MODEL_IOS_MUSIC + - "; U; CPU iOS " + - USER_AGENT_VERSION_IOS_MUSIC + - " like Mac OS X)"; private AppClient() { } + private static String androidUserAgent(String clientVersion) { + return PACKAGE_NAME_ANDROID_MUSIC + + "/" + + clientVersion + + " (Linux; U; Android " + + OS_VERSION_ANDROID_MUSIC + + "; GB) gzip"; + } + + private static String iOSUserAgent(String clientVersion) { + return PACKAGE_NAME_IOS_MUSIC + + "/" + + clientVersion + + "(" + + DEVICE_MODEL_IOS_MUSIC + + "; U; CPU iOS " + + USER_AGENT_VERSION_IOS_MUSIC + + " like Mac OS X)"; + } + public enum ClientType { - ANDROID_MUSIC(21, - Build.MODEL, + ANDROID_MUSIC_4_27(21, + DEVICE_MODEL_ANDROID_MUSIC, OS_VERSION_ANDROID_MUSIC, - USER_AGENT_ANDROID_MUSIC, - CLIENT_VERSION_ANDROID_MUSIC + androidUserAgent(CLIENT_VERSION_ANDROID_MUSIC_4_27), + CLIENT_VERSION_ANDROID_MUSIC_4_27 ), - IOS_MUSIC( + ANDROID_MUSIC_5_29(21, + DEVICE_MODEL_ANDROID_MUSIC, + OS_VERSION_ANDROID_MUSIC, + androidUserAgent(CLIENT_VERSION_ANDROID_MUSIC_5_29), + CLIENT_VERSION_ANDROID_MUSIC_5_29 + ), + IOS_MUSIC_6_21( 26, DEVICE_MODEL_IOS_MUSIC, OS_VERSION_IOS_MUSIC, - USER_AGENT_IOS_MUSIC, - CLIENT_VERSION_IOS_MUSIC + iOSUserAgent(CLIENT_VERSION_IOS_MUSIC_6_21), + CLIENT_VERSION_IOS_MUSIC_6_21 + ), + IOS_MUSIC_7_04( + 26, + DEVICE_MODEL_IOS_MUSIC, + OS_VERSION_IOS_MUSIC, + iOSUserAgent(CLIENT_VERSION_IOS_MUSIC_7_04), + CLIENT_VERSION_IOS_MUSIC_7_04 ); /** diff --git a/extensions/shared/src/main/java/app/revanced/extension/music/settings/Settings.java b/extensions/shared/src/main/java/app/revanced/extension/music/settings/Settings.java index dfdedc6d2..77bac406c 100644 --- a/extensions/shared/src/main/java/app/revanced/extension/music/settings/Settings.java +++ b/extensions/shared/src/main/java/app/revanced/extension/music/settings/Settings.java @@ -180,8 +180,8 @@ public class Settings extends BaseSettings { public static final BooleanSetting DISABLE_DRC_AUDIO = new BooleanSetting("revanced_disable_drc_audio", FALSE, true); public static final BooleanSetting ENABLE_OPUS_CODEC = new BooleanSetting("revanced_enable_opus_codec", FALSE, true); public static final BooleanSetting SETTINGS_IMPORT_EXPORT = new BooleanSetting("revanced_extended_settings_import_export", FALSE, false); - public static final BooleanSetting SPOOF_CLIENT_LEGACY = new BooleanSetting("revanced_spoof_client_legacy", FALSE, true); - public static final EnumSetting SPOOF_CLIENT_TYPE = new EnumSetting<>("revanced_spoof_client_type", ClientType.ANDROID_MUSIC, true); + public static final BooleanSetting SPOOF_CLIENT = new BooleanSetting("revanced_spoof_client", FALSE, true); + public static final EnumSetting SPOOF_CLIENT_TYPE = new EnumSetting<>("revanced_spoof_client_type", ClientType.IOS_MUSIC_6_21, true); // PreferenceScreen: Return YouTube Dislike diff --git a/extensions/shared/src/main/java/app/revanced/extension/shared/patches/PatchStatus.java b/extensions/shared/src/main/java/app/revanced/extension/shared/patches/PatchStatus.java index a90ce4e62..75d62dc85 100644 --- a/extensions/shared/src/main/java/app/revanced/extension/shared/patches/PatchStatus.java +++ b/extensions/shared/src/main/java/app/revanced/extension/shared/patches/PatchStatus.java @@ -12,11 +12,6 @@ public class PatchStatus { return ClientType.IOS; } - public static boolean SpoofClient() { - // Replace this with true If the Spoof client patch succeeds - return false; - } - public static boolean SpoofStreamingData() { // Replace this with true If the Spoof streaming data patch succeeds return false; diff --git a/extensions/shared/src/main/java/app/revanced/extension/shared/settings/BaseSettings.java b/extensions/shared/src/main/java/app/revanced/extension/shared/settings/BaseSettings.java index 1be356f54..a9acc8be6 100644 --- a/extensions/shared/src/main/java/app/revanced/extension/shared/settings/BaseSettings.java +++ b/extensions/shared/src/main/java/app/revanced/extension/shared/settings/BaseSettings.java @@ -36,10 +36,6 @@ public class BaseSettings { public static final EnumSetting RETURN_YOUTUBE_USERNAME_DISPLAY_FORMAT = new EnumSetting<>("revanced_return_youtube_username_display_format", DisplayFormat.USERNAME_ONLY, true); public static final StringSetting RETURN_YOUTUBE_USERNAME_YOUTUBE_DATA_API_V3_DEVELOPER_KEY = new StringSetting("revanced_return_youtube_username_youtube_data_api_v3_developer_key", "", true, false); - // Used only in YouTube Music. - // Moved to a shared class to prevent YouTube from accessing YouTube Music's extension classes. - public static final BooleanSetting SPOOF_CLIENT = new BooleanSetting("revanced_spoof_client", FALSE, true); - public static final BooleanSetting SPOOF_STREAMING_DATA = new BooleanSetting("revanced_spoof_streaming_data", TRUE, true, "revanced_spoof_streaming_data_user_dialog_message"); public static final EnumSetting SPOOF_STREAMING_DATA_TYPE = new EnumSetting<>("revanced_spoof_streaming_data_type", SpoofStreamingDataDefaultClient(), true); public static final BooleanSetting SPOOF_STREAMING_DATA_SYNC_VIDEO_LENGTH = new BooleanSetting("revanced_spoof_streaming_data_sync_video_length", TRUE, true); diff --git a/patches/src/main/kotlin/app/revanced/patches/music/utils/fix/client/SpoofClientPatch.kt b/patches/src/main/kotlin/app/revanced/patches/music/utils/fix/client/SpoofClientPatch.kt index d22922baf..af3dc5463 100644 --- a/patches/src/main/kotlin/app/revanced/patches/music/utils/fix/client/SpoofClientPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/music/utils/fix/client/SpoofClientPatch.kt @@ -4,24 +4,23 @@ import app.revanced.patcher.extensions.InstructionExtensions.addInstruction import app.revanced.patcher.extensions.InstructionExtensions.addInstructions import app.revanced.patcher.extensions.InstructionExtensions.getInstruction import app.revanced.patcher.extensions.InstructionExtensions.instructions -import app.revanced.patcher.extensions.InstructionExtensions.replaceInstruction import app.revanced.patcher.patch.PatchException import app.revanced.patcher.patch.bytecodePatch import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod.Companion.toMutable -import app.revanced.patches.music.utils.compatibility.Constants.COMPATIBLE_PACKAGE +import app.revanced.patches.music.utils.compatibility.Constants import app.revanced.patches.music.utils.extension.Constants.MISC_PATH import app.revanced.patches.music.utils.patch.PatchList.SPOOF_CLIENT import app.revanced.patches.music.utils.playbackSpeedBottomSheetFingerprint +import app.revanced.patches.music.utils.playservice.is_7_25_or_greater +import app.revanced.patches.music.utils.playservice.versionCheckPatch import app.revanced.patches.music.utils.settings.CategoryType import app.revanced.patches.music.utils.settings.ResourceUtils.updatePatchStatus import app.revanced.patches.music.utils.settings.addPreferenceWithIntent import app.revanced.patches.music.utils.settings.addSwitchPreference import app.revanced.patches.music.utils.settings.settingsPatch -import app.revanced.patches.shared.blockrequest.blockRequestPatch import app.revanced.patches.shared.createPlayerRequestBodyWithModelFingerprint -import app.revanced.patches.shared.extension.Constants.PATCHES_PATH import app.revanced.patches.shared.indexOfModelInstruction -import app.revanced.util.findMethodOrThrow +import app.revanced.util.Utils.printWarn import app.revanced.util.fingerprint.matchOrThrow import app.revanced.util.fingerprint.methodOrThrow import app.revanced.util.fingerprint.mutableClassOrThrow @@ -53,14 +52,26 @@ val spoofClientPatch = bytecodePatch( SPOOF_CLIENT.summary, false, ) { - dependsOn( - settingsPatch, - blockRequestPatch + compatibleWith( + Constants.YOUTUBE_MUSIC_PACKAGE_NAME( + "6.20.51", + "6.29.59", + "6.42.55", + "6.51.53", + "7.16.53", + ), ) - compatibleWith(COMPATIBLE_PACKAGE) + dependsOn( + settingsPatch, + versionCheckPatch, + ) execute { + if (is_7_25_or_greater) { + printWarn("\"${SPOOF_CLIENT.title}\" is not supported in this version. Use YouTube Music 7.24.51 or earlier.") + return@execute + } // region Get field references to be used below. @@ -262,24 +273,11 @@ val spoofClientPatch = bytecodePatch( // endregion - findMethodOrThrow("$PATCHES_PATH/PatchStatus;") { - name == "SpoofClient" - }.replaceInstruction( - 0, - "const/4 v0, 0x1" - ) - addSwitchPreference( CategoryType.MISC, "revanced_spoof_client", "false" ) - addSwitchPreference( - CategoryType.MISC, - "revanced_spoof_client_legacy", - "false", - "revanced_spoof_client" - ) addPreferenceWithIntent( CategoryType.MISC, "revanced_spoof_client_type", diff --git a/patches/src/main/resources/music/settings/host/values/arrays.xml b/patches/src/main/resources/music/settings/host/values/arrays.xml index c0fcf769b..81986ed4c 100644 --- a/patches/src/main/resources/music/settings/host/values/arrays.xml +++ b/patches/src/main/resources/music/settings/host/values/arrays.xml @@ -56,12 +56,14 @@ 4.27.53 - @string/revanced_spoof_client_type_entry_android_music - @string/revanced_spoof_client_type_entry_ios_music + @string/revanced_spoof_client_type_entry_ios_music_6_21 + @string/revanced_spoof_client_type_entry_android_music_5_29 + @string/revanced_spoof_client_type_entry_android_music_4_27 - ANDROID_MUSIC - IOS_MUSIC + IOS_MUSIC_6_21 + ANDROID_MUSIC_5_29 + ANDROID_MUSIC_4_27 @string/revanced_spoof_streaming_data_type_entry_android_vr diff --git a/patches/src/main/resources/music/settings/host/values/strings.xml b/patches/src/main/resources/music/settings/host/values/strings.xml index 9278a9f5c..d04d6e15b 100644 --- a/patches/src/main/resources/music/settings/host/values/strings.xml +++ b/patches/src/main/resources/music/settings/host/values/strings.xml @@ -452,14 +452,13 @@ Tap the continue button and allow optimization changes." "Spoof the client to prevent playback issues. ※ When used with 'Spoofing streaming data', playback issues may occur." - Use old client - "Spoofing with version 4.27.53. - -OPUS codec may not work." Default client - Defines a default client to spoofing. - Android Music - iOS Music + "Defines a default client to spoofing. + +※ When using the Android client, it is recommended to use it with 'Spoof app version'." + Android Music 4.27.53 + Android Music 5.29.53 + iOS Music 6.21 Spoof streaming data "Spoof the streaming data to prevent playback issues.