diff --git a/extensions/shared/src/main/java/app/revanced/extension/youtube/patches/spoof/ClientType.java b/extensions/shared/src/main/java/app/revanced/extension/youtube/patches/spoof/ClientType.java index de6a2a12c..2c1f0d55f 100644 --- a/extensions/shared/src/main/java/app/revanced/extension/youtube/patches/spoof/ClientType.java +++ b/extensions/shared/src/main/java/app/revanced/extension/youtube/patches/spoof/ClientType.java @@ -8,6 +8,17 @@ import android.os.Build; import androidx.annotation.Nullable; public enum ClientType { + // Specific purpose for age restricted, or private videos, because the iOS client is not logged in. + ANDROID_VR(28, + "Quest 3", + "12", + "com.google.android.apps.youtube.vr.oculus/1.56.21 (Linux; U; Android 12; GB) gzip", + "32", // Android 12.1 + "1.56.21", + "ANDROID_VR", + true + ), + // Specific for kids videos. // https://dumps.tadiphone.dev/dumps/oculus/eureka IOS(5, // iPhone 15 supports AV1 hardware decoding. @@ -25,14 +36,9 @@ public enum ClientType { null, // Version number should be a valid iOS release. // https://www.ipa4fun.com/history/185230 - "19.10.7" - ), - ANDROID_VR(28, - "Quest 3", - "12", - "com.google.android.apps.youtube.vr.oculus/1.56.21 (Linux; U; Android 12; GB) gzip", - "32", // Android 12.1 - "1.56.21" + "19.10.7", + "IOS", + false ); /** @@ -44,7 +50,7 @@ public enum ClientType { /** * Device model, equivalent to {@link Build#MODEL} (System property: ro.product.model) */ - public final String model; + public final String deviceModel; /** * Device OS version. @@ -63,17 +69,37 @@ public enum ClientType { @Nullable public final String androidSdkVersion; + /** + * Client name. + */ + public final String clientName; + /** * App version. */ - public final String appVersion; + public final String clientVersion; - ClientType(int id, String model, String osVersion, String userAgent, @Nullable String androidSdkVersion, String appVersion) { + /** + * If the client can access the API logged in. + */ + public final boolean canLogin; + + ClientType(int id, + String deviceModel, + String osVersion, + String userAgent, + @Nullable String androidSdkVersion, + String clientVersion, + String clientName, + boolean canLogin + ) { this.id = id; - this.model = model; + this.deviceModel = deviceModel; this.osVersion = osVersion; this.userAgent = userAgent; this.androidSdkVersion = androidSdkVersion; - this.appVersion = appVersion; + this.clientVersion = clientVersion; + this.clientName = clientName; + this.canLogin = canLogin; } } diff --git a/extensions/shared/src/main/java/app/revanced/extension/youtube/patches/spoof/requests/PlayerRoutes.java b/extensions/shared/src/main/java/app/revanced/extension/youtube/patches/spoof/requests/PlayerRoutes.java index 364dc173a..3388892cc 100644 --- a/extensions/shared/src/main/java/app/revanced/extension/youtube/patches/spoof/requests/PlayerRoutes.java +++ b/extensions/shared/src/main/java/app/revanced/extension/youtube/patches/spoof/requests/PlayerRoutes.java @@ -12,15 +12,13 @@ import app.revanced.extension.youtube.requests.Requester; import app.revanced.extension.youtube.requests.Route; final class PlayerRoutes { - private static final String YT_API_URL = "https://youtubei.googleapis.com/youtubei/v1/"; - static final Route.CompiledRoute GET_STREAMING_DATA = new Route( Route.Method.POST, "player" + "?fields=streamingData" + "&alt=proto" ).compile(); - + private static final String YT_API_URL = "https://youtubei.googleapis.com/youtubei/v1/"; /** * TCP connection and HTTP read timeout */ @@ -30,15 +28,15 @@ final class PlayerRoutes { } static String createInnertubeBody(ClientType clientType) { - JSONObject innerTubeBody = new JSONObject(); + JSONObject innerTubeBody = new JSONObject(); try { JSONObject context = new JSONObject(); JSONObject client = new JSONObject(); client.put("clientName", clientType.name()); - client.put("clientVersion", clientType.appVersion); - client.put("deviceModel", clientType.model); + client.put("clientVersion", clientType.clientVersion); + client.put("deviceModel", clientType.deviceModel); client.put("osVersion", clientType.osVersion); if (clientType.androidSdkVersion != null) { client.put("androidSdkVersion", clientType.androidSdkVersion); @@ -57,7 +55,9 @@ final class PlayerRoutes { return innerTubeBody.toString(); } - /** @noinspection SameParameterValue*/ + /** + * @noinspection SameParameterValue + */ static HttpURLConnection getPlayerResponseConnectionFromRoute(Route.CompiledRoute route, ClientType clientType) throws IOException { var connection = Requester.getConnectionFromCompiledRoute(YT_API_URL, route); diff --git a/extensions/shared/src/main/java/app/revanced/extension/youtube/patches/spoof/requests/StreamingDataRequest.java b/extensions/shared/src/main/java/app/revanced/extension/youtube/patches/spoof/requests/StreamingDataRequest.java index e66f4d885..0c09e0fa7 100644 --- a/extensions/shared/src/main/java/app/revanced/extension/youtube/patches/spoof/requests/StreamingDataRequest.java +++ b/extensions/shared/src/main/java/app/revanced/extension/youtube/patches/spoof/requests/StreamingDataRequest.java @@ -28,7 +28,7 @@ import app.revanced.extension.youtube.settings.Settings; /** * Video streaming data. Fetching is tied to the behavior YT uses, * where this class fetches the streams only when YT fetches. - * + *
* Effectively the cache expiration of these fetches is the same as the stock app,
* since the stock app would not use expired streams and therefor
* the extension replace stream hook is called only if YT
@@ -37,38 +37,20 @@ import app.revanced.extension.youtube.settings.Settings;
public class StreamingDataRequest {
private static final ClientType[] CLIENT_ORDER_TO_USE;
-
- static {
- ClientType[] allClientTypes = ClientType.values();
- ClientType preferredClient = Settings.SPOOF_VIDEO_STREAMS_CLIENT_TYPE.get();
-
- CLIENT_ORDER_TO_USE = new ClientType[allClientTypes.length];
- CLIENT_ORDER_TO_USE[0] = preferredClient;
-
- int i = 1;
- for (ClientType c : allClientTypes) {
- if (c != preferredClient) {
- CLIENT_ORDER_TO_USE[i++] = c;
- }
- }
- }
-
+ private static final String AUTHORIZATION_HEADER = "Authorization";
private static final String[] REQUEST_HEADER_KEYS = {
- "Authorization", // Available only to logged in users.
+ AUTHORIZATION_HEADER, // Available only to logged-in users.
"X-GOOG-API-FORMAT-VERSION",
"X-Goog-Visitor-Id"
};
-
/**
* TCP connection and HTTP read timeout.
*/
private static final int HTTP_TIMEOUT_MILLISECONDS = 10 * 1000;
-
/**
* Any arbitrarily large value, but must be at least twice {@link #HTTP_TIMEOUT_MILLISECONDS}
*/
private static final int MAX_MILLISECONDS_TO_WAIT_FOR_FETCH = 20 * 1000;
-
private static final Map