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 index 0613ec951..6e6e18eaf 100644 --- 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 @@ -316,6 +316,10 @@ object AppClient { * Whether a poToken is required to get playback for more than 1 minute. */ val requirePoToken: Boolean = false, + /** + * Client name for innertube body. + */ + val clientName: String, /** * Friendly name displayed in stats for nerds. */ @@ -330,8 +334,22 @@ object AppClient { androidSdkVersion = ANDROID_SDK_VERSION_ANDROID_VR, clientVersion = CLIENT_VERSION_ANDROID_VR, chipset = CHIPSET_ANDROID_VR, + clientName = "ANDROID_VR", friendlyName = "Android VR" ), + ANDROID_VR_NO_AUTH( + id = 28, + deviceMake = DEVICE_MAKE_ANDROID_VR, + 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, + chipset = CHIPSET_ANDROID_VR, + supportsCookies = false, + clientName = "ANDROID_VR", + friendlyName = "Android VR No auth" + ), ANDROID_UNPLUGGED( id = 29, deviceMake = DEVICE_MAKE_ANDROID_UNPLUGGED, @@ -343,6 +361,7 @@ object AppClient { gmscoreVersionCode = GMS_CORE_VERSION_CODE_ANDROID_UNPLUGGED, chipset = CHIPSET_ANDROID_UNPLUGGED, requireAuth = true, + clientName = "ANDROID_UNPLUGGED", friendlyName = "Android TV" ), ANDROID_CREATOR( @@ -356,6 +375,7 @@ object AppClient { gmscoreVersionCode = GMS_CORE_VERSION_CODE_ANDROID_CREATOR, chipset = CHIPSET_ANDROID_CREATOR, requireAuth = true, + clientName = "ANDROID_CREATOR", friendlyName = "Android Studio" ), IOS_UNPLUGGED( @@ -367,6 +387,7 @@ object AppClient { userAgent = USER_AGENT_IOS_UNPLUGGED, clientVersion = CLIENT_VERSION_IOS_UNPLUGGED, requireAuth = true, + clientName = "IOS_UNPLUGGED", friendlyName = if (forceAVC()) "iOS TV Force AVC" else @@ -382,6 +403,7 @@ object AppClient { clientVersion = CLIENT_VERSION_IOS, supportsCookies = false, requirePoToken = true, + clientName = "IOS", friendlyName = if (forceAVC()) "iOS Force AVC" else @@ -398,11 +420,10 @@ object AppClient { gmscoreVersionCode = GMS_CORE_VERSION_CODE_ANDROID_MUSIC, chipset = CHIPSET_ANDROID_MUSIC, requireAuth = true, + clientName = "ANDROID_MUSIC", friendlyName = "Android Music" ); - val clientName: String = name - companion object { val CLIENT_ORDER_TO_USE_YOUTUBE: Array = arrayOf( ANDROID_VR, @@ -410,6 +431,7 @@ object AppClient { IOS_UNPLUGGED, ANDROID_CREATOR, IOS, + ANDROID_VR_NO_AUTH, ) internal val CLIENT_ORDER_TO_USE_YOUTUBE_MUSIC: Array = arrayOf( diff --git a/extensions/shared/src/main/java/app/revanced/extension/shared/patches/spoof/SpoofStreamingDataPatch.java b/extensions/shared/src/main/java/app/revanced/extension/shared/patches/spoof/SpoofStreamingDataPatch.java index 7361c97d5..fbebfe515 100644 --- a/extensions/shared/src/main/java/app/revanced/extension/shared/patches/spoof/SpoofStreamingDataPatch.java +++ b/extensions/shared/src/main/java/app/revanced/extension/shared/patches/spoof/SpoofStreamingDataPatch.java @@ -13,8 +13,10 @@ import java.util.Collections; import java.util.LinkedHashMap; import java.util.Map; +import app.revanced.extension.shared.patches.client.AppClient.ClientType; import app.revanced.extension.shared.patches.spoof.requests.StreamingDataRequest; import app.revanced.extension.shared.settings.BaseSettings; +import app.revanced.extension.shared.settings.Setting; import app.revanced.extension.shared.utils.Logger; import app.revanced.extension.shared.utils.Utils; @@ -341,4 +343,12 @@ public class SpoofStreamingDataPatch { return videoFormat; } + + public static final class AudioStreamLanguageOverrideAvailability implements Setting.Availability { + @Override + public boolean isAvailable() { + return BaseSettings.SPOOF_STREAMING_DATA.get() && + BaseSettings.SPOOF_STREAMING_DATA_TYPE.get() == ClientType.ANDROID_VR_NO_AUTH; + } + } } diff --git a/extensions/shared/src/main/java/app/revanced/extension/shared/patches/spoof/requests/PlayerRoutes.kt b/extensions/shared/src/main/java/app/revanced/extension/shared/patches/spoof/requests/PlayerRoutes.kt index ab0e56bc0..d16448c59 100644 --- a/extensions/shared/src/main/java/app/revanced/extension/shared/patches/spoof/requests/PlayerRoutes.kt +++ b/extensions/shared/src/main/java/app/revanced/extension/shared/patches/spoof/requests/PlayerRoutes.kt @@ -5,6 +5,7 @@ import app.revanced.extension.shared.patches.client.WebClient import app.revanced.extension.shared.requests.Requester import app.revanced.extension.shared.requests.Route import app.revanced.extension.shared.requests.Route.CompiledRoute +import app.revanced.extension.shared.settings.BaseSettings import app.revanced.extension.shared.utils.Logger import app.revanced.extension.shared.utils.Utils import org.apache.commons.lang3.StringUtils @@ -77,7 +78,7 @@ object PlayerRoutes { client.put("clientVersion", clientType.clientVersion) client.put("osName", clientType.osName) client.put("osVersion", clientType.osVersion) - if (clientType.osName != "iOS") { + if (clientType.osName == "Android") { client.put("androidSdkVersion", clientType.androidSdkVersion) if (clientType.gmscoreVersionCode != null) { client.put("gmscoreVersionCode", clientType.gmscoreVersionCode) @@ -86,12 +87,18 @@ object PlayerRoutes { client.put("chipset", clientType.chipset) } } - if (setLocale) { - client.put("hl", LOCALE_LANGUAGE) - client.put("gl", LOCALE_COUNTRY) - client.put("timeZone", TIME_ZONE_ID) - client.put("utcOffsetMinutes", "$UTC_OFFSET_MINUTES") - } + client.put( + "hl", + if (setLocale) { + BaseSettings.SPOOF_STREAMING_DATA_LANGUAGE.get().language + } else { + LOCALE_LANGUAGE + } + ) + client.put("gl", LOCALE_COUNTRY) + client.put("timeZone", TIME_ZONE_ID) + client.put("utcOffsetMinutes", "$UTC_OFFSET_MINUTES") + val context = JSONObject() context.put("client", client) diff --git a/extensions/shared/src/main/java/app/revanced/extension/shared/patches/spoof/requests/StreamingDataRequest.kt b/extensions/shared/src/main/java/app/revanced/extension/shared/patches/spoof/requests/StreamingDataRequest.kt index 3eb64af98..e8fc4cb11 100644 --- a/extensions/shared/src/main/java/app/revanced/extension/shared/patches/spoof/requests/StreamingDataRequest.kt +++ b/extensions/shared/src/main/java/app/revanced/extension/shared/patches/spoof/requests/StreamingDataRequest.kt @@ -93,9 +93,14 @@ class StreamingDataRequest private constructor( "X-GOOG-API-FORMAT-VERSION", VISITOR_ID_HEADER ) + private val SPOOF_STREAMING_DATA_TYPE: AppClient.ClientType = + BaseSettings.SPOOF_STREAMING_DATA_TYPE.get() private val CLIENT_ORDER_TO_USE: Array = - availableClientTypes(BaseSettings.SPOOF_STREAMING_DATA_TYPE.get()) + availableClientTypes(SPOOF_STREAMING_DATA_TYPE) + + private val DEFAULT_CLIENT_IS_ANDROID_VR_NO_AUTH: Boolean = + SPOOF_STREAMING_DATA_TYPE == AppClient.ClientType.ANDROID_VR_NO_AUTH private var lastSpoofedClientType: AppClient.ClientType? = null @@ -177,8 +182,6 @@ class StreamingDataRequest private constructor( connection.connectTimeout = HTTP_TIMEOUT_MILLISECONDS connection.readTimeout = HTTP_TIMEOUT_MILLISECONDS - val setLocale = - !clientType.supportsCookies || playerHeaders[AUTHORIZATION_HEADER] == null val usePoToken = clientType.requirePoToken && !StringUtils.isAnyEmpty(botGuardPoToken, visitorId) @@ -209,7 +212,7 @@ class StreamingDataRequest private constructor( videoId = videoId, botGuardPoToken = botGuardPoToken, visitorId = visitorId, - setLocale = setLocale + setLocale = DEFAULT_CLIENT_IS_ANDROID_VR_NO_AUTH, ) Logger.printDebug { "Set poToken (botGuardPoToken):\n$botGuardPoToken" } } else { @@ -217,9 +220,10 @@ class StreamingDataRequest private constructor( createApplicationRequestBody( clientType = clientType, videoId = videoId, - setLocale = setLocale + setLocale = DEFAULT_CLIENT_IS_ANDROID_VR_NO_AUTH, ) } + connection.setFixedLengthStreamingMode(requestBody.size) connection.outputStream.write(requestBody) 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 2044089f1..63c3c5b05 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 @@ -6,6 +6,7 @@ import static app.revanced.extension.shared.patches.PatchStatus.HideFullscreenAd import app.revanced.extension.shared.patches.ReturnYouTubeUsernamePatch.DisplayFormat; import app.revanced.extension.shared.patches.client.AppClient.ClientType; +import app.revanced.extension.shared.patches.spoof.SpoofStreamingDataPatch.AudioStreamLanguageOverrideAvailability; /** * Settings shared across multiple apps. @@ -39,6 +40,7 @@ public class BaseSettings { 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); 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_LANGUAGE = new EnumSetting<>("revanced_spoof_streaming_data_language", AppLanguage.DEFAULT, new AudioStreamLanguageOverrideAvailability()); public static final BooleanSetting SPOOF_STREAMING_DATA_IOS_FORCE_AVC = new BooleanSetting("revanced_spoof_streaming_data_ios_force_avc", FALSE, true, "revanced_spoof_streaming_data_ios_force_avc_user_dialog_message"); public static final BooleanSetting SPOOF_STREAMING_DATA_STATS_FOR_NERDS = new BooleanSetting("revanced_spoof_streaming_data_stats_for_nerds", TRUE); 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 59dee4e88..eaddcfd11 100644 --- a/patches/src/main/resources/youtube/settings/host/values/arrays.xml +++ b/patches/src/main/resources/youtube/settings/host/values/arrays.xml @@ -363,12 +363,14 @@ @string/revanced_spoof_streaming_data_type_entry_android_vr + @string/revanced_spoof_streaming_data_type_entry_android_vr_no_auth @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_ios ANDROID_VR + ANDROID_VR_NO_AUTH 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 a6ced114b..2ba5374a5 100644 --- a/patches/src/main/resources/youtube/settings/host/values/strings.xml +++ b/patches/src/main/resources/youtube/settings/host/values/strings.xml @@ -1980,6 +1980,8 @@ Tap the continue button and allow optimization changes." "Android TV (Login required)" Android VR + "Android VR +(No auth)" "iOS (PoToken required)" "iOS TV @@ -2001,6 +2003,7 @@ AVC has a maximum resolution of 1080p, Opus audio codec is not available, and vi Show in Stats for nerds Client used to fetch streaming data is shown in Stats for nerds. Client used to fetch streaming data is hidden in Stats for nerds. + VR default audio stream language PoToken / VisitorData diff --git a/patches/src/main/resources/youtube/settings/values-v21/strings.xml b/patches/src/main/resources/youtube/settings/values-v21/strings.xml index 6fe87a4c3..760062454 100644 --- a/patches/src/main/resources/youtube/settings/values-v21/strings.xml +++ b/patches/src/main/resources/youtube/settings/values-v21/strings.xml @@ -4,4 +4,5 @@ @string/revanced_spoof_streaming_data_side_effects_android @string/revanced_spoof_streaming_data_side_effects_android @string/revanced_spoof_streaming_data_side_effects_android + @string/revanced_spoof_streaming_data_side_effects_android diff --git a/patches/src/main/resources/youtube/settings/xml/revanced_prefs.xml b/patches/src/main/resources/youtube/settings/xml/revanced_prefs.xml index 8c4324e90..7b8ee05a2 100644 --- a/patches/src/main/resources/youtube/settings/xml/revanced_prefs.xml +++ b/patches/src/main/resources/youtube/settings/xml/revanced_prefs.xml @@ -797,6 +797,7 @@ +