From 8365d798a4b202073b4f66ca93b31abca97af1bf Mon Sep 17 00:00:00 2001
From: rlaphoenix <rlaphoenix@pm.me>
Date: Tue, 28 Feb 2023 17:14:02 +0000
Subject: [PATCH] Pass shaka-packager & aria CTRL+C to caller as
 KeyboardInterrupt()s

---
 devine/core/downloaders/aria2c.py | 97 +++++++++++++++++--------------
 devine/core/drm/widevine.py       |  3 +
 2 files changed, 56 insertions(+), 44 deletions(-)

diff --git a/devine/core/downloaders/aria2c.py b/devine/core/downloaders/aria2c.py
index 47b8e1a..2e6d701 100644
--- a/devine/core/downloaders/aria2c.py
+++ b/devine/core/downloaders/aria2c.py
@@ -83,53 +83,62 @@ def aria2c(
                 return aria2c(uri, out, headers, pproxy_)
         arguments += ["--all-proxy", proxy]
 
-    p = subprocess.Popen(
-        [executable, *arguments],
-        stdin=subprocess.PIPE,
-        stderr=[None, subprocess.DEVNULL][silent],
-        stdout=(
-            subprocess.PIPE if progress else
-            subprocess.DEVNULL if silent else
-            None
-        ),
-        universal_newlines=True
-    )
+    try:
+        p = subprocess.Popen(
+            [executable, *arguments],
+            stdin=subprocess.PIPE,
+            stderr=[None, subprocess.DEVNULL][silent],
+            stdout=(
+                subprocess.PIPE if progress else
+                subprocess.DEVNULL if silent else
+                None
+            ),
+            universal_newlines=True
+        )
+        p._stdin_write(uri)  # noqa
 
-    p._stdin_write(uri)  # noqa
+        if progress:
+            is_dl_summary = False
+            for line in iter(p.stdout.readline, ""):
+                line = line.strip()
+                if line:
+                    if line.startswith("[") and line.endswith("]"):
+                        if "%" in line:
+                            # id, dledMiB/totalMiB(x%), CN:xx, DL:xxMiB, ETA:Xs
+                            # eta may not always be available
+                            data_parts = line[1:-1].split()
+                            perc_parts = data_parts[1].split("(")
+                            if len(perc_parts) == 2:
+                                # might otherwise be e.g., 0B/0B, with no % symbol provided
+                                progress(
+                                    total=100,
+                                    completed=int(perc_parts[1][:-2]),
+                                    downloaded=f"{data_parts[3].split(':')[1]}/s"
+                                )
+                    elif line.startswith("Download Results"):
+                        # we know it's 100% downloaded, but let's use the avg dl speed value
+                        is_dl_summary = True
+                    elif is_dl_summary and "OK" in line and "|" in line:
+                        gid, status, avg_speed, path_or_uri = line.split("|")
+                        progress(total=100, completed=100, downloaded=avg_speed.strip())
+                    elif not is_dl_summary:
+                        buffer_msg = line.split(" ", maxsplit=2)
+                        buffer_msg = f"[Aria2c]: {buffer_msg[-1].strip()}"
+                        console.log(Text.from_ansi(buffer_msg))
 
-    if progress:
-        is_dl_summary = False
-        for line in iter(p.stdout.readline, ""):
-            line = line.strip()
-            if line:
-                if line.startswith("[") and line.endswith("]"):
-                    if "%" in line:
-                        # id, dledMiB/totalMiB(x%), CN:xx, DL:xxMiB, ETA:Xs
-                        # eta may not always be available
-                        data_parts = line[1:-1].split()
-                        perc_parts = data_parts[1].split("(")
-                        if len(perc_parts) == 2:
-                            # might otherwise be e.g., 0B/0B, with no % symbol provided
-                            progress(
-                                total=100,
-                                completed=int(perc_parts[1][:-2]),
-                                downloaded=f"{data_parts[3].split(':')[1]}/s"
-                            )
-                elif line.startswith("Download Results"):
-                    # we know it's 100% downloaded, but let's use the avg dl speed value
-                    is_dl_summary = True
-                elif is_dl_summary and "OK" in line and "|" in line:
-                    gid, status, avg_speed, path_or_uri = line.split("|")
-                    progress(total=100, completed=100, downloaded=avg_speed.strip())
-                elif not is_dl_summary:
-                    buffer_msg = line.split(" ", maxsplit=2)
-                    buffer_msg = f"[Aria2c]: {buffer_msg[-1].strip()}"
-                    console.log(Text.from_ansi(buffer_msg))
+        p.wait()
 
-    p.wait()
-
-    if p.returncode != 0:
-        raise subprocess.CalledProcessError(p.returncode, arguments)
+        if p.returncode != 0:
+            raise subprocess.CalledProcessError(p.returncode, arguments)
+    except ConnectionResetError:
+        # interrupted while passing URI to download
+        raise KeyboardInterrupt()
+    except subprocess.CalledProcessError as e:
+        if e.returncode in (7, 0xC000013A):
+            # 7 is when Aria2(c) handled the CTRL+C
+            # 0xC000013A is when it never got the chance to
+            raise KeyboardInterrupt()
+        raise
 
     return p.returncode
 
diff --git a/devine/core/drm/widevine.py b/devine/core/drm/widevine.py
index 12cf3f3..6107099 100644
--- a/devine/core/drm/widevine.py
+++ b/devine/core/drm/widevine.py
@@ -234,6 +234,7 @@ class Widevine:
 
         decrypted_path = path.with_suffix(f".decrypted{path.suffix}")
         config.directories.temp.mkdir(parents=True, exist_ok=True)
+
         try:
             subprocess.check_call([
                 executable,
@@ -253,6 +254,8 @@ class Widevine:
                 "--temp_dir", config.directories.temp
             ], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
         except subprocess.CalledProcessError as e:
+            if e.returncode == 0xC000013A:  # STATUS_CONTROL_C_EXIT
+                raise KeyboardInterrupt()
             raise subprocess.SubprocessError(f"Failed to Decrypt! Shaka Packager Error: {e}")
 
         path.unlink()