j
This commit is contained in:
@@ -11,6 +11,7 @@ from urllib.parse import urlparse
|
||||
from API.HTTP import HTTPClient, _download_direct_file
|
||||
from API.alldebrid import AllDebridClient, parse_magnet_or_hash, is_torrent_file
|
||||
from ProviderCore.base import Provider, SearchResult
|
||||
from SYS.provider_helpers import TableProviderMixin
|
||||
from SYS.utils import sanitize_filename
|
||||
from SYS.logger import log, debug
|
||||
from SYS.models import DownloadError
|
||||
@@ -541,7 +542,32 @@ def adjust_output_dir_for_alldebrid(
|
||||
return output_dir
|
||||
|
||||
|
||||
class AllDebrid(Provider):
|
||||
class AllDebrid(TableProviderMixin, Provider):
|
||||
"""AllDebrid account provider with magnet folder/file browsing and downloads.
|
||||
|
||||
This provider uses the new table system (strict ResultTable adapter pattern) for
|
||||
consistent selection and auto-stage integration across all providers. It exposes
|
||||
magnets as folder rows and files as file rows, with metadata enrichment for:
|
||||
- magnet_id: For routing to _download_magnet_by_id
|
||||
- status/ready: For showing sync state
|
||||
- _selection_args/_selection_action: For @N expansion control
|
||||
- relpath: For proper file hierarchy in downloads
|
||||
|
||||
KEY FEATURES:
|
||||
- Table system: Using ResultTable adapter for strict column/metadata handling
|
||||
- Selection override: Full metadata control via _selection_args/_selection_action
|
||||
- Auto-stages: download-file is auto-inserted when @N is used on magnet folders
|
||||
- File unlocking: URLs with /f/ paths are automatically unlocked via API before download
|
||||
- Drill-down: Selecting a folder row (@N) fetches and displays all files
|
||||
|
||||
SELECTION FLOW:
|
||||
1. User runs: search-file -provider alldebrid "ubuntu"
|
||||
2. Results show magnet folders and (optionally) files
|
||||
3. User selects a row: @1
|
||||
4. Selection metadata routes to download-file with -magnet-id
|
||||
5. download-file calls provider.download_items() with magnet_id
|
||||
6. Provider fetches files, unlocks locked URLs, and downloads
|
||||
"""
|
||||
# Magnet URIs should be routed through this provider.
|
||||
TABLE_AUTO_STAGES = {"alldebrid": ["download-file"]}
|
||||
AUTO_STAGE_USE_SELECTION_ARGS = True
|
||||
@@ -1147,6 +1173,7 @@ class AllDebrid(Provider):
|
||||
"file": file_node,
|
||||
"provider": "alldebrid",
|
||||
"provider_view": "files",
|
||||
# Selection metadata for table system
|
||||
"_selection_args": ["-magnet-id", str(magnet_id)],
|
||||
"_selection_action": ["download-file", "-provider", "alldebrid", "-magnet-id", str(magnet_id)],
|
||||
}
|
||||
@@ -1521,6 +1548,12 @@ try:
|
||||
|
||||
|
||||
def _columns_factory(rows: List[ResultModel]) -> List[ColumnSpec]:
|
||||
"""Build column specifications from available metadata in rows.
|
||||
|
||||
This factory inspects all rows and creates ColumnSpec entries only
|
||||
for metadata that is actually present in the result set. This avoids
|
||||
empty columns in the display.
|
||||
"""
|
||||
cols = [title_column()]
|
||||
if _has_metadata(rows, "magnet_name"):
|
||||
cols.append(metadata_column("magnet_name", "Magnet"))
|
||||
@@ -1531,7 +1564,7 @@ try:
|
||||
if _has_metadata(rows, "ready"):
|
||||
cols.append(metadata_column("ready", "Ready"))
|
||||
if _has_metadata(rows, "relpath"):
|
||||
cols.append(metadata_column("relpath", "Relpath"))
|
||||
cols.append(metadata_column("relpath", "File Path"))
|
||||
if _has_metadata(rows, "provider_view"):
|
||||
cols.append(metadata_column("provider_view", "View"))
|
||||
if _has_metadata(rows, "size"):
|
||||
@@ -1540,22 +1573,45 @@ try:
|
||||
|
||||
|
||||
def _selection_fn(row: ResultModel) -> List[str]:
|
||||
"""Return selection args for @N expansion and auto-download integration.
|
||||
|
||||
Selection precedence:
|
||||
1. Explicit _selection_action (full command args)
|
||||
2. Explicit _selection_args (URL-specific args)
|
||||
3. Magic routing based on provider_view (files vs folders)
|
||||
4. Magnet ID routing for folder-type rows
|
||||
5. Direct URL for file rows
|
||||
|
||||
This ensures that selector overrides all pre-codes and gives users full power.
|
||||
"""
|
||||
metadata = row.metadata or {}
|
||||
|
||||
# First try explicit action (full command)
|
||||
action = metadata.get("_selection_action") or metadata.get("selection_action")
|
||||
if isinstance(action, (list, tuple)) and action:
|
||||
return [str(x) for x in action if x is not None]
|
||||
|
||||
# Next try explicit args (typically URL-based)
|
||||
args = metadata.get("_selection_args") or metadata.get("selection_args")
|
||||
if isinstance(args, (list, tuple)) and args:
|
||||
return [str(x) for x in args if x is not None]
|
||||
|
||||
# Magic routing by view type
|
||||
view = metadata.get("provider_view") or metadata.get("view") or ""
|
||||
if view == "files":
|
||||
# File rows: pass direct URL for immediate download
|
||||
if row.path:
|
||||
return ["-url", row.path]
|
||||
|
||||
# Folder rows: use magnet_id to fetch and download all files
|
||||
magnet_id = metadata.get("magnet_id")
|
||||
if magnet_id is not None:
|
||||
return ["-magnet-id", str(magnet_id)]
|
||||
|
||||
# Fallback: try direct URL
|
||||
if row.path:
|
||||
return ["-url", row.path]
|
||||
|
||||
return ["-title", row.title or ""]
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user