Merge pull request #243 from TeamNewPipe/fix/yt_decryption

Fix/yt decryption
This commit is contained in:
Tobias Groza 2020-01-24 02:18:40 +01:00 committed by GitHub
commit ff61e28424
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 24 additions and 22 deletions

View File

@ -56,7 +56,7 @@ public abstract class Extractor{
} }
protected void assertPageFetched() { protected void assertPageFetched() {
if(!pageFetched) throw new IllegalStateException("Page is not fetched. Make sure you call fetchPage()"); if (!pageFetched) throw new IllegalStateException("Page is not fetched. Make sure you call fetchPage()");
} }
protected boolean isPageFetched() { protected boolean isPageFetched() {

View File

@ -677,8 +677,10 @@ public class YoutubeStreamExtractor extends StreamExtractor {
private static final String VERIFIED_URL_PARAMS = "&has_verified=1&bpctr=9999999999"; private static final String VERIFIED_URL_PARAMS = "&has_verified=1&bpctr=9999999999";
private final static String DECYRYPTION_SIGNATURE_FUNCTION_REGEX = private final static String DECRYPTION_SIGNATURE_FUNCTION_REGEX =
"([\\w$]+)\\s*=\\s*function\\((\\w+)\\)\\{\\s*\\2=\\s*\\2\\.split\\(\"\"\\)\\s*;"; "([\\w$]+)\\s*=\\s*function\\((\\w+)\\)\\{\\s*\\2=\\s*\\2\\.split\\(\"\"\\)\\s*;";
private final static String DECRYPTION_SIGNATURE_FUNCTION_REGEX_2 =
"\\b([\\w$]{2})\\s*=\\s*function\\((\\w+)\\)\\{\\s*\\2=\\s*\\2\\.split\\(\"\"\\)\\s*;";
private final static String DECRYPTION_AKAMAIZED_STRING_REGEX = private final static String DECRYPTION_AKAMAIZED_STRING_REGEX =
"yt\\.akamaized\\.net/\\)\\s*\\|\\|\\s*.*?\\s*c\\s*&&\\s*d\\.set\\([^,]+\\s*,\\s*(:encodeURIComponent\\s*\\()([a-zA-Z0-9$]+)\\("; "yt\\.akamaized\\.net/\\)\\s*\\|\\|\\s*.*?\\s*c\\s*&&\\s*d\\.set\\([^,]+\\s*,\\s*(:encodeURIComponent\\s*\\()([a-zA-Z0-9$]+)\\(";
private final static String DECRYPTION_AKAMAIZED_SHORT_STRING_REGEX = private final static String DECRYPTION_AKAMAIZED_SHORT_STRING_REGEX =
@ -697,7 +699,8 @@ public class YoutubeStreamExtractor extends StreamExtractor {
final String playerUrl; final String playerUrl;
// Check if the video is age restricted // Check if the video is age restricted
if (!doc.select("meta[property=\"og:restrictions:age\"]").isEmpty()) { Elements e = doc.select("meta[property=\"og:restrictions:age\"]");
if (!e.isEmpty()) {
final EmbeddedInfo info = getEmbeddedInfo(); final EmbeddedInfo info = getEmbeddedInfo();
final String videoInfoUrl = getVideoInfoUrl(getId(), info.sts); final String videoInfoUrl = getVideoInfoUrl(getId(), info.sts);
final String infoPageResponse = downloader.get(videoInfoUrl, getExtractorLocalization()).responseBody(); final String infoPageResponse = downloader.get(videoInfoUrl, getExtractorLocalization()).responseBody();
@ -773,7 +776,7 @@ public class YoutubeStreamExtractor extends StreamExtractor {
private JsonObject getPlayerResponse() throws ParsingException { private JsonObject getPlayerResponse() throws ParsingException {
try { try {
String playerResponseStr; String playerResponseStr;
if(playerArgs != null) { if (playerArgs != null) {
playerResponseStr = playerArgs.getString("player_response"); playerResponseStr = playerArgs.getString("player_response");
} else { } else {
playerResponseStr = videoInfoPage.get("player_response"); playerResponseStr = videoInfoPage.get("player_response");
@ -805,7 +808,7 @@ public class YoutubeStreamExtractor extends StreamExtractor {
final String sts = Parser.matchGroup1(stsPattern, embedPageContent); final String sts = Parser.matchGroup1(stsPattern, embedPageContent);
return new EmbeddedInfo(playerUrl, sts); return new EmbeddedInfo(playerUrl, sts);
} catch (Exception i) { } catch (Exception i) {
// if it failes we simply reply with no sts as then it does not seem to be necessary // if it fails we simply reply with no sts as then it does not seem to be necessary
return new EmbeddedInfo(playerUrl, ""); return new EmbeddedInfo(playerUrl, "");
} }
@ -868,30 +871,28 @@ public class YoutubeStreamExtractor extends StreamExtractor {
} }
private String getDecryptionFuncName(String playerCode) throws DecryptException { private String getDecryptionFuncName(String playerCode) throws DecryptException {
String decryptionFunctionName; String[] decryptionFuncNameRegexes = {
// Cascading things in catch is ugly, but its faster than running a match before getting the actual name DECRYPTION_SIGNATURE_FUNCTION_REGEX_2,
// to se if the function can actually be found with the given regex. DECRYPTION_SIGNATURE_FUNCTION_REGEX,
// However if this cascading should propably be cleaned up somehow as it looks a bit weird. DECRYPTION_AKAMAIZED_SHORT_STRING_REGEX,
try { DECRYPTION_AKAMAIZED_STRING_REGEX
decryptionFunctionName = Parser.matchGroup1(DECYRYPTION_SIGNATURE_FUNCTION_REGEX, playerCode); };
} catch (Parser.RegexException re) { Parser.RegexException exception = null;
for (String regex : decryptionFuncNameRegexes) {
try { try {
decryptionFunctionName = Parser.matchGroup1(DECRYPTION_AKAMAIZED_SHORT_STRING_REGEX, playerCode); return Parser.matchGroup1(regex, playerCode);
} catch (Parser.RegexException re2) { } catch (Parser.RegexException re) {
try { if (exception == null)
decryptionFunctionName = Parser.matchGroup1(DECRYPTION_AKAMAIZED_STRING_REGEX, playerCode); exception = re;
} catch (Parser.RegexException re3) {
throw new DecryptException("Could not find decrypt function with any of the given patterns.", re);
}
} }
} }
return decryptionFunctionName; throw new DecryptException("Could not find decrypt function with any of the given patterns.", exception);
} }
@Nonnull @Nonnull
private List<SubtitlesInfo> getAvailableSubtitlesInfo() throws SubtitlesException { private List<SubtitlesInfo> getAvailableSubtitlesInfo() throws SubtitlesException {
// If the video is age restricted getPlayerConfig will fail // If the video is age restricted getPlayerConfig will fail
if(isAgeRestricted) return Collections.emptyList(); if (isAgeRestricted) return Collections.emptyList();
final JsonObject captions; final JsonObject captions;
if (!playerResponse.has("captions")) { if (!playerResponse.has("captions")) {
@ -908,7 +909,7 @@ public class YoutubeStreamExtractor extends StreamExtractor {
// This check is necessary since there may be cases where subtitles metadata do not contain caption track info // This check is necessary since there may be cases where subtitles metadata do not contain caption track info
// e.g. https://www.youtube.com/watch?v=-Vpwatutnko // e.g. https://www.youtube.com/watch?v=-Vpwatutnko
final int captionsSize = captionsArray.size(); final int captionsSize = captionsArray.size();
if(captionsSize == 0) return Collections.emptyList(); if (captionsSize == 0) return Collections.emptyList();
List<SubtitlesInfo> result = new ArrayList<>(); List<SubtitlesInfo> result = new ArrayList<>();
for (int i = 0; i < captionsSize; i++) { for (int i = 0; i < captionsSize; i++) {

View File

@ -67,6 +67,7 @@ public class Parser {
if (foundMatch) { if (foundMatch) {
return mat.group(group); return mat.group(group);
} else { } else {
// only pass input to exception message when it is not too long
if (input.length() > 1024) { if (input.length() > 1024) {
throw new RegexException("failed to find pattern \"" + pat.pattern()); throw new RegexException("failed to find pattern \"" + pat.pattern());
} else { } else {