mirror of https://github.com/devine-dl/devine.git
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:
parent
401d0481df
commit
eb3f268d64
|
@ -10,7 +10,6 @@ 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
|
||||
|
||||
|
@ -29,13 +28,15 @@ 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)
|
||||
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.
|
||||
|
||||
\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))
|
||||
|
@ -54,9 +55,9 @@ def list_(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
|
||||
console.log(service)
|
||||
log.info(service)
|
||||
for profile, authorizations in dict(sorted(profiles.items())).items():
|
||||
console.log(f' "{profile}": {", ".join(authorizations)}')
|
||||
log.info(f' "{profile}": {", ".join(authorizations)}')
|
||||
|
||||
|
||||
@auth.command(
|
||||
|
@ -81,7 +82,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:
|
||||
console.log(f"Cookie: {cookie}")
|
||||
log.info(f"Cookie: {cookie}")
|
||||
log.debug(cookie.read_text(encoding="utf8").strip())
|
||||
found = True
|
||||
break
|
||||
|
@ -90,7 +91,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:
|
||||
console.log(f"Credential: {':'.join(list(credential))}")
|
||||
log.info(f"Credential: {':'.join(list(credential))}")
|
||||
found = True
|
||||
break
|
||||
|
||||
|
@ -105,24 +106,26 @@ 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)
|
||||
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.
|
||||
|
||||
\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():
|
||||
console.log(f"{service_}: {profile or '--'}")
|
||||
log.info(f"{service_}: {profile or '--'}")
|
||||
found_profile = True
|
||||
|
||||
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")
|
||||
console.log(f"The default profile is {default}")
|
||||
log.info(f"The default profile is {default}")
|
||||
|
||||
|
||||
@auth.command(
|
||||
|
@ -132,7 +135,8 @@ def status(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.")
|
||||
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.
|
||||
|
||||
|
@ -144,6 +148,7 @@ def delete(profile: str, service: str, cookie: bool, credential: bool):
|
|||
Profile and Service names are case-sensitive.
|
||||
Comments may be removed from config!
|
||||
"""
|
||||
log = ctx.obj
|
||||
service_f = service
|
||||
profile_f = profile
|
||||
found = False
|
||||
|
@ -154,7 +159,7 @@ def delete(profile: str, service: str, cookie: bool, credential: bool):
|
|||
for cookie_ in cookie_dir.glob("*.txt"):
|
||||
if cookie_.stem == profile_f:
|
||||
cookie_.unlink()
|
||||
console.log(f"Deleted Cookie: {cookie_}")
|
||||
log.info(f"Deleted Cookie: {cookie_}")
|
||||
found = True
|
||||
break
|
||||
|
||||
|
@ -169,7 +174,7 @@ def delete(profile: str, service: str, cookie: bool, credential: bool):
|
|||
data = yaml.load(config_path)
|
||||
del data["credentials"][key][profile_f]
|
||||
yaml.dump(data, config_path)
|
||||
console.log(f"Deleted Credential: {credential_}")
|
||||
log.info(f"Deleted Credential: {credential_}")
|
||||
found = True
|
||||
break
|
||||
|
||||
|
@ -219,7 +224,7 @@ def add(ctx: click.Context, profile: str, service: str, cookie: Optional[str] =
|
|||
if cookie:
|
||||
cookie = Path(cookie)
|
||||
else:
|
||||
console.log("Skipped adding a Cookie...")
|
||||
log.info("Skipped adding a Cookie...")
|
||||
|
||||
if credential:
|
||||
try:
|
||||
|
@ -234,7 +239,7 @@ def add(ctx: click.Context, profile: str, service: str, cookie: Optional[str] =
|
|||
except ValueError as e:
|
||||
raise click.ClickException(str(e))
|
||||
else:
|
||||
console.log("Skipped adding a Credential...")
|
||||
log.info("Skipped adding a Credential...")
|
||||
|
||||
if cookie:
|
||||
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.")
|
||||
sys.exit(1)
|
||||
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:
|
||||
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][profile] = credential.dumps()
|
||||
yaml.dump(data, config_path)
|
||||
console.log(f"Added Credential: {credential}")
|
||||
log.info(f"Added Credential: {credential}")
|
||||
|
|
|
@ -6,7 +6,6 @@ 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
|
||||
|
||||
|
||||
|
@ -81,10 +80,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
|
||||
console.log(f"Set {key} to {repr(value)}")
|
||||
log.info(f"Set {key} to {repr(value)}")
|
||||
elif is_delete:
|
||||
del parent_data[trailing_key]
|
||||
console.log(f"Unset {key}")
|
||||
log.info(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)
|
||||
|
|
|
@ -151,15 +151,15 @@ class dl:
|
|||
with console.status("Preparing Service and Profile Authentication...", spinner="dots"):
|
||||
if 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:
|
||||
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
|
||||
if service_config_path.is_file():
|
||||
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:
|
||||
self.service_config = {}
|
||||
merge_dict(config.services.get(self.service), self.service_config)
|
||||
|
@ -170,7 +170,7 @@ class dl:
|
|||
except ValueError as e:
|
||||
self.log.error(f"Failed to load Widevine CDM, {e}")
|
||||
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})"
|
||||
)
|
||||
|
||||
|
@ -180,7 +180,7 @@ class dl:
|
|||
vault_type = vault["type"]
|
||||
del vault["type"]
|
||||
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"):
|
||||
self.proxy_providers = []
|
||||
|
@ -191,7 +191,7 @@ class dl:
|
|||
if get_binary_path("hola-proxy"):
|
||||
self.proxy_providers.append(Hola())
|
||||
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:
|
||||
requested_provider = None
|
||||
|
@ -215,16 +215,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
|
||||
console.log(f"Using {proxy_provider.__class__.__name__} Proxy: {proxy}")
|
||||
self.log.info(f"Using {proxy_provider.__class__.__name__} Proxy: {proxy}")
|
||||
else:
|
||||
for proxy_provider in self.proxy_providers:
|
||||
proxy_uri = proxy_provider.get_proxy(proxy)
|
||||
if 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
|
||||
else:
|
||||
console.log(f"Using explicit Proxy: {proxy}")
|
||||
self.log.info(f"Using explicit Proxy: {proxy}")
|
||||
|
||||
ctx.obj = ContextData(
|
||||
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")
|
||||
sys.exit(1)
|
||||
service.authenticate(cookies, credential)
|
||||
console.log("Authenticated with Service")
|
||||
self.log.info("Authenticated with Service")
|
||||
|
||||
with console.status("Fetching Title Metadata...", spinner="dots"):
|
||||
titles = service.get_titles()
|
||||
|
@ -426,7 +426,7 @@ class dl:
|
|||
download_table.add_row(selected_tracks)
|
||||
|
||||
if skip_dl:
|
||||
console.log("Skipping Download...")
|
||||
self.log.info("Skipping Download...")
|
||||
else:
|
||||
with Live(
|
||||
Padding(
|
||||
|
@ -481,7 +481,7 @@ class dl:
|
|||
except KeyboardInterrupt:
|
||||
self.DL_POOL_STOP.set()
|
||||
pool.shutdown(wait=False, cancel_futures=True)
|
||||
console.log("Received Keyboard Interrupt, stopping...")
|
||||
self.log.info("Received Keyboard Interrupt, stopping...")
|
||||
return
|
||||
|
||||
video_track_n = 0
|
||||
|
@ -515,9 +515,9 @@ class dl:
|
|||
if cc:
|
||||
# will not appear in track listings as it's added after all times it lists
|
||||
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:
|
||||
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:
|
||||
self.log.error(
|
||||
"Cannot extract Closed Captions as the ccextractor executable was not found..."
|
||||
|
@ -548,7 +548,7 @@ class dl:
|
|||
track.OnRepacked(track)
|
||||
if has_repacked:
|
||||
# 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)
|
||||
|
||||
|
@ -662,7 +662,7 @@ class dl:
|
|||
drm.content_keys.update(from_vaults)
|
||||
|
||||
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:
|
||||
cek_tree.add(f"[logging.level.error]No key was returned for {kid.hex}, cannot decrypt...")
|
||||
|
|
|
@ -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,13 +17,14 @@ def env() -> None:
|
|||
@env.command()
|
||||
def info() -> None:
|
||||
"""Displays information about the current environment."""
|
||||
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}")
|
||||
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}")
|
||||
|
||||
|
||||
@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)
|
||||
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)
|
||||
console.log(f"Clearing cache directory: {cache_dir}")
|
||||
log.info(f"Clearing cache directory: {cache_dir}")
|
||||
files_count = len(list(cache_dir.glob("**/*")))
|
||||
if not files_count:
|
||||
console.log("No files to delete")
|
||||
log.info("No files to delete")
|
||||
else:
|
||||
console.log(f"Deleting {files_count} files...")
|
||||
log.info(f"Deleting {files_count} files...")
|
||||
shutil.rmtree(cache_dir)
|
||||
console.log("Cleared")
|
||||
log.info("Cleared")
|
||||
|
||||
|
||||
@clear.command()
|
||||
def temp() -> None:
|
||||
"""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("**/*")))
|
||||
if not files_count:
|
||||
console.log("No files to delete")
|
||||
log.info("No files to delete")
|
||||
else:
|
||||
console.log(f"Deleting {files_count} files...")
|
||||
log.info(f"Deleting {files_count} files...")
|
||||
shutil.rmtree(config.directories.temp)
|
||||
console.log("Cleared")
|
||||
log.info("Cleared")
|
||||
|
|
|
@ -6,7 +6,6 @@ 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
|
||||
|
@ -53,10 +52,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:]
|
||||
|
||||
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:
|
||||
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
|
||||
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()
|
||||
|
||||
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
|
||||
|
||||
bad_keys = {
|
||||
|
@ -85,7 +84,7 @@ def copy(to_vault: str, from_vaults: list[str], service: Optional[str] = None) -
|
|||
}
|
||||
|
||||
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:
|
||||
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
|
||||
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()
|
||||
|
@ -142,6 +141,7 @@ 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_:
|
||||
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)
|
||||
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()
|
||||
|
@ -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):
|
||||
console.log(f"{vault} already has a {service_tag} Table")
|
||||
log.info(f"{vault} already has a {service_tag} Table")
|
||||
else:
|
||||
try:
|
||||
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:
|
||||
log.error(f"{vault} user has no create table permission, skipping...")
|
||||
continue
|
||||
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!")
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
import logging
|
||||
from pathlib import Path
|
||||
from typing import Optional
|
||||
|
||||
|
@ -27,28 +28,30 @@ def wvd() -> None:
|
|||
@click.argument("paths", type=Path, nargs=-1)
|
||||
def add(paths: list[Path]) -> None:
|
||||
"""Add one or more WVD (Widevine Device) files to the WVDs Directory."""
|
||||
log = logging.getLogger("wvd")
|
||||
for path in paths:
|
||||
dst_path = config.directories.wvds / path.name
|
||||
|
||||
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():
|
||||
console.log(f"WVD named '{path.stem}' already exists...")
|
||||
log.error(f"WVD named '{path.stem}' already exists...")
|
||||
else:
|
||||
# TODO: Check for and log errors
|
||||
_ = Device.load(path) # test if WVD is valid
|
||||
shutil.move(path, config.directories.wvds)
|
||||
console.log(f"Added {path.stem}")
|
||||
log.info(f"Added {path.stem}")
|
||||
|
||||
|
||||
@wvd.command()
|
||||
@click.argument("names", type=str, nargs=-1)
|
||||
def delete(names: list[str]) -> None:
|
||||
"""Delete one or more WVD (Widevine Device) files from the WVDs Directory."""
|
||||
log = logging.getLogger("wvd")
|
||||
for name in names:
|
||||
path = (config.directories.wvds / name).with_suffix(".wvd")
|
||||
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
|
||||
|
||||
answer = Prompt.ask(
|
||||
|
@ -58,11 +61,11 @@ def delete(names: list[str]) -> None:
|
|||
console=console
|
||||
)
|
||||
if answer == "n":
|
||||
console.log("Aborting...")
|
||||
log.info("Aborting...")
|
||||
continue
|
||||
|
||||
Path.unlink(path)
|
||||
console.log(f"Deleted {name}")
|
||||
log.info(f"Deleted {name}")
|
||||
|
||||
|
||||
@wvd.command()
|
||||
|
@ -79,26 +82,28 @@ def parse(path: Path) -> None:
|
|||
if named:
|
||||
path = config.directories.wvds / f"{path.name}.wvd"
|
||||
|
||||
log = logging.getLogger("wvd")
|
||||
|
||||
device = Device.load(path)
|
||||
|
||||
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(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("Client ID:")
|
||||
console.log(device.client_id)
|
||||
log.info("Client ID:")
|
||||
log.info(device.client_id)
|
||||
|
||||
console.log("VMP:")
|
||||
log.info("VMP:")
|
||||
if device.client_id.vmp_data:
|
||||
file_hashes = FileHashes()
|
||||
file_hashes.ParseFromString(device.client_id.vmp_data)
|
||||
console.log(str(file_hashes))
|
||||
log.info(str(file_hashes))
|
||||
else:
|
||||
console.log("None")
|
||||
log.info("None")
|
||||
|
||||
|
||||
@wvd.command()
|
||||
|
@ -124,9 +129,10 @@ def dump(wvd_paths: list[Path], out_dir: Path) -> None:
|
|||
|
||||
device = Device.load(wvd_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}")
|
||||
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}")
|
||||
|
||||
device_meta = {
|
||||
"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.write_text(yaml.dump(device_meta), encoding="utf8")
|
||||
console.log(" + Device Metadata")
|
||||
log.info(" + Device Metadata")
|
||||
|
||||
if device.private_key:
|
||||
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(
|
||||
device.private_key.export_key(format="DER")
|
||||
)
|
||||
console.log(" + Private Key")
|
||||
log.info(" + Private Key")
|
||||
else:
|
||||
console.log("[logging.level.warning] - No Private Key available")
|
||||
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())
|
||||
console.log(" + Client ID")
|
||||
log.info(" + Client ID")
|
||||
else:
|
||||
console.log("[logging.level.warning] - No Client ID available")
|
||||
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)
|
||||
console.log(" + VMP (File Hashes)")
|
||||
log.info(" + VMP (File Hashes)")
|
||||
else:
|
||||
console.log(" - No VMP (File Hashes) available")
|
||||
log.info(" - No VMP (File Hashes) available")
|
||||
|
||||
|
||||
@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"
|
||||
device.dump(out_path)
|
||||
|
||||
console.log(f"Created binary WVD file, {out_path.name}")
|
||||
console.log(f" + Saved to: {out_path.absolute()}")
|
||||
log = logging.getLogger("wvd")
|
||||
|
||||
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(f"Created binary WVD file, {out_path.name}")
|
||||
log.info(f" + Saved to: {out_path.absolute()}")
|
||||
|
||||
console.log("Client ID:")
|
||||
console.log(device.client_id)
|
||||
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("VMP:")
|
||||
log.info("Client ID:")
|
||||
log.info(device.client_id)
|
||||
|
||||
log.info("VMP:")
|
||||
if device.client_id.vmp_data:
|
||||
file_hashes = FileHashes()
|
||||
file_hashes.ParseFromString(device.client_id.vmp_data)
|
||||
console.log(str(file_hashes))
|
||||
log.info(str(file_hashes))
|
||||
else:
|
||||
console.log("None")
|
||||
log.info("None")
|
||||
|
|
|
@ -26,7 +26,6 @@ from pywidevine.pssh import PSSH
|
|||
from requests import Session
|
||||
from rich import filesize
|
||||
|
||||
from devine.core.console import console
|
||||
from devine.core.constants import AnyTrack
|
||||
from devine.core.downloaders import aria2c
|
||||
from devine.core.drm import Widevine
|
||||
|
@ -545,7 +544,7 @@ class DASH:
|
|||
except KeyboardInterrupt:
|
||||
state_event.set()
|
||||
pool.shutdown(wait=False, cancel_futures=True)
|
||||
console.log("Received Keyboard Interrupt, stopping...")
|
||||
log.info("Received Keyboard Interrupt, stopping...")
|
||||
return
|
||||
|
||||
@staticmethod
|
||||
|
|
|
@ -24,7 +24,6 @@ from pywidevine.pssh import PSSH
|
|||
from requests import Session
|
||||
from rich import filesize
|
||||
|
||||
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
|
||||
|
@ -385,7 +384,7 @@ class HLS:
|
|||
except KeyboardInterrupt:
|
||||
state_event.set()
|
||||
pool.shutdown(wait=False, cancel_futures=True)
|
||||
console.log("Received Keyboard Interrupt, stopping...")
|
||||
log.info("Received Keyboard Interrupt, stopping...")
|
||||
return
|
||||
|
||||
@staticmethod
|
||||
|
|
|
@ -53,17 +53,17 @@ class Service(metaclass=ABCMeta):
|
|||
# no explicit proxy, let's get one to GEOFENCE if needed
|
||||
current_region = get_ip_info(self.session)["country"].lower()
|
||||
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:
|
||||
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:
|
||||
self.proxy = proxy_provider.get_proxy(requested_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
|
||||
else:
|
||||
console.log("Service has no Geofence")
|
||||
self.log.info("Service has no Geofence")
|
||||
|
||||
if self.proxy:
|
||||
self.session.proxies.update({"all": self.proxy})
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
from __future__ import annotations
|
||||
|
||||
import logging
|
||||
import math
|
||||
import re
|
||||
import subprocess
|
||||
|
@ -10,7 +11,6 @@ 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,14 +296,15 @@ class Video(Track):
|
|||
if not executable:
|
||||
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:
|
||||
file = f.read(60000)
|
||||
|
||||
x264 = re.search(br"(.{16})(x264)", file)
|
||||
if not x264:
|
||||
console.log(" - No x264 encode settings were found, unsupported...")
|
||||
log.info(" - No x264 encode settings were found, unsupported...")
|
||||
return False
|
||||
|
||||
uuid = x264.group(1).hex()
|
||||
|
@ -322,7 +323,7 @@ class Video(Track):
|
|||
str(cleaned_path)
|
||||
], check=True)
|
||||
|
||||
console.log(" + Removed")
|
||||
log.info(" + Removed")
|
||||
|
||||
self.swap(cleaned_path)
|
||||
|
||||
|
|
Loading…
Reference in New Issue