mirror of https://github.com/devine-dl/devine.git
Replace log.info calls with console.log calls
I've moved log.info calls to console.log calls to reduce conflicts of logs at the same time as console refreshes, but also to reduce unnecessary log level text being printed to the console. We don't need to know if a log is an `info` level log, but I've kept log.error's and such as we would want to know if a log is an error log and such.
This commit is contained in:
parent
3e1a067724
commit
62d91a3e77
|
@ -10,6 +10,7 @@ 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
|
||||||
|
|
||||||
|
@ -28,15 +29,13 @@ 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)
|
||||||
@click.pass_context
|
def list_(service: Optional[str] = None) -> None:
|
||||||
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))
|
||||||
|
@ -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
|
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
|
||||||
log.info(service)
|
console.log(service)
|
||||||
for profile, authorizations in dict(sorted(profiles.items())).items():
|
for profile, authorizations in dict(sorted(profiles.items())).items():
|
||||||
log.info(f' "{profile}": {", ".join(authorizations)}')
|
console.log(f' "{profile}": {", ".join(authorizations)}')
|
||||||
|
|
||||||
|
|
||||||
@auth.command(
|
@auth.command(
|
||||||
|
@ -82,7 +81,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:
|
||||||
log.info(f"Cookie: {cookie}")
|
console.log(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
|
||||||
|
@ -91,7 +90,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:
|
||||||
log.info(f"Credential: {':'.join(list(credential))}")
|
console.log(f"Credential: {':'.join(list(credential))}")
|
||||||
found = True
|
found = True
|
||||||
break
|
break
|
||||||
|
|
||||||
|
@ -106,26 +105,24 @@ 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)
|
||||||
@click.pass_context
|
def status(service: Optional[str] = None) -> None:
|
||||||
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():
|
||||||
log.info(f"{service_}: {profile or '--'}")
|
console.log(f"{service_}: {profile or '--'}")
|
||||||
found_profile = True
|
found_profile = True
|
||||||
|
|
||||||
if not found_profile:
|
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")
|
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(
|
@auth.command(
|
||||||
|
@ -135,8 +132,7 @@ def status(ctx: click.Context, 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.")
|
||||||
@click.pass_context
|
def delete(profile: str, service: str, cookie: bool, credential: bool):
|
||||||
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.
|
||||||
|
|
||||||
|
@ -148,7 +144,6 @@ def delete(ctx: click.Context, profile: str, service: str, cookie: bool, credent
|
||||||
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
|
||||||
|
@ -159,7 +154,7 @@ def delete(ctx: click.Context, profile: str, service: str, cookie: bool, credent
|
||||||
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()
|
||||||
log.info(f"Deleted Cookie: {cookie_}")
|
console.log(f"Deleted Cookie: {cookie_}")
|
||||||
found = True
|
found = True
|
||||||
break
|
break
|
||||||
|
|
||||||
|
@ -174,7 +169,7 @@ def delete(ctx: click.Context, profile: str, service: str, cookie: bool, credent
|
||||||
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)
|
||||||
log.info(f"Deleted Credential: {credential_}")
|
console.log(f"Deleted Credential: {credential_}")
|
||||||
found = True
|
found = True
|
||||||
break
|
break
|
||||||
|
|
||||||
|
@ -224,7 +219,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:
|
||||||
log.info("Skipped adding a Cookie...")
|
console.log("Skipped adding a Cookie...")
|
||||||
|
|
||||||
if credential:
|
if credential:
|
||||||
try:
|
try:
|
||||||
|
@ -239,7 +234,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:
|
||||||
log.info("Skipped adding a Credential...")
|
console.log("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")
|
||||||
|
@ -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.")
|
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)
|
||||||
log.info(f"Moved Cookie file to: {final_path}")
|
console.log(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
|
||||||
|
@ -263,4 +258,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)
|
||||||
log.info(f"Added Credential: {credential}")
|
console.log(f"Added Credential: {credential}")
|
||||||
|
|
|
@ -6,6 +6,7 @@ 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
|
||||||
|
|
||||||
|
|
||||||
|
@ -80,10 +81,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
|
||||||
log.info(f"Set {key} to {repr(value)}")
|
console.log(f"Set {key} to {repr(value)}")
|
||||||
elif is_delete:
|
elif is_delete:
|
||||||
del parent_data[trailing_key]
|
del parent_data[trailing_key]
|
||||||
log.info(f"Unset {key}")
|
console.log(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)
|
||||||
|
|
|
@ -30,6 +30,7 @@ from pywidevine.remotecdm import RemoteCdm
|
||||||
from tqdm import tqdm
|
from tqdm import tqdm
|
||||||
|
|
||||||
from devine.core.config import config
|
from devine.core.config import config
|
||||||
|
from devine.core.console import console
|
||||||
from devine.core.constants import AnyTrack, context_settings
|
from devine.core.constants import AnyTrack, context_settings
|
||||||
from devine.core.credential import Credential
|
from devine.core.credential import Credential
|
||||||
from devine.core.downloaders import aria2c
|
from devine.core.downloaders import aria2c
|
||||||
|
@ -140,43 +141,43 @@ class dl:
|
||||||
|
|
||||||
self.service = Services.get_tag(ctx.invoked_subcommand)
|
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:
|
if profile:
|
||||||
self.profile = profile
|
self.profile = profile
|
||||||
self.log.info(f" + Profile: {self.profile} (explicit)")
|
console.log(f" + Profile: {self.profile} (explicit)")
|
||||||
else:
|
else:
|
||||||
self.profile = self.get_profile(self.service)
|
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:
|
try:
|
||||||
self.cdm = self.get_cdm(self.service, self.profile)
|
self.cdm = self.get_cdm(self.service, self.profile)
|
||||||
except ValueError as e:
|
except ValueError as e:
|
||||||
self.log.error(f" - {e}")
|
self.log.error(f" - {e}")
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
self.log.info(
|
console.log(
|
||||||
f" + {self.cdm.__class__.__name__}: {self.cdm.system_id} (L{self.cdm.security_level})"
|
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)
|
self.vaults = Vaults(self.service)
|
||||||
for vault in config.key_vaults:
|
for vault in config.key_vaults:
|
||||||
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)
|
||||||
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
|
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"))
|
||||||
self.log.info(" + Got Service Config")
|
console.log(" + Got Service Config")
|
||||||
else:
|
else:
|
||||||
self.service_config = {}
|
self.service_config = {}
|
||||||
self.log.info(" - No Service Config")
|
console.log(" - No Service Config")
|
||||||
merge_dict(config.services.get(self.service), self.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 = []
|
self.proxy_providers = []
|
||||||
if config.proxy_providers.get("basic"):
|
if config.proxy_providers.get("basic"):
|
||||||
self.proxy_providers.append(Basic(**config.proxy_providers["basic"]))
|
self.proxy_providers.append(Basic(**config.proxy_providers["basic"]))
|
||||||
|
@ -185,7 +186,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:
|
||||||
self.log.info(f" + {proxy_provider.__class__.__name__}: {repr(proxy_provider)}")
|
console.log(f" + {proxy_provider.__class__.__name__}: {repr(proxy_provider)}")
|
||||||
|
|
||||||
if proxy:
|
if proxy:
|
||||||
requested_provider = None
|
requested_provider = None
|
||||||
|
@ -194,7 +195,7 @@ class dl:
|
||||||
requested_provider, proxy = proxy.split(":", maxsplit=1)
|
requested_provider, proxy = proxy.split(":", maxsplit=1)
|
||||||
if re.match(r"^[a-z]{2}(?:\d+)?$", proxy, re.IGNORECASE):
|
if re.match(r"^[a-z]{2}(?:\d+)?$", proxy, re.IGNORECASE):
|
||||||
proxy = proxy.lower()
|
proxy = proxy.lower()
|
||||||
self.log.info(f"Getting a Proxy to '{proxy}'")
|
console.log(f"Getting a Proxy to '{proxy}'")
|
||||||
if requested_provider:
|
if requested_provider:
|
||||||
proxy_provider = next((
|
proxy_provider = next((
|
||||||
x
|
x
|
||||||
|
@ -209,16 +210,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
|
||||||
self.log.info(f" + {proxy} (from {proxy_provider.__class__.__name__})")
|
console.log(f" + {proxy} (from {proxy_provider.__class__.__name__})")
|
||||||
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
|
||||||
self.log.info(f" + {proxy} (from {proxy_provider.__class__.__name__})")
|
console.log(f" + {proxy} (from {proxy_provider.__class__.__name__})")
|
||||||
break
|
break
|
||||||
else:
|
else:
|
||||||
self.log.info(f"Proxy: {proxy} (from args)")
|
console.log(f"Proxy: {proxy} (from args)")
|
||||||
|
|
||||||
ctx.obj = ContextData(
|
ctx.obj = ContextData(
|
||||||
config=self.service_config,
|
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.")
|
self.log.error(f"The Profile '{self.profile}' has no Cookies or Credentials. Check for typos.")
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
self.log.info(f"Authenticating with Profile '{self.profile}'")
|
console.log(f"Authenticating with Profile '{self.profile}'")
|
||||||
service.authenticate(cookies, credential)
|
service.authenticate(cookies, credential)
|
||||||
self.log.info(" + Authenticated")
|
console.log(" + Authenticated")
|
||||||
|
|
||||||
self.log.info("Retrieving Titles")
|
console.log("Retrieving Titles")
|
||||||
titles = service.get_titles()
|
titles = service.get_titles()
|
||||||
if not titles:
|
if not titles:
|
||||||
self.log.error(" - No titles returned!")
|
self.log.error(" - No titles returned!")
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
for line in str(titles).splitlines(keepends=False):
|
for line in str(titles).splitlines(keepends=False):
|
||||||
self.log.info(line)
|
console.log(line)
|
||||||
|
|
||||||
if list_titles:
|
if list_titles:
|
||||||
for title in titles:
|
for title in titles:
|
||||||
self.log.info(title)
|
console.log(title)
|
||||||
return
|
return
|
||||||
|
|
||||||
for i, title in enumerate(titles):
|
for i, title in enumerate(titles):
|
||||||
if isinstance(title, Episode) and wanted and f"{title.season}x{title.number}" not in wanted:
|
if isinstance(title, Episode) and wanted and f"{title.season}x{title.number}" not in wanted:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
self.log.info(f"Getting tracks for {title}")
|
console.log(f"Getting tracks for {title}")
|
||||||
if slow and i != 0:
|
if slow and i != 0:
|
||||||
delay = random.randint(60, 120)
|
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)
|
time.sleep(delay)
|
||||||
|
|
||||||
title.tracks.add(service.get_tracks(title), warn_only=True)
|
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_subtitles(by_language=s_lang)
|
||||||
title.tracks.sort_chapters()
|
title.tracks.sort_chapters()
|
||||||
|
|
||||||
self.log.info("> All Tracks:")
|
console.log("> All Tracks:")
|
||||||
title.tracks.print()
|
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)):
|
if isinstance(title, (Movie, Episode)):
|
||||||
# filter video tracks
|
# filter video tracks
|
||||||
|
@ -412,7 +413,7 @@ class dl:
|
||||||
continue # only wanted to see what tracks were available and chosen
|
continue # only wanted to see what tracks were available and chosen
|
||||||
|
|
||||||
if skip_dl:
|
if skip_dl:
|
||||||
self.log.info("Skipping Download...")
|
console.log("Skipping Download...")
|
||||||
else:
|
else:
|
||||||
with tqdm(total=len(title.tracks)) as pbar:
|
with tqdm(total=len(title.tracks)) as pbar:
|
||||||
with ThreadPoolExecutor(workers) as pool:
|
with ThreadPoolExecutor(workers) as pool:
|
||||||
|
@ -458,7 +459,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)
|
||||||
self.log.info("Received Keyboard Interrupt, stopping...")
|
console.log("Received Keyboard Interrupt, stopping...")
|
||||||
return
|
return
|
||||||
|
|
||||||
if not skip_dl:
|
if not skip_dl:
|
||||||
|
@ -473,7 +474,7 @@ class dl:
|
||||||
cookie_jar.set_cookie(cookie)
|
cookie_jar.set_cookie(cookie)
|
||||||
cookie_jar.save(ignore_discard=True)
|
cookie_jar.save(ignore_discard=True)
|
||||||
|
|
||||||
self.log.info("Processed all titles!")
|
console.log("Processed all titles!")
|
||||||
|
|
||||||
def prepare_drm(
|
def prepare_drm(
|
||||||
self,
|
self,
|
||||||
|
@ -494,7 +495,7 @@ class dl:
|
||||||
return
|
return
|
||||||
|
|
||||||
if isinstance(drm, Widevine):
|
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:
|
for kid in drm.kids:
|
||||||
if kid in drm.content_keys:
|
if kid in drm.content_keys:
|
||||||
|
@ -504,9 +505,9 @@ class dl:
|
||||||
content_key, vault_used = self.vaults.get_key(kid)
|
content_key, vault_used = self.vaults.get_key(kid)
|
||||||
if content_key:
|
if content_key:
|
||||||
drm.content_keys[kid] = content_key
|
drm.content_keys[kid] = content_key
|
||||||
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)
|
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:
|
elif vaults_only:
|
||||||
self.log.error(f" - No Content Key found in any Vault for {kid.hex}")
|
self.log.error(f" - No Content Key found in any Vault for {kid.hex}")
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
@ -530,7 +531,7 @@ class dl:
|
||||||
msg += " *"
|
msg += " *"
|
||||||
if key == "0" * 32:
|
if key == "0" * 32:
|
||||||
msg += " (Unusable!)"
|
msg += " (Unusable!)"
|
||||||
self.log.info(msg)
|
console.log(msg)
|
||||||
|
|
||||||
drm.content_keys = {
|
drm.content_keys = {
|
||||||
kid_: key
|
kid_: key
|
||||||
|
@ -543,7 +544,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)
|
||||||
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:
|
if kid not in drm.content_keys:
|
||||||
self.log.error(f" - No usable key was returned for {kid.hex}, cannot continue")
|
self.log.error(f" - No usable key was returned for {kid.hex}, cannot continue")
|
||||||
|
@ -576,7 +577,7 @@ class dl:
|
||||||
else:
|
else:
|
||||||
proxy = None
|
proxy = None
|
||||||
|
|
||||||
self.log.info(f"Downloading: {track}")
|
console.log(f"Downloading: {track}")
|
||||||
|
|
||||||
if config.directories.temp.is_file():
|
if config.directories.temp.is_file():
|
||||||
self.log.error(f"Temp Directory '{config.directories.temp}' must be a Directory, not a 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)
|
track.OnDownloaded(track)
|
||||||
|
|
||||||
if track.needs_repack:
|
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()
|
track.repackage()
|
||||||
self.log.info(" + Repackaged")
|
console.log(" + Repackaged")
|
||||||
if callable(track.OnRepacked):
|
if callable(track.OnRepacked):
|
||||||
track.OnRepacked(track)
|
track.OnRepacked(track)
|
||||||
|
|
||||||
|
@ -695,7 +696,7 @@ class dl:
|
||||||
for x in ffprobe(track.path).get("streams", [])
|
for x in ffprobe(track.path).get("streams", [])
|
||||||
)
|
)
|
||||||
):
|
):
|
||||||
self.log.info("Checking for EIA-CC Captions")
|
console.log("Checking for EIA-CC Captions")
|
||||||
try:
|
try:
|
||||||
# TODO: Figure out the real language, it might be different
|
# TODO: Figure out the real language, it might be different
|
||||||
# EIA-CC tracks sadly don't carry language information :(
|
# EIA-CC tracks sadly don't carry language information :(
|
||||||
|
@ -714,15 +715,15 @@ class dl:
|
||||||
)
|
)
|
||||||
if cc:
|
if cc:
|
||||||
title.tracks.add(cc)
|
title.tracks.add(cc)
|
||||||
self.log.info(" + Found & Extracted an EIA-CC Caption")
|
console.log(" + Found & Extracted an EIA-CC Caption")
|
||||||
except EnvironmentError:
|
except EnvironmentError:
|
||||||
self.log.error(" - Track needs to have CC extracted, but ccextractor wasn't found")
|
self.log.error(" - Track needs to have CC extracted, but ccextractor wasn't found")
|
||||||
sys.exit(1)
|
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:
|
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."""
|
"""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)):
|
if isinstance(title, (Movie, Episode)):
|
||||||
muxed_path, return_code = title.tracks.mux(str(title))
|
muxed_path, return_code = title.tracks.mux(str(title))
|
||||||
|
@ -731,7 +732,7 @@ class dl:
|
||||||
elif return_code >= 2:
|
elif return_code >= 2:
|
||||||
self.log.error(" - Failed to Mux video to Matroska file")
|
self.log.error(" - Failed to Mux video to Matroska file")
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
self.log.info(f" + Muxed to {muxed_path}")
|
console.log(f" + Muxed to {muxed_path}")
|
||||||
else:
|
else:
|
||||||
# dont mux
|
# dont mux
|
||||||
muxed_path = title.tracks.audio[0].path
|
muxed_path = title.tracks.audio[0].path
|
||||||
|
@ -747,7 +748,7 @@ class dl:
|
||||||
final_path = final_dir / f"{final_filename}{muxed_path.suffix}"
|
final_path = final_dir / f"{final_filename}{muxed_path.suffix}"
|
||||||
|
|
||||||
shutil.move(muxed_path, final_path)
|
shutil.move(muxed_path, final_path)
|
||||||
self.log.info(f" + Moved to {final_path}")
|
console.log(f" + Moved to {final_path}")
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def get_profile(service: str) -> Optional[str]:
|
def get_profile(service: str) -> Optional[str]:
|
||||||
|
|
|
@ -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,14 +17,13 @@ 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."""
|
||||||
log = logging.getLogger("env")
|
console.log(f"[Root Config] : {config.directories.user_configs / config.filenames.root_config}")
|
||||||
log.info(f"[Root Config] : {config.directories.user_configs / config.filenames.root_config}")
|
console.log(f"[Cookies] : {config.directories.cookies}")
|
||||||
log.info(f"[Cookies] : {config.directories.cookies}")
|
console.log(f"[WVDs] : {config.directories.wvds}")
|
||||||
log.info(f"[WVDs] : {config.directories.wvds}")
|
console.log(f"[Cache] : {config.directories.cache}")
|
||||||
log.info(f"[Cache] : {config.directories.cache}")
|
console.log(f"[Logs] : {config.directories.logs}")
|
||||||
log.info(f"[Logs] : {config.directories.logs}")
|
console.log(f"[Temp Files] : {config.directories.temp}")
|
||||||
log.info(f"[Temp Files] : {config.directories.temp}")
|
console.log(f"[Downloads] : {config.directories.downloads}")
|
||||||
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)
|
||||||
|
@ -36,29 +35,27 @@ 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)
|
||||||
log.info(f"Clearing cache directory: {cache_dir}")
|
console.log(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:
|
||||||
log.info("No files to delete")
|
console.log("No files to delete")
|
||||||
else:
|
else:
|
||||||
log.info(f"Deleting {files_count} files...")
|
console.log(f"Deleting {files_count} files...")
|
||||||
shutil.rmtree(cache_dir)
|
shutil.rmtree(cache_dir)
|
||||||
log.info("Cleared")
|
console.log("Cleared")
|
||||||
|
|
||||||
|
|
||||||
@clear.command()
|
@clear.command()
|
||||||
def temp() -> None:
|
def temp() -> None:
|
||||||
"""Clear the environment temp directory."""
|
"""Clear the environment temp directory."""
|
||||||
log = logging.getLogger("env")
|
console.log(f"Clearing temp directory: {config.directories.temp}")
|
||||||
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:
|
||||||
log.info("No files to delete")
|
console.log("No files to delete")
|
||||||
else:
|
else:
|
||||||
log.info(f"Deleting {files_count} files...")
|
console.log(f"Deleting {files_count} files...")
|
||||||
shutil.rmtree(config.directories.temp)
|
shutil.rmtree(config.directories.temp)
|
||||||
log.info("Cleared")
|
console.log("Cleared")
|
||||||
|
|
|
@ -6,6 +6,7 @@ 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
|
||||||
|
@ -52,10 +53,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:]
|
||||||
|
|
||||||
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:
|
if service:
|
||||||
service = Services.get_tag(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
|
total_added = 0
|
||||||
for from_vault in from_vaults:
|
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()
|
services = from_vault.get_services()
|
||||||
|
|
||||||
for service_ in 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
|
content_keys = list(from_vault.get_keys(service_)) # important as it's a generator we iterate twice
|
||||||
|
|
||||||
bad_keys = {
|
bad_keys = {
|
||||||
|
@ -84,7 +85,7 @@ def copy(to_vault: str, from_vaults: list[str], service: Optional[str] = None) -
|
||||||
}
|
}
|
||||||
|
|
||||||
total_count = len(content_keys)
|
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:
|
try:
|
||||||
added = to_vault.add_keys(service_, content_keys)
|
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
|
total_added += added
|
||||||
existed = total_count - 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()
|
@kv.command()
|
||||||
|
@ -141,7 +142,6 @@ 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_:
|
||||||
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)
|
added_count = vault.add_keys(service, kid_keys)
|
||||||
existed_count = total_count - added_count
|
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()
|
@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):
|
||||||
log.info(f"{vault} already has a {service_tag} Table")
|
console.log(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)
|
||||||
log.info(f"{vault}: Created {service_tag} Table")
|
console.log(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:
|
||||||
log.info(f"{vault} does not use tables, skipping...")
|
console.log(f"{vault} does not use tables, skipping...")
|
||||||
|
|
||||||
log.info("Done!")
|
console.log("Done!")
|
||||||
|
|
|
@ -10,6 +10,7 @@ from pywidevine.license_protocol_pb2 import FileHashes
|
||||||
from unidecode import UnidecodeError, unidecode
|
from unidecode import UnidecodeError, unidecode
|
||||||
|
|
||||||
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
|
||||||
|
|
||||||
|
|
||||||
|
@ -34,28 +35,26 @@ 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)
|
||||||
|
|
||||||
log.info(f"System ID: {device.system_id}")
|
console.log(f"System ID: {device.system_id}")
|
||||||
log.info(f"Security Level: {device.security_level}")
|
console.log(f"Security Level: {device.security_level}")
|
||||||
log.info(f"Type: {device.type}")
|
console.log(f"Type: {device.type}")
|
||||||
log.info(f"Flags: {device.flags}")
|
console.log(f"Flags: {device.flags}")
|
||||||
log.info(f"Private Key: {bool(device.private_key)}")
|
console.log(f"Private Key: {bool(device.private_key)}")
|
||||||
log.info(f"Client ID: {bool(device.client_id)}")
|
console.log(f"Client ID: {bool(device.client_id)}")
|
||||||
log.info(f"VMP: {bool(device.client_id.vmp_data)}")
|
console.log(f"VMP: {bool(device.client_id.vmp_data)}")
|
||||||
|
|
||||||
log.info("Client ID:")
|
console.log("Client ID:")
|
||||||
log.info(device.client_id)
|
console.log(device.client_id)
|
||||||
|
|
||||||
log.info("VMP:")
|
console.log("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)
|
||||||
log.info(str(file_hashes))
|
console.log(str(file_hashes))
|
||||||
else:
|
else:
|
||||||
log.info("None")
|
console.log("None")
|
||||||
|
|
||||||
|
|
||||||
@wvd.command()
|
@wvd.command()
|
||||||
|
@ -82,9 +81,9 @@ def dump(wvd_paths: list[Path], out_dir: Path) -> None:
|
||||||
device = Device.load(wvd_path)
|
device = Device.load(wvd_path)
|
||||||
|
|
||||||
log = logging.getLogger("wvd")
|
log = logging.getLogger("wvd")
|
||||||
log.info(f"Dumping: {wvd_path}")
|
console.log(f"Dumping: {wvd_path}")
|
||||||
log.info(f"L{device.security_level} {device.system_id} {device.type.name}")
|
console.log(f"L{device.security_level} {device.system_id} {device.type.name}")
|
||||||
log.info(f"Saving to: {out_path}")
|
console.log(f"Saving to: {out_path}")
|
||||||
|
|
||||||
device_meta = {
|
device_meta = {
|
||||||
"wvd": {
|
"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 = 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")
|
||||||
log.info(" + Device Metadata")
|
console.log(" + 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"
|
||||||
|
@ -111,23 +110,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")
|
||||||
)
|
)
|
||||||
log.info(" + Private Key")
|
console.log(" + Private Key")
|
||||||
else:
|
else:
|
||||||
log.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())
|
||||||
log.info(" + Client ID")
|
console.log(" + Client ID")
|
||||||
else:
|
else:
|
||||||
log.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)
|
||||||
log.info(" + VMP (File Hashes)")
|
console.log(" + VMP (File Hashes)")
|
||||||
else:
|
else:
|
||||||
log.info(" - No VMP (File Hashes) available")
|
console.log(" - No VMP (File Hashes) available")
|
||||||
|
|
||||||
|
|
||||||
@wvd.command()
|
@wvd.command()
|
||||||
|
@ -191,15 +190,15 @@ def new(
|
||||||
|
|
||||||
log = logging.getLogger("wvd")
|
log = logging.getLogger("wvd")
|
||||||
|
|
||||||
log.info(f"Created binary WVD file, {out_path.name}")
|
console.log(f"Created binary WVD file, {out_path.name}")
|
||||||
log.info(f" + Saved to: {out_path.absolute()}")
|
console.log(f" + Saved to: {out_path.absolute()}")
|
||||||
log.info(f" + System ID: {device.system_id}")
|
console.log(f" + System ID: {device.system_id}")
|
||||||
log.info(f" + Security Level: {device.security_level}")
|
console.log(f" + Security Level: {device.security_level}")
|
||||||
log.info(f" + Type: {device.type}")
|
console.log(f" + Type: {device.type}")
|
||||||
log.info(f" + Flags: {device.flags}")
|
console.log(f" + Flags: {device.flags}")
|
||||||
log.info(f" + Private Key: {bool(device.private_key)}")
|
console.log(f" + Private Key: {bool(device.private_key)}")
|
||||||
log.info(f" + Client ID: {bool(device.client_id)}")
|
console.log(f" + Client ID: {bool(device.client_id)}")
|
||||||
log.info(f" + VMP: {bool(device.client_id.vmp_data)}")
|
console.log(f" + VMP: {bool(device.client_id.vmp_data)}")
|
||||||
|
|
||||||
log.debug("Client ID:")
|
log.debug("Client ID:")
|
||||||
log.debug(device.client_id)
|
log.debug(device.client_id)
|
||||||
|
@ -208,6 +207,6 @@ def new(
|
||||||
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)
|
||||||
log.info(str(file_hashes))
|
console.log(str(file_hashes))
|
||||||
else:
|
else:
|
||||||
log.info("None")
|
console.log("None")
|
||||||
|
|
|
@ -25,6 +25,7 @@ from pywidevine.pssh import PSSH
|
||||||
from requests import Session
|
from requests import Session
|
||||||
from tqdm import tqdm
|
from tqdm import tqdm
|
||||||
|
|
||||||
|
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
|
||||||
|
@ -524,7 +525,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)
|
||||||
log.info("Received Keyboard Interrupt, stopping...")
|
console.log("Received Keyboard Interrupt, stopping...")
|
||||||
return
|
return
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
|
|
|
@ -23,6 +23,7 @@ from pywidevine.pssh import PSSH
|
||||||
from requests import Session
|
from requests import Session
|
||||||
from tqdm import tqdm
|
from tqdm import tqdm
|
||||||
|
|
||||||
|
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
|
||||||
|
@ -371,7 +372,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)
|
||||||
log.info("Received Keyboard Interrupt, stopping...")
|
console.log("Received Keyboard Interrupt, stopping...")
|
||||||
return
|
return
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
import logging
|
|
||||||
import math
|
import math
|
||||||
import re
|
import re
|
||||||
import subprocess
|
import subprocess
|
||||||
|
@ -11,6 +10,7 @@ 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,15 +296,14 @@ 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.")
|
||||||
|
|
||||||
log = logging.getLogger("x264-clean")
|
console.log("Removing EIA-CC from Video Track with FFMPEG")
|
||||||
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:
|
||||||
log.info(" - No x264 encode settings were found, unsupported...")
|
console.log(" - No x264 encode settings were found, unsupported...")
|
||||||
return False
|
return False
|
||||||
|
|
||||||
uuid = x264.group(1).hex()
|
uuid = x264.group(1).hex()
|
||||||
|
@ -323,7 +322,7 @@ class Video(Track):
|
||||||
str(cleaned_path)
|
str(cleaned_path)
|
||||||
], check=True)
|
], check=True)
|
||||||
|
|
||||||
log.info(" + Removed")
|
console.log(" + Removed")
|
||||||
|
|
||||||
self.swap(cleaned_path)
|
self.swap(cleaned_path)
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue