mirror of
https://github.com/revanced/revanced-integrations.git
synced 2024-12-01 00:02:55 +01:00
fix(YouTube - Client spoof): Restore seekbar thumbnails
This works around the issue, but causes seekbar thumbnails to be in low quality.
This commit is contained in:
parent
bfae6b56ab
commit
978f630c02
@ -1,12 +1,11 @@
|
|||||||
package app.revanced.integrations.patches;
|
package app.revanced.integrations.patches.spoof;
|
||||||
|
|
||||||
import android.view.View;
|
import app.revanced.integrations.patches.VideoInformation;
|
||||||
import android.view.ViewGroup;
|
|
||||||
import android.widget.ImageView;
|
|
||||||
import app.revanced.integrations.settings.SettingsEnum;
|
import app.revanced.integrations.settings.SettingsEnum;
|
||||||
import app.revanced.integrations.shared.PlayerType;
|
import app.revanced.integrations.shared.PlayerType;
|
||||||
import app.revanced.integrations.utils.LogHelper;
|
import app.revanced.integrations.utils.LogHelper;
|
||||||
|
|
||||||
|
import static app.revanced.integrations.patches.spoof.requests.StoryBoardRendererRequester.fetchStoryboardsRenderer;
|
||||||
import static app.revanced.integrations.utils.ReVancedUtils.containsAny;
|
import static app.revanced.integrations.utils.ReVancedUtils.containsAny;
|
||||||
|
|
||||||
/** @noinspection unused*/
|
/** @noinspection unused*/
|
||||||
@ -40,6 +39,8 @@ public class SpoofSignaturePatch {
|
|||||||
|
|
||||||
private static boolean isPlayingShorts;
|
private static boolean isPlayingShorts;
|
||||||
|
|
||||||
|
private static String storyboardRendererSpec = "";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Injection point.
|
* Injection point.
|
||||||
*
|
*
|
||||||
@ -63,6 +64,7 @@ public class SpoofSignaturePatch {
|
|||||||
// This will cause playback issues in the feed, but it's better than manipulating the history.
|
// This will cause playback issues in the feed, but it's better than manipulating the history.
|
||||||
parameters;
|
parameters;
|
||||||
|
|
||||||
|
fetchStoryboardsRenderer(VideoInformation.getVideoId());
|
||||||
return INCOGNITO_PARAMETERS;
|
return INCOGNITO_PARAMETERS;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -75,16 +77,15 @@ public class SpoofSignaturePatch {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Injection point.
|
* Injection point.
|
||||||
*
|
|
||||||
* @param view seekbar thumbnail view. Includes both shorts and regular videos.
|
|
||||||
*/
|
*/
|
||||||
public static void seekbarImageViewCreated(ImageView view) {
|
public static String getStoryboardRendererSpec() {
|
||||||
if (!SettingsEnum.SPOOF_SIGNATURE.getBoolean()) return;
|
return storyboardRendererSpec;
|
||||||
if (isPlayingShorts) return;
|
}
|
||||||
|
|
||||||
view.setVisibility(View.GONE);
|
public static void setStoryboardRendererSpec(String newlyLoadedStoryboardRendererSpec) {
|
||||||
// Also hide the border around the thumbnail (otherwise a 1 pixel wide bordered frame is visible).
|
if (storyboardRendererSpec.equals(newlyLoadedStoryboardRendererSpec))
|
||||||
ViewGroup parentLayout = (ViewGroup) view.getParent();
|
return;
|
||||||
parentLayout.setPadding(0, 0, 0, 0);
|
|
||||||
|
storyboardRendererSpec = newlyLoadedStoryboardRendererSpec;
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -0,0 +1,79 @@
|
|||||||
|
package app.revanced.integrations.patches.spoof.requests;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.annotation.Nullable;
|
||||||
|
import app.revanced.integrations.patches.spoof.SpoofSignaturePatch;
|
||||||
|
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;
|
||||||
|
|
||||||
|
public class StoryBoardRendererRequester {
|
||||||
|
private static final String INNER_TUBE_BODY =
|
||||||
|
"{" +
|
||||||
|
"\"context\": " +
|
||||||
|
"{" +
|
||||||
|
"\"client\": " +
|
||||||
|
"{ " +
|
||||||
|
"\"clientName\": \"ANDROID\", \"clientVersion\": \"18.37.36\", \"platform\": \"MOBILE\", " +
|
||||||
|
"\"osName\": \"Android\", \"osVersion\": \"12\", \"androidSdkVersion\": 31 " +
|
||||||
|
"} " +
|
||||||
|
"}, " +
|
||||||
|
"\"videoId\": \"%s\"" +
|
||||||
|
"}";
|
||||||
|
|
||||||
|
private StoryBoardRendererRequester() {
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: Find a way to increase the quality of SeekBar thumbnail previews
|
||||||
|
public static void fetchStoryboardsRenderer(@NonNull String videoId) {
|
||||||
|
ReVancedUtils.verifyOffMainThread();
|
||||||
|
|
||||||
|
try {
|
||||||
|
final byte[] innerTubeBody = String.format(INNER_TUBE_BODY, videoId).getBytes(StandardCharsets.UTF_8);
|
||||||
|
|
||||||
|
HttpURLConnection connection = StoryBoardRendererRoutes.getPlayerResponseConnectionFromRoute();
|
||||||
|
connection.getOutputStream().write(innerTubeBody, 0, innerTubeBody.length);
|
||||||
|
|
||||||
|
final int responseCode = connection.getResponseCode();
|
||||||
|
|
||||||
|
if (responseCode == 200) {
|
||||||
|
final JSONObject playerResponse = Requester.parseJSONObject(connection);
|
||||||
|
|
||||||
|
final JSONObject storyboards = playerResponse.getJSONObject("storyboards");
|
||||||
|
final String storyboardsRendererTag = storyboards.has("playerLiveStoryboardSpecRenderer")
|
||||||
|
? "playerLiveStoryboardSpecRenderer"
|
||||||
|
: "playerStoryboardSpecRenderer";
|
||||||
|
final JSONObject storyboardsRenderer = storyboards.getJSONObject(storyboardsRendererTag);
|
||||||
|
final String storyboardsRendererSpec = storyboardsRenderer.getString("spec");
|
||||||
|
|
||||||
|
SpoofSignaturePatch.setStoryboardRendererSpec(storyboardsRendererSpec);
|
||||||
|
LogHelper.printDebug(() -> "StoryBoard renderer spec: " + storyboardsRendererSpec);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
handleConnectionError("API not available: " + responseCode, null);
|
||||||
|
}
|
||||||
|
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);
|
||||||
|
} catch (Exception ex) {
|
||||||
|
handleConnectionError("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("");
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,34 @@
|
|||||||
|
package app.revanced.integrations.patches.spoof.requests;
|
||||||
|
|
||||||
|
import app.revanced.integrations.requests.Requester;
|
||||||
|
import app.revanced.integrations.requests.Route;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.net.HttpURLConnection;
|
||||||
|
|
||||||
|
/** @noinspection unused*/
|
||||||
|
public final class StoryBoardRendererRoutes {
|
||||||
|
private static final String YT_API_URL = "https://www.youtube.com/youtubei/v1/";
|
||||||
|
private static final String YT_API_KEY = "AIzaSyA8eiZmM1FaDVjRy-df2KTyQ_vz_yYM39w";
|
||||||
|
|
||||||
|
static final Route GET_PLAYER_RESPONSE_BODY = new Route(Route.Method.POST, "player?key={api_key}");
|
||||||
|
|
||||||
|
private StoryBoardRendererRoutes() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public static HttpURLConnection getPlayerResponseConnectionFromRoute() throws IOException {
|
||||||
|
var connection = Requester.getConnectionFromRoute(YT_API_URL, GET_PLAYER_RESPONSE_BODY, YT_API_KEY);
|
||||||
|
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");
|
||||||
|
connection.setRequestProperty("Accept-Language", "en-GB, en;q=0.9");
|
||||||
|
connection.setRequestProperty("Pragma", "no-cache");
|
||||||
|
connection.setRequestProperty("Cache-Control", "no-cache");
|
||||||
|
connection.setUseCaches(false);
|
||||||
|
connection.setDoOutput(true);
|
||||||
|
connection.setConnectTimeout(5000);
|
||||||
|
connection.setReadTimeout(5000);
|
||||||
|
return connection;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user