Skip to content

Commit

Permalink
[YouTube] Fix some decryption exceptions by retrying
Browse files Browse the repository at this point in the history
  • Loading branch information
Stypox committed Oct 15, 2020
1 parent 2463884 commit 19e8626
Showing 1 changed file with 37 additions and 28 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -633,11 +633,10 @@ public String getErrorMessage() {
@Override
public void onFetchPage(@Nonnull Downloader downloader) throws IOException, ExtractionException {
final String url = getUrl() + "&pbj=1";
final String playerUrl;

initialAjaxJson = getJsonResponse(url, getExtractorLocalization());

final String playerUrl;

if (initialAjaxJson.getObject(2).has("response")) { // age-restricted videos
initialData = initialAjaxJson.getObject(2).getObject("response");
ageLimit = 18;
Expand All @@ -647,12 +646,31 @@ public void onFetchPage(@Nonnull Downloader downloader) throws IOException, Extr
final String infoPageResponse = downloader.get(videoInfoUrl, getExtractorLocalization()).responseBody();
videoInfoPage.putAll(Parser.compatParseMap(infoPageResponse));
playerUrl = info.url;

} else {
initialData = initialAjaxJson.getObject(3).getObject("response");
ageLimit = NO_AGE_LIMIT;
JsonObject playerConfig;

// sometimes at random YouTube does not provide the player config,
// so just retry the same request three times
int attempts = 2;
while (true) {
playerConfig = initialAjaxJson.getObject(2).getObject("player", null);
if (playerConfig != null) {
break;
}

if (attempts <= 0) {
throw new ParsingException(
"YouTube did not provide player config even after three attempts");
}
initialAjaxJson = getJsonResponse(url, getExtractorLocalization());
--attempts;
}
initialData = initialAjaxJson.getObject(3).getObject("response");

playerArgs = getPlayerArgs(initialAjaxJson.getObject(2).getObject("player"));
playerUrl = getPlayerUrl(initialAjaxJson.getObject(2).getObject("player"));
playerArgs = getPlayerArgs(playerConfig);
playerUrl = getPlayerUrl(playerConfig);
}

playerResponse = getPlayerResponse();
Expand All @@ -674,36 +692,27 @@ public void onFetchPage(@Nonnull Downloader downloader) throws IOException, Extr
}
}

private JsonObject getPlayerArgs(JsonObject playerConfig) throws ParsingException {
JsonObject playerArgs;

private JsonObject getPlayerArgs(final JsonObject playerConfig) throws ParsingException {
//attempt to load the youtube js player JSON arguments
try {
playerArgs = playerConfig.getObject("args");
} catch (Exception e) {
throw new ParsingException("Could not parse yt player config", e);
final JsonObject playerArgs = playerConfig.getObject("args", null);
if (playerArgs == null) {
throw new ParsingException("Could not extract args from YouTube player config");
}

return playerArgs;
}

private String getPlayerUrl(JsonObject playerConfig) throws ParsingException {
try {
// The Youtube service needs to be initialized by downloading the
// js-Youtube-player. This is done in order to get the algorithm
// for decrypting cryptic signatures inside certain stream urls.
String playerUrl;

JsonObject ytAssets = playerConfig.getObject("assets");
playerUrl = ytAssets.getString("js");
private String getPlayerUrl(final JsonObject playerConfig) throws ParsingException {
// The Youtube service needs to be initialized by downloading the
// js-Youtube-player. This is done in order to get the algorithm
// for decrypting cryptic signatures inside certain stream URLs.
final String playerUrl = playerConfig.getObject("assets").getString("js");

if (playerUrl.startsWith("//")) {
playerUrl = HTTPS + playerUrl;
}
return playerUrl;
} catch (Exception e) {
throw new ParsingException("Could not load decryption code for the Youtube service.", e);
if (playerUrl == null) {
throw new ParsingException("Could not extract js URL from YouTube player config");
} else if (playerUrl.startsWith("//")) {
return HTTPS + playerUrl;
}
return playerUrl;
}

private JsonObject getPlayerResponse() throws ParsingException {
Expand Down

0 comments on commit 19e8626

Please sign in to comment.