Skip to content

Commit

Permalink
fix(YouTube - Client spoof): Removed unused code (#480)
Browse files Browse the repository at this point in the history
Co-authored-by: oSumAtrIX <johan.melkonyan1@web.de>
  • Loading branch information
LisoUseInAIKyrios and oSumAtrIX committed Sep 25, 2023
1 parent 8999361 commit e6903bf
Show file tree
Hide file tree
Showing 5 changed files with 92 additions and 54 deletions.
@@ -1,13 +1,15 @@
package app.revanced.integrations.patches.spoof;

import static app.revanced.integrations.patches.spoof.requests.StoryBoardRendererRequester.fetchStoryboardRenderer;
import static app.revanced.integrations.utils.ReVancedUtils.containsAny;

import androidx.annotation.Nullable;

import app.revanced.integrations.patches.VideoInformation;
import app.revanced.integrations.settings.SettingsEnum;
import app.revanced.integrations.shared.PlayerType;
import app.revanced.integrations.utils.LogHelper;

import static app.revanced.integrations.patches.spoof.requests.StoryBoardRendererRequester.fetchStoryboardsRenderer;
import static app.revanced.integrations.utils.ReVancedUtils.containsAny;

/** @noinspection unused*/
public class SpoofSignaturePatch {
/**
Expand All @@ -31,16 +33,18 @@ public class SpoofSignaturePatch {
*/
private static final String SCRIM_PARAMETER = "SAFgAXgB";


/**
* Parameters used in YouTube Shorts.
*/
private static final String SHORTS_PLAYER_PARAMETERS = "8AEB";

private static boolean isPlayingShorts;
/**
* Last video id loaded. Used to prevent reloading the same spec multiple times.
*/
private static volatile String currentVideoId;

private static String storyboardRendererSpec = "";
private static int recommendedLevel;
@Nullable
private static volatile StoryboardRenderer renderer;

/**
* Injection point.
Expand All @@ -60,8 +64,7 @@ public static String spoofParameter(String parameters) {


// Shorts do not need to be spoofed.
//noinspection AssignmentUsedAsCondition
if (isPlayingShorts = parameters.startsWith(SHORTS_PLAYER_PARAMETERS)) return parameters;
if (parameters.startsWith(SHORTS_PLAYER_PARAMETERS)) return parameters;

boolean isPlayingFeed = PlayerType.getCurrent() == PlayerType.INLINE_MINIMAL && containsAny(parameters, AUTOPLAY_PARAMETERS);
if (isPlayingFeed) return SettingsEnum.SPOOF_SIGNATURE_IN_FEED.getBoolean() ?
Expand All @@ -72,7 +75,13 @@ public static String spoofParameter(String parameters) {
// This will cause playback issues in the feed, but it's better than manipulating the history.
parameters;

fetchStoryboardsRenderer(VideoInformation.getVideoId());
String videoId = VideoInformation.getVideoId();
if (!videoId.equals(currentVideoId)) {
currentVideoId = videoId;
renderer = fetchStoryboardRenderer(videoId);
LogHelper.printDebug(() -> "Fetched: " + renderer);
}

return INCOGNITO_PARAMETERS;
}

Expand All @@ -83,14 +92,18 @@ public static boolean getSeekbarThumbnailOverrideValue() {
return SettingsEnum.SPOOF_SIGNATURE.getBoolean();
}


/**
* Injection point.
* Called from background threads and from the main thread.
*/
@Nullable
public static String getStoryboardRendererSpec(String originalStoryboardRendererSpec) {
if (!SettingsEnum.SPOOF_SIGNATURE.getBoolean()) return originalStoryboardRendererSpec;

return storyboardRendererSpec;
StoryboardRenderer currentRenderer = renderer;
if (currentRenderer == null) return originalStoryboardRendererSpec;

return currentRenderer.getSpec();
}

/**
Expand All @@ -99,14 +112,10 @@ public static String getStoryboardRendererSpec(String originalStoryboardRenderer
public static int getRecommendedLevel(int originalLevel) {
if (!SettingsEnum.SPOOF_SIGNATURE.getBoolean()) return originalLevel;

return recommendedLevel;
}
StoryboardRenderer currentRenderer = renderer;
if (currentRenderer == null) return originalLevel;

public static void setStoryboardRendererSpec(String newlyLoadedStoryboardRendererSpec) {
storyboardRendererSpec = newlyLoadedStoryboardRendererSpec;
return currentRenderer.getRecommendedLevel();
}

public static void setRecommendedLevel(int level) {
recommendedLevel = level;
}
}
@@ -0,0 +1,32 @@
package app.revanced.integrations.patches.spoof;

import androidx.annotation.NonNull;
import org.jetbrains.annotations.NotNull;

public final class StoryboardRenderer {
private final String spec;
private final int recommendedLevel;

public StoryboardRenderer(String spec, int recommendedLevel) {
this.spec = spec;
this.recommendedLevel = recommendedLevel;
}

@NonNull
public String getSpec() {
return spec;
}

public int getRecommendedLevel() {
return recommendedLevel;
}

@NotNull
@Override
public String toString() {
return "StoryboardRenderer{" +
"spec='" + spec + '\'' +
", recommendedLevel=" + recommendedLevel +
'}';
}
}
Expand Up @@ -6,21 +6,21 @@
import java.io.IOException;
import java.net.HttpURLConnection;

/** @noinspection unused*/
public final class StoryBoardRendererRoutes {
final class PlayerRoutes {
private static final String YT_API_URL = "https://www.youtube.com/youtubei/v1/";
static final Route GET_STORYBOARD_SPEC = new Route(
static final Route.CompiledRoute POST_STORYBOARD_SPEC_RENDERER = new Route(
Route.Method.POST,
"player" +
"?fields=storyboards.playerStoryboardSpecRenderer," +
"storyboards.playerLiveStoryboardSpecRenderer"
);
).compile();

private StoryBoardRendererRoutes() {
private PlayerRoutes() {
}

public static HttpURLConnection getPlayerResponseConnectionFromRoute() throws IOException {
var connection = Requester.getConnectionFromRoute(YT_API_URL, GET_STORYBOARD_SPEC);
/** @noinspection SameParameterValue*/
static HttpURLConnection getPlayerResponseConnectionFromRoute(Route.CompiledRoute route) throws IOException {
var connection = Requester.getConnectionFromCompiledRoute(YT_API_URL, route);
connection.setRequestProperty("User-Agent", "com.google.android.youtube/18.37.36 (Linux; U; Android 12; GB) gzip");
connection.setRequestProperty("X-Goog-Api-Format-Version", "2");
connection.setRequestProperty("Content-Type", "application/json");
Expand Down
Expand Up @@ -2,16 +2,18 @@

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import app.revanced.integrations.patches.spoof.SpoofSignaturePatch;
import app.revanced.integrations.patches.spoof.StoryboardRenderer;
import app.revanced.integrations.requests.Requester;
import app.revanced.integrations.utils.LogHelper;
import app.revanced.integrations.utils.ReVancedUtils;
import org.json.JSONObject;

import java.io.IOException;
import java.net.HttpURLConnection;
import java.net.SocketTimeoutException;
import java.nio.charset.StandardCharsets;
import java.util.Objects;

import static app.revanced.integrations.patches.spoof.requests.PlayerRoutes.POST_STORYBOARD_SPEC_RENDERER;

public class StoryBoardRendererRequester {
private static final String INNER_TUBE_BODY =
Expand All @@ -30,14 +32,15 @@ public class StoryBoardRendererRequester {
private StoryBoardRendererRequester() {
}

// TODO: Find a way to increase the quality of SeekBar thumbnail previews
public static void fetchStoryboardsRenderer(@NonNull String videoId) {
ReVancedUtils.verifyOffMainThread();

@Nullable
public static StoryboardRenderer fetchStoryboardRenderer(@NonNull String videoId) {
try {
ReVancedUtils.verifyOffMainThread();
Objects.requireNonNull(videoId);

final byte[] innerTubeBody = String.format(INNER_TUBE_BODY, videoId).getBytes(StandardCharsets.UTF_8);

HttpURLConnection connection = StoryBoardRendererRoutes.getPlayerResponseConnectionFromRoute();
HttpURLConnection connection = PlayerRoutes.getPlayerResponseConnectionFromRoute(POST_STORYBOARD_SPEC_RENDERER);
connection.getOutputStream().write(innerTubeBody, 0, innerTubeBody.length);

final int responseCode = connection.getResponseCode();
Expand All @@ -49,33 +52,23 @@ public static void fetchStoryboardsRenderer(@NonNull String videoId) {
final String storyboardsRendererTag = storyboards.has("playerLiveStoryboardSpecRenderer")
? "playerLiveStoryboardSpecRenderer"
: "playerStoryboardSpecRenderer";
final JSONObject storyboardsRenderer = storyboards.getJSONObject(storyboardsRendererTag);
final String storyboardsRendererSpec = storyboardsRenderer.getString("spec");

SpoofSignaturePatch.setStoryboardRendererSpec(storyboardsRendererSpec);
SpoofSignaturePatch.setRecommendedLevel(storyboardsRenderer.getInt("recommendedLevel"));

LogHelper.printDebug(() -> "StoryBoard renderer spec: " + storyboardsRendererSpec);
final var renderer = storyboards.getJSONObject(storyboardsRendererTag);

return new StoryboardRenderer(
renderer.getString("spec"),
renderer.getInt("recommendedLevel")
);
} else {
handleConnectionError("API not available: " + responseCode, null);
LogHelper.printException(() -> "API not available: " + responseCode);
connection.disconnect();
}
connection.disconnect();
} catch (SocketTimeoutException ex) {
handleConnectionError("API timed out", ex);
} catch (IOException ex) {
handleConnectionError(String.format("Failed to fetch StoryBoard URL (%s)", ex.getMessage()), ex);
LogHelper.printException(() -> "API timed out", ex);
} catch (Exception ex) {
handleConnectionError("Failed to fetch StoryBoard URL", ex);
LogHelper.printException(() -> "Failed to fetch StoryBoard URL", ex);
}
}

private static void handleConnectionError(@NonNull String toastMessage, @Nullable Exception ex) {
if (ex != null)
LogHelper.printException(() -> toastMessage, ex);
else
LogHelper.printException(() -> toastMessage);

SpoofSignaturePatch.setStoryboardRendererSpec("");
return null;
}
}
Expand Up @@ -16,7 +16,11 @@ private Requester() {
}

public static HttpURLConnection getConnectionFromRoute(String apiUrl, Route route, String... params) throws IOException {
String url = apiUrl + route.compile(params).getCompiledRoute();
return getConnectionFromCompiledRoute(apiUrl, route.compile(params));
}

public static HttpURLConnection getConnectionFromCompiledRoute(String apiUrl, Route.CompiledRoute route) throws IOException {
String url = apiUrl + route.getCompiledRoute();
HttpURLConnection connection = (HttpURLConnection) new URL(url).openConnection();
connection.setRequestMethod(route.getMethod().name());
connection.setRequestProperty("User-agent", System.getProperty("http.agent") + ";revanced");
Expand Down

0 comments on commit e6903bf

Please sign in to comment.