X-Git-Url: https://code.delx.au/youtube-cgi/blobdiff_plain/dfa94a1f0604025ee8160001f4b97cb23256c4fb..9175ff3ee7725517e7b39b2f3e60b1a309af602b:/youtube.cgi diff --git a/youtube.cgi b/youtube.cgi index fc10e08..da6109c 100755 --- a/youtube.cgi +++ b/youtube.cgi @@ -84,9 +84,10 @@ def urlopen(url, offset=None): global referrer req = urllib2.Request(url) - if referrer: + if not referrer: + referrer = url + else: req.add_header("Referer", referrer) - referrer = url req.add_header("User-Agent", USER_AGENT) @@ -130,41 +131,69 @@ def get_player_config(doc): if p1 >= 0 and p2 > 0: return json.loads(line[p1:p2]) -def extract_function(output, script, func_name): - p1 = script.find("function " + func_name + "(") - p2 = script.find("}", p1) - code = script[p1:p2+1] - output.append(code) - deps = re.findall(R"[^\.][= ]([\$0-9a-zA-Z]+)\(", code) - deps = set(deps) - deps.remove(func_name) - for dep in deps: - extract_function(output, script, dep) - -def decode_signature(js_url, s): - script = urlopen(js_url).read() - func_name = re.search(R"\b([a-zA-Z]+)\([a-zA-Z]+\.s\);", script).groups()[0] +def extract_js(script): + PREFIX = "(function(){" + SUFFIX = "})();\n" + assert script.startswith(PREFIX) + assert script.endswith(SUFFIX) + + return script[len(PREFIX):-len(SUFFIX)] - codes = [] - extract_function(codes, script, func_name) +def find_func_name(script): + FUNC_NAME = R"([a-zA-Z0-9$]+)" + FUNC_PARAMS = R"(\([a-zA-Z]+\.s\))" + PATTERN = FUNC_NAME + FUNC_PARAMS + ";" + + match = re.search(PATTERN, script) + func_name = match.groups()[0] + return func_name + +def decode_signature(js_url, signature): + script = urlopen(js_url).read() + func_name = find_func_name(script) + params = { + "func_name": func_name, + "signature": json.dumps(signature), + "code": json.dumps(extract_js(script)), + } p = subprocess.Popen( - "js", + "nodejs", shell=True, close_fds=True, stdin=subprocess.PIPE, stdout=subprocess.PIPE ) - for code in codes: - p.stdin.write(code + "\n") - p.stdin.write("console.log(%s('%s'));\n" % (func_name, s)) + js_decode_script = (""" + var vm = require("vm"); + + var sandbox = { + window: { + location: {}, + history: { + pushState: function(){} + } + }, + document: {}, + navigator: {}, + signature: %(signature)s, + transformed_signature: null + }; + + var execstring = ";transformed_signature = %(func_name)s(signature);"; + vm.runInNewContext(%(code)s + execstring, sandbox); + + console.log(sandbox.transformed_signature); + """ % params) + + p.stdin.write(js_decode_script) p.stdin.close() - signature = p.stdout.read().strip() + transformed_signature = p.stdout.read().strip() if p.wait() != 0: raise Exception("js failed to execute: %d" % p.returncode) - return signature + return transformed_signature def get_best_video(player_config): url_data_list = player_config["args"]["url_encoded_fmt_stream_map"].split(",")