mirror of
https://github.com/TeamNewPipe/NewPipeExtractor.git
synced 2024-12-13 05:40:34 +05:30
[Youtube] Adjust throttling function extraction to changes (#1191)
* [Youtube] Adjust throttling function extraction to changes --------- Co-authored-by: Stypox <stypox@pm.me>
This commit is contained in:
parent
bba3b6c69b
commit
d39fc43282
@ -1,5 +1,7 @@
|
|||||||
package org.schabi.newpipe.extractor.services.youtube;
|
package org.schabi.newpipe.extractor.services.youtube;
|
||||||
|
|
||||||
|
import static org.schabi.newpipe.extractor.utils.Parser.matchGroup1MultiplePatterns;
|
||||||
|
|
||||||
import org.schabi.newpipe.extractor.exceptions.ParsingException;
|
import org.schabi.newpipe.extractor.exceptions.ParsingException;
|
||||||
import org.schabi.newpipe.extractor.utils.JavaScript;
|
import org.schabi.newpipe.extractor.utils.JavaScript;
|
||||||
import org.schabi.newpipe.extractor.utils.Parser;
|
import org.schabi.newpipe.extractor.utils.Parser;
|
||||||
@ -20,13 +22,13 @@ final class YoutubeSignatureUtils {
|
|||||||
*/
|
*/
|
||||||
static final String DEOBFUSCATION_FUNCTION_NAME = "deobfuscate";
|
static final String DEOBFUSCATION_FUNCTION_NAME = "deobfuscate";
|
||||||
|
|
||||||
private static final String[] FUNCTION_REGEXES = {
|
private static final Pattern[] FUNCTION_REGEXES = {
|
||||||
"\\bm=([a-zA-Z0-9$]{2,})\\(decodeURIComponent\\(h\\.s\\)\\)",
|
|
||||||
"\\bc&&\\(c=([a-zA-Z0-9$]{2,})\\(decodeURIComponent\\(c\\)\\)",
|
|
||||||
// CHECKSTYLE:OFF
|
// CHECKSTYLE:OFF
|
||||||
"(?:\\b|[^a-zA-Z0-9$])([a-zA-Z0-9$]{2,})\\s*=\\s*function\\(\\s*a\\s*\\)\\s*\\{\\s*a\\s*=\\s*a\\.split\\(\\s*\"\"\\s*\\)",
|
Pattern.compile("\\bm=([a-zA-Z0-9$]{2,})\\(decodeURIComponent\\(h\\.s\\)\\)"),
|
||||||
|
Pattern.compile("\\bc&&\\(c=([a-zA-Z0-9$]{2,})\\(decodeURIComponent\\(c\\)\\)"),
|
||||||
|
Pattern.compile("(?:\\b|[^a-zA-Z0-9$])([a-zA-Z0-9$]{2,})\\s*=\\s*function\\(\\s*a\\s*\\)\\s*\\{\\s*a\\s*=\\s*a\\.split\\(\\s*\"\"\\s*\\)"),
|
||||||
|
Pattern.compile("([\\w$]+)\\s*=\\s*function\\((\\w+)\\)\\{\\s*\\2=\\s*\\2\\.split\\(\"\"\\)\\s*;")
|
||||||
// CHECKSTYLE:ON
|
// CHECKSTYLE:ON
|
||||||
"([\\w$]+)\\s*=\\s*function\\((\\w+)\\)\\{\\s*\\2=\\s*\\2\\.split\\(\"\"\\)\\s*;"
|
|
||||||
};
|
};
|
||||||
|
|
||||||
private static final String STS_REGEX = "signatureTimestamp[=:](\\d+)";
|
private static final String STS_REGEX = "signatureTimestamp[=:](\\d+)";
|
||||||
@ -104,19 +106,12 @@ final class YoutubeSignatureUtils {
|
|||||||
@Nonnull
|
@Nonnull
|
||||||
private static String getDeobfuscationFunctionName(@Nonnull final String javaScriptPlayerCode)
|
private static String getDeobfuscationFunctionName(@Nonnull final String javaScriptPlayerCode)
|
||||||
throws ParsingException {
|
throws ParsingException {
|
||||||
Parser.RegexException exception = null;
|
try {
|
||||||
for (final String regex : FUNCTION_REGEXES) {
|
return matchGroup1MultiplePatterns(FUNCTION_REGEXES, javaScriptPlayerCode);
|
||||||
try {
|
} catch (final Parser.RegexException e) {
|
||||||
return Parser.matchGroup1(regex, javaScriptPlayerCode);
|
throw new ParsingException(
|
||||||
} catch (final Parser.RegexException e) {
|
"Could not find deobfuscation function with any of the known patterns", e);
|
||||||
if (exception == null) {
|
|
||||||
exception = e;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
throw new ParsingException(
|
|
||||||
"Could not find deobfuscation function with any of the known patterns", exception);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nonnull
|
@Nonnull
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
package org.schabi.newpipe.extractor.services.youtube;
|
package org.schabi.newpipe.extractor.services.youtube;
|
||||||
|
|
||||||
|
import static org.schabi.newpipe.extractor.utils.Parser.matchMultiplePatterns;
|
||||||
|
|
||||||
import org.schabi.newpipe.extractor.exceptions.ParsingException;
|
import org.schabi.newpipe.extractor.exceptions.ParsingException;
|
||||||
import org.schabi.newpipe.extractor.utils.JavaScript;
|
import org.schabi.newpipe.extractor.utils.JavaScript;
|
||||||
import org.schabi.newpipe.extractor.utils.Parser;
|
import org.schabi.newpipe.extractor.utils.Parser;
|
||||||
@ -18,10 +20,33 @@ final class YoutubeThrottlingParameterUtils {
|
|||||||
|
|
||||||
private static final Pattern THROTTLING_PARAM_PATTERN = Pattern.compile("[&?]n=([^&]+)");
|
private static final Pattern THROTTLING_PARAM_PATTERN = Pattern.compile("[&?]n=([^&]+)");
|
||||||
|
|
||||||
private static final Pattern DEOBFUSCATION_FUNCTION_NAME_PATTERN = Pattern.compile(
|
private static final String SINGLE_CHAR_VARIABLE_REGEX = "[a-zA-Z0-9$_]";
|
||||||
// CHECKSTYLE:OFF
|
|
||||||
"\\.get\\(\"n\"\\)\\)&&\\([a-zA-Z0-9$_]=([a-zA-Z0-9$_]+)(?:\\[(\\d+)])?\\([a-zA-Z0-9$_]\\)");
|
private static final String FUNCTION_NAME_REGEX = SINGLE_CHAR_VARIABLE_REGEX + "+";
|
||||||
// CHECKSTYLE:ON
|
|
||||||
|
private static final String ARRAY_ACCESS_REGEX = "\\[(\\d+)]";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The first regex matches this, where we want BDa:
|
||||||
|
* <p>
|
||||||
|
* (b=String.fromCharCode(110),c=a.get(b))&&(c=<strong>BDa</strong><strong>[0]</strong>(c)
|
||||||
|
* <p>
|
||||||
|
* Array access is optional, but needs to be handled, since the actual function is inside the
|
||||||
|
* array.
|
||||||
|
*/
|
||||||
|
// CHECKSTYLE:OFF
|
||||||
|
private static final Pattern[] DEOBFUSCATION_FUNCTION_NAME_REGEXES = {
|
||||||
|
Pattern.compile("\\(" + SINGLE_CHAR_VARIABLE_REGEX + "=String\\.fromCharCode\\(110\\),"
|
||||||
|
+ SINGLE_CHAR_VARIABLE_REGEX + "=" + SINGLE_CHAR_VARIABLE_REGEX + "\\.get\\("
|
||||||
|
+ SINGLE_CHAR_VARIABLE_REGEX + "\\)\\)" + "&&\\(" + SINGLE_CHAR_VARIABLE_REGEX
|
||||||
|
+ "=(" + FUNCTION_NAME_REGEX + ")" + "(?:" + ARRAY_ACCESS_REGEX + ")?\\("
|
||||||
|
+ SINGLE_CHAR_VARIABLE_REGEX + "\\)"),
|
||||||
|
Pattern.compile("\\.get\\(\"n\"\\)\\)&&\\(" + SINGLE_CHAR_VARIABLE_REGEX
|
||||||
|
+ "=(" + FUNCTION_NAME_REGEX + ")(?:" + ARRAY_ACCESS_REGEX + ")?\\("
|
||||||
|
+ SINGLE_CHAR_VARIABLE_REGEX + "\\)"),
|
||||||
|
};
|
||||||
|
// CHECKSTYLE:ON
|
||||||
|
|
||||||
|
|
||||||
// Escape the curly end brace to allow compatibility with Android's regex engine
|
// Escape the curly end brace to allow compatibility with Android's regex engine
|
||||||
// See https://stackoverflow.com/q/45074813
|
// See https://stackoverflow.com/q/45074813
|
||||||
@ -48,11 +73,13 @@ final class YoutubeThrottlingParameterUtils {
|
|||||||
@Nonnull
|
@Nonnull
|
||||||
static String getDeobfuscationFunctionName(@Nonnull final String javaScriptPlayerCode)
|
static String getDeobfuscationFunctionName(@Nonnull final String javaScriptPlayerCode)
|
||||||
throws ParsingException {
|
throws ParsingException {
|
||||||
final Matcher matcher = DEOBFUSCATION_FUNCTION_NAME_PATTERN.matcher(javaScriptPlayerCode);
|
final Matcher matcher;
|
||||||
if (!matcher.find()) {
|
try {
|
||||||
throw new ParsingException("Failed to find deobfuscation function name pattern \""
|
matcher = matchMultiplePatterns(DEOBFUSCATION_FUNCTION_NAME_REGEXES,
|
||||||
+ DEOBFUSCATION_FUNCTION_NAME_PATTERN
|
javaScriptPlayerCode);
|
||||||
+ "\" in the base JavaScript player code");
|
} catch (final Parser.RegexException e) {
|
||||||
|
throw new ParsingException("Could not find deobfuscation function with any of the "
|
||||||
|
+ "known patterns in the base JavaScript player code", e);
|
||||||
}
|
}
|
||||||
|
|
||||||
final String functionName = matcher.group(1);
|
final String functionName = matcher.group(1);
|
||||||
|
@ -78,6 +78,37 @@ public final class Parser {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static String matchGroup1MultiplePatterns(final Pattern[] patterns, final String input)
|
||||||
|
throws RegexException {
|
||||||
|
return matchMultiplePatterns(patterns, input).group(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Matcher matchMultiplePatterns(final Pattern[] patterns, final String input)
|
||||||
|
throws RegexException {
|
||||||
|
Parser.RegexException exception = null;
|
||||||
|
for (final Pattern pattern : patterns) {
|
||||||
|
final Matcher matcher = pattern.matcher(input);
|
||||||
|
if (matcher.find()) {
|
||||||
|
return matcher;
|
||||||
|
} else if (exception == null) {
|
||||||
|
// only pass input to exception message when it is not too long
|
||||||
|
if (input.length() > 1024) {
|
||||||
|
exception = new RegexException("Failed to find pattern \"" + pattern.pattern()
|
||||||
|
+ "\"");
|
||||||
|
} else {
|
||||||
|
exception = new RegexException("Failed to find pattern \"" + pattern.pattern()
|
||||||
|
+ "\" inside of \"" + input + "\"");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (exception == null) {
|
||||||
|
throw new RegexException("Empty patterns array passed to matchMultiplePatterns");
|
||||||
|
} else {
|
||||||
|
throw exception;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public static boolean isMatch(final String pattern, final String input) {
|
public static boolean isMatch(final String pattern, final String input) {
|
||||||
final Pattern pat = Pattern.compile(pattern);
|
final Pattern pat = Pattern.compile(pattern);
|
||||||
final Matcher mat = pat.matcher(input);
|
final Matcher mat = pat.matcher(input);
|
||||||
|
Loading…
Reference in New Issue
Block a user