diff --git a/extensions/shared/src/main/java/app/revanced/extension/shared/patches/client/AppClient.java b/extensions/shared/src/main/java/app/revanced/extension/shared/patches/client/AppClient.java deleted file mode 100644 index c67094f29..000000000 --- a/extensions/shared/src/main/java/app/revanced/extension/shared/patches/client/AppClient.java +++ /dev/null @@ -1,327 +0,0 @@ -package app.revanced.extension.shared.patches.client; - -import static app.revanced.extension.shared.patches.PatchStatus.SpoofStreamingDataMusic; - -import android.os.Build; - -import androidx.annotation.Nullable; - -import app.revanced.extension.shared.settings.BaseSettings; - -public class AppClient { - // IOS - /** - * Video not playable: Paid / Movie / Private / Age-restricted - * Note: Audio track available - */ - private static final String PACKAGE_NAME_IOS = "com.google.ios.youtube"; - /** - * The hardcoded client version of the iOS app used for InnerTube requests with this client. - * - *

- * It can be extracted by getting the latest release version of the app on - * the App - * Store page of the YouTube app, in the {@code What’s New} section. - *

- */ - private static final String CLIENT_VERSION_IOS = forceAVC() - ? "17.40.5" - : "19.29.1"; - /** - * The device machine id for the iPhone 15 Pro Max (iPhone16,2), used to get HDR with AV1 hardware decoding. - * - *

- * See this GitHub Gist for more - * information. - *

- */ - private static final String DEVICE_MODEL_IOS = forceAVC() - ? "iPhone12,5" // 11 Pro Max. (last device with iOS 13) - : "iPhone16,2"; // 15 Pro Max. - private static final String OS_VERSION_IOS = forceAVC() - ? "13.7.17H35" // Last release of iOS 13. - : "17.7.2.21H221"; - private static final String USER_AGENT_VERSION_IOS = forceAVC() - ? "13_7" - : "17_7_2"; - private static final String USER_AGENT_IOS = - iOSUserAgent(PACKAGE_NAME_IOS, CLIENT_VERSION_IOS); - - - // IOS UNPLUGGED - /** - * Video not playable: Paid / Movie - * Note: Audio track available - */ - private static final String PACKAGE_NAME_IOS_UNPLUGGED = "com.google.ios.youtubeunplugged"; - /** - * The hardcoded client version of the iOS app used for InnerTube requests with this client. - * - *

- * It can be extracted by getting the latest release version of the app on - * the App - * Store page of the YouTube TV app, in the {@code What’s New} section. - *

- */ - private static final String CLIENT_VERSION_IOS_UNPLUGGED = forceAVC() - ? "6.45" - : "8.33"; - private static final String USER_AGENT_IOS_UNPLUGGED = - iOSUserAgent(PACKAGE_NAME_IOS_UNPLUGGED, CLIENT_VERSION_IOS_UNPLUGGED); - - - // IOS MUSIC - /** - * Video not playable: All videos that can't be played on YouTube Music - */ - private static final String PACKAGE_NAME_IOS_MUSIC = "com.google.ios.youtubemusic"; - /** - * The hardcoded client version of the iOS app used for InnerTube requests with this client. - * - *

- * It can be extracted by getting the latest release version of the app on - * the App - * Store page of the YouTube Music app, in the {@code What’s New} section. - *

- */ - private static final String CLIENT_VERSION_IOS_MUSIC = "7.04"; - private static final String USER_AGENT_IOS_MUSIC = - iOSUserAgent(PACKAGE_NAME_IOS_MUSIC, CLIENT_VERSION_IOS_MUSIC); - - - // ANDROID VR - /** - * Video not playable: Kids - * Note: Audio track is not available - *

- * Package name for YouTube VR (Google DayDream): com.google.android.apps.youtube.vr (Deprecated) - * Package name for YouTube VR (Meta Quests): com.google.android.apps.youtube.vr.oculus - * Package name for YouTube VR (ByteDance Pico 4): com.google.android.apps.youtube.vr.pico - */ - private static final String PACKAGE_NAME_ANDROID_VR = "com.google.android.apps.youtube.vr.oculus"; - /** - * The hardcoded client version of the Android VR app used for InnerTube requests with this client. - * - *

- * It can be extracted by getting the latest release version of the app on - * the App - * Store page of the YouTube app, in the {@code Additional details} section. - *

- */ - private static final String CLIENT_VERSION_ANDROID_VR = "1.61.48"; - /** - * The device machine id for the Meta Quest 3, used to get opus codec with the Android VR client. - * - *

- * See this GitLab for more - * information. - *

- */ - private static final String DEVICE_MODEL_ANDROID_VR = "Quest 3"; - private static final String OS_VERSION_ANDROID_VR = "12"; - /** - * The SDK version for Android 12 is 31, - * but for some reason the build.props for the {@code Quest 3} state that the SDK version is 32. - */ - private static final String ANDROID_SDK_VERSION_ANDROID_VR = "32"; - private static final String USER_AGENT_ANDROID_VR = - androidUserAgent(PACKAGE_NAME_ANDROID_VR, CLIENT_VERSION_ANDROID_VR, OS_VERSION_ANDROID_VR); - - - // ANDROID UNPLUGGED - /** - * Video not playable: Playlists / Music - * Note: Audio track is not available - */ - private static final String PACKAGE_NAME_ANDROID_UNPLUGGED = "com.google.android.apps.youtube.unplugged"; - private static final String CLIENT_VERSION_ANDROID_UNPLUGGED = "8.16.0"; - /** - * The device machine id for the Chromecast with Google TV 4K. - * - *

- * See this GitLab for more - * information. - *

- */ - private static final String DEVICE_MODEL_ANDROID_UNPLUGGED = "Google TV Streamer"; - private static final String OS_VERSION_ANDROID_UNPLUGGED = "14"; - private static final String ANDROID_SDK_VERSION_ANDROID_UNPLUGGED = "34"; - private static final String USER_AGENT_ANDROID_UNPLUGGED = - androidUserAgent(PACKAGE_NAME_ANDROID_UNPLUGGED, CLIENT_VERSION_ANDROID_UNPLUGGED, OS_VERSION_ANDROID_UNPLUGGED); - - - private AppClient() { - } - - private static String androidUserAgent(String packageName, String clientVersion, String osVersion) { - return packageName + - "/" + - clientVersion + - " (Linux; U; Android " + - osVersion + - "; GB) gzip"; - } - - private static String iOSUserAgent(String packageName, String clientVersion) { - return packageName + - "/" + - clientVersion + - "(" + - DEVICE_MODEL_IOS + - "; U; CPU iOS " + - USER_AGENT_VERSION_IOS + - " like Mac OS X)"; - } - - public enum ClientType { - ANDROID_VR(28, - DEVICE_MODEL_ANDROID_VR, - OS_VERSION_ANDROID_VR, - USER_AGENT_ANDROID_VR, - ANDROID_SDK_VERSION_ANDROID_VR, - CLIENT_VERSION_ANDROID_VR, - true, - false, - "Android VR" - ), - ANDROID_UNPLUGGED(29, - DEVICE_MODEL_ANDROID_UNPLUGGED, - OS_VERSION_ANDROID_UNPLUGGED, - USER_AGENT_ANDROID_UNPLUGGED, - ANDROID_SDK_VERSION_ANDROID_UNPLUGGED, - CLIENT_VERSION_ANDROID_UNPLUGGED, - true, - false, - "Android TV" - ), - IOS_UNPLUGGED(33, - DEVICE_MODEL_IOS, - OS_VERSION_IOS, - USER_AGENT_IOS_UNPLUGGED, - null, - CLIENT_VERSION_IOS_UNPLUGGED, - true, - false, - forceAVC() - ? "iOS TV Force AVC" - : "iOS TV" - ), - IOS(5, - DEVICE_MODEL_IOS, - OS_VERSION_IOS, - USER_AGENT_IOS, - null, - CLIENT_VERSION_IOS, - false, - true, - forceAVC() - ? "iOS Force AVC" - : "iOS" - ), - IOS_MUSIC( - 26, - DEVICE_MODEL_IOS, - OS_VERSION_IOS, - USER_AGENT_IOS_MUSIC, - null, - CLIENT_VERSION_IOS_MUSIC, - true, - false, - "iOS Music" - ); - - /** - * YouTube - * client type - */ - public final int id; - - public final String clientName; - - /** - * Device model, equivalent to {@link Build#MODEL} (System property: ro.product.model) - */ - public final String deviceModel; - - /** - * Device OS version. - */ - public final String osVersion; - - /** - * Player user-agent. - */ - public final String userAgent; - - /** - * Android SDK version, equivalent to {@link Build.VERSION#SDK} (System property: ro.build.version.sdk) - * Field is null if not applicable. - */ - @Nullable - public final String androidSdkVersion; - - /** - * App version. - */ - public final String clientVersion; - - /** - * If the client can access the API logged in. - */ - public final boolean canLogin; - - /** - * If a poToken should be used. - */ - public final boolean usePoToken; - - /** - * Friendly name displayed in stats for nerds. - */ - public final String friendlyName; - - ClientType(int id, - String deviceModel, - String osVersion, - String userAgent, - @Nullable String androidSdkVersion, - String clientVersion, - boolean canLogin, - boolean usePoToken, - String friendlyName - ) { - this.id = id; - this.clientName = name(); - this.deviceModel = deviceModel; - this.clientVersion = clientVersion; - this.osVersion = osVersion; - this.androidSdkVersion = androidSdkVersion; - this.userAgent = userAgent; - this.canLogin = canLogin; - this.usePoToken = usePoToken; - this.friendlyName = friendlyName; - } - - private static final ClientType[] CLIENT_ORDER_TO_USE_YOUTUBE = { - ANDROID_VR, - ANDROID_UNPLUGGED, - IOS_UNPLUGGED, - IOS, - }; - - private static final ClientType[] CLIENT_ORDER_TO_USE_YOUTUBE_MUSIC = { - ANDROID_VR, - IOS_MUSIC, - }; - } - - private static boolean forceAVC() { - return BaseSettings.SPOOF_STREAMING_DATA_IOS_FORCE_AVC.get(); - } - - public static ClientType[] getAvailableClientTypes() { - return SpoofStreamingDataMusic() - ? ClientType.CLIENT_ORDER_TO_USE_YOUTUBE_MUSIC - : ClientType.CLIENT_ORDER_TO_USE_YOUTUBE; - } -} diff --git a/extensions/shared/src/main/java/app/revanced/extension/shared/patches/client/AppClient.kt b/extensions/shared/src/main/java/app/revanced/extension/shared/patches/client/AppClient.kt new file mode 100644 index 000000000..f4728d69b --- /dev/null +++ b/extensions/shared/src/main/java/app/revanced/extension/shared/patches/client/AppClient.kt @@ -0,0 +1,294 @@ +package app.revanced.extension.shared.patches.client + +import android.os.Build +import app.revanced.extension.shared.patches.PatchStatus +import app.revanced.extension.shared.settings.BaseSettings + +object AppClient { + // IOS + /** + * Video not playable: Paid / Movie / Private / Age-restricted + * Note: Audio track available + */ + private const val PACKAGE_NAME_IOS = "com.google.ios.youtube" + + /** + * The hardcoded client version of the iOS app used for InnerTube requests with this client. + * + * It can be extracted by getting the latest release version of the app on + * [the App Store page of the YouTube app](https://apps.apple.com/us/app/youtube-watch-listen-stream/id544007664/), + * in the `What’s New` section. + */ + private val CLIENT_VERSION_IOS = if (forceAVC()) + "17.40.5" + else + "19.29.1" + + /** + * The device machine id for the iPhone 15 Pro Max (iPhone16,2), + * used to get HDR with AV1 hardware decoding. + * See [this GitHub Gist](https://gist.github.com/adamawolf/3048717) for more information. + */ + private val DEVICE_MODEL_IOS = if (forceAVC()) + "iPhone12,5" // 11 Pro Max. (last device with iOS 13) + else + "iPhone16,2" // 15 Pro Max. + private val OS_VERSION_IOS = if (forceAVC()) + "13.7.17H35" // Last release of iOS 13. + else + "17.7.2.21H221" + private val USER_AGENT_VERSION_IOS = if (forceAVC()) + "13_7" + else + "17_7_2" + private val USER_AGENT_IOS = iOSUserAgent(PACKAGE_NAME_IOS, CLIENT_VERSION_IOS) + + + // IOS UNPLUGGED + /** + * Video not playable: Paid / Movie + * Note: Audio track available + */ + private const val PACKAGE_NAME_IOS_UNPLUGGED = "com.google.ios.youtubeunplugged" + + /** + * The hardcoded client version of the iOS app used for InnerTube requests with this client. + * + * It can be extracted by getting the latest release version of the app on + * [the App Store page of the YouTube TV app](https://apps.apple.com/us/app/youtube-tv/id1193350206/), + * in the `What’s New` section. + */ + private val CLIENT_VERSION_IOS_UNPLUGGED = if (forceAVC()) + "6.45" + else + "8.33" + private val USER_AGENT_IOS_UNPLUGGED = + iOSUserAgent(PACKAGE_NAME_IOS_UNPLUGGED, CLIENT_VERSION_IOS_UNPLUGGED) + + + // ANDROID VR + /** + * Video not playable: Kids + * Note: Audio track is not available + * + * Package name for YouTube VR (Google DayDream): com.google.android.apps.youtube.vr (Deprecated) + * Package name for YouTube VR (Meta Quests): com.google.android.apps.youtube.vr.oculus + * Package name for YouTube VR (ByteDance Pico 4): com.google.android.apps.youtube.vr.pico + */ + private const val PACKAGE_NAME_ANDROID_VR = "com.google.android.apps.youtube.vr.oculus" + + /** + * The hardcoded client version of the Android VR app used for InnerTube requests with this client. + * + * It can be extracted by getting the latest release version of the app on + * [the App Store page of the YouTube app](https://www.meta.com/en-us/experiences/2002317119880945/), + * in the `Additional details` section. + */ + private const val CLIENT_VERSION_ANDROID_VR = "1.61.48" + + /** + * The device machine id for the Meta Quest 3, used to get opus codec with the Android VR client. + * See [this GitLab](https://dumps.tadiphone.dev/dumps/oculus/eureka) for more information. + */ + private const val DEVICE_MODEL_ANDROID_VR = "Quest 3" + private const val OS_VERSION_ANDROID_VR = "12" + + /** + * The SDK version for Android 12 is 31, + * but for some reason the build.props for the `Quest 3` state that the SDK version is 32. + */ + private const val ANDROID_SDK_VERSION_ANDROID_VR = "32" + private val USER_AGENT_ANDROID_VR = + androidUserAgent(PACKAGE_NAME_ANDROID_VR, CLIENT_VERSION_ANDROID_VR, OS_VERSION_ANDROID_VR) + + + // ANDROID UNPLUGGED + /** + * Video not playable: Playlists / Music + * Note: Audio track is not available + */ + private const val PACKAGE_NAME_ANDROID_UNPLUGGED = "com.google.android.apps.youtube.unplugged" + private const val CLIENT_VERSION_ANDROID_UNPLUGGED = "8.16.0" + + /** + * The device machine id for the Chromecast with Google TV 4K. + * See [this GitLab](https://dumps.tadiphone.dev/dumps/google/kirkwood) for more information. + */ + private const val DEVICE_MODEL_ANDROID_UNPLUGGED = "Google TV Streamer" + private const val OS_VERSION_ANDROID_UNPLUGGED = "14" + private const val ANDROID_SDK_VERSION_ANDROID_UNPLUGGED = "34" + private val USER_AGENT_ANDROID_UNPLUGGED = androidUserAgent( + PACKAGE_NAME_ANDROID_UNPLUGGED, + CLIENT_VERSION_ANDROID_UNPLUGGED, + OS_VERSION_ANDROID_UNPLUGGED + ) + + + // ANDROID MUSIC + /** + * Video not playable: All videos that can't be played on YouTube Music + */ + private const val PACKAGE_NAME_ANDROID_MUSIC = "com.google.android.apps.youtube.music" + + /** + * Older client versions don't seem to require poToken. + * It is not the default client yet, as it requires sufficient testing. + */ + private const val CLIENT_VERSION_ANDROID_MUSIC = "4.27.53" + private val ANDROID_SDK_VERSION_ANDROID_MUSIC = Build.VERSION.SDK_INT.toString() + private val USER_AGENT_ANDROID_MUSIC = androidUserAgent( + PACKAGE_NAME_ANDROID_MUSIC, + CLIENT_VERSION_ANDROID_MUSIC + ) + + + private fun androidUserAgent( + packageName: String, + clientVersion: String, + osVersion: String? = Build.VERSION.RELEASE + ): String { + return packageName + + "/" + + clientVersion + + " (Linux; U; Android " + + osVersion + + "; GB) gzip" + } + + private fun iOSUserAgent(packageName: String, clientVersion: String): String { + return packageName + + "/" + + clientVersion + + "(" + + DEVICE_MODEL_IOS + + "; U; CPU iOS " + + USER_AGENT_VERSION_IOS + + " like Mac OS X)" + } + + private fun forceAVC(): Boolean { + return BaseSettings.SPOOF_STREAMING_DATA_IOS_FORCE_AVC.get() + } + + @JvmStatic + val availableClientTypes: Array + get() = if (PatchStatus.SpoofStreamingDataMusic()) + ClientType.CLIENT_ORDER_TO_USE_YOUTUBE_MUSIC + else + ClientType.CLIENT_ORDER_TO_USE_YOUTUBE + + enum class ClientType( + /** + * [YouTube client type](https://github.com/zerodytrash/YouTube-Internal-Clients?tab=readme-ov-file#clients) + */ + val id: Int, + /** + * Device model, equivalent to [Build.MODEL] (System property: ro.product.model) + */ + @JvmField + val deviceModel: String? = Build.MODEL, + /** + * Device OS version, equivalent to [Build.VERSION.RELEASE] (System property: ro.system.build.version.release) + */ + @JvmField + val osVersion: String? = Build.VERSION.RELEASE, + /** + * Client user-agent. + */ + @JvmField + val userAgent: String, + /** + * Android SDK version, equivalent to [Build.VERSION.SDK] (System property: ro.build.version.sdk) + * Field is null if not applicable. + */ + @JvmField + val androidSdkVersion: String? = null, + /** + * App version. + */ + @JvmField + val clientVersion: String, + /** + * If the client can access the API logged in. + */ + @JvmField + val canLogin: Boolean? = true, + /** + * If a poToken should be used. + */ + @JvmField + val usePoToken: Boolean? = false, + /** + * Friendly name displayed in stats for nerds. + */ + @JvmField + val friendlyName: String + ) { + ANDROID_VR( + id = 28, + deviceModel = DEVICE_MODEL_ANDROID_VR, + osVersion = OS_VERSION_ANDROID_VR, + userAgent = USER_AGENT_ANDROID_VR, + androidSdkVersion = ANDROID_SDK_VERSION_ANDROID_VR, + clientVersion = CLIENT_VERSION_ANDROID_VR, + friendlyName = "Android VR" + ), + ANDROID_UNPLUGGED( + id = 29, + deviceModel = DEVICE_MODEL_ANDROID_UNPLUGGED, + osVersion = OS_VERSION_ANDROID_UNPLUGGED, + userAgent = USER_AGENT_ANDROID_UNPLUGGED, + androidSdkVersion = ANDROID_SDK_VERSION_ANDROID_UNPLUGGED, + clientVersion = CLIENT_VERSION_ANDROID_UNPLUGGED, + friendlyName = "Android TV" + ), + IOS_UNPLUGGED( + id = 33, + deviceModel = DEVICE_MODEL_IOS, + osVersion = OS_VERSION_IOS, + userAgent = USER_AGENT_IOS_UNPLUGGED, + clientVersion = CLIENT_VERSION_IOS_UNPLUGGED, + friendlyName = if (forceAVC()) + "iOS TV Force AVC" + else + "iOS TV" + ), + IOS( + id = 5, + deviceModel = DEVICE_MODEL_IOS, + osVersion = OS_VERSION_IOS, + userAgent = USER_AGENT_IOS, + clientVersion = CLIENT_VERSION_IOS, + canLogin = false, + usePoToken = true, + friendlyName = if (forceAVC()) + "iOS Force AVC" + else + "iOS" + ), + ANDROID_MUSIC( + id = 21, + userAgent = USER_AGENT_ANDROID_MUSIC, + androidSdkVersion = ANDROID_SDK_VERSION_ANDROID_MUSIC, + clientVersion = CLIENT_VERSION_ANDROID_MUSIC, + friendlyName = "Android Music" + ); + + @JvmField + val clientName: String = name + + companion object { + val CLIENT_ORDER_TO_USE_YOUTUBE: Array = arrayOf( + ANDROID_VR, + ANDROID_UNPLUGGED, + IOS_UNPLUGGED, + IOS, + ) + + internal val CLIENT_ORDER_TO_USE_YOUTUBE_MUSIC: Array = arrayOf( + ANDROID_VR, + ANDROID_MUSIC, + ) + } + } +} 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 81986ed4c..e61708942 100644 --- a/patches/src/main/resources/music/settings/host/values/arrays.xml +++ b/patches/src/main/resources/music/settings/host/values/arrays.xml @@ -67,12 +67,10 @@ @string/revanced_spoof_streaming_data_type_entry_android_vr - @string/revanced_spoof_streaming_data_type_entry_ios - @string/revanced_spoof_streaming_data_type_entry_ios_music + @string/revanced_spoof_streaming_data_type_entry_android_music ANDROID_VR - IOS - IOS_MUSIC + ANDROID_MUSIC 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 8415983e2..7d62c7fd5 100644 --- a/patches/src/main/resources/music/settings/host/values/strings.xml +++ b/patches/src/main/resources/music/settings/host/values/strings.xml @@ -468,10 +468,8 @@ Tap the continue button and allow optimization changes." Defines a default client that fetches streaming data. Show in Stats for nerds Shows the client used to fetch streaming data in Stats for nerds. - iOS - iOS Music - Android TV Android VR + Android Music Sanitize sharing links Removes tracking query parameters from URLs when sharing links. diff --git a/patches/src/main/resources/youtube/settings/host/values/arrays.xml b/patches/src/main/resources/youtube/settings/host/values/arrays.xml index 3ae7d2bf4..904839887 100644 --- a/patches/src/main/resources/youtube/settings/host/values/arrays.xml +++ b/patches/src/main/resources/youtube/settings/host/values/arrays.xml @@ -241,25 +241,17 @@ HEART_TINT HIDDEN - - @string/revanced_spoof_streaming_data_type_entry_android_unplugged + @string/revanced_spoof_streaming_data_type_entry_android_vr - - - ANDROID_UNPLUGGED - ANDROID_VR - - - @string/revanced_spoof_streaming_data_type_entry_ios + @string/revanced_spoof_streaming_data_type_entry_android_unplugged @string/revanced_spoof_streaming_data_type_entry_ios_unplugged - @string/revanced_spoof_streaming_data_type_entry_android_unplugged - @string/revanced_spoof_streaming_data_type_entry_android_vr + @string/revanced_spoof_streaming_data_type_entry_ios - - IOS - IOS_UNPLUGGED - ANDROID_UNPLUGGED + ANDROID_VR + ANDROID_UNPLUGGED + IOS_UNPLUGGED + IOS diff --git a/patches/src/main/resources/youtube/settings/host/values/strings.xml b/patches/src/main/resources/youtube/settings/host/values/strings.xml index 3aaf77a14..9055a4b6b 100644 --- a/patches/src/main/resources/youtube/settings/host/values/strings.xml +++ b/patches/src/main/resources/youtube/settings/host/values/strings.xml @@ -1906,15 +1906,11 @@ Tap the continue button and allow optimization changes." "Streaming data is not spoofed. Video playback may not work." Turning off this setting may cause video playback issues. Default client - iOS - iOS Music - iOS TV - Android Creator Android TV Android VR + iOS + iOS TV Spoofing side effects - • Not yet found. - • Movies or paid videos may not play. "• Audio track menu is missing. • Stable volume is not available. • Disable forced auto audio tracks is not available."