Revert back to using logging over console.log where possible

It seems the commit I made to do this change initially seemed to help, it was actually pointless and issues I had were caused by other problems.

For consistency it seems best to stick with the logging module with the RichHandler applied. Using just console.log means being unable to control the log level and which level of logs appear.
This commit is contained in:
rlaphoenix 2023-02-26 21:03:36 +00:00
parent 401d0481df
commit eb3f268d64
10 changed files with 134 additions and 120 deletions

View File

@ -10,7 +10,6 @@ import click
from ruamel.yaml import YAML from ruamel.yaml import YAML
from devine.core.config import Config, config from devine.core.config import Config, config
from devine.core.console import console
from devine.core.constants import context_settings from devine.core.constants import context_settings
from devine.core.credential import Credential from devine.core.credential import Credential
@ -29,13 +28,15 @@ def auth(ctx: click.Context) -> None:
short_help="List profiles and their state for a service or all services.", short_help="List profiles and their state for a service or all services.",
context_settings=context_settings) context_settings=context_settings)
@click.argument("service", type=str, required=False) @click.argument("service", type=str, required=False)
def list_(service: Optional[str] = None) -> None: @click.pass_context
def list_(ctx: click.Context, service: Optional[str] = None) -> None:
""" """
List profiles and their state for a service or all services. List profiles and their state for a service or all services.
\b \b
Profile and Service names are case-insensitive. Profile and Service names are case-insensitive.
""" """
log = ctx.obj
service_f = service service_f = service
auth_data: dict[str, dict[str, list]] = defaultdict(lambda: defaultdict(list)) auth_data: dict[str, dict[str, list]] = defaultdict(lambda: defaultdict(list))
@ -54,9 +55,9 @@ def list_(service: Optional[str] = None) -> None:
for service, profiles in dict(sorted(auth_data.items())).items(): # type:ignore for service, profiles in dict(sorted(auth_data.items())).items(): # type:ignore
if service_f and service != service_f.upper(): if service_f and service != service_f.upper():
continue continue
console.log(service) log.info(service)
for profile, authorizations in dict(sorted(profiles.items())).items(): for profile, authorizations in dict(sorted(profiles.items())).items():
console.log(f' "{profile}": {", ".join(authorizations)}') log.info(f' "{profile}": {", ".join(authorizations)}')
@auth.command( @auth.command(
@ -81,7 +82,7 @@ def view(ctx: click.Context, profile: str, service: str) -> None:
if cookie_dir.name == service_f: if cookie_dir.name == service_f:
for cookie in cookie_dir.glob("*.txt"): for cookie in cookie_dir.glob("*.txt"):
if cookie.stem == profile_f: if cookie.stem == profile_f:
console.log(f"Cookie: {cookie}") log.info(f"Cookie: {cookie}")
log.debug(cookie.read_text(encoding="utf8").strip()) log.debug(cookie.read_text(encoding="utf8").strip())
found = True found = True
break break
@ -90,7 +91,7 @@ def view(ctx: click.Context, profile: str, service: str) -> None:
if service == service_f: if service == service_f:
for profile, credential in credentials.items(): for profile, credential in credentials.items():
if profile == profile_f: if profile == profile_f:
console.log(f"Credential: {':'.join(list(credential))}") log.info(f"Credential: {':'.join(list(credential))}")
found = True found = True
break break
@ -105,24 +106,26 @@ def view(ctx: click.Context, profile: str, service: str) -> None:
short_help="Check what profile is used by services.", short_help="Check what profile is used by services.",
context_settings=context_settings) context_settings=context_settings)
@click.argument("service", type=str, required=False) @click.argument("service", type=str, required=False)
def status(service: Optional[str] = None) -> None: @click.pass_context
def status(ctx: click.Context, service: Optional[str] = None) -> None:
""" """
Check what profile is used by services. Check what profile is used by services.
\b \b
Service names are case-sensitive. Service names are case-sensitive.
""" """
log = ctx.obj
found_profile = False found_profile = False
for service_, profile in config.profiles.items(): for service_, profile in config.profiles.items():
if not service or service_.upper() == service.upper(): if not service or service_.upper() == service.upper():
console.log(f"{service_}: {profile or '--'}") log.info(f"{service_}: {profile or '--'}")
found_profile = True found_profile = True
if not found_profile: if not found_profile:
console.log(f"No profile has been explicitly set for {service}") log.info(f"No profile has been explicitly set for {service}")
default = config.profiles.get("default", "not set") default = config.profiles.get("default", "not set")
console.log(f"The default profile is {default}") log.info(f"The default profile is {default}")
@auth.command( @auth.command(
@ -132,7 +135,8 @@ def status(service: Optional[str] = None) -> None:
@click.argument("service", type=str) @click.argument("service", type=str)
@click.option("--cookie", is_flag=True, default=False, help="Only delete the cookie.") @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.option("--credential", is_flag=True, default=False, help="Only delete the credential.")
def delete(profile: str, service: str, cookie: bool, credential: bool): @click.pass_context
def delete(ctx: click.Context, profile: str, service: str, cookie: bool, credential: bool):
""" """
Delete a profile and all of its authorization from a service. Delete a profile and all of its authorization from a service.
@ -144,6 +148,7 @@ def delete(profile: str, service: str, cookie: bool, credential: bool):
Profile and Service names are case-sensitive. Profile and Service names are case-sensitive.
Comments may be removed from config! Comments may be removed from config!
""" """
log = ctx.obj
service_f = service service_f = service
profile_f = profile profile_f = profile
found = False found = False
@ -154,7 +159,7 @@ def delete(profile: str, service: str, cookie: bool, credential: bool):
for cookie_ in cookie_dir.glob("*.txt"): for cookie_ in cookie_dir.glob("*.txt"):
if cookie_.stem == profile_f: if cookie_.stem == profile_f:
cookie_.unlink() cookie_.unlink()
console.log(f"Deleted Cookie: {cookie_}") log.info(f"Deleted Cookie: {cookie_}")
found = True found = True
break break
@ -169,7 +174,7 @@ def delete(profile: str, service: str, cookie: bool, credential: bool):
data = yaml.load(config_path) data = yaml.load(config_path)
del data["credentials"][key][profile_f] del data["credentials"][key][profile_f]
yaml.dump(data, config_path) yaml.dump(data, config_path)
console.log(f"Deleted Credential: {credential_}") log.info(f"Deleted Credential: {credential_}")
found = True found = True
break break
@ -219,7 +224,7 @@ def add(ctx: click.Context, profile: str, service: str, cookie: Optional[str] =
if cookie: if cookie:
cookie = Path(cookie) cookie = Path(cookie)
else: else:
console.log("Skipped adding a Cookie...") log.info("Skipped adding a Cookie...")
if credential: if credential:
try: try:
@ -234,7 +239,7 @@ def add(ctx: click.Context, profile: str, service: str, cookie: Optional[str] =
except ValueError as e: except ValueError as e:
raise click.ClickException(str(e)) raise click.ClickException(str(e))
else: else:
console.log("Skipped adding a Credential...") log.info("Skipped adding a Credential...")
if cookie: if cookie:
final_path = (config.directories.cookies / service / profile).with_suffix(".txt") final_path = (config.directories.cookies / service / profile).with_suffix(".txt")
@ -243,7 +248,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.") log.error(f"A Cookie file for the Profile {profile} on {service} already exists.")
sys.exit(1) sys.exit(1)
shutil.move(cookie, final_path) shutil.move(cookie, final_path)
console.log(f"Moved Cookie file to: {final_path}") log.info(f"Moved Cookie file to: {final_path}")
if credential: if credential:
config_path = Config._Directories.user_configs / Config._Filenames.root_config config_path = Config._Directories.user_configs / Config._Filenames.root_config
@ -258,4 +263,4 @@ def add(ctx: click.Context, profile: str, service: str, cookie: Optional[str] =
data["credentials"][service] = {} data["credentials"][service] = {}
data["credentials"][service][profile] = credential.dumps() data["credentials"][service][profile] = credential.dumps()
yaml.dump(data, config_path) yaml.dump(data, config_path)
console.log(f"Added Credential: {credential}") log.info(f"Added Credential: {credential}")

View File

@ -6,7 +6,6 @@ import click
from ruamel.yaml import YAML from ruamel.yaml import YAML
from devine.core.config import config from devine.core.config import config
from devine.core.console import console
from devine.core.constants import context_settings from devine.core.constants import context_settings
@ -81,10 +80,10 @@ def cfg(ctx: click.Context, key: str, value: str, unset: bool, list_: bool) -> N
parent_data = parent_data[key] parent_data = parent_data[key]
if is_write: if is_write:
parent_data[trailing_key] = value parent_data[trailing_key] = value
console.log(f"Set {key} to {repr(value)}") log.info(f"Set {key} to {repr(value)}")
elif is_delete: elif is_delete:
del parent_data[trailing_key] del parent_data[trailing_key]
console.log(f"Unset {key}") log.info(f"Unset {key}")
except KeyError: except KeyError:
raise click.ClickException(f"Key '{key}' does not exist in the config.") raise click.ClickException(f"Key '{key}' does not exist in the config.")
config_path.parent.mkdir(parents=True, exist_ok=True) config_path.parent.mkdir(parents=True, exist_ok=True)

View File

@ -151,15 +151,15 @@ class dl:
with console.status("Preparing Service and Profile Authentication...", spinner="dots"): with console.status("Preparing Service and Profile Authentication...", spinner="dots"):
if profile: if profile:
self.profile = profile self.profile = profile
console.log(f"Profile: '{self.profile}' from the --profile argument") self.log.info(f"Profile: '{self.profile}' from the --profile argument")
else: else:
self.profile = self.get_profile(self.service) self.profile = self.get_profile(self.service)
console.log(f"Profile: '{self.profile}' from the config") self.log.info(f"Profile: '{self.profile}' from the config")
service_config_path = Services.get_path(self.service) / config.filenames.config service_config_path = Services.get_path(self.service) / config.filenames.config
if service_config_path.is_file(): if service_config_path.is_file():
self.service_config = yaml.safe_load(service_config_path.read_text(encoding="utf8")) self.service_config = yaml.safe_load(service_config_path.read_text(encoding="utf8"))
console.log("Service Config loaded") self.log.info("Service Config loaded")
else: else:
self.service_config = {} self.service_config = {}
merge_dict(config.services.get(self.service), self.service_config) merge_dict(config.services.get(self.service), self.service_config)
@ -170,7 +170,7 @@ class dl:
except ValueError as e: except ValueError as e:
self.log.error(f"Failed to load Widevine CDM, {e}") self.log.error(f"Failed to load Widevine CDM, {e}")
sys.exit(1) sys.exit(1)
console.log( self.log.info(
f"Loaded {self.cdm.__class__.__name__} Widevine CDM: {self.cdm.system_id} (L{self.cdm.security_level})" f"Loaded {self.cdm.__class__.__name__} Widevine CDM: {self.cdm.system_id} (L{self.cdm.security_level})"
) )
@ -180,7 +180,7 @@ class dl:
vault_type = vault["type"] vault_type = vault["type"]
del vault["type"] del vault["type"]
self.vaults.load(vault_type, **vault) self.vaults.load(vault_type, **vault)
console.log(f"Loaded {len(self.vaults)} Vaults") self.log.info(f"Loaded {len(self.vaults)} Vaults")
with console.status("Loading Proxy Providers...", spinner="dots"): with console.status("Loading Proxy Providers...", spinner="dots"):
self.proxy_providers = [] self.proxy_providers = []
@ -191,7 +191,7 @@ class dl:
if get_binary_path("hola-proxy"): if get_binary_path("hola-proxy"):
self.proxy_providers.append(Hola()) self.proxy_providers.append(Hola())
for proxy_provider in self.proxy_providers: for proxy_provider in self.proxy_providers:
console.log(f"Loaded {proxy_provider.__class__.__name__}: {proxy_provider}") self.log.info(f"Loaded {proxy_provider.__class__.__name__}: {proxy_provider}")
if proxy: if proxy:
requested_provider = None requested_provider = None
@ -215,16 +215,16 @@ class dl:
self.log.error(f"The proxy provider {requested_provider} had no proxy for {proxy}") self.log.error(f"The proxy provider {requested_provider} had no proxy for {proxy}")
sys.exit(1) sys.exit(1)
proxy = ctx.params["proxy"] = proxy_uri proxy = ctx.params["proxy"] = proxy_uri
console.log(f"Using {proxy_provider.__class__.__name__} Proxy: {proxy}") self.log.info(f"Using {proxy_provider.__class__.__name__} Proxy: {proxy}")
else: else:
for proxy_provider in self.proxy_providers: for proxy_provider in self.proxy_providers:
proxy_uri = proxy_provider.get_proxy(proxy) proxy_uri = proxy_provider.get_proxy(proxy)
if proxy_uri: if proxy_uri:
proxy = ctx.params["proxy"] = proxy_uri proxy = ctx.params["proxy"] = proxy_uri
console.log(f"Using {proxy_provider.__class__.__name__} Proxy: {proxy}") self.log.info(f"Using {proxy_provider.__class__.__name__} Proxy: {proxy}")
break break
else: else:
console.log(f"Using explicit Proxy: {proxy}") self.log.info(f"Using explicit Proxy: {proxy}")
ctx.obj = ContextData( ctx.obj = ContextData(
config=self.service_config, config=self.service_config,
@ -283,7 +283,7 @@ class dl:
self.log.error(f"The Profile '{self.profile}' has no Cookies or Credentials, Check for typos") self.log.error(f"The Profile '{self.profile}' has no Cookies or Credentials, Check for typos")
sys.exit(1) sys.exit(1)
service.authenticate(cookies, credential) service.authenticate(cookies, credential)
console.log("Authenticated with Service") self.log.info("Authenticated with Service")
with console.status("Fetching Title Metadata...", spinner="dots"): with console.status("Fetching Title Metadata...", spinner="dots"):
titles = service.get_titles() titles = service.get_titles()
@ -426,7 +426,7 @@ class dl:
download_table.add_row(selected_tracks) download_table.add_row(selected_tracks)
if skip_dl: if skip_dl:
console.log("Skipping Download...") self.log.info("Skipping Download...")
else: else:
with Live( with Live(
Padding( Padding(
@ -481,7 +481,7 @@ class dl:
except KeyboardInterrupt: except KeyboardInterrupt:
self.DL_POOL_STOP.set() self.DL_POOL_STOP.set()
pool.shutdown(wait=False, cancel_futures=True) pool.shutdown(wait=False, cancel_futures=True)
console.log("Received Keyboard Interrupt, stopping...") self.log.info("Received Keyboard Interrupt, stopping...")
return return
video_track_n = 0 video_track_n = 0
@ -515,9 +515,9 @@ class dl:
if cc: if cc:
# will not appear in track listings as it's added after all times it lists # will not appear in track listings as it's added after all times it lists
title.tracks.add(cc) title.tracks.add(cc)
console.log(f"Extracted a Closed Caption from Video track {video_track_n + 1}") self.log.info(f"Extracted a Closed Caption from Video track {video_track_n + 1}")
else: else:
console.log(f"No Closed Captions were found in Video track {video_track_n + 1}") self.log.info(f"No Closed Captions were found in Video track {video_track_n + 1}")
except EnvironmentError: except EnvironmentError:
self.log.error( self.log.error(
"Cannot extract Closed Captions as the ccextractor executable was not found..." "Cannot extract Closed Captions as the ccextractor executable was not found..."
@ -548,7 +548,7 @@ class dl:
track.OnRepacked(track) track.OnRepacked(track)
if has_repacked: if has_repacked:
# we don't want to fill up the log with "Repacked x track" # we don't want to fill up the log with "Repacked x track"
console.log("Repacked one or more tracks with FFMPEG") self.log.info("Repacked one or more tracks with FFMPEG")
final_path = self.mux_tracks(title, not no_folder, not no_source) final_path = self.mux_tracks(title, not no_folder, not no_source)
@ -662,7 +662,7 @@ class dl:
drm.content_keys.update(from_vaults) drm.content_keys.update(from_vaults)
cached_keys = self.vaults.add_keys(drm.content_keys) cached_keys = self.vaults.add_keys(drm.content_keys)
console.log(f" + Newly added to {cached_keys}/{len(drm.content_keys)} Vaults") self.log.info(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:
cek_tree.add(f"[logging.level.error]No key was returned for {kid.hex}, cannot decrypt...") cek_tree.add(f"[logging.level.error]No key was returned for {kid.hex}, cannot decrypt...")

View File

@ -1,10 +1,10 @@
import logging
import shutil import shutil
from typing import Optional from typing import Optional
import click import click
from devine.core.config import config from devine.core.config import config
from devine.core.console import console
from devine.core.constants import context_settings from devine.core.constants import context_settings
from devine.core.services import Services from devine.core.services import Services
@ -17,13 +17,14 @@ def env() -> None:
@env.command() @env.command()
def info() -> None: def info() -> None:
"""Displays information about the current environment.""" """Displays information about the current environment."""
console.log(f"[Root Config] : {config.directories.user_configs / config.filenames.root_config}") log = logging.getLogger("env")
console.log(f"[Cookies] : {config.directories.cookies}") log.info(f"[Root Config] : {config.directories.user_configs / config.filenames.root_config}")
console.log(f"[WVDs] : {config.directories.wvds}") log.info(f"[Cookies] : {config.directories.cookies}")
console.log(f"[Cache] : {config.directories.cache}") log.info(f"[WVDs] : {config.directories.wvds}")
console.log(f"[Logs] : {config.directories.logs}") log.info(f"[Cache] : {config.directories.cache}")
console.log(f"[Temp Files] : {config.directories.temp}") log.info(f"[Logs] : {config.directories.logs}")
console.log(f"[Downloads] : {config.directories.downloads}") log.info(f"[Temp Files] : {config.directories.temp}")
log.info(f"[Downloads] : {config.directories.downloads}")
@env.group(name="clear", short_help="Clear an environment directory.", context_settings=context_settings) @env.group(name="clear", short_help="Clear an environment directory.", context_settings=context_settings)
@ -35,27 +36,29 @@ def clear() -> None:
@click.argument("service", type=str, required=False) @click.argument("service", type=str, required=False)
def cache(service: Optional[str]) -> None: def cache(service: Optional[str]) -> None:
"""Clear the environment cache directory.""" """Clear the environment cache directory."""
log = logging.getLogger("env")
cache_dir = config.directories.cache cache_dir = config.directories.cache
if service: if service:
cache_dir = cache_dir / Services.get_tag(service) cache_dir = cache_dir / Services.get_tag(service)
console.log(f"Clearing cache directory: {cache_dir}") log.info(f"Clearing cache directory: {cache_dir}")
files_count = len(list(cache_dir.glob("**/*"))) files_count = len(list(cache_dir.glob("**/*")))
if not files_count: if not files_count:
console.log("No files to delete") log.info("No files to delete")
else: else:
console.log(f"Deleting {files_count} files...") log.info(f"Deleting {files_count} files...")
shutil.rmtree(cache_dir) shutil.rmtree(cache_dir)
console.log("Cleared") log.info("Cleared")
@clear.command() @clear.command()
def temp() -> None: def temp() -> None:
"""Clear the environment temp directory.""" """Clear the environment temp directory."""
console.log(f"Clearing temp directory: {config.directories.temp}") log = logging.getLogger("env")
log.info(f"Clearing temp directory: {config.directories.temp}")
files_count = len(list(config.directories.temp.glob("**/*"))) files_count = len(list(config.directories.temp.glob("**/*")))
if not files_count: if not files_count:
console.log("No files to delete") log.info("No files to delete")
else: else:
console.log(f"Deleting {files_count} files...") log.info(f"Deleting {files_count} files...")
shutil.rmtree(config.directories.temp) shutil.rmtree(config.directories.temp)
console.log("Cleared") log.info("Cleared")

View File

@ -6,7 +6,6 @@ from typing import Optional
import click import click
from devine.core.config import config from devine.core.config import config
from devine.core.console import console
from devine.core.constants import context_settings from devine.core.constants import context_settings
from devine.core.services import Services from devine.core.services import Services
from devine.core.vault import Vault from devine.core.vault import Vault
@ -53,10 +52,10 @@ def copy(to_vault: str, from_vaults: list[str], service: Optional[str] = None) -
to_vault: Vault = vaults.vaults[0] to_vault: Vault = vaults.vaults[0]
from_vaults: list[Vault] = vaults.vaults[1:] from_vaults: list[Vault] = vaults.vaults[1:]
console.log(f"Copying data from {', '.join([x.name for x in from_vaults])}, into {to_vault.name}") log.info(f"Copying data from {', '.join([x.name for x in from_vaults])}, into {to_vault.name}")
if service: if service:
service = Services.get_tag(service) service = Services.get_tag(service)
console.log(f"Only copying data for service {service}") log.info(f"Only copying data for service {service}")
total_added = 0 total_added = 0
for from_vault in from_vaults: for from_vault in from_vaults:
@ -66,7 +65,7 @@ def copy(to_vault: str, from_vaults: list[str], service: Optional[str] = None) -
services = from_vault.get_services() services = from_vault.get_services()
for service_ in services: for service_ in services:
console.log(f"Getting data from {from_vault} for {service_}") log.info(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 content_keys = list(from_vault.get_keys(service_)) # important as it's a generator we iterate twice
bad_keys = { bad_keys = {
@ -85,7 +84,7 @@ def copy(to_vault: str, from_vaults: list[str], service: Optional[str] = None) -
} }
total_count = len(content_keys) total_count = len(content_keys)
console.log(f"Adding {total_count} Content Keys to {to_vault} for {service_}") log.info(f"Adding {total_count} Content Keys to {to_vault} for {service_}")
try: try:
added = to_vault.add_keys(service_, content_keys) added = to_vault.add_keys(service_, content_keys)
@ -96,9 +95,9 @@ def copy(to_vault: str, from_vaults: list[str], service: Optional[str] = None) -
total_added += added total_added += added
existed = total_count - added existed = total_count - added
console.log(f"{to_vault} ({service_}): {added} newly added, {existed} already existed (skipped)") log.info(f"{to_vault} ({service_}): {added} newly added, {existed} already existed (skipped)")
console.log(f"{to_vault}: {total_added} total newly added") log.info(f"{to_vault}: {total_added} total newly added")
@kv.command() @kv.command()
@ -142,6 +141,7 @@ def add(file: Path, service: str, vaults: list[str]) -> None:
if len(vaults) < 1: if len(vaults) < 1:
raise click.ClickException("You must provide at least one Vault.") raise click.ClickException("You must provide at least one Vault.")
log = logging.getLogger("kv")
service = Services.get_tag(service) service = Services.get_tag(service)
vaults_ = Vaults() vaults_ = Vaults()
@ -168,12 +168,12 @@ def add(file: Path, service: str, vaults: list[str]) -> None:
total_count = len(kid_keys) total_count = len(kid_keys)
for vault in vaults_: for vault in vaults_:
console.log(f"Adding {total_count} Content Keys to {vault}") log.info(f"Adding {total_count} Content Keys to {vault}")
added_count = vault.add_keys(service, kid_keys) added_count = vault.add_keys(service, kid_keys)
existed_count = total_count - added_count existed_count = total_count - added_count
console.log(f"{vault}: {added_count} newly added, {existed_count} already existed (skipped)") log.info(f"{vault}: {added_count} newly added, {existed_count} already existed (skipped)")
console.log("Done!") log.info("Done!")
@kv.command() @kv.command()
@ -196,15 +196,15 @@ def prepare(vaults: list[str]) -> None:
if hasattr(vault, "has_table") and hasattr(vault, "create_table"): if hasattr(vault, "has_table") and hasattr(vault, "create_table"):
for service_tag in Services.get_tags(): for service_tag in Services.get_tags():
if vault.has_table(service_tag): if vault.has_table(service_tag):
console.log(f"{vault} already has a {service_tag} Table") log.info(f"{vault} already has a {service_tag} Table")
else: else:
try: try:
vault.create_table(service_tag, commit=True) vault.create_table(service_tag, commit=True)
console.log(f"{vault}: Created {service_tag} Table") log.info(f"{vault}: Created {service_tag} Table")
except PermissionError: except PermissionError:
log.error(f"{vault} user has no create table permission, skipping...") log.error(f"{vault} user has no create table permission, skipping...")
continue continue
else: else:
console.log(f"{vault} does not use tables, skipping...") log.info(f"{vault} does not use tables, skipping...")
console.log("Done!") log.info("Done!")

View File

@ -1,3 +1,4 @@
import logging
from pathlib import Path from pathlib import Path
from typing import Optional from typing import Optional
@ -27,28 +28,30 @@ def wvd() -> None:
@click.argument("paths", type=Path, nargs=-1) @click.argument("paths", type=Path, nargs=-1)
def add(paths: list[Path]) -> None: def add(paths: list[Path]) -> None:
"""Add one or more WVD (Widevine Device) files to the WVDs Directory.""" """Add one or more WVD (Widevine Device) files to the WVDs Directory."""
log = logging.getLogger("wvd")
for path in paths: for path in paths:
dst_path = config.directories.wvds / path.name dst_path = config.directories.wvds / path.name
if not path.exists(): if not path.exists():
console.log(f"The WVD path '{path}' does not exist...") log.error(f"The WVD path '{path}' does not exist...")
elif dst_path.exists(): elif dst_path.exists():
console.log(f"WVD named '{path.stem}' already exists...") log.error(f"WVD named '{path.stem}' already exists...")
else: else:
# TODO: Check for and log errors # TODO: Check for and log errors
_ = Device.load(path) # test if WVD is valid _ = Device.load(path) # test if WVD is valid
shutil.move(path, config.directories.wvds) shutil.move(path, config.directories.wvds)
console.log(f"Added {path.stem}") log.info(f"Added {path.stem}")
@wvd.command() @wvd.command()
@click.argument("names", type=str, nargs=-1) @click.argument("names", type=str, nargs=-1)
def delete(names: list[str]) -> None: def delete(names: list[str]) -> None:
"""Delete one or more WVD (Widevine Device) files from the WVDs Directory.""" """Delete one or more WVD (Widevine Device) files from the WVDs Directory."""
log = logging.getLogger("wvd")
for name in names: for name in names:
path = (config.directories.wvds / name).with_suffix(".wvd") path = (config.directories.wvds / name).with_suffix(".wvd")
if not path.exists(): if not path.exists():
console.log(f"[logging.level.error]No WVD file exists by the name '{name}'...") log.error(f"No WVD file exists by the name '{name}'...")
continue continue
answer = Prompt.ask( answer = Prompt.ask(
@ -58,11 +61,11 @@ def delete(names: list[str]) -> None:
console=console console=console
) )
if answer == "n": if answer == "n":
console.log("Aborting...") log.info("Aborting...")
continue continue
Path.unlink(path) Path.unlink(path)
console.log(f"Deleted {name}") log.info(f"Deleted {name}")
@wvd.command() @wvd.command()
@ -79,26 +82,28 @@ def parse(path: Path) -> None:
if named: if named:
path = config.directories.wvds / f"{path.name}.wvd" path = config.directories.wvds / f"{path.name}.wvd"
log = logging.getLogger("wvd")
device = Device.load(path) device = Device.load(path)
console.log(f"System ID: {device.system_id}") log.info(f"System ID: {device.system_id}")
console.log(f"Security Level: {device.security_level}") log.info(f"Security Level: {device.security_level}")
console.log(f"Type: {device.type}") log.info(f"Type: {device.type}")
console.log(f"Flags: {device.flags}") log.info(f"Flags: {device.flags}")
console.log(f"Private Key: {bool(device.private_key)}") log.info(f"Private Key: {bool(device.private_key)}")
console.log(f"Client ID: {bool(device.client_id)}") log.info(f"Client ID: {bool(device.client_id)}")
console.log(f"VMP: {bool(device.client_id.vmp_data)}") log.info(f"VMP: {bool(device.client_id.vmp_data)}")
console.log("Client ID:") log.info("Client ID:")
console.log(device.client_id) log.info(device.client_id)
console.log("VMP:") log.info("VMP:")
if device.client_id.vmp_data: if device.client_id.vmp_data:
file_hashes = FileHashes() file_hashes = FileHashes()
file_hashes.ParseFromString(device.client_id.vmp_data) file_hashes.ParseFromString(device.client_id.vmp_data)
console.log(str(file_hashes)) log.info(str(file_hashes))
else: else:
console.log("None") log.info("None")
@wvd.command() @wvd.command()
@ -124,9 +129,10 @@ def dump(wvd_paths: list[Path], out_dir: Path) -> None:
device = Device.load(wvd_path) device = Device.load(wvd_path)
console.log(f"Dumping: {wvd_path}") log = logging.getLogger("wvd")
console.log(f"L{device.security_level} {device.system_id} {device.type.name}") log.info(f"Dumping: {wvd_path}")
console.log(f"Saving to: {out_path}") log.info(f"L{device.security_level} {device.system_id} {device.type.name}")
log.info(f"Saving to: {out_path}")
device_meta = { device_meta = {
"wvd": { "wvd": {
@ -142,7 +148,7 @@ def dump(wvd_paths: list[Path], out_dir: Path) -> None:
device_meta_path = out_path / "metadata.yml" device_meta_path = out_path / "metadata.yml"
device_meta_path.write_text(yaml.dump(device_meta), encoding="utf8") device_meta_path.write_text(yaml.dump(device_meta), encoding="utf8")
console.log(" + Device Metadata") log.info(" + Device Metadata")
if device.private_key: if device.private_key:
private_key_path = out_path / "private_key.pem" private_key_path = out_path / "private_key.pem"
@ -153,23 +159,23 @@ def dump(wvd_paths: list[Path], out_dir: Path) -> None:
private_key_path.with_suffix(".der").write_bytes( private_key_path.with_suffix(".der").write_bytes(
device.private_key.export_key(format="DER") device.private_key.export_key(format="DER")
) )
console.log(" + Private Key") log.info(" + Private Key")
else: else:
console.log("[logging.level.warning] - No Private Key available") log.warning(" - No Private Key available")
if device.client_id: if device.client_id:
client_id_path = out_path / "client_id.bin" client_id_path = out_path / "client_id.bin"
client_id_path.write_bytes(device.client_id.SerializeToString()) client_id_path.write_bytes(device.client_id.SerializeToString())
console.log(" + Client ID") log.info(" + Client ID")
else: else:
console.log("[logging.level.warning] - No Client ID available") log.warning(" - No Client ID available")
if device.client_id.vmp_data: if device.client_id.vmp_data:
vmp_path = out_path / "vmp.bin" vmp_path = out_path / "vmp.bin"
vmp_path.write_bytes(device.client_id.vmp_data) vmp_path.write_bytes(device.client_id.vmp_data)
console.log(" + VMP (File Hashes)") log.info(" + VMP (File Hashes)")
else: else:
console.log(" - No VMP (File Hashes) available") log.info(" - No VMP (File Hashes) available")
@wvd.command() @wvd.command()
@ -231,24 +237,26 @@ def new(
out_path = (output or config.directories.wvds) / f"{name}_{device.system_id}_l{device.security_level}.wvd" out_path = (output or config.directories.wvds) / f"{name}_{device.system_id}_l{device.security_level}.wvd"
device.dump(out_path) device.dump(out_path)
console.log(f"Created binary WVD file, {out_path.name}") log = logging.getLogger("wvd")
console.log(f" + Saved to: {out_path.absolute()}")
console.log(f"System ID: {device.system_id}") log.info(f"Created binary WVD file, {out_path.name}")
console.log(f"Security Level: {device.security_level}") log.info(f" + Saved to: {out_path.absolute()}")
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)}")
console.log("Client ID:") log.info(f"System ID: {device.system_id}")
console.log(device.client_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("VMP:") log.info("Client ID:")
log.info(device.client_id)
log.info("VMP:")
if device.client_id.vmp_data: if device.client_id.vmp_data:
file_hashes = FileHashes() file_hashes = FileHashes()
file_hashes.ParseFromString(device.client_id.vmp_data) file_hashes.ParseFromString(device.client_id.vmp_data)
console.log(str(file_hashes)) log.info(str(file_hashes))
else: else:
console.log("None") log.info("None")

View File

@ -26,7 +26,6 @@ from pywidevine.pssh import PSSH
from requests import Session from requests import Session
from rich import filesize from rich import filesize
from devine.core.console import console
from devine.core.constants import AnyTrack from devine.core.constants import AnyTrack
from devine.core.downloaders import aria2c from devine.core.downloaders import aria2c
from devine.core.drm import Widevine from devine.core.drm import Widevine
@ -545,7 +544,7 @@ class DASH:
except KeyboardInterrupt: except KeyboardInterrupt:
state_event.set() state_event.set()
pool.shutdown(wait=False, cancel_futures=True) pool.shutdown(wait=False, cancel_futures=True)
console.log("Received Keyboard Interrupt, stopping...") log.info("Received Keyboard Interrupt, stopping...")
return return
@staticmethod @staticmethod

View File

@ -24,7 +24,6 @@ from pywidevine.pssh import PSSH
from requests import Session from requests import Session
from rich import filesize from rich import filesize
from devine.core.console import console
from devine.core.constants import AnyTrack from devine.core.constants import AnyTrack
from devine.core.downloaders import aria2c from devine.core.downloaders import aria2c
from devine.core.drm import DRM_T, ClearKey, Widevine from devine.core.drm import DRM_T, ClearKey, Widevine
@ -385,7 +384,7 @@ class HLS:
except KeyboardInterrupt: except KeyboardInterrupt:
state_event.set() state_event.set()
pool.shutdown(wait=False, cancel_futures=True) pool.shutdown(wait=False, cancel_futures=True)
console.log("Received Keyboard Interrupt, stopping...") log.info("Received Keyboard Interrupt, stopping...")
return return
@staticmethod @staticmethod

View File

@ -53,17 +53,17 @@ class Service(metaclass=ABCMeta):
# no explicit proxy, let's get one to GEOFENCE if needed # no explicit proxy, let's get one to GEOFENCE if needed
current_region = get_ip_info(self.session)["country"].lower() current_region = get_ip_info(self.session)["country"].lower()
if any(x.lower() == current_region for x in self.GEOFENCE): if any(x.lower() == current_region for x in self.GEOFENCE):
console.log("Service is not Geoblocked in your region") self.log.info("Service is not Geoblocked in your region")
else: else:
requested_proxy = self.GEOFENCE[0] # first is likely main region requested_proxy = self.GEOFENCE[0] # first is likely main region
console.log(f"Service is Geoblocked in your region, getting a Proxy to {requested_proxy}") self.log.info(f"Service is Geoblocked in your region, getting a Proxy to {requested_proxy}")
for proxy_provider in ctx.obj.proxy_providers: for proxy_provider in ctx.obj.proxy_providers:
self.proxy = proxy_provider.get_proxy(requested_proxy) self.proxy = proxy_provider.get_proxy(requested_proxy)
if self.proxy: if self.proxy:
console.log(f"Got Proxy from {proxy_provider.__class__.__name__}") self.log.info(f"Got Proxy from {proxy_provider.__class__.__name__}")
break break
else: else:
console.log("Service has no Geofence") self.log.info("Service has no Geofence")
if self.proxy: if self.proxy:
self.session.proxies.update({"all": self.proxy}) self.session.proxies.update({"all": self.proxy})

View File

@ -1,5 +1,6 @@
from __future__ import annotations from __future__ import annotations
import logging
import math import math
import re import re
import subprocess import subprocess
@ -10,7 +11,6 @@ from typing import Any, Optional, Union
from langcodes import Language from langcodes import Language
from devine.core.config import config from devine.core.config import config
from devine.core.console import console
from devine.core.tracks.subtitle import Subtitle from devine.core.tracks.subtitle import Subtitle
from devine.core.tracks.track import Track from devine.core.tracks.track import Track
from devine.core.utilities import FPS, get_binary_path, get_boxes from devine.core.utilities import FPS, get_binary_path, get_boxes
@ -296,14 +296,15 @@ class Video(Track):
if not executable: if not executable:
raise EnvironmentError("FFmpeg executable \"ffmpeg\" was not found but is required for this call.") raise EnvironmentError("FFmpeg executable \"ffmpeg\" was not found but is required for this call.")
console.log("Removing EIA-CC from Video Track with FFMPEG") log = logging.getLogger("x264-clean")
log.info("Removing EIA-CC from Video Track with FFMPEG")
with open(self.path, "rb") as f: with open(self.path, "rb") as f:
file = f.read(60000) file = f.read(60000)
x264 = re.search(br"(.{16})(x264)", file) x264 = re.search(br"(.{16})(x264)", file)
if not x264: if not x264:
console.log(" - No x264 encode settings were found, unsupported...") log.info(" - No x264 encode settings were found, unsupported...")
return False return False
uuid = x264.group(1).hex() uuid = x264.group(1).hex()
@ -322,7 +323,7 @@ class Video(Track):
str(cleaned_path) str(cleaned_path)
], check=True) ], check=True)
console.log(" + Removed") log.info(" + Removed")
self.swap(cleaned_path) self.swap(cleaned_path)