Merge branch 'master' into dev

This commit is contained in:
TobiGr 2020-10-28 14:28:06 +01:00
commit 62912ee834
2 changed files with 47 additions and 23 deletions

View File

@ -5,7 +5,7 @@ allprojects {
sourceCompatibility = 1.7 sourceCompatibility = 1.7
targetCompatibility = 1.7 targetCompatibility = 1.7
version 'v0.20.1' version 'v0.20.2'
group 'com.github.TeamNewPipe' group 'com.github.TeamNewPipe'
repositories { repositories {

View File

@ -3,6 +3,10 @@ package org.schabi.newpipe.extractor.services.youtube.extractors;
import com.grack.nanojson.JsonArray; import com.grack.nanojson.JsonArray;
import com.grack.nanojson.JsonObject; import com.grack.nanojson.JsonObject;
import com.grack.nanojson.JsonParser; import com.grack.nanojson.JsonParser;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
import org.mozilla.javascript.Context; import org.mozilla.javascript.Context;
import org.mozilla.javascript.Function; import org.mozilla.javascript.Function;
import org.mozilla.javascript.ScriptableObject; import org.mozilla.javascript.ScriptableObject;
@ -100,6 +104,7 @@ public class YoutubeStreamExtractor extends StreamExtractor {
private JsonObject videoPrimaryInfoRenderer; private JsonObject videoPrimaryInfoRenderer;
private JsonObject videoSecondaryInfoRenderer; private JsonObject videoSecondaryInfoRenderer;
private int ageLimit; private int ageLimit;
private boolean newJsonScheme;
@Nonnull @Nonnull
private List<SubtitlesInfo> subtitlesInfos = new ArrayList<>(); private List<SubtitlesInfo> subtitlesInfos = new ArrayList<>();
@ -664,29 +669,25 @@ public class YoutubeStreamExtractor extends StreamExtractor {
} else { } else {
ageLimit = NO_AGE_LIMIT; ageLimit = NO_AGE_LIMIT;
JsonObject playerConfig; 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"); initialData = initialAjaxJson.getObject(3).getObject("response");
// sometimes at random YouTube does not provide the player config
playerConfig = initialAjaxJson.getObject(2).getObject("player", null);
if (playerConfig == null) {
newJsonScheme = true;
final EmbeddedInfo info = getEmbeddedInfo();
final String videoInfoUrl = getVideoInfoUrl(getId(), info.sts);
final String infoPageResponse = downloader.get(videoInfoUrl, getExtractorLocalization()).responseBody();
videoInfoPage.putAll(Parser.compatParseMap(infoPageResponse));
playerUrl = info.url;
} else {
playerArgs = getPlayerArgs(playerConfig); playerArgs = getPlayerArgs(playerConfig);
playerUrl = getPlayerUrl(playerConfig); playerUrl = getPlayerUrl(playerConfig);
} }
}
playerResponse = getPlayerResponse(); playerResponse = getPlayerResponse();
final JsonObject playabilityStatus = playerResponse.getObject("playabilityStatus"); final JsonObject playabilityStatus = playerResponse.getObject("playabilityStatus");
@ -732,6 +733,10 @@ public class YoutubeStreamExtractor extends StreamExtractor {
private JsonObject getPlayerResponse() throws ParsingException { private JsonObject getPlayerResponse() throws ParsingException {
try { try {
String playerResponseStr; String playerResponseStr;
if (newJsonScheme) {
return initialAjaxJson.getObject(2).getObject("playerResponse");
}
if (playerArgs != null) { if (playerArgs != null) {
playerResponseStr = playerArgs.getString("player_response"); playerResponseStr = playerArgs.getString("player_response");
} else { } else {
@ -751,11 +756,30 @@ public class YoutubeStreamExtractor extends StreamExtractor {
final String embedPageContent = downloader.get(embedUrl, getExtractorLocalization()).responseBody(); final String embedPageContent = downloader.get(embedUrl, getExtractorLocalization()).responseBody();
// Get player url // Get player url
String playerUrl = null;
try {
final String assetsPattern = "\"assets\":.+?\"js\":\\s*(\"[^\"]+\")"; final String assetsPattern = "\"assets\":.+?\"js\":\\s*(\"[^\"]+\")";
String playerUrl = Parser.matchGroup1(assetsPattern, embedPageContent) playerUrl = Parser.matchGroup1(assetsPattern, embedPageContent)
.replace("\\", "").replace("\"", ""); .replace("\\", "").replace("\"", "");
} catch (Parser.RegexException ex) {
// playerUrl is still available in the file, just somewhere else
final Document doc = Jsoup.parse(embedPageContent);
final Elements elems = doc.select("script").attr("name", "player_ias/base");
for (Element elem : elems) {
if (elem.attr("src").contains("base.js")) {
playerUrl = elem.attr("src");
}
}
if (playerUrl == null) {
throw new ParsingException("Could not get playerUrl");
}
}
if (playerUrl.startsWith("//")) { if (playerUrl.startsWith("//")) {
playerUrl = HTTPS + playerUrl; playerUrl = HTTPS + playerUrl;
} else if (playerUrl.startsWith("/")) {
playerUrl = HTTPS + "//youtube.com" + playerUrl;
} }
try { try {