]> code.delx.au - youtube-cgi/blobdiff - youtube.cgi
changed script prefix/suffix
[youtube-cgi] / youtube.cgi
index 11d25382834538cca991e9ad4fe70c36d858aaec..349842fb24b03f22789edfd1e38603bb9583e87c 100755 (executable)
@@ -131,16 +131,13 @@ 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 extract_js(script):
+    PREFIX = "var _yt_player={};(function(g){var window=this;"
+    SUFFIX = ";})(_yt_player);\n"
+    assert script.startswith(PREFIX)
+    assert script.endswith(SUFFIX)
+
+    return script[len(PREFIX):-len(SUFFIX)]
 
 def find_func_name(script):
     FUNC_NAME = R"([a-zA-Z0-9$]+)"
@@ -151,30 +148,56 @@ def find_func_name(script):
     func_name = match.groups()[0]
     return func_name
 
-def decode_signature(js_url, s):
+def decode_signature(js_url, signature):
     script = urlopen(js_url).read()
     func_name = find_func_name(script)
 
-    codes = []
-    extract_function(codes, script, func_name)
-
+    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 = {
+            location: {
+                hash: '',
+                href: '',
+                protocol: 'http:'
+            },
+            history: {
+                pushState: function(){}
+            },
+            document: {},
+            navigator: {},
+            signature: %(signature)s,
+            transformed_signature: null
+        };
+        sandbox.window = sandbox;
+
+        var code_string = %(code)s + ';';
+        var exec_string = 'transformed_signature = %(func_name)s(signature);';
+        vm.runInNewContext(code_string + exec_string, 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(",")