From 6acb52dfa0dfa76a6e0158aedcb510bbb1d94a8a Mon Sep 17 00:00:00 2001 From: Nose Date: Sun, 28 Dec 2025 03:51:48 -0800 Subject: [PATCH] jj --- Provider/alldebrid.py | 30 +++++++++++++++++++++++++----- cmdlet/download_file.py | 38 +++++++++++++++++++++++++++++++++++++- scripts/setup.py | 4 +--- 3 files changed, 63 insertions(+), 9 deletions(-) diff --git a/Provider/alldebrid.py b/Provider/alldebrid.py index 705e513..d1c05fa 100644 --- a/Provider/alldebrid.py +++ b/Provider/alldebrid.py @@ -152,15 +152,20 @@ class AllDebrid(Provider): return None @staticmethod - def _flatten_files(items: Any) -> Iterable[Dict[str, Any]]: - """Flatten AllDebrid magnet file tree into file dicts. + def _flatten_files(items: Any, *, _prefix: Optional[List[str]] = None) -> Iterable[Dict[str, Any]]: + """Flatten AllDebrid magnet file tree into file dicts, preserving relative paths. API commonly returns: - file: {n: name, s: size, l: link} - folder: {n: name, e: [sub_items]} + This flattener attaches a best-effort relative path to each yielded file node + as `_relpath` using POSIX separators (e.g., "Season 1/E01.mkv"). + Some call sites in this repo also expect {name, size, link}, so we accept both. """ + prefix = list(_prefix or []) + if not items: return if isinstance(items, dict): @@ -174,13 +179,21 @@ class AllDebrid(Provider): children = node.get('e') or node.get('children') if isinstance(children, list): - yield from AllDebrid._flatten_files(children) + folder_name = node.get('n') or node.get('name') + next_prefix = prefix + if isinstance(folder_name, str) and folder_name.strip(): + next_prefix = prefix + [folder_name.strip()] + yield from AllDebrid._flatten_files(children, _prefix=next_prefix) continue name = node.get('n') or node.get('name') link = node.get('l') or node.get('link') if isinstance(name, str) and name.strip() and isinstance(link, str) and link.strip(): - yield node + rel_parts = prefix + [name.strip()] + relpath = "/".join([p for p in rel_parts if p]) + enriched = dict(node) + enriched["_relpath"] = relpath + yield enriched def search( self, @@ -269,6 +282,7 @@ class AllDebrid(Provider): for file_node in self._flatten_files(file_tree): file_name = str(file_node.get('n') or file_node.get('name') or '').strip() file_url = str(file_node.get('l') or file_node.get('link') or '').strip() + relpath = str(file_node.get('_relpath') or file_name or '').strip() file_size = file_node.get('s') or file_node.get('size') if not file_name or not file_url: continue @@ -300,7 +314,13 @@ class AllDebrid(Provider): ("Folder", magnet_name), ("ID", str(magnet_id)), ], - full_metadata={"magnet": magnet_status, "magnet_id": magnet_id, "file": file_node}, + full_metadata={ + "magnet": magnet_status, + "magnet_id": magnet_id, + "magnet_name": magnet_name, + "relpath": relpath, + "file": file_node, + }, ) ) if len(results) >= max(1, limit): diff --git a/cmdlet/download_file.py b/cmdlet/download_file.py index d9c239a..04bb00a 100644 --- a/cmdlet/download_file.py +++ b/cmdlet/download_file.py @@ -815,7 +815,43 @@ class Download_File(Cmdlet): full_metadata=full_metadata if isinstance(full_metadata, dict) else {}, ) debug(f"[download-file] Downloading provider item via {table}: {sr.title}") - downloaded_path = provider.download(sr, final_output_dir) + + # Preserve provider structure when possible (AllDebrid folders -> subfolders). + output_dir = final_output_dir + try: + if str(table).strip().lower() == "alldebrid": + from ProviderCore.download import sanitize_filename as _sf + + md = full_metadata if isinstance(full_metadata, dict) else {} + magnet_name = None + if isinstance(md, dict): + magnet_name = md.get("magnet_name") or md.get("folder") + if not magnet_name: + magnet_name = str(get_field(item, "detail") or "").strip() or None + + if magnet_name: + output_dir = Path(output_dir) / _sf(str(magnet_name)) + + relpath = None + if isinstance(md, dict): + relpath = md.get("relpath") + if not relpath and isinstance(md.get("file"), dict): + relpath = md["file"].get("_relpath") + + if relpath: + parts = [p for p in str(relpath).replace("\\", "/").split("/") if p and p not in {".", ".."}] + # relpath includes the filename; only join parent directories. + for part in parts[:-1]: + output_dir = Path(output_dir) / _sf(part) + + try: + Path(output_dir).mkdir(parents=True, exist_ok=True) + except Exception: + output_dir = final_output_dir + except Exception: + output_dir = final_output_dir + + downloaded_path = provider.download(sr, output_dir) provider_sr = sr # OpenLibrary: if provider download failed, do NOT try to download the OpenLibrary page HTML. diff --git a/scripts/setup.py b/scripts/setup.py index 5f9b416..4283fad 100644 --- a/scripts/setup.py +++ b/scripts/setup.py @@ -16,9 +16,7 @@ scripts/setup.py """ -Unified project setup helper (Python-only). -#!/usr/bin/env python3 -"""scripts/setup.py +""" scripts/setup.py Unified project setup helper (Python-only).