From d961d349c35c93c53ae419935d93fa4533fe71ca Mon Sep 17 00:00:00 2001 From: Kavin <20838718+FireMasterK@users.noreply.github.com> Date: Sun, 18 Jun 2023 20:54:52 +0100 Subject: [PATCH] [YouTube] Check whether player responses are valid for all InnerTube clients used (#1070) Co-authored-by: Audric V <74829229+AudricV@users.noreply.github.com> --- .../extractors/YoutubeStreamExtractor.java | 42 ++++++++++++------- 1 file changed, 28 insertions(+), 14 deletions(-) diff --git a/extractor/src/main/java/org/schabi/newpipe/extractor/services/youtube/extractors/YoutubeStreamExtractor.java b/extractor/src/main/java/org/schabi/newpipe/extractor/services/youtube/extractors/YoutubeStreamExtractor.java index 17462aac3..113f2d4a3 100644 --- a/extractor/src/main/java/org/schabi/newpipe/extractor/services/youtube/extractors/YoutubeStreamExtractor.java +++ b/extractor/src/main/java/org/schabi/newpipe/extractor/services/youtube/extractors/YoutubeStreamExtractor.java @@ -868,6 +868,10 @@ public class YoutubeStreamExtractor extends StreamExtractor { playerMicroFormatRenderer = youtubePlayerResponse.getObject("microformat") .getObject("playerMicroformatRenderer"); + if (isPlayerResponseNotValid(playerResponse, videoId)) { + throw new ExtractionException("Initial player response is not valid"); + } + final byte[] body = JsonWriter.string( prepareDesktopJsonBuilder(localization, contentCountry) .value(VIDEO_ID, videoId) @@ -1058,6 +1062,11 @@ public class YoutubeStreamExtractor extends StreamExtractor { final JsonObject tvHtml5EmbedPlayerResponse = getJsonPostResponse(PLAYER, createDesktopPlayerBody(localization, contentCountry, videoId, sts, true, html5Cpn), localization); + + if (isPlayerResponseNotValid(tvHtml5EmbedPlayerResponse, videoId)) { + return; + } + final JsonObject streamingData = tvHtml5EmbedPlayerResponse.getObject( STREAMING_DATA); if (!isNullOrEmpty(streamingData)) { @@ -1067,12 +1076,24 @@ public class YoutubeStreamExtractor extends StreamExtractor { } /** - * Checks whether an additional player response is not valid. + * Checks whether a player response is invalid. * *

* If YouTube detect that requests come from a third party client, they may replace the real * player response by another one of a video saying that this content is not available on this - * app and to watch it on the latest version of YouTube. + * app and to watch it on the latest version of YouTube. This behavior has been observed on the + * {@code ANDROID} client, see + * + * https://github.com/TeamNewPipe/NewPipe/issues/8713. + *

+ * + *

+ * YouTube may also sometimes for currently unknown reasons rate-limit an IP, and replace the + * real one by a player response with a video that says that the requested video is + * unavailable. This behaviour has been observed in Piped on the InnerTube clients used by the + * extractor ({@code ANDROID} and {@code WEB} clients) which should apply for all clients, see + * + * https://github.com/TeamPiped/Piped/issues/2487. *

* *

@@ -1080,22 +1101,15 @@ public class YoutubeStreamExtractor extends StreamExtractor { * same as the one requested by the extractor. *

* - *

- * This behavior has been already observed on the {@code ANDROID} client, see - * - * https://github.com/TeamNewPipe/NewPipe/issues/8713. - *

- * - * @param additionalPlayerResponse an additional response to the one of the {@code HTML5} - * client used - * @param videoId the video ID of the content requested + * @param playerResponse a player response from any client + * @param videoId the video ID of the content requested * @return whether the video ID of the player response is not equal to the one requested */ private static boolean isPlayerResponseNotValid( - @Nonnull final JsonObject additionalPlayerResponse, + @Nonnull final JsonObject playerResponse, @Nonnull final String videoId) { - return !videoId.equals(additionalPlayerResponse.getObject("videoDetails") - .getString("videoId", "")); + return !videoId.equals(playerResponse.getObject("videoDetails") + .getString("videoId")); } private static void storePlayerJs() throws ParsingException {