Log DRM license info under track downloads

This commit is contained in:
rlaphoenix 2023-02-25 17:21:13 +00:00
parent 178bd01069
commit 70106d32ce
1 changed files with 92 additions and 59 deletions

View File

@ -16,7 +16,7 @@ from copy import deepcopy
from functools import partial from functools import partial
from http.cookiejar import MozillaCookieJar from http.cookiejar import MozillaCookieJar
from pathlib import Path from pathlib import Path
from threading import Event from threading import Event, Lock
from typing import Any, Callable, Optional from typing import Any, Callable, Optional
import click import click
@ -34,6 +34,7 @@ from rich.progress import BarColumn, Progress, SpinnerColumn, TextColumn, TimeRe
from rich.rule import Rule from rich.rule import Rule
from rich.table import Table from rich.table import Table
from rich.text import Text from rich.text import Text
from rich.tree import Tree
from devine.core.config import config from devine.core.config import config
from devine.core.console import console from devine.core.console import console
@ -130,6 +131,7 @@ class dl:
return dl(ctx, **kwargs) return dl(ctx, **kwargs)
DL_POOL_STOP = Event() DL_POOL_STOP = Event()
DRM_TABLE_LOCK = Lock()
def __init__( def __init__(
self, self,
@ -421,13 +423,16 @@ class dl:
selected_tracks, tracks_progress_callables = title.tracks.tree(add_progress=True) selected_tracks, tracks_progress_callables = title.tracks.tree(add_progress=True)
download_table = Table.grid()
download_table.add_row(selected_tracks)
if skip_dl: if skip_dl:
console.log("Skipping Download...") console.log("Skipping Download...")
else: else:
with Live( with Live(
Padding( Padding(
selected_tracks, download_table,
(0, 5, 1, 5) (1, 5)
), ),
console=console, console=console,
refresh_per_second=5 refresh_per_second=5
@ -441,7 +446,10 @@ class dl:
track=track, track=track,
title=title, title=title,
prepare_drm=partial( prepare_drm=partial(
partial(
self.prepare_drm, self.prepare_drm,
table=download_table
),
track=track, track=track,
title=title, title=title,
certificate=partial( certificate=partial(
@ -509,6 +517,7 @@ class dl:
title: Title_T, title: Title_T,
certificate: Callable, certificate: Callable,
licence: Callable, licence: Callable,
table: Table = None,
cdm_only: bool = False, cdm_only: bool = False,
vaults_only: bool = False, vaults_only: bool = False,
export: Optional[Path] = None export: Optional[Path] = None
@ -521,7 +530,19 @@ class dl:
return return
if isinstance(drm, Widevine): if isinstance(drm, Widevine):
console.log(f"Licensing Content Keys using Widevine for {drm.pssh.dumps()}") with self.DRM_TABLE_LOCK:
cek_tree = Tree(Text.assemble(
("Widevine", "cyan"),
(f"({drm.pssh.dumps()})", "text"),
overflow="fold"
))
pre_existing_tree = next((
x
for x in table.columns[0].cells
if isinstance(x, Tree) and x.label == cek_tree.label
), None)
if pre_existing_tree:
cek_tree = pre_existing_tree
for kid in drm.kids: for kid in drm.kids:
if kid in drm.content_keys: if kid in drm.content_keys:
@ -531,11 +552,14 @@ class dl:
content_key, vault_used = self.vaults.get_key(kid) content_key, vault_used = self.vaults.get_key(kid)
if content_key: if content_key:
drm.content_keys[kid] = content_key drm.content_keys[kid] = content_key
console.log(f" + {kid.hex}:{content_key} ({vault_used})") label = f"[text2]{kid.hex}:{content_key} from {vault_used}"
add_count = self.vaults.add_key(kid, content_key, excluding=vault_used) if not any(x.label == label for x in cek_tree.children):
console.log(f" + Cached to {add_count}/{len(self.vaults) - 1} Vaults") cek_tree.add(label)
self.vaults.add_key(kid, content_key, excluding=vault_used)
elif vaults_only: elif vaults_only:
self.log.error(f" - No Content Key found in any Vault for {kid.hex}") cek_tree.add(f"[logging.level.error]No Vault has a Key for {kid.hex}, cannot decrypt...")
if not pre_existing_tree:
table.add_row(cek_tree)
sys.exit(1) sys.exit(1)
if kid not in drm.content_keys and not vaults_only: if kid not in drm.content_keys and not vaults_only:
@ -548,16 +572,19 @@ class dl:
certificate=certificate certificate=certificate
) )
except ValueError as e: except ValueError as e:
self.log.error(str(e)) cek_tree.add(f"[logging.level.error]{str(e)}")
if not pre_existing_tree:
table.add_row(cek_tree)
sys.exit(1) sys.exit(1)
for kid_, key in drm.content_keys.items(): for kid_, key in drm.content_keys.items():
msg = f" + {kid_.hex}:{key}"
if kid_ == kid:
msg += " *"
if key == "0" * 32: if key == "0" * 32:
msg += " (Unusable!)" key = f"[red]{key}[/]"
console.log(msg) if kid_ == kid:
key += " *"
label = f"[text2]{kid_.hex}:{key}"
if not any(x.label == label for x in cek_tree.children):
cek_tree.add(label)
drm.content_keys = { drm.content_keys = {
kid_: key kid_: key
@ -573,9 +600,15 @@ class dl:
console.log(f" + Newly added to {cached_keys}/{len(drm.content_keys)} Vaults") console.log(f" + Newly added to {cached_keys}/{len(drm.content_keys)} Vaults")
if kid not in drm.content_keys: if kid not in drm.content_keys:
self.log.error(f" - No usable key was returned for {kid.hex}, cannot continue") cek_tree.add(f"[logging.level.error]No key was returned for {kid.hex}, cannot decrypt...")
if not pre_existing_tree:
table.add_row(cek_tree)
sys.exit(1) sys.exit(1)
if cek_tree.children and not pre_existing_tree:
table.add_row()
table.add_row(cek_tree)
if export: if export:
keys = {} keys = {}
if export.is_file(): if export.is_file():