diff --git a/app/library/Download.py b/app/library/Download.py index 71da56df..92c0e0d5 100644 --- a/app/library/Download.py +++ b/app/library/Download.py @@ -151,9 +151,9 @@ class Download: def _download(self): try: - params = ( + params: dict = ( YTDLPOpts.get_instance() - .preset(self.preset, with_cookies=not self.info.cookies) + .preset(self.preset) .add({"break_on_existing": True}) .add_cli(args=self.info.cli, from_user=True) .add( diff --git a/app/library/DownloadQueue.py b/app/library/DownloadQueue.py index 3af15f2d..5c3ec100 100644 --- a/app/library/DownloadQueue.py +++ b/app/library/DownloadQueue.py @@ -418,10 +418,7 @@ class DownloadQueue(metaclass=Singleton): "level": logging.WARNING, "name": "callback-logger", }, - **YTDLPOpts.get_instance() - .preset(name=item.preset, with_cookies=not item.cookies) - .add_cli(args=item.cli, from_user=True) - .get_all(), + **YTDLPOpts.get_instance().preset(name=item.preset).add_cli(args=item.cli, from_user=True).get_all(), } if yt_conf.get("external_downloader"): @@ -558,7 +555,7 @@ class DownloadQueue(metaclass=Singleton): for id in ids: try: - item = self.done.get(key=id) + item: Download = self.done.get(key=id) except KeyError as e: status[id] = str(e) status["status"] = "error" @@ -569,6 +566,10 @@ class DownloadQueue(metaclass=Singleton): removed_files = 0 filename: str = "" + LOG.info( + f"{remove_file=} {itemRef} - Removing local files: {self.config.remove_files}, {item.info.status=}" + ) + if remove_file and self.config.remove_files and "finished" == item.info.status: filename = str(item.info.filename) if item.info.folder: @@ -577,17 +578,22 @@ class DownloadQueue(metaclass=Singleton): try: rf = Path( calc_download_path( - base_path=self.config.download_path, + base_path=Path(self.config.download_path), folder=filename, create_path=False, ) ) - if rf.stem and rf.is_file() and rf.exists(): - for f in rf.parent.glob(f"{glob.escape(rf.stem)}.*"): - if f.is_file() and f.exists() and not f.name.startswith("."): - removed_files += 1 - LOG.debug(f"Removing '{itemRef}' local file '{f.name}'.") - f.unlink(missing_ok=True) + if rf.is_file() and rf.exists(): + if rf.stem and rf.suffix: + for f in rf.parent.glob(f"{glob.escape(rf.stem)}.*"): + if f.is_file() and f.exists() and not f.name.startswith("."): + removed_files += 1 + LOG.debug(f"Removing '{itemRef}' local file '{f.name}'.") + f.unlink(missing_ok=True) + else: + LOG.debug(f"Removing '{itemRef}' local file '{rf.name}'.") + rf.unlink(missing_ok=True) + removed_files += 1 else: LOG.warning(f"Failed to remove '{itemRef}' local file '{filename}'. File not found.") except Exception as e: diff --git a/app/library/HttpAPI.py b/app/library/HttpAPI.py index b7bf3f01..d11b693a 100644 --- a/app/library/HttpAPI.py +++ b/app/library/HttpAPI.py @@ -132,7 +132,7 @@ class HttpAPI(Common): return decorator async def on_shutdown(self, _: web.Application): - LOG.debug("Shutting down http API server.") + pass def attach(self, app: web.Application) -> "HttpAPI": """ @@ -598,7 +598,7 @@ class HttpAPI(Common): if ytdlp_proxy := self.config.get_ytdlp_args().get("proxy", None): opts["proxy"] = ytdlp_proxy - ytdlp_opts = YTDLPOpts.get_instance().preset(name=preset, with_cookies=True).add(opts).get_all() + ytdlp_opts = YTDLPOpts.get_instance().preset(name=preset).add(opts).get_all() data = extract_info( config=ytdlp_opts, @@ -960,7 +960,7 @@ class HttpAPI(Common): opts = {} if ytdlp_proxy := self.config.get_ytdlp_args().get("proxy", None): opts["proxy"] = ytdlp_proxy - ytdlp_opts = YTDLPOpts.get_instance().preset(name=preset, with_cookies=True).add(opts).get_all() + ytdlp_opts = YTDLPOpts.get_instance().preset(name=preset).add(opts).get_all() data = extract_info( config=ytdlp_opts, @@ -1145,7 +1145,7 @@ class HttpAPI(Common): item["cli"] = "" try: - ins.validate(item) + Tasks.validate(item) except ValueError as e: return web.json_response( {"error": f"Failed to validate task '{item.get('name')}'. '{e!s}'"}, @@ -1497,7 +1497,7 @@ class HttpAPI(Common): return web.Response(status=web.HTTPNotModified.status_code, headers={"Last-Modified": lastMod}) return web.Response( - body=await Subtitle(download_path=self.config.download_path).make(file=realFile), + body=await Subtitle().make(file=realFile), headers={ "Content-Type": "text/vtt; charset=UTF-8", "X-Accel-Buffering": "no", diff --git a/app/library/YTDLPOpts.py b/app/library/YTDLPOpts.py index 77458cfd..2954165a 100644 --- a/app/library/YTDLPOpts.py +++ b/app/library/YTDLPOpts.py @@ -2,11 +2,11 @@ import logging from pathlib import Path from .config import Config -from .Presets import Presets +from .Presets import Presets, Preset from .Singleton import Singleton from .Utils import REMOVE_KEYS, arg_converter, calc_download_path, load_cookies, merge_dict -LOG = logging.getLogger("YTDLPOpts") +LOG: logging.Logger = logging.getLogger("YTDLPOpts") class YTDLPOpts(metaclass=Singleton): @@ -79,11 +79,11 @@ class YTDLPOpts(metaclass=Singleton): YTDLPOpts: The instance of the class """ - bad_options = {} + bad_options: dict = {} if from_user: - bad_options = {k: v for d in REMOVE_KEYS for k, v in d.items()} + bad_options: dict[str, str] = {k: v for d in REMOVE_KEYS for k, v in d.items()} - removed_options = [] + removed_options: list = [] for key, value in config.items(): if from_user and key in bad_options: @@ -97,19 +97,18 @@ class YTDLPOpts(metaclass=Singleton): return self - def preset(self, name: str, with_cookies: bool = False) -> "YTDLPOpts": + def preset(self, name: str) -> "YTDLPOpts": """ Add the preset options to the item options. Args: name (str): The name of the preset - with_cookies (bool): If the cookies should be added Returns: YTDLPOpts: The instance of the class """ - preset = Presets.get_instance().get(name) + preset: Preset | None = Presets.get_instance().get(name) if not preset or "default" == name: return self @@ -122,25 +121,26 @@ class YTDLPOpts(metaclass=Singleton): msg = f"Invalid preset '{preset.name}' command options for yt-dlp. '{e!s}'." raise ValueError(msg) from e - if preset.cookies and with_cookies: - file = Path(self._config.config_path, "cookies", f"{preset.id}.txt") + if preset.cookies: + file: Path = Path(self._config.config_path) / "cookies" / f"{preset.id}.txt" if not file.parent.exists(): - file.parent.mkdir(parents=True) + file.parent.mkdir(parents=True, exist_ok=True) - with open(file, "w") as f: - f.write(preset.cookies) + file.write_text(preset.cookies) - load_cookies(str(file)) - - self._preset_opts["cookiefile"] = str(file) + try: + load_cookies(file) + self._preset_opts["cookiefile"] = str(file) + except ValueError as e: + LOG.error(str(e)) if preset.template: self._preset_opts["outtmpl"] = {"default": preset.template, "chapter": self._config.output_template_chapter} if preset.folder: self._preset_opts["paths"] = { - "home": calc_download_path(base_path=self._config.download_path, folder=preset.folder), + "home": calc_download_path(base_path=Path(self._config.download_path), folder=preset.folder), "temp": self._config.temp_path, } @@ -157,7 +157,7 @@ class YTDLPOpts(metaclass=Singleton): dict: The options """ - default_opts = {} + default_opts: dict = {} default_opts["paths"] = {"home": self._config.download_path, "temp": self._config.temp_path} default_opts["outtmpl"] = { "default": self._config.output_template, @@ -167,7 +167,7 @@ class YTDLPOpts(metaclass=Singleton): if not isinstance(self._item_cli, list): self._item_cli = [] - merge = [] + merge: list[str] = [] if self._config._ytdlp_cli_mutable and len(self._config._ytdlp_cli_mutable) > 1: merge.append(self._config._ytdlp_cli_mutable) @@ -178,12 +178,16 @@ class YTDLPOpts(metaclass=Singleton): # prepend the yt-dlp command options to the list self._item_cli = merge + self._item_cli - user_cli = {} + user_cli: dict = {} if len(self._item_cli) > 0: try: - removed_options = [] - user_cli = arg_converter(args="\n".join(self._item_cli), level=True, removed_options=removed_options) + removed_options: list = [] + user_cli: dict = arg_converter( + args="\n".join(self._item_cli), + level=True, + removed_options=removed_options, + ) if len(removed_options) > 0: LOG.warning("Removed the following options: '%s'.", ", ".join(removed_options))