diff --git a/.vscode/settings.json b/.vscode/settings.json index cd8d9648..ad57e7c4 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -98,6 +98,7 @@ "smhd", "socketio", "sstr", + "SUPPRESSHELP", "tebibytes", "tiktok", "timespec", diff --git a/app/library/Utils.py b/app/library/Utils.py index 9cf1c146..26257ad4 100644 --- a/app/library/Utils.py +++ b/app/library/Utils.py @@ -43,7 +43,21 @@ REMOVE_KEYS: list = [ "progress_template": "--progress-template", "consoletitle": "--console-title", "progress_with_newline": "--newline", - "forcejson": "-j, --dump-json", + "forcejson": "-j, --dump-single-json", + "opt_update_to": "--update-to", + "opt_ap_list_mso": "--ap-list-mso", + "opt_batch_file": "-a, --batch-file", + "opt_alias": "--alias", + "opt_list_extractors": "--list-extractors", + "opt_version": "--version", + "opt_help": "-h, --help", + "opt_update": "-U, --update", + "opt_list_subtitles": "--list-subs", + "opt_list_thumbnails": "--list-thumbnails", + "opt_list_format": "-F, --list-formats", + "opt_dump_agent": "--dump-user-agent", + "opt_extractor_descriptions": "--extractor-descriptions", + "opt_list_impersonate_targets": "--list-impersonate-targets" }, ] diff --git a/app/library/ytdlp.py b/app/library/ytdlp.py index 5dae3510..ecbc61e9 100644 --- a/app/library/ytdlp.py +++ b/app/library/ytdlp.py @@ -1,3 +1,7 @@ +from __future__ import annotations + +from typing import Any + import yt_dlp import app.postprocessors # noqa: F401 @@ -12,3 +16,44 @@ class YTDLP(yt_dlp.YoutubeDL): return None return super()._delete_downloaded_files(*args, **kwargs) + + +def ytdlp_options() -> list[dict[str, Any]]: + """ + Collect yt-dlp options and return them in a structured format. + + Returns: + list[dict[str, Any]]: A list of dictionaries containing option flags, descriptions, + + """ + from yt_dlp.options import create_parser + + from app.library.Utils import REMOVE_KEYS + + parser = create_parser() + + ignored_flags: set[str] = { + f.strip() for group in REMOVE_KEYS for v in group.values() for f in v.split(",") if f.strip() + } + + def collect(opts, group: str) -> list[dict[str, Any]]: + return [ + { + "flags": list(getattr(opt, "_short_opts", [])) + list(getattr(opt, "_long_opts", [])), + "description": getattr(opt, "help", None), + "group": group, + "ignored": any( + f in ignored_flags for f in getattr(opt, "_short_opts", []) + getattr(opt, "_long_opts", []) + ), + } + for opt in opts + if ( + (getattr(opt, "_short_opts", []) or getattr(opt, "_long_opts", [])) + and getattr(opt, "help", None) + and "SUPPRESSHELP" not in getattr(opt, "help", "") + ) + ] + + return collect(parser.option_list, "root") + [ + entry for grp in parser.option_groups for entry in collect(grp.option_list, grp.title or "other") + ] diff --git a/app/routes/api/yt_dlp.py b/app/routes/api/yt_dlp.py index ca7c2677..49291c20 100644 --- a/app/routes/api/yt_dlp.py +++ b/app/routes/api/yt_dlp.py @@ -296,3 +296,19 @@ async def archive_recheck(cache: Cache) -> Response: response.append({id: bool(data.get("id", None)) if isinstance(data, dict) else False}) return web.json_response(data=response, status=web.HTTPOk.status_code) + + +@route("GET", "api/yt-dlp/options/", "get_options") +async def get_options() -> Response: + """ + Get the yt-dlp CLI options. + + Returns: + Response: The response object with the yt-dlp CLI options. + + """ + from app.library.ytdlp import ytdlp_options + + return web.json_response( + body=json.dumps(ytdlp_options(), indent=4, default=str), status=web.HTTPOk.status_code + ) diff --git a/ui/app/assets/css/style.css b/ui/app/assets/css/style.css index e2b67b87..f4db7fe0 100644 --- a/ui/app/assets/css/style.css +++ b/ui/app/assets/css/style.css @@ -357,3 +357,10 @@ table.is-fixed { div.is-centered { justify-content: center; } + + +.modal-content-max { + width: max-content; + padding: 0; + margin: 0; +} diff --git a/ui/app/components/ConditionForm.vue b/ui/app/components/ConditionForm.vue index 4ede9228..ee1edaa7 100644 --- a/ui/app/components/ConditionForm.vue +++ b/ui/app/components/ConditionForm.vue @@ -59,7 +59,7 @@ - + The name that refers to this condition. @@ -81,7 +81,7 @@ - + yt-dlp [--match-filters] logic. @@ -92,19 +92,20 @@