Fix for Google changes master
authorJames Bunton <jamesbunton@delx.net.au>
Mon, 3 Feb 2020 14:42:05 +0000 (01:42 +1100)
committerJames Bunton <jamesbunton@delx.net.au>
Mon, 3 Feb 2020 14:42:05 +0000 (01:42 +1100)
youtube.cgi

index ef7b608..c9937b7 100755 (executable)
@@ -150,9 +150,10 @@ def extract_js(script):
 
 def find_func_name(script):
     FUNC_NAME = R"([a-zA-Z0-9$]+)"
+    DECODE_URI_COMPONENT = R"(\(decodeURIComponent)?"
     FUNC_PARAMS = R"(\([a-zA-Z,\.]+\.s\))"
     TERMINATOR = R"[,;\)]"
-    PATTERN = FUNC_NAME + FUNC_PARAMS + TERMINATOR
+    PATTERN = FUNC_NAME + DECODE_URI_COMPONENT + FUNC_PARAMS + TERMINATOR
 
     match = re.search(PATTERN, script)
     func_name = match.groups()[0]
@@ -202,24 +203,10 @@ def decode_signature(js_url, signature):
         sandbox.window = sandbox;
 
         const code_string = %(code)s + ';';
-        const exec_string = 'transformed_signature = %(func_name)s("", "MARKER", signature);';
+        const exec_string = 'transformed_signature = %(func_name)s(signature);';
         vm.runInNewContext(code_string + exec_string, sandbox);
 
-        function findSignature(obj) {
-            if (typeof obj !== 'object') {
-                return;
-            }
-            for (const [key, value] of Object.entries(obj)) {
-                if (key === 'MARKER') {
-                    return value;
-                }
-                const result = findSignature(value);
-                if (result) {
-                    return result;
-                }
-            }
-        }
-        console.log(findSignature(sandbox.transformed_signature));
+        console.log(sandbox.transformed_signature);
     """ % params)
 
     p.stdin.write(js_decode_script.encode("utf-8"))
@@ -233,19 +220,19 @@ def decode_signature(js_url, signature):
     return transformed_signature
 
 def get_best_video(player_config):
-    url_data_list = player_config["args"]["url_encoded_fmt_stream_map"].split(",")
     js_url = player_config["assets"]["js"]
 
+    player_args = player_config["args"]
+    player_response = json.loads(player_args["player_response"])
+    formats = player_response["streamingData"]["formats"]
+
     best_url = None
     best_quality = None
     best_extension = None
-    for url_data in url_data_list:
-        url_data = urllib.parse.parse_qs(url_data)
-        mimetype = url_data["type"][0].split(";")[0]
-        quality = url_data["quality"][0]
+    for format_data in formats:
+        mimetype = format_data["mimeType"].split(";")[0]
+        quality = format_data["quality"]
 
-        if "stereo3d" in url_data:
-            continue
         if quality not in QUALITIES:
             continue
         if mimetype not in MIMETYPES:
@@ -257,17 +244,17 @@ def get_best_video(player_config):
         if best_quality is not None and quality < best_quality:
             continue
 
-        video_url = url_data["url"][0]
-        if "sig" in url_data:
-            signature = url_data["sig"][0]
-        elif "s" in url_data:
-            signature = decode_signature(js_url, url_data["s"][0])
-        else:
-            signature = None
-
-        if signature:
-            sp = url_data.get("sp", ["signature"])[0]
+        if "cipher" in format_data:
+            cipher = urllib.parse.parse_qs(format_data["cipher"])
+            video_url = cipher["url"][0]
+            if "sig" in cipher:
+                signature = cipher["sig"][0]
+            elif "s" in cipher:
+                signature = decode_signature(js_url, cipher["s"][0])
+            sp = cipher.get("sp", ["signature"])[0]
             video_url = append_to_qs(video_url, {sp: signature})
+        else:
+            video_url = format_data["url"]
 
         best_url = video_url
         best_quality = quality