diff --git a/devine/commands/auth.py b/devine/commands/auth.py index e73b187..a11a516 100644 --- a/devine/commands/auth.py +++ b/devine/commands/auth.py @@ -10,6 +10,7 @@ import click from ruamel.yaml import YAML from devine.core.config import Config, config +from devine.core.console import console from devine.core.constants import context_settings from devine.core.credential import Credential @@ -28,15 +29,13 @@ def auth(ctx: click.Context) -> None: short_help="List profiles and their state for a service or all services.", context_settings=context_settings) @click.argument("service", type=str, required=False) -@click.pass_context -def list_(ctx: click.Context, service: Optional[str] = None) -> None: +def list_(service: Optional[str] = None) -> None: """ List profiles and their state for a service or all services. \b Profile and Service names are case-insensitive. """ - log = ctx.obj service_f = service auth_data: dict[str, dict[str, list]] = defaultdict(lambda: defaultdict(list)) @@ -55,9 +54,9 @@ def list_(ctx: click.Context, service: Optional[str] = None) -> None: for service, profiles in dict(sorted(auth_data.items())).items(): # type:ignore if service_f and service != service_f.upper(): continue - log.info(service) + console.log(service) for profile, authorizations in dict(sorted(profiles.items())).items(): - log.info(f' "{profile}": {", ".join(authorizations)}') + console.log(f' "{profile}": {", ".join(authorizations)}') @auth.command( @@ -82,7 +81,7 @@ def view(ctx: click.Context, profile: str, service: str) -> None: if cookie_dir.name == service_f: for cookie in cookie_dir.glob("*.txt"): if cookie.stem == profile_f: - log.info(f"Cookie: {cookie}") + console.log(f"Cookie: {cookie}") log.debug(cookie.read_text(encoding="utf8").strip()) found = True break @@ -91,7 +90,7 @@ def view(ctx: click.Context, profile: str, service: str) -> None: if service == service_f: for profile, credential in credentials.items(): if profile == profile_f: - log.info(f"Credential: {':'.join(list(credential))}") + console.log(f"Credential: {':'.join(list(credential))}") found = True break @@ -106,26 +105,24 @@ def view(ctx: click.Context, profile: str, service: str) -> None: short_help="Check what profile is used by services.", context_settings=context_settings) @click.argument("service", type=str, required=False) -@click.pass_context -def status(ctx: click.Context, service: Optional[str] = None) -> None: +def status(service: Optional[str] = None) -> None: """ Check what profile is used by services. \b Service names are case-sensitive. """ - log = ctx.obj found_profile = False for service_, profile in config.profiles.items(): if not service or service_.upper() == service.upper(): - log.info(f"{service_}: {profile or '--'}") + console.log(f"{service_}: {profile or '--'}") found_profile = True if not found_profile: - log.info(f"No profile has been explicitly set for {service}") + console.log(f"No profile has been explicitly set for {service}") default = config.profiles.get("default", "not set") - log.info(f"The default profile is {default}") + console.log(f"The default profile is {default}") @auth.command( @@ -135,8 +132,7 @@ def status(ctx: click.Context, service: Optional[str] = None) -> None: @click.argument("service", type=str) @click.option("--cookie", is_flag=True, default=False, help="Only delete the cookie.") @click.option("--credential", is_flag=True, default=False, help="Only delete the credential.") -@click.pass_context -def delete(ctx: click.Context, profile: str, service: str, cookie: bool, credential: bool): +def delete(profile: str, service: str, cookie: bool, credential: bool): """ Delete a profile and all of its authorization from a service. @@ -148,7 +144,6 @@ def delete(ctx: click.Context, profile: str, service: str, cookie: bool, credent Profile and Service names are case-sensitive. Comments may be removed from config! """ - log = ctx.obj service_f = service profile_f = profile found = False @@ -159,7 +154,7 @@ def delete(ctx: click.Context, profile: str, service: str, cookie: bool, credent for cookie_ in cookie_dir.glob("*.txt"): if cookie_.stem == profile_f: cookie_.unlink() - log.info(f"Deleted Cookie: {cookie_}") + console.log(f"Deleted Cookie: {cookie_}") found = True break @@ -174,7 +169,7 @@ def delete(ctx: click.Context, profile: str, service: str, cookie: bool, credent data = yaml.load(config_path) del data["credentials"][key][profile_f] yaml.dump(data, config_path) - log.info(f"Deleted Credential: {credential_}") + console.log(f"Deleted Credential: {credential_}") found = True break @@ -224,7 +219,7 @@ def add(ctx: click.Context, profile: str, service: str, cookie: Optional[str] = if cookie: cookie = Path(cookie) else: - log.info("Skipped adding a Cookie...") + console.log("Skipped adding a Cookie...") if credential: try: @@ -239,7 +234,7 @@ def add(ctx: click.Context, profile: str, service: str, cookie: Optional[str] = except ValueError as e: raise click.ClickException(str(e)) else: - log.info("Skipped adding a Credential...") + console.log("Skipped adding a Credential...") if cookie: final_path = (config.directories.cookies / service / profile).with_suffix(".txt") @@ -248,7 +243,7 @@ def add(ctx: click.Context, profile: str, service: str, cookie: Optional[str] = log.error(f"A Cookie file for the Profile {profile} on {service} already exists.") sys.exit(1) shutil.move(cookie, final_path) - log.info(f"Moved Cookie file to: {final_path}") + console.log(f"Moved Cookie file to: {final_path}") if credential: config_path = Config._Directories.user_configs / Config._Filenames.root_config @@ -263,4 +258,4 @@ def add(ctx: click.Context, profile: str, service: str, cookie: Optional[str] = data["credentials"][service] = {} data["credentials"][service][profile] = credential.dumps() yaml.dump(data, config_path) - log.info(f"Added Credential: {credential}") + console.log(f"Added Credential: {credential}") diff --git a/devine/commands/cfg.py b/devine/commands/cfg.py index a02f91a..1d7a9e0 100644 --- a/devine/commands/cfg.py +++ b/devine/commands/cfg.py @@ -6,6 +6,7 @@ import click from ruamel.yaml import YAML from devine.core.config import config +from devine.core.console import console from devine.core.constants import context_settings @@ -80,10 +81,10 @@ def cfg(ctx: click.Context, key: str, value: str, unset: bool, list_: bool) -> N parent_data = parent_data[key] if is_write: parent_data[trailing_key] = value - log.info(f"Set {key} to {repr(value)}") + console.log(f"Set {key} to {repr(value)}") elif is_delete: del parent_data[trailing_key] - log.info(f"Unset {key}") + console.log(f"Unset {key}") except KeyError: raise click.ClickException(f"Key '{key}' does not exist in the config.") config_path.parent.mkdir(parents=True, exist_ok=True) diff --git a/devine/commands/dl.py b/devine/commands/dl.py index b066815..3c6a9ea 100644 --- a/devine/commands/dl.py +++ b/devine/commands/dl.py @@ -30,6 +30,7 @@ from pywidevine.remotecdm import RemoteCdm from tqdm import tqdm from devine.core.config import config +from devine.core.console import console from devine.core.constants import AnyTrack, context_settings from devine.core.credential import Credential from devine.core.downloaders import aria2c @@ -140,43 +141,43 @@ class dl: self.service = Services.get_tag(ctx.invoked_subcommand) - self.log.info(f"Loading Profile Data for {self.service}") + console.log(f"Loading Profile Data for {self.service}") if profile: self.profile = profile - self.log.info(f" + Profile: {self.profile} (explicit)") + console.log(f" + Profile: {self.profile} (explicit)") else: self.profile = self.get_profile(self.service) - self.log.info(f" + Profile: {self.profile} (from config)") + console.log(f" + Profile: {self.profile} (from config)") - self.log.info("Initializing Widevine CDM") + console.log("Initializing Widevine CDM") try: self.cdm = self.get_cdm(self.service, self.profile) except ValueError as e: self.log.error(f" - {e}") sys.exit(1) - self.log.info( + console.log( f" + {self.cdm.__class__.__name__}: {self.cdm.system_id} (L{self.cdm.security_level})" ) - self.log.info("Loading Vaults") + console.log("Loading Vaults") self.vaults = Vaults(self.service) for vault in config.key_vaults: vault_type = vault["type"] del vault["type"] self.vaults.load(vault_type, **vault) - self.log.info(f" + {len(self.vaults)} Vaults") + console.log(f" + {len(self.vaults)} Vaults") - self.log.info("Getting Service Config") + console.log("Getting Service Config") service_config_path = Services.get_path(self.service) / config.filenames.config if service_config_path.is_file(): self.service_config = yaml.safe_load(service_config_path.read_text(encoding="utf8")) - self.log.info(" + Got Service Config") + console.log(" + Got Service Config") else: self.service_config = {} - self.log.info(" - No Service Config") + console.log(" - No Service Config") merge_dict(config.services.get(self.service), self.service_config) - self.log.info("Loading Proxy Providers") + console.log("Loading Proxy Providers") self.proxy_providers = [] if config.proxy_providers.get("basic"): self.proxy_providers.append(Basic(**config.proxy_providers["basic"])) @@ -185,7 +186,7 @@ class dl: if get_binary_path("hola-proxy"): self.proxy_providers.append(Hola()) for proxy_provider in self.proxy_providers: - self.log.info(f" + {proxy_provider.__class__.__name__}: {repr(proxy_provider)}") + console.log(f" + {proxy_provider.__class__.__name__}: {repr(proxy_provider)}") if proxy: requested_provider = None @@ -194,7 +195,7 @@ class dl: requested_provider, proxy = proxy.split(":", maxsplit=1) if re.match(r"^[a-z]{2}(?:\d+)?$", proxy, re.IGNORECASE): proxy = proxy.lower() - self.log.info(f"Getting a Proxy to '{proxy}'") + console.log(f"Getting a Proxy to '{proxy}'") if requested_provider: proxy_provider = next(( x @@ -209,16 +210,16 @@ class dl: self.log.error(f"The proxy provider {requested_provider} had no proxy for {proxy}") sys.exit(1) proxy = ctx.params["proxy"] = proxy_uri - self.log.info(f" + {proxy} (from {proxy_provider.__class__.__name__})") + console.log(f" + {proxy} (from {proxy_provider.__class__.__name__})") else: for proxy_provider in self.proxy_providers: proxy_uri = proxy_provider.get_proxy(proxy) if proxy_uri: proxy = ctx.params["proxy"] = proxy_uri - self.log.info(f" + {proxy} (from {proxy_provider.__class__.__name__})") + console.log(f" + {proxy} (from {proxy_provider.__class__.__name__})") break else: - self.log.info(f"Proxy: {proxy} (from args)") + console.log(f"Proxy: {proxy} (from args)") ctx.obj = ContextData( config=self.service_config, @@ -274,32 +275,32 @@ class dl: self.log.error(f"The Profile '{self.profile}' has no Cookies or Credentials. Check for typos.") sys.exit(1) - self.log.info(f"Authenticating with Profile '{self.profile}'") + console.log(f"Authenticating with Profile '{self.profile}'") service.authenticate(cookies, credential) - self.log.info(" + Authenticated") + console.log(" + Authenticated") - self.log.info("Retrieving Titles") + console.log("Retrieving Titles") titles = service.get_titles() if not titles: self.log.error(" - No titles returned!") sys.exit(1) for line in str(titles).splitlines(keepends=False): - self.log.info(line) + console.log(line) if list_titles: for title in titles: - self.log.info(title) + console.log(title) return for i, title in enumerate(titles): if isinstance(title, Episode) and wanted and f"{title.season}x{title.number}" not in wanted: continue - self.log.info(f"Getting tracks for {title}") + console.log(f"Getting tracks for {title}") if slow and i != 0: delay = random.randint(60, 120) - self.log.info(f" - Delaying by {delay} seconds due to --slow ...") + console.log(f" - Delaying by {delay} seconds due to --slow ...") time.sleep(delay) title.tracks.add(service.get_tracks(title), warn_only=True) @@ -324,10 +325,10 @@ class dl: title.tracks.sort_subtitles(by_language=s_lang) title.tracks.sort_chapters() - self.log.info("> All Tracks:") + console.log("> All Tracks:") title.tracks.print() - self.log.info("> Selected Tracks:") # log early so errors logs make sense + console.log("> Selected Tracks:") # log early so errors logs make sense if isinstance(title, (Movie, Episode)): # filter video tracks @@ -412,7 +413,7 @@ class dl: continue # only wanted to see what tracks were available and chosen if skip_dl: - self.log.info("Skipping Download...") + console.log("Skipping Download...") else: with tqdm(total=len(title.tracks)) as pbar: with ThreadPoolExecutor(workers) as pool: @@ -458,7 +459,7 @@ class dl: except KeyboardInterrupt: self.DL_POOL_STOP.set() pool.shutdown(wait=False, cancel_futures=True) - self.log.info("Received Keyboard Interrupt, stopping...") + console.log("Received Keyboard Interrupt, stopping...") return if not skip_dl: @@ -473,7 +474,7 @@ class dl: cookie_jar.set_cookie(cookie) cookie_jar.save(ignore_discard=True) - self.log.info("Processed all titles!") + console.log("Processed all titles!") def prepare_drm( self, @@ -494,7 +495,7 @@ class dl: return if isinstance(drm, Widevine): - self.log.info(f"Licensing Content Keys using Widevine for {drm.pssh.dumps()}") + console.log(f"Licensing Content Keys using Widevine for {drm.pssh.dumps()}") for kid in drm.kids: if kid in drm.content_keys: @@ -504,9 +505,9 @@ class dl: content_key, vault_used = self.vaults.get_key(kid) if content_key: drm.content_keys[kid] = content_key - self.log.info(f" + {kid.hex}:{content_key} ({vault_used})") + console.log(f" + {kid.hex}:{content_key} ({vault_used})") add_count = self.vaults.add_key(kid, content_key, excluding=vault_used) - self.log.info(f" + Cached to {add_count}/{len(self.vaults) - 1} Vaults") + console.log(f" + Cached to {add_count}/{len(self.vaults) - 1} Vaults") elif vaults_only: self.log.error(f" - No Content Key found in any Vault for {kid.hex}") sys.exit(1) @@ -530,7 +531,7 @@ class dl: msg += " *" if key == "0" * 32: msg += " (Unusable!)" - self.log.info(msg) + console.log(msg) drm.content_keys = { kid_: key @@ -543,7 +544,7 @@ class dl: drm.content_keys.update(from_vaults) cached_keys = self.vaults.add_keys(drm.content_keys) - self.log.info(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: self.log.error(f" - No usable key was returned for {kid.hex}, cannot continue") @@ -576,7 +577,7 @@ class dl: else: proxy = None - self.log.info(f"Downloading: {track}") + console.log(f"Downloading: {track}") if config.directories.temp.is_file(): self.log.error(f"Temp Directory '{config.directories.temp}' must be a Directory, not a file") @@ -681,9 +682,9 @@ class dl: track.OnDownloaded(track) if track.needs_repack: - self.log.info("Repackaging stream with FFMPEG (fix malformed streams)") + console.log("Repackaging stream with FFMPEG (fix malformed streams)") track.repackage() - self.log.info(" + Repackaged") + console.log(" + Repackaged") if callable(track.OnRepacked): track.OnRepacked(track) @@ -695,7 +696,7 @@ class dl: for x in ffprobe(track.path).get("streams", []) ) ): - self.log.info("Checking for EIA-CC Captions") + console.log("Checking for EIA-CC Captions") try: # TODO: Figure out the real language, it might be different # EIA-CC tracks sadly don't carry language information :( @@ -714,15 +715,15 @@ class dl: ) if cc: title.tracks.add(cc) - self.log.info(" + Found & Extracted an EIA-CC Caption") + console.log(" + Found & Extracted an EIA-CC Caption") except EnvironmentError: self.log.error(" - Track needs to have CC extracted, but ccextractor wasn't found") sys.exit(1) - self.log.info(" + No EIA-CC Captions...") + console.log(" + No EIA-CC Captions...") def mux_tracks(self, title: Title_T, season_folder: bool = True, add_source: bool = True) -> None: """Mux Tracks, Delete Pre-Mux files, and move to the final location.""" - self.log.info("Muxing Tracks into a Matroska Container") + console.log("Muxing Tracks into a Matroska Container") if isinstance(title, (Movie, Episode)): muxed_path, return_code = title.tracks.mux(str(title)) @@ -731,7 +732,7 @@ class dl: elif return_code >= 2: self.log.error(" - Failed to Mux video to Matroska file") sys.exit(1) - self.log.info(f" + Muxed to {muxed_path}") + console.log(f" + Muxed to {muxed_path}") else: # dont mux muxed_path = title.tracks.audio[0].path @@ -747,7 +748,7 @@ class dl: final_path = final_dir / f"{final_filename}{muxed_path.suffix}" shutil.move(muxed_path, final_path) - self.log.info(f" + Moved to {final_path}") + console.log(f" + Moved to {final_path}") @staticmethod def get_profile(service: str) -> Optional[str]: diff --git a/devine/commands/env.py b/devine/commands/env.py index 9dddb76..a9dd180 100644 --- a/devine/commands/env.py +++ b/devine/commands/env.py @@ -1,10 +1,10 @@ -import logging import shutil from typing import Optional import click from devine.core.config import config +from devine.core.console import console from devine.core.constants import context_settings from devine.core.services import Services @@ -17,14 +17,13 @@ def env() -> None: @env.command() def info() -> None: """Displays information about the current environment.""" - log = logging.getLogger("env") - log.info(f"[Root Config] : {config.directories.user_configs / config.filenames.root_config}") - log.info(f"[Cookies] : {config.directories.cookies}") - log.info(f"[WVDs] : {config.directories.wvds}") - log.info(f"[Cache] : {config.directories.cache}") - log.info(f"[Logs] : {config.directories.logs}") - log.info(f"[Temp Files] : {config.directories.temp}") - log.info(f"[Downloads] : {config.directories.downloads}") + console.log(f"[Root Config] : {config.directories.user_configs / config.filenames.root_config}") + console.log(f"[Cookies] : {config.directories.cookies}") + console.log(f"[WVDs] : {config.directories.wvds}") + console.log(f"[Cache] : {config.directories.cache}") + console.log(f"[Logs] : {config.directories.logs}") + console.log(f"[Temp Files] : {config.directories.temp}") + console.log(f"[Downloads] : {config.directories.downloads}") @env.group(name="clear", short_help="Clear an environment directory.", context_settings=context_settings) @@ -36,29 +35,27 @@ def clear() -> None: @click.argument("service", type=str, required=False) def cache(service: Optional[str]) -> None: """Clear the environment cache directory.""" - log = logging.getLogger("env") cache_dir = config.directories.cache if service: cache_dir = cache_dir / Services.get_tag(service) - log.info(f"Clearing cache directory: {cache_dir}") + console.log(f"Clearing cache directory: {cache_dir}") files_count = len(list(cache_dir.glob("**/*"))) if not files_count: - log.info("No files to delete") + console.log("No files to delete") else: - log.info(f"Deleting {files_count} files...") + console.log(f"Deleting {files_count} files...") shutil.rmtree(cache_dir) - log.info("Cleared") + console.log("Cleared") @clear.command() def temp() -> None: """Clear the environment temp directory.""" - log = logging.getLogger("env") - log.info(f"Clearing temp directory: {config.directories.temp}") + console.log(f"Clearing temp directory: {config.directories.temp}") files_count = len(list(config.directories.temp.glob("**/*"))) if not files_count: - log.info("No files to delete") + console.log("No files to delete") else: - log.info(f"Deleting {files_count} files...") + console.log(f"Deleting {files_count} files...") shutil.rmtree(config.directories.temp) - log.info("Cleared") + console.log("Cleared") diff --git a/devine/commands/kv.py b/devine/commands/kv.py index 6655a39..6cd513f 100644 --- a/devine/commands/kv.py +++ b/devine/commands/kv.py @@ -6,6 +6,7 @@ from typing import Optional import click from devine.core.config import config +from devine.core.console import console from devine.core.constants import context_settings from devine.core.services import Services from devine.core.vault import Vault @@ -52,10 +53,10 @@ def copy(to_vault: str, from_vaults: list[str], service: Optional[str] = None) - to_vault: Vault = vaults.vaults[0] from_vaults: list[Vault] = vaults.vaults[1:] - log.info(f"Copying data from {', '.join([x.name for x in from_vaults])}, into {to_vault.name}") + console.log(f"Copying data from {', '.join([x.name for x in from_vaults])}, into {to_vault.name}") if service: service = Services.get_tag(service) - log.info(f"Only copying data for service {service}") + console.log(f"Only copying data for service {service}") total_added = 0 for from_vault in from_vaults: @@ -65,7 +66,7 @@ def copy(to_vault: str, from_vaults: list[str], service: Optional[str] = None) - services = from_vault.get_services() for service_ in services: - log.info(f"Getting data from {from_vault} for {service_}") + console.log(f"Getting data from {from_vault} for {service_}") content_keys = list(from_vault.get_keys(service_)) # important as it's a generator we iterate twice bad_keys = { @@ -84,7 +85,7 @@ def copy(to_vault: str, from_vaults: list[str], service: Optional[str] = None) - } total_count = len(content_keys) - log.info(f"Adding {total_count} Content Keys to {to_vault} for {service_}") + console.log(f"Adding {total_count} Content Keys to {to_vault} for {service_}") try: added = to_vault.add_keys(service_, content_keys) @@ -95,9 +96,9 @@ def copy(to_vault: str, from_vaults: list[str], service: Optional[str] = None) - total_added += added existed = total_count - added - log.info(f"{to_vault} ({service_}): {added} newly added, {existed} already existed (skipped)") + console.log(f"{to_vault} ({service_}): {added} newly added, {existed} already existed (skipped)") - log.info(f"{to_vault}: {total_added} total newly added") + console.log(f"{to_vault}: {total_added} total newly added") @kv.command() @@ -141,7 +142,6 @@ def add(file: Path, service: str, vaults: list[str]) -> None: if len(vaults) < 1: raise click.ClickException("You must provide at least one Vault.") - log = logging.getLogger("kv") service = Services.get_tag(service) vaults_ = Vaults() @@ -168,12 +168,12 @@ def add(file: Path, service: str, vaults: list[str]) -> None: total_count = len(kid_keys) for vault in vaults_: - log.info(f"Adding {total_count} Content Keys to {vault}") + console.log(f"Adding {total_count} Content Keys to {vault}") added_count = vault.add_keys(service, kid_keys) existed_count = total_count - added_count - log.info(f"{vault}: {added_count} newly added, {existed_count} already existed (skipped)") + console.log(f"{vault}: {added_count} newly added, {existed_count} already existed (skipped)") - log.info("Done!") + console.log("Done!") @kv.command() @@ -196,15 +196,15 @@ def prepare(vaults: list[str]) -> None: if hasattr(vault, "has_table") and hasattr(vault, "create_table"): for service_tag in Services.get_tags(): if vault.has_table(service_tag): - log.info(f"{vault} already has a {service_tag} Table") + console.log(f"{vault} already has a {service_tag} Table") else: try: vault.create_table(service_tag, commit=True) - log.info(f"{vault}: Created {service_tag} Table") + console.log(f"{vault}: Created {service_tag} Table") except PermissionError: log.error(f"{vault} user has no create table permission, skipping...") continue else: - log.info(f"{vault} does not use tables, skipping...") + console.log(f"{vault} does not use tables, skipping...") - log.info("Done!") + console.log("Done!") diff --git a/devine/commands/wvd.py b/devine/commands/wvd.py index a31b43e..84a688f 100644 --- a/devine/commands/wvd.py +++ b/devine/commands/wvd.py @@ -10,6 +10,7 @@ from pywidevine.license_protocol_pb2 import FileHashes from unidecode import UnidecodeError, unidecode from devine.core.config import config +from devine.core.console import console from devine.core.constants import context_settings @@ -34,28 +35,26 @@ def parse(path: Path) -> None: if named: path = config.directories.wvds / f"{path.name}.wvd" - log = logging.getLogger("wvd") - device = Device.load(path) - log.info(f"System ID: {device.system_id}") - log.info(f"Security Level: {device.security_level}") - log.info(f"Type: {device.type}") - log.info(f"Flags: {device.flags}") - log.info(f"Private Key: {bool(device.private_key)}") - log.info(f"Client ID: {bool(device.client_id)}") - log.info(f"VMP: {bool(device.client_id.vmp_data)}") + console.log(f"System ID: {device.system_id}") + console.log(f"Security Level: {device.security_level}") + console.log(f"Type: {device.type}") + console.log(f"Flags: {device.flags}") + console.log(f"Private Key: {bool(device.private_key)}") + console.log(f"Client ID: {bool(device.client_id)}") + console.log(f"VMP: {bool(device.client_id.vmp_data)}") - log.info("Client ID:") - log.info(device.client_id) + console.log("Client ID:") + console.log(device.client_id) - log.info("VMP:") + console.log("VMP:") if device.client_id.vmp_data: file_hashes = FileHashes() file_hashes.ParseFromString(device.client_id.vmp_data) - log.info(str(file_hashes)) + console.log(str(file_hashes)) else: - log.info("None") + console.log("None") @wvd.command() @@ -82,9 +81,9 @@ def dump(wvd_paths: list[Path], out_dir: Path) -> None: device = Device.load(wvd_path) log = logging.getLogger("wvd") - log.info(f"Dumping: {wvd_path}") - log.info(f"L{device.security_level} {device.system_id} {device.type.name}") - log.info(f"Saving to: {out_path}") + console.log(f"Dumping: {wvd_path}") + console.log(f"L{device.security_level} {device.system_id} {device.type.name}") + console.log(f"Saving to: {out_path}") device_meta = { "wvd": { @@ -100,7 +99,7 @@ def dump(wvd_paths: list[Path], out_dir: Path) -> None: device_meta_path = out_path / "metadata.yml" device_meta_path.write_text(yaml.dump(device_meta), encoding="utf8") - log.info(" + Device Metadata") + console.log(" + Device Metadata") if device.private_key: private_key_path = out_path / "private_key.pem" @@ -111,23 +110,23 @@ def dump(wvd_paths: list[Path], out_dir: Path) -> None: private_key_path.with_suffix(".der").write_bytes( device.private_key.export_key(format="DER") ) - log.info(" + Private Key") + console.log(" + Private Key") else: log.warning(" - No Private Key available") if device.client_id: client_id_path = out_path / "client_id.bin" client_id_path.write_bytes(device.client_id.SerializeToString()) - log.info(" + Client ID") + console.log(" + Client ID") else: log.warning(" - No Client ID available") if device.client_id.vmp_data: vmp_path = out_path / "vmp.bin" vmp_path.write_bytes(device.client_id.vmp_data) - log.info(" + VMP (File Hashes)") + console.log(" + VMP (File Hashes)") else: - log.info(" - No VMP (File Hashes) available") + console.log(" - No VMP (File Hashes) available") @wvd.command() @@ -191,15 +190,15 @@ def new( log = logging.getLogger("wvd") - log.info(f"Created binary WVD file, {out_path.name}") - log.info(f" + Saved to: {out_path.absolute()}") - log.info(f" + System ID: {device.system_id}") - log.info(f" + Security Level: {device.security_level}") - log.info(f" + Type: {device.type}") - log.info(f" + Flags: {device.flags}") - log.info(f" + Private Key: {bool(device.private_key)}") - log.info(f" + Client ID: {bool(device.client_id)}") - log.info(f" + VMP: {bool(device.client_id.vmp_data)}") + console.log(f"Created binary WVD file, {out_path.name}") + console.log(f" + Saved to: {out_path.absolute()}") + console.log(f" + System ID: {device.system_id}") + console.log(f" + Security Level: {device.security_level}") + console.log(f" + Type: {device.type}") + console.log(f" + Flags: {device.flags}") + console.log(f" + Private Key: {bool(device.private_key)}") + console.log(f" + Client ID: {bool(device.client_id)}") + console.log(f" + VMP: {bool(device.client_id.vmp_data)}") log.debug("Client ID:") log.debug(device.client_id) @@ -208,6 +207,6 @@ def new( if device.client_id.vmp_data: file_hashes = FileHashes() file_hashes.ParseFromString(device.client_id.vmp_data) - log.info(str(file_hashes)) + console.log(str(file_hashes)) else: - log.info("None") + console.log("None") diff --git a/devine/core/manifests/dash.py b/devine/core/manifests/dash.py index 046d0f6..3ba5565 100644 --- a/devine/core/manifests/dash.py +++ b/devine/core/manifests/dash.py @@ -25,6 +25,7 @@ from pywidevine.pssh import PSSH from requests import Session from tqdm import tqdm +from devine.core.console import console from devine.core.constants import AnyTrack from devine.core.downloaders import aria2c from devine.core.drm import Widevine @@ -524,7 +525,7 @@ class DASH: except KeyboardInterrupt: state_event.set() pool.shutdown(wait=False, cancel_futures=True) - log.info("Received Keyboard Interrupt, stopping...") + console.log("Received Keyboard Interrupt, stopping...") return @staticmethod diff --git a/devine/core/manifests/hls.py b/devine/core/manifests/hls.py index 3ed4f5c..c71993b 100644 --- a/devine/core/manifests/hls.py +++ b/devine/core/manifests/hls.py @@ -23,6 +23,7 @@ from pywidevine.pssh import PSSH from requests import Session from tqdm import tqdm +from devine.core.console import console from devine.core.constants import AnyTrack from devine.core.downloaders import aria2c from devine.core.drm import DRM_T, ClearKey, Widevine @@ -371,7 +372,7 @@ class HLS: except KeyboardInterrupt: state_event.set() pool.shutdown(wait=False, cancel_futures=True) - log.info("Received Keyboard Interrupt, stopping...") + console.log("Received Keyboard Interrupt, stopping...") return @staticmethod diff --git a/devine/core/tracks/video.py b/devine/core/tracks/video.py index 47b5e72..d2e3edf 100644 --- a/devine/core/tracks/video.py +++ b/devine/core/tracks/video.py @@ -1,6 +1,5 @@ from __future__ import annotations -import logging import math import re import subprocess @@ -11,6 +10,7 @@ from typing import Any, Optional, Union from langcodes import Language from devine.core.config import config +from devine.core.console import console from devine.core.tracks.subtitle import Subtitle from devine.core.tracks.track import Track from devine.core.utilities import FPS, get_binary_path, get_boxes @@ -296,15 +296,14 @@ class Video(Track): if not executable: raise EnvironmentError("FFmpeg executable \"ffmpeg\" was not found but is required for this call.") - log = logging.getLogger("x264-clean") - log.info("Removing EIA-CC from Video Track with FFMPEG") + console.log("Removing EIA-CC from Video Track with FFMPEG") with open(self.path, "rb") as f: file = f.read(60000) x264 = re.search(br"(.{16})(x264)", file) if not x264: - log.info(" - No x264 encode settings were found, unsupported...") + console.log(" - No x264 encode settings were found, unsupported...") return False uuid = x264.group(1).hex() @@ -323,7 +322,7 @@ class Video(Track): str(cleaned_path) ], check=True) - log.info(" + Removed") + console.log(" + Removed") self.swap(cleaned_path)