diff --git a/app/library/YTDLPOpts.py b/app/library/YTDLPOpts.py
index 80ba5551..f5ccab41 100644
--- a/app/library/YTDLPOpts.py
+++ b/app/library/YTDLPOpts.py
@@ -1,6 +1,7 @@
import logging
import shlex
from pathlib import Path
+from typing import Any
from .config import Config
from .Presets import Preset, Presets
@@ -28,7 +29,7 @@ class ARGSMerger:
if not args or not isinstance(args, str) or len(args) < 2:
return self
- _args = shlex.split(args)
+ _args: list[str] = shlex.split(args)
if len(_args) > 0:
self.args.extend(_args)
@@ -124,8 +125,8 @@ class YTDLPCli:
raise ValueError(msg)
self.item = item
- self.preset = item.get_preset()
- self._config = config or Config.get_instance()
+ self.preset: Preset = item.get_preset()
+ self._config: Config = config or Config.get_instance()
def build(self) -> tuple[str, dict]:
"""
@@ -138,7 +139,7 @@ class YTDLPCli:
template: str | None = None
save_path: str | None = None
cookie_file: Path | None = None
- cli_args = ARGSMerger.get_instance()
+ cli_args: ARGSMerger = ARGSMerger.get_instance()
if self.item.cookies:
cookie_file = create_cookies_file(self.item.cookies)
@@ -160,10 +161,10 @@ class YTDLPCli:
template = self.preset.template
if self.preset.cli:
- cli_args.add(self.preset.cli)
+ cli_args.add(self._replace_vars(self.preset.cli))
if self.item.cli:
- cli_args.add(self.item.cli)
+ cli_args.add(self._replace_vars(self.item.cli))
if not save_path:
save_path = self._config.download_path
@@ -172,24 +173,22 @@ class YTDLPCli:
template = self._config.output_template
if cookie_file:
- cli_args.add(f'--cookies "{cookie_file!s}"')
+ cli_args.add(self._replace_vars(f'--cookies "{cookie_file!s}"'))
if template:
- cli_args.add(f'--output "{template}"')
+ cli_args.add(self._replace_vars(f'--output "{template}"'))
if save_path:
- cli_args.add(f'--paths "home:{save_path}"')
+ cli_args.add(self._replace_vars(f'--paths "home:{save_path}"'))
- cli_args.add(f'--paths "temp:{self._config.temp_path}"')
+ cli_args.add(self._replace_vars(f'--paths "temp:{self._config.temp_path}"'))
if self.item.url:
cli_args.add(self.item.url)
- command = str(cli_args)
- for k, v in self._config.get_replacers().items():
- command = command.replace(f"%({k})s", v if isinstance(v, str) else str(v))
+ command: str = self._replace_vars(str(cli_args))
- info = {
+ info: dict[str, Any] = {
"command": command,
"dict": cli_args.as_dict(),
"ytdlp": cli_args.as_ytdlp(),
@@ -202,6 +201,22 @@ class YTDLPCli:
return command, info
+ def _replace_vars(self, text: str) -> str:
+ """
+ Replace variables in the given text.
+
+ Args:
+ text (str): The text to replace variables in
+
+ Returns:
+ str: The text with variables replaced
+
+ """
+ for k, v in self._config.get_replacers().items():
+ text: str = text.replace(f"%({k})s", v if isinstance(v, str) else str(v))
+
+ return text
+
class YTDLPOpts:
def __init__(self):
diff --git a/app/routes/api/yt_dlp.py b/app/routes/api/yt_dlp.py
index 3da5b60b..e11ec531 100644
--- a/app/routes/api/yt_dlp.py
+++ b/app/routes/api/yt_dlp.py
@@ -9,6 +9,7 @@ from aiohttp.web import Request, Response
from app.library.cache import Cache
from app.library.config import Config
+from app.library.encoder import Encoder
from app.library.ItemDTO import Item
from app.library.Presets import Presets
from app.library.router import route
@@ -276,13 +277,14 @@ async def get_archive_ids(request: Request, config: Config) -> Response:
@route("POST", "api/yt-dlp/command/", "make_command")
-async def make_command(request: Request, config: Config) -> Response:
+async def make_command(request: Request, config: Config, encoder: Encoder) -> Response:
"""
Build yt-dlp CLI command.
Args:
request (Request): The request object.
config (Config): The config instance.
+ encoder (Encoder): The encoder instance.
Returns:
Response: The response object with the merged fields and final yt-dlp CLI command string.
@@ -304,7 +306,7 @@ async def make_command(request: Request, config: Config) -> Response:
return web.json_response(data={"error": str(e), "data": data}, status=web.HTTPBadRequest.status_code)
try:
- command, _ = YTDLPCli(item=it, config=config).build()
+ command, info = YTDLPCli(item=it, config=config).build()
except Exception as e:
LOG.exception(e)
return web.json_response(
@@ -312,4 +314,7 @@ async def make_command(request: Request, config: Config) -> Response:
status=web.HTTPBadRequest.status_code,
)
+ if request.query.get("full", False):
+ return web.json_response(data=info, status=web.HTTPOk.status_code, dumps=encoder.encode)
+
return web.json_response(data={"command": command}, status=web.HTTPOk.status_code)
diff --git a/ui/app/assets/css/style.css b/ui/app/assets/css/style.css
index fb18446a..c6bd7d8a 100644
--- a/ui/app/assets/css/style.css
+++ b/ui/app/assets/css/style.css
@@ -289,6 +289,10 @@ hr {
white-space: pre-wrap;
}
+.is-pre-wrap-force {
+ white-space: pre-wrap !important;
+}
+
.has-text-bold {
font-weight: bold;
}
@@ -370,4 +374,3 @@ div.is-centered {
padding: 0;
margin: 0 auto;
}
-
diff --git a/ui/app/components/ModalText.vue b/ui/app/components/ModalText.vue
new file mode 100644
index 00000000..008981da
--- /dev/null
+++ b/ui/app/components/ModalText.vue
@@ -0,0 +1,85 @@
+
+
+
+