From 16b59af88fb7e6b6f19e12749f2b63a047bf3025 Mon Sep 17 00:00:00 2001 From: AudricV <74829229+AudricV@users.noreply.github.com> Date: Mon, 8 Aug 2022 22:40:49 +0200 Subject: [PATCH] [YouTube] Ensure that an additional player response is the correct one 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. We can detect this by checking whether the video ID of the player response returned is the same as the one requested by the extractor. --- .../extractors/YoutubeStreamExtractor.java | 40 +++++++++++++++++++ 1 file changed, 40 insertions(+) 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 5b9ae5801a..979ce85eea 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 @@ -926,6 +926,10 @@ private void fetchAndroidMobileJsonPlayer(@Nonnull final ContentCountry contentC mobileBody, localization, "&t=" + generateTParameter() + "&id=" + videoId); + if (isPlayerResponseNotValid(androidPlayerResponse, videoId)) { + return; + } + final JsonObject streamingData = androidPlayerResponse.getObject(STREAMING_DATA); if (!isNullOrEmpty(streamingData)) { androidStreamingData = streamingData; @@ -957,6 +961,10 @@ private void fetchIosMobileJsonPlayer(@Nonnull final ContentCountry contentCount mobileBody, localization, "&t=" + generateTParameter() + "&id=" + videoId); + if (isPlayerResponseNotValid(iosPlayerResponse, videoId)) { + return; + } + final JsonObject streamingData = iosPlayerResponse.getObject(STREAMING_DATA); if (!isNullOrEmpty(streamingData)) { iosStreamingData = streamingData; @@ -995,6 +1003,38 @@ private void fetchTvHtml5EmbedJsonPlayer(@Nonnull final ContentCountry contentCo } } + /** + * Checks whether an additional player response is not valid. + * + *
+ * 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. + *
+ * + *+ * We can detect this by checking whether the video ID of the player response returned is the + * 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 + * @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 String videoId) { + return !videoId.equals(additionalPlayerResponse.getObject("videoDetails") + .getString("videoId", "")); + } + private static void storePlayerJs() throws ParsingException { try { playerCode = YoutubeJavaScriptExtractor.extractJavaScriptCode();