diff --git a/README.md b/README.md index efd913d8..695bf527 100644 --- a/README.md +++ b/README.md @@ -317,4 +317,5 @@ Certain configuration values can be set via environment variables, using the `-e | YTP_TASKS_HANDLER_TIMER | The cron expression for the tasks handler timer | `15 */1 * * *` | | YTP_PLAYLIST_ITEMS_CONCURRENCY | The number of playlist items be to processed at same time | `1` | | YTP_TEMP_DISABLED | Disable temp files handling. | `false` | +| YTP_DOWNLOAD_PATH_DEPTH | How many subdirectories to show in auto complete. | `1` | diff --git a/app/library/Utils.py b/app/library/Utils.py index 3ec83650..9cf1c146 100644 --- a/app/library/Utils.py +++ b/app/library/Utils.py @@ -1405,6 +1405,32 @@ def find_unpickleable(obj, name="root", seen=None): find_unpickleable(value, f"{name}.{attr}", seen) except Exception as ie: LOG.error(f"[ERROR] Accessing {name}.{attr}: {ie}") - elif isinstance(obj, (list, tuple, set)): + elif isinstance(obj, list | tuple | set): for idx, item in enumerate(obj): find_unpickleable(item, f"{name}[{idx}]", seen) + + +def list_folders(path: Path, base: Path, depth_limit: int) -> list[str]: + """ + List all folders relative to a base path, up to a specified depth limit. + + Args: + path (Path): The path to start listing folders from. + base (Path): The base path to which the folders should be relative. + depth_limit (int): The maximum depth to traverse from the base path. + + Returns: + list[str]: A list of folder paths relative to the base path, up to the specified + + """ + rel_depth: int = len(path.relative_to(base).parts) + if rel_depth > depth_limit: + return [] + + folders: list[str] = [] + for entry in path.iterdir(): + if entry.is_dir(): + folders.append(str(entry.relative_to(base))) + folders.extend(list_folders(entry, base, depth_limit)) + + return folders diff --git a/app/library/config.py b/app/library/config.py index 57407530..1d40a753 100644 --- a/app/library/config.py +++ b/app/library/config.py @@ -25,6 +25,9 @@ class Config: download_path: str = "." """The path to the download directory.""" + download_path_depth: int = 2 + """How many subdirectories to show in auto complete.""" + temp_path: str = "/tmp" """The path to the temporary directory.""" @@ -219,6 +222,7 @@ class Config: "extract_info_timeout", "debugpy_port", "playlist_items_concurrency", + "download_path_depth", ) "The variables that are integers." diff --git a/app/routes/socket/connection.py b/app/routes/socket/connection.py index 28407a4d..bce02997 100644 --- a/app/routes/socket/connection.py +++ b/app/routes/socket/connection.py @@ -10,7 +10,7 @@ from app.library.DownloadQueue import DownloadQueue from app.library.Events import EventBus, Events from app.library.Presets import Presets from app.library.router import RouteType, route -from app.library.Utils import tail_log +from app.library.Utils import list_folders, tail_log LOG: logging.Logger = logging.getLogger(__name__) @@ -29,7 +29,11 @@ async def connect(config: Config, queue: DownloadQueue, notify: EventBus, sid: s "paused": queue.is_paused(), } - data["folders"] = [folder.name for folder in Path(config.download_path).iterdir() if folder.is_dir()] + data["folders"] = list_folders( + path=Path(config.download_path), + base=Path(config.download_path), + depth_limit=config.download_path_depth-1, + ) await notify.emit( Events.CONNECTED,