diff --git a/app/library/Utils.py b/app/library/Utils.py index 123222ee..a86074f4 100644 --- a/app/library/Utils.py +++ b/app/library/Utils.py @@ -643,7 +643,7 @@ def arg_converter( # important to ignore external config files. args = "--ignore-config " + args - opts = yt_dlp.parse_options(shlex.split(args)).ydl_opts + opts = yt_dlp.parse_options(shlex.split(args, posix=os.name != "nt")).ydl_opts diff = {k: v for k, v in opts.items() if default_opts[k] != v} if not keep_defaults else opts.items() if "postprocessors" in diff: diff["postprocessors"] = [pp for pp in diff["postprocessors"] if pp not in default_opts["postprocessors"]] diff --git a/app/library/config.py b/app/library/config.py index be384bbb..6fca0d6a 100644 --- a/app/library/config.py +++ b/app/library/config.py @@ -117,13 +117,13 @@ class Config(metaclass=Singleton): extract_info_timeout: int = 70 """The timeout to use for extracting video information.""" - db_file: str = "{config_path}/ytptube.db" + db_file: str = "{config_path}{os_sep}ytptube.db" """The path to the database file.""" - archive_file: str = "{config_path}/archive.log" + archive_file: str = "{config_path}{os_sep}archive.log" """The path to the download archive file.""" - apprise_config: str = "{config_path}/apprise.yml" + apprise_config: str = "{config_path}{os_sep}apprise.yml" """The path to the Apprise configuration file.""" ui_update_title: bool = True @@ -295,6 +295,9 @@ class Config(metaclass=Singleton): _manager: SyncManager | None = None "The manager instance." + os_sep: str = os.path.sep + "The system path separator." + @staticmethod def get_instance(is_native: bool = False) -> "Config": cls = Config(is_native) @@ -528,7 +531,7 @@ class Config(metaclass=Singleton): dict[str, str]: The replacer variables. """ - keys: tuple[str] = ("download_path", "temp_path", "config_path", "archive_file") + keys: tuple[str] = ("os_sep", "download_path", "temp_path", "config_path", "archive_file") return {k: getattr(self, k) for k in keys} @staticmethod diff --git a/app/local.py b/app/local.py index 9ddc7d2b..cae170ad 100644 --- a/app/local.py +++ b/app/local.py @@ -69,6 +69,8 @@ def open_browser_when_ready(url: str, timeout: float = 5.0) -> None: def app_start(host: str, port: int) -> None: import asyncio + from aiohttp.web_runner import GracefulExit + from app.main import Main try: @@ -77,7 +79,10 @@ def app_start(host: str, port: int) -> None: loop = asyncio.new_event_loop() asyncio.set_event_loop(loop) - Main(is_native=True).start(host, port) + try: + Main(is_native=True).start(host, port) + except GracefulExit: + sys.exit(0) def update_env_file(env_file: pathlib.Path, port: int) -> None: diff --git a/app/routes/api/system.py b/app/routes/api/system.py index a1edbd99..79a538b8 100644 --- a/app/routes/api/system.py +++ b/app/routes/api/system.py @@ -4,6 +4,7 @@ import time from aiohttp import web from aiohttp.web import Request, Response +from aiohttp.web_runner import GracefulExit from app.library.config import Config from app.library.DownloadQueue import DownloadQueue @@ -117,6 +118,7 @@ async def shutdown_system(request: Request, config: Config, encoder: Encoder, no await asyncio.sleep(0.5) await app.shutdown() await app.cleanup() + raise GracefulExit # Schedule shutdown after response asyncio.create_task(do_shutdown()) diff --git a/app/routes/socket/terminal.py b/app/routes/socket/terminal.py index 401951dd..146c39ff 100644 --- a/app/routes/socket/terminal.py +++ b/app/routes/socket/terminal.py @@ -38,7 +38,7 @@ async def cli_post(config: Config, notify: EventBus, sid: str, data: str): try: LOG.info(f"Cli command from client '{sid}'. '{data}'") - args: list[str] = ["yt-dlp", *shlex.split(data)] + args: list[str] = ["yt-dlp", *shlex.split(data, posix=os.name != "nt")] _env: dict[str, str] = os.environ.copy() _env.update( {