From fa9c084397507c09efe6216683b07459958b6b7b Mon Sep 17 00:00:00 2001 From: arabcoders Date: Tue, 1 Apr 2025 20:05:35 +0300 Subject: [PATCH 01/10] remove presets v1.0 --- app/library/DownloadQueue.py | 2 +- app/library/HttpAPI.py | 16 +--- app/library/Presets.py | 64 +++++++------- app/library/Tasks.py | 31 ++----- app/library/Utils.py | 40 ++++++++- app/library/YTDLPOpts.py | 21 +---- ui/components/PresetForm.vue | 161 ++++++++--------------------------- ui/pages/presets.vue | 14 --- 8 files changed, 112 insertions(+), 237 deletions(-) diff --git a/app/library/DownloadQueue.py b/app/library/DownloadQueue.py index 491910ff..edf4214a 100644 --- a/app/library/DownloadQueue.py +++ b/app/library/DownloadQueue.py @@ -392,7 +392,7 @@ class DownloadQueue(metaclass=Singleton): { "status": "text" } """ - _preset = Presets.get_instance().get(name=preset) + _preset = Presets.get_instance().get(preset) config = config if config else {} if cli: diff --git a/app/library/HttpAPI.py b/app/library/HttpAPI.py index 74387c55..30f31e88 100644 --- a/app/library/HttpAPI.py +++ b/app/library/HttpAPI.py @@ -501,7 +501,7 @@ class HttpAPI(Common): preset = request.query.get("preset") if preset: - exists = Presets.get_instance().get(name=preset) + exists = Presets.get_instance().get(preset) if not exists: return web.json_response( data={"status": False, "message": f"Preset '{preset}' does not exist."}, @@ -674,7 +674,7 @@ class HttpAPI(Common): preset = request.query.get("preset") if preset: - exists = Presets.get_instance().get(name=preset) + exists = Presets.get_instance().get(preset) if not exists: return web.json_response( data={"status": False, "message": f"Preset '{preset}' does not exist."}, @@ -790,18 +790,6 @@ class HttpAPI(Common): if not item.get("id", None) or not validate_uuid(item.get("id"), version=4): item["id"] = str(uuid.uuid4()) - if not item.get("args", None) or str(item.get("args")).strip() == "": - item["args"] = {} - - if item.get("args", None) and isinstance(item.get("args"), str): - item["args"] = json.loads(item.get("args")) - - if not item.get("postprocessors", None) or str(item.get("postprocessors")).strip() == "": - item["postprocessors"] = [] - - if item.get("postprocessors", None) and isinstance(item.get("postprocessors"), str): - item["postprocessors"] = json.loads(item.get("postprocessors")) - try: cls.validate(item) except ValueError as e: diff --git a/app/library/Presets.py b/app/library/Presets.py index 83f65e16..cfec885b 100644 --- a/app/library/Presets.py +++ b/app/library/Presets.py @@ -11,6 +11,7 @@ from .config import Config from .encoder import Encoder from .Events import EventBus, Events from .Singleton import Singleton +from .Utils import arg_converter, clean_item LOG = logging.getLogger("presets") @@ -26,12 +27,6 @@ class Preset: format: str """The format of the preset.""" - args: dict[str, list[str] | bool] = field(default_factory=dict) - """The arguments of the preset.""" - - postprocessors: list = field(default_factory=list) - """The postprocessors of the preset.""" - folder: str = "" """The default download folder to use if non is given.""" @@ -83,13 +78,19 @@ class Presets(metaclass=Singleton): pass with open(os.path.join(os.path.dirname(__file__), "presets.json")) as f: - self._default_presets = [Preset(**preset) for preset in json.load(f)] + for i, preset in enumerate(json.load(f)): + try: + self.validate(preset) + self._default_presets.append(Preset(**preset)) + except Exception as e: + LOG.error(f"Failed to parse default preset '{i}'. '{e!s}'.") + continue - EventBus.get_instance().subscribe( - Events.PRESETS_ADD, - lambda data, _, **kwargs: self.add(**data.data), # noqa: ARG005 - f"{__class__.__name__}.save", - ) + def event_handler(_, __): + msg = "Not implemented" + raise Exception(msg) + + EventBus.get_instance().subscribe(Events.PRESETS_ADD, event_handler, f"{__class__.__name__}.save") @staticmethod def get_instance() -> "Presets": @@ -150,22 +151,27 @@ class Presets(metaclass=Singleton): LOG.info(f"No presets were defined in '{self._file}'.") return self - needSaving = False + need_save = False for i, preset in enumerate(presets): try: if "id" not in preset: preset["id"] = str(uuid.uuid4()) - needSaving = True + need_save = True + preset, preset_status = clean_item(preset, keys=("args", "postprocessors")) preset = Preset(**preset) + + if preset_status: + need_save = True + self._presets.append(preset) except Exception as e: LOG.error(f"Failed to parse preset at list position '{i}'. '{e!s}'.") continue - if needSaving: - LOG.info("Saving presets due to missing ids.") + if need_save: + LOG.info("Saving presets due to format, or id change.") self.save(self._presets) return self @@ -198,7 +204,7 @@ class Presets(metaclass=Singleton): """ if not isinstance(preset, dict): if not isinstance(preset, Preset): - msg = "Invalid preset type." + msg = f"Invalid preset type. Was expecting a (Preset|dict), but got '{type(preset).__name__}'." raise ValueError(msg) # noqa: TRY004 preset = preset.serialize() @@ -215,18 +221,8 @@ class Presets(metaclass=Singleton): msg = "No format found." raise ValueError(msg) - if preset.get("args") and not isinstance(preset.get("args"), dict): - msg = "Invalid args type. expected dict." - raise ValueError(msg) - - if preset.get("postprocessors") and not isinstance(preset.get("postprocessors"), list): - msg = "Invalid postprocessors type. expected list." - raise ValueError(msg) - if preset.get("cli"): try: - from .Utils import arg_converter - arg_converter(args=preset.get("cli")) except Exception as e: msg = f"Invalid cli options. '{e!s}'." @@ -270,26 +266,24 @@ class Presets(metaclass=Singleton): return self - def get(self, id: str | None = None, name: str | None = None) -> Preset | None: + def get(self, id_or_name: str) -> Preset | None: """ Get the preset by id or name. Args: - id (str|None): The id of the preset. - name (str|None): The name of the preset. + id_or_name (str): The id or name of the preset. Returns: Preset|None: The preset if found, None otherwise. """ - if not id and not name: + if not id_or_name: return None for preset in self.get_all(): - if preset.id == id: - return preset + if id_or_name not in (preset.id, preset.name): + continue - if preset.name == name: - return preset + return preset return None diff --git a/app/library/Tasks.py b/app/library/Tasks.py index dc695114..6ffb1e0e 100644 --- a/app/library/Tasks.py +++ b/app/library/Tasks.py @@ -15,6 +15,7 @@ from .encoder import Encoder from .Events import EventBus, Events, error, info, success from .Scheduler import Scheduler from .Singleton import Singleton +from .Utils import clean_item LOG = logging.getLogger("tasks") @@ -140,13 +141,13 @@ class Tasks(metaclass=Singleton): LOG.info(f"No tasks were defined in '{self._file}'.") return self - need_update = False + need_save = False for i, task in enumerate(tasks): try: - task, task_status = self.clean_task(task) + task, task_status = clean_item(task, keys=("cookies", "config")) task = Task(**task) if task_status: - need_update = True + need_save = True except Exception as e: LOG.error(f"Failed to parse task at list position '{i}'. '{e!s}'.") continue @@ -160,7 +161,7 @@ class Tasks(metaclass=Singleton): LOG.exception(e) LOG.error(f"Failed to queue task '{i}: {task.name}'. '{e!s}'.") - if need_update: + if need_save: LOG.info("Updating tasks file to remove old keys.") self.save(self.get_all()) @@ -223,6 +224,7 @@ class Tasks(metaclass=Singleton): if task.get("cli"): try: from .Utils import arg_converter + arg_converter(args=task.get("cli")) except Exception as e: msg = f"Invalid cli options. '{e!s}'." @@ -266,27 +268,6 @@ class Tasks(metaclass=Singleton): return self - def clean_task(self, task: dict) -> tuple[dict, bool]: - """ - Clean the task from old keys. - - Args: - task (dict): The task to clean. - - Returns: - tuple[dict, bool]: The cleaned task and a status if the task was cleaned. - - """ - status = False - removedKeys = ["cookies", "config"] - - for key in removedKeys: - if key in task: - status = True - task.pop(key) - - return task, status - async def _runner(self, task: Task): """ Run the task. diff --git a/app/library/Utils.py b/app/library/Utils.py index 155f1ceb..a09e6bd6 100644 --- a/app/library/Utils.py +++ b/app/library/Utils.py @@ -522,8 +522,6 @@ def arg_converter( bad_options.update(item.items()) - LOG.debug("Removed %i the following options: '%s'.", level, ", ".join(bad_options.values())) - for key in diff.copy(): if key not in bad_options: continue @@ -889,3 +887,41 @@ def get_files(base_path: str, dir: str | None = None): ) return contents + + +def clean_item(item: dict, keys: list | tuple) -> tuple[dict, bool]: + """ + Remove given keys from a dictionary. + This function modifies the dictionary in place and returns a tuple + containing the modified dictionary and a boolean indicating + whether any keys were removed. + + Args: + item (dict): The item to clean. + keys (list|tuple): The keys to remove. + + Returns: + tuple[dict, bool]: The cleaned item and a the status of cleaning operation. + + Raises: + TypeError: If item is not a dictionary or keys is not a list or tuple. + + """ + status = False + + if not isinstance(item, dict): + msg = "Item must be a dictionary." + raise TypeError(msg) + + if not isinstance(keys, list | tuple): + msg = "Keys must be a list or tuple." + raise TypeError(msg) + + for key in keys: + if key not in item: + continue + + status = True + item.pop(key) + + return item, status diff --git a/app/library/YTDLPOpts.py b/app/library/YTDLPOpts.py index 2a87ca91..1e884828 100644 --- a/app/library/YTDLPOpts.py +++ b/app/library/YTDLPOpts.py @@ -78,7 +78,7 @@ class YTDLPOpts(metaclass=Singleton): YTDLPOpts: The instance of the class """ - preset = Presets.get_instance().get(name=name) + preset = Presets.get_instance().get(name) if not preset or "default" == name: return self @@ -118,25 +118,6 @@ class YTDLPOpts(metaclass=Singleton): "temp": self._config.temp_path, } - # @Deprecated - To be removed in future versions. - if not preset.cli: - if preset.postprocessors and isinstance(preset.postprocessors, list) and len(preset.postprocessors) > 0: - self._preset_opts["postprocessors"] = preset.postprocessors - - if preset.args and isinstance(preset.args, dict) and len(preset.args) > 0: - bad_options = {k: v for d in REMOVE_KEYS for k, v in d.items()} - removed_options = [] - for key, value in preset.args.items(): - if key in bad_options: - removed_options.append(bad_options[key]) - continue - self._preset_opts[key] = value - - if len(removed_options) > 0: - LOG.warning( - "Removed the following options '%s' from '%s' args.", ", ".join(removed_options), preset.name - ) - return self def get_all(self, keep: bool = False) -> dict: diff --git a/ui/components/PresetForm.vue b/ui/components/PresetForm.vue index ba9447db..0cbd7439 100644 --- a/ui/components/PresetForm.vue +++ b/ui/components/PresetForm.vue @@ -27,13 +27,13 @@
-
+
-
@@ -51,31 +51,35 @@
-
-
@@ -83,12 +87,12 @@
-
+
-
@@ -101,19 +105,19 @@
-
+
-
Use this output template if non are given with URL. if not set, it will defaults to {{ config.app.output_template }}. - For more information visit this url. + For more information visit this page.
@@ -122,11 +126,12 @@
- +