dfdsf
This commit is contained in:
157
cmdlets/download_provider.py
Normal file
157
cmdlets/download_provider.py
Normal file
@@ -0,0 +1,157 @@
|
||||
"""download-provider cmdlet: Download items from external providers."""
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import Any, Dict, Sequence, List, Optional
|
||||
from pathlib import Path
|
||||
import sys
|
||||
import json
|
||||
|
||||
from SYS.logger import log, debug
|
||||
from Provider.registry import get_search_provider, SearchResult
|
||||
from SYS.utils import unique_path
|
||||
|
||||
from ._shared import Cmdlet, CmdletArg, should_show_help, get_field, coerce_to_pipe_object
|
||||
import pipeline as ctx
|
||||
|
||||
# Optional dependencies
|
||||
try:
|
||||
from config import get_local_storage_path, resolve_output_dir
|
||||
except Exception: # pragma: no cover
|
||||
get_local_storage_path = None # type: ignore
|
||||
resolve_output_dir = None # type: ignore
|
||||
|
||||
class Download_Provider(Cmdlet):
|
||||
"""Download items from external providers."""
|
||||
|
||||
def __init__(self):
|
||||
super().__init__(
|
||||
name="download-provider",
|
||||
summary="Download items from external providers (soulseek, libgen, etc).",
|
||||
usage="download-provider [item] [-output DIR]",
|
||||
arg=[
|
||||
CmdletArg("output", type="string", alias="o", description="Output directory"),
|
||||
],
|
||||
detail=[
|
||||
"Download items from external providers.",
|
||||
"Usually called automatically by @N selection on provider results.",
|
||||
"Can be used manually by piping a provider result item.",
|
||||
],
|
||||
exec=self.run
|
||||
)
|
||||
self.register()
|
||||
|
||||
def run(self, result: Any, args: Sequence[str], config: Dict[str, Any]) -> int:
|
||||
"""Execute download-provider cmdlet."""
|
||||
if should_show_help(args):
|
||||
ctx.emit(self.__dict__)
|
||||
return 0
|
||||
|
||||
# Parse arguments
|
||||
output_dir_arg = None
|
||||
i = 0
|
||||
while i < len(args):
|
||||
arg = args[i]
|
||||
if arg in ("-output", "--output", "-o") and i + 1 < len(args):
|
||||
output_dir_arg = args[i+1]
|
||||
i += 2
|
||||
else:
|
||||
i += 1
|
||||
|
||||
# Determine output directory
|
||||
if output_dir_arg:
|
||||
output_dir = Path(output_dir_arg)
|
||||
elif resolve_output_dir:
|
||||
output_dir = resolve_output_dir(config)
|
||||
else:
|
||||
output_dir = Path("./downloads")
|
||||
|
||||
output_dir.mkdir(parents=True, exist_ok=True)
|
||||
|
||||
# Process input result
|
||||
items = []
|
||||
if isinstance(result, list):
|
||||
items = result
|
||||
elif result:
|
||||
items = [result]
|
||||
|
||||
if not items:
|
||||
log("No items to download", file=sys.stderr)
|
||||
return 1
|
||||
|
||||
success_count = 0
|
||||
|
||||
for item in items:
|
||||
try:
|
||||
# Extract provider info
|
||||
table = get_field(item, "table")
|
||||
if not table:
|
||||
log(f"Skipping item without provider info: {item}", file=sys.stderr)
|
||||
continue
|
||||
|
||||
provider = get_search_provider(table, config)
|
||||
if not provider:
|
||||
log(f"Provider '{table}' not available for download", file=sys.stderr)
|
||||
continue
|
||||
|
||||
# Reconstruct SearchResult if needed
|
||||
# The provider.download method expects a SearchResult object or compatible dict
|
||||
if isinstance(item, dict):
|
||||
# Ensure full_metadata is present
|
||||
if "full_metadata" not in item and "extra" in item:
|
||||
item["full_metadata"] = item["extra"].get("full_metadata", {})
|
||||
|
||||
search_result = SearchResult(
|
||||
table=table,
|
||||
title=item.get("title", "Unknown"),
|
||||
path=item.get("path", ""),
|
||||
full_metadata=item.get("full_metadata", {})
|
||||
)
|
||||
else:
|
||||
# Assume it's an object with attributes (like PipeObject)
|
||||
full_metadata = getattr(item, "full_metadata", {})
|
||||
# Check extra dict if full_metadata is missing/empty
|
||||
if not full_metadata and hasattr(item, "extra") and isinstance(item.extra, dict):
|
||||
full_metadata = item.extra.get("full_metadata", {})
|
||||
# Fallback: if full_metadata key isn't there, maybe the extra dict IS the metadata
|
||||
if not full_metadata and "username" in item.extra:
|
||||
full_metadata = item.extra
|
||||
|
||||
search_result = SearchResult(
|
||||
table=table,
|
||||
title=getattr(item, "title", "Unknown"),
|
||||
path=getattr(item, "path", ""),
|
||||
full_metadata=full_metadata
|
||||
)
|
||||
|
||||
debug(f"[download-provider] Downloading '{search_result.title}' via {table}...")
|
||||
downloaded_path = provider.download(search_result, output_dir)
|
||||
|
||||
if downloaded_path:
|
||||
debug(f"[download-provider] Download successful: {downloaded_path}")
|
||||
|
||||
# Create PipeObject for the downloaded file
|
||||
pipe_obj = coerce_to_pipe_object({
|
||||
"path": str(downloaded_path),
|
||||
"title": search_result.title,
|
||||
"table": "local", # Now it's a local file
|
||||
"media_kind": getattr(item, "media_kind", "other"),
|
||||
"tags": getattr(item, "tags", []),
|
||||
"full_metadata": search_result.full_metadata
|
||||
})
|
||||
|
||||
ctx.emit(pipe_obj)
|
||||
success_count += 1
|
||||
else:
|
||||
log(f"Download failed for '{search_result.title}'", file=sys.stderr)
|
||||
|
||||
except Exception as e:
|
||||
log(f"Error downloading item: {e}", file=sys.stderr)
|
||||
import traceback
|
||||
debug(traceback.format_exc())
|
||||
|
||||
if success_count > 0:
|
||||
return 0
|
||||
return 1
|
||||
|
||||
# Register cmdlet instance
|
||||
Download_Provider_Instance = Download_Provider()
|
||||
Reference in New Issue
Block a user