[YouTube] Check whether player responses are valid for all InnerTube clients used (#1070)

Co-authored-by: Audric V <74829229+AudricV@users.noreply.github.com>
This commit is contained in:
Kavin 2023-06-18 20:54:52 +01:00 committed by GitHub
parent ad97f08048
commit d961d349c3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -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.
*
* <p>
* 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
* <a href="https://github.com/TeamNewPipe/NewPipe/issues/8713">
* https://github.com/TeamNewPipe/NewPipe/issues/8713</a>.
* </p>
*
* <p>
* 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
* <a href="https://github.com/TeamPiped/Piped/issues/2487">
* https://github.com/TeamPiped/Piped/issues/2487</a>.
* </p>
*
* <p>
@ -1080,22 +1101,15 @@ public class YoutubeStreamExtractor extends StreamExtractor {
* same as the one requested by the extractor.
* </p>
*
* <p>
* This behavior has been already observed on the {@code ANDROID} client, see
* <a href="https://github.com/TeamNewPipe/NewPipe/issues/8713">
* https://github.com/TeamNewPipe/NewPipe/issues/8713</a>.
* </p>
*
* @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 {