From 8f73d7622b315b045e4476b162fc6d8083bf6287 Mon Sep 17 00:00:00 2001 From: Jakub Kot Date: Mon, 19 Dec 2022 14:06:54 +0100 Subject: [PATCH] added option to use output dir for web downloads --- spotdl/utils/arguments.py | 11 +++++++++++ spotdl/utils/config.py | 1 + spotdl/utils/web.py | 34 +++++++++++++++++++++++----------- 3 files changed, 35 insertions(+), 11 deletions(-) diff --git a/spotdl/utils/arguments.py b/spotdl/utils/arguments.py index 28c75d8ba..040b18725 100644 --- a/spotdl/utils/arguments.py +++ b/spotdl/utils/arguments.py @@ -482,6 +482,17 @@ def parse_web_options(parser: _ArgumentGroup): help="The allowed origins for the web server.", ) + # Add use output directory argument + parser.add_argument( + "--web-use-output-dir", + action="store_const", + const=True, + help=( + "Use the output directory instead of the session directory for downloads. (" + "This might cause issues if you have multiple users using the web-ui at the same time)" + ), + ) + def parse_misc_options(parser: _ArgumentGroup): """ diff --git a/spotdl/utils/config.py b/spotdl/utils/config.py index ee1dc4653..8ddbb4c13 100644 --- a/spotdl/utils/config.py +++ b/spotdl/utils/config.py @@ -161,4 +161,5 @@ def get_config() -> Dict[str, Any]: "playlist_numbering": False, "preserve_original_audio": False, "scan_for_songs": False, + "web_use_output_dir": False, } diff --git a/spotdl/utils/web.py b/spotdl/utils/web.py index 76126f11d..73d301fd4 100644 --- a/spotdl/utils/web.py +++ b/spotdl/utils/web.py @@ -7,6 +7,7 @@ import asyncio import logging import os +from pathlib import Path from typing import Dict, Any, List, Optional import mimetypes @@ -200,7 +201,7 @@ async def websocket_endpoint(websocket: WebSocket, client_id: str): await asyncio.sleep(1) - # Wait 5 seconds before shutting down + # Wait 1 second before shutting down # This is to prevent the server from shutting down when a client # disconnects and reconnects quickly (e.g. when refreshing the page) if len(app_state.ws_instances) == 0: @@ -270,9 +271,12 @@ async def download_url( - returns the file path if the song was downloaded. """ - state.downloader.output = str( - (get_spotdl_path() / f"web/sessions/{client_id}").absolute() - ) + if state.settings.get("web_use_output_dir", False): + state.downloader.output = state.settings["output"] + else: + state.downloader.output = str( + (get_spotdl_path() / f"web/sessions/{client_id}").absolute() + ) ws_instance = WSProgressHandler.get_instance(client_id) if ws_instance is not None: @@ -296,10 +300,7 @@ async def download_url( status_code=500, detail=f"Error downloading: {song.name}" ) - # Strip Filename - filename = os.path.basename(path) - - return filename + return str(path.absolute()) except Exception as exception: state.logger.error(f"Error downloading! {exception}") @@ -310,7 +311,9 @@ async def download_url( @router.get("/api/download/file") -async def download_file(file: str, client_id: str) -> FileResponse: +async def download_file( + file: str, state: ApplicationState = Depends(get_current_state) +) -> FileResponse: """ Download file using path. @@ -321,9 +324,18 @@ async def download_file(file: str, client_id: str) -> FileResponse: - returns the file response, filename specified to return as attachment. """ + expected_path = str((get_spotdl_path() / "web/sessions").absolute()) + if state.settings.get("web_use_output_dir", False): + expected_path = str(Path(state.settings["output"].split("{", 1)[0]).absolute()) + + if (not file.endswith(state.settings["format"])) or ( + not file.startswith(expected_path) + ): + raise HTTPException(status_code=400, detail="Invalid download path.") + return FileResponse( - str((get_spotdl_path() / f"web/sessions/{client_id}/{file}").absolute()), - filename=file, + file, + filename=os.path.basename(file), )