df
Some checks failed
smoke-mm / Install & smoke test mm --help (push) Has been cancelled

This commit is contained in:
2025-12-29 17:05:03 -08:00
parent 226de9316a
commit c019c00aed
104 changed files with 19669 additions and 12954 deletions

View File

@@ -44,8 +44,12 @@ class Download_File(Cmdlet):
SharedArgs.URL,
SharedArgs.PATH,
# Prefer -path for output directory to match other cmdlets; keep -output for backwards compatibility.
CmdletArg(name="-output", type="string", alias="o", description="(deprecated) Output directory (use -path instead)"),
CmdletArg(
name="-output",
type="string",
alias="o",
description="(deprecated) Output directory (use -path instead)",
),
],
detail=[
"Download files directly via HTTP without yt-dlp processing.",
@@ -67,7 +71,7 @@ class Download_File(Cmdlet):
raw_url = [raw_url]
expanded_urls: List[str] = []
for u in (raw_url or []):
for u in raw_url or []:
if u is None:
continue
s = str(u).strip()
@@ -99,7 +103,9 @@ class Download_File(Cmdlet):
return 1
@staticmethod
def _build_preview(raw_urls: Sequence[str], piped_items: Sequence[Any], total_items: int) -> List[Any]:
def _build_preview(
raw_urls: Sequence[str], piped_items: Sequence[Any], total_items: int
) -> List[Any]:
try:
preview: List[Any] = []
preview.extend(list(raw_urls or [])[: max(0, total_items)])
@@ -212,7 +218,11 @@ class Download_File(Cmdlet):
title = str(get_field(item, "title") or "").strip() if item is not None else ""
except Exception:
title = ""
table_title = f"Internet Archive: {title}".strip().rstrip(":") if title else f"Internet Archive: {identifier}"
table_title = (
f"Internet Archive: {title}".strip().rstrip(":")
if title
else f"Internet Archive: {identifier}"
)
try:
from result_table import ResultTable
@@ -329,7 +339,9 @@ class Download_File(Cmdlet):
config: Dict[str, Any],
provider_hint: Optional[str] = None,
) -> None:
title_val = (title_hint or downloaded_path.stem or "Unknown").strip() or downloaded_path.stem
title_val = (
title_hint or downloaded_path.stem or "Unknown"
).strip() or downloaded_path.stem
hash_value = self._compute_file_hash(downloaded_path)
tag: List[str] = []
if tags_hint:
@@ -406,9 +418,13 @@ class Download_File(Cmdlet):
provider = _get_provider("telegram", config)
if provider is None:
raise DownloadError("Telegram provider not configured or not available (check telethon/app_id/api_hash)")
raise DownloadError(
"Telegram provider not configured or not available (check telethon/app_id/api_hash)"
)
sr = SearchResult(table="telegram", title=str(url), path=str(url), full_metadata={})
sr = SearchResult(
table="telegram", title=str(url), path=str(url), full_metadata={}
)
downloaded_path = None
telegram_info: Optional[Dict[str, Any]] = None
if hasattr(provider, "download_url"):
@@ -428,9 +444,15 @@ class Download_File(Cmdlet):
try:
chat_info_raw = telegram_info.get("chat")
msg_info_raw = telegram_info.get("message")
chat_info: Dict[str, Any] = chat_info_raw if isinstance(chat_info_raw, dict) else {}
msg_info: Dict[str, Any] = msg_info_raw if isinstance(msg_info_raw, dict) else {}
channel = str(chat_info.get("title") or chat_info.get("username") or "").strip()
chat_info: Dict[str, Any] = (
chat_info_raw if isinstance(chat_info_raw, dict) else {}
)
msg_info: Dict[str, Any] = (
msg_info_raw if isinstance(msg_info_raw, dict) else {}
)
channel = str(
chat_info.get("title") or chat_info.get("username") or ""
).strip()
post = msg_info.get("id")
except Exception:
channel = ""
@@ -479,7 +501,16 @@ class Download_File(Cmdlet):
p = urlparse(str(url))
h = (p.hostname or "").strip().lower()
path = (p.path or "").strip().lower()
if "libgen" in h and any(x in path for x in ("/edition.php", "/file.php", "/ads.php", "/get.php", "/series.php")):
if "libgen" in h and any(
x in path
for x in (
"/edition.php",
"/file.php",
"/ads.php",
"/get.php",
"/series.php",
)
):
provider_name = "libgen"
except Exception:
pass
@@ -489,7 +520,9 @@ class Download_File(Cmdlet):
if provider_name == "openlibrary":
provider = get_provider("openlibrary", config)
if provider is None:
raise DownloadError("OpenLibrary provider not configured or not available")
raise DownloadError(
"OpenLibrary provider not configured or not available"
)
edition_id = self._openlibrary_edition_id_from_url(str(url))
title_hint = self._title_hint_from_url_slug(str(url))
@@ -512,7 +545,9 @@ class Download_File(Cmdlet):
# High-level steps for OpenLibrary borrow/download flow.
progress.begin_steps(5)
def _progress(kind: str, done: int, total: Optional[int], label: str) -> None:
def _progress(
kind: str, done: int, total: Optional[int], label: str
) -> None:
# kind:
# - "step": advance step text
# - "pages": update pipe percent/status
@@ -525,7 +560,9 @@ class Download_File(Cmdlet):
t = int(total) if isinstance(total, int) else 0
d = int(done) if isinstance(done, int) else 0
if t > 0:
pct = int(round((max(0, min(d, t)) / max(1, t)) * 100.0))
pct = int(
round((max(0, min(d, t)) / max(1, t)) * 100.0)
)
progress.set_percent(pct)
progress.set_status(f"downloading pages {d}/{t}")
else:
@@ -538,9 +575,15 @@ class Download_File(Cmdlet):
except Exception:
lbl = "download"
progress.begin_transfer(label=lbl, total=total)
progress.update_transfer(label=lbl, completed=done, total=total)
progress.update_transfer(
label=lbl, completed=done, total=total
)
try:
if isinstance(total, int) and total > 0 and int(done) >= int(total):
if (
isinstance(total, int)
and total > 0
and int(done) >= int(total)
):
progress.finish_transfer(label=lbl)
except Exception:
pass
@@ -590,12 +633,18 @@ class Download_File(Cmdlet):
exec_fn = getattr(_SEARCH_PROVIDER_CMDLET, "exec", None)
if callable(exec_fn):
ret = exec_fn(None, ["-provider", "libgen", "-query", fallback_query], config)
ret = exec_fn(
None,
["-provider", "libgen", "-query", fallback_query],
config,
)
try:
table = pipeline_context.get_last_result_table()
items = pipeline_context.get_last_result_items()
if table is not None:
pipeline_context.set_last_result_table_overlay(table, items)
pipeline_context.set_last_result_table_overlay(
table, items
)
except Exception:
pass
@@ -606,7 +655,10 @@ class Download_File(Cmdlet):
except Exception:
pass
log("[download-file] OpenLibrary URL could not be downloaded", file=sys.stderr)
log(
"[download-file] OpenLibrary URL could not be downloaded",
file=sys.stderr,
)
continue
# Generic provider URL handler (if a provider implements `download_url`).
@@ -734,11 +786,18 @@ class Download_File(Cmdlet):
full_metadata = get_field(item, "full_metadata")
target = get_field(item, "path") or get_field(item, "url")
if str(table or "").lower() == "alldebrid" and str(media_kind or "").lower() == "folder":
if (
str(table or "").lower() == "alldebrid"
and str(media_kind or "").lower() == "folder"
):
magnet_id = None
if isinstance(full_metadata, dict):
magnet_id = full_metadata.get("magnet_id")
if magnet_id is None and isinstance(target, str) and target.lower().startswith("alldebrid:magnet:"):
if (
magnet_id is None
and isinstance(target, str)
and target.lower().startswith("alldebrid:magnet:")
):
try:
magnet_id = int(target.split(":")[-1])
except Exception:
@@ -748,12 +807,20 @@ class Download_File(Cmdlet):
provider = get_search_provider("alldebrid", config)
if provider is not None:
try:
files = provider.search("*", limit=10_000, filters={"view": "files", "magnet_id": int(magnet_id)})
files = provider.search(
"*",
limit=10_000,
filters={"view": "files", "magnet_id": int(magnet_id)},
)
except Exception:
files = []
# If the magnet isn't ready, provider.search returns a single not-ready folder row.
if files and len(files) == 1 and getattr(files[0], "media_kind", "") == "folder":
if (
files
and len(files) == 1
and getattr(files[0], "media_kind", "") == "folder"
):
detail = getattr(files[0], "detail", "")
log(
f"[download-file] AllDebrid magnet {magnet_id} not ready ({detail or 'unknown'})",
@@ -761,7 +828,9 @@ class Download_File(Cmdlet):
)
else:
for sr in files:
expanded_items.append(sr.to_dict() if hasattr(sr, "to_dict") else sr)
expanded_items.append(
sr.to_dict() if hasattr(sr, "to_dict") else sr
)
continue
expanded_items.append(item)
@@ -784,7 +853,9 @@ class Download_File(Cmdlet):
get_search_provider = registry.get("get_search_provider")
SearchResult = registry.get("SearchResult")
expanded_items = self._expand_provider_items(piped_items=piped_items, registry=registry, config=config)
expanded_items = self._expand_provider_items(
piped_items=piped_items, registry=registry, config=config
)
for item in expanded_items:
try:
@@ -800,7 +871,11 @@ class Download_File(Cmdlet):
tags_list = None
full_metadata = get_field(item, "full_metadata")
if (not full_metadata) and isinstance(item, dict) and isinstance(item.get("extra"), dict):
if (
(not full_metadata)
and isinstance(item, dict)
and isinstance(item.get("extra"), dict)
):
extra_md = item["extra"].get("full_metadata")
if isinstance(extra_md, dict):
full_metadata = extra_md
@@ -832,7 +907,9 @@ class Download_File(Cmdlet):
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
magnet_name = (
str(get_field(item, "detail") or "").strip() or None
)
magnet_dir_name = _sf(str(magnet_name)) if magnet_name else ""
@@ -845,7 +922,9 @@ class Download_File(Cmdlet):
base_tail_norm = _sf(base_tail).lower() if base_tail.strip() else ""
magnet_dir_norm = magnet_dir_name.lower() if magnet_dir_name else ""
if magnet_dir_name and (not base_tail_norm or base_tail_norm != magnet_dir_norm):
if magnet_dir_name and (
not base_tail_norm or base_tail_norm != magnet_dir_norm
):
output_dir = Path(output_dir) / magnet_dir_name
relpath = None
@@ -855,7 +934,11 @@ class Download_File(Cmdlet):
relpath = md["file"].get("_relpath")
if relpath:
parts = [p for p in str(relpath).replace("\\", "/").split("/") if p and p not in {".", ".."}]
parts = [
p
for p in str(relpath).replace("\\", "/").split("/")
if p and p not in {".", ".."}
]
# If the provider relpath already includes the magnet folder name as a
# root directory (common), strip it to prevent double nesting.
@@ -881,7 +964,11 @@ class Download_File(Cmdlet):
provider_sr = sr
# OpenLibrary: if provider download failed, do NOT try to download the OpenLibrary page HTML.
if downloaded_path is None and attempted_provider_download and str(table or "").lower() == "openlibrary":
if (
downloaded_path is None
and attempted_provider_download
and str(table or "").lower() == "openlibrary"
):
availability = None
reason = None
if isinstance(full_metadata, dict):
@@ -898,7 +985,10 @@ class Download_File(Cmdlet):
if not title_text and isinstance(full_metadata, dict):
title_text = str(full_metadata.get("title") or "").strip()
if title_text:
log(f"[download-file] Not available on OpenLibrary; searching LibGen for: {title_text}", file=sys.stderr)
log(
f"[download-file] Not available on OpenLibrary; searching LibGen for: {title_text}",
file=sys.stderr,
)
from cmdlet.search_provider import CMDLET as _SEARCH_PROVIDER_CMDLET
fallback_query = title_text
@@ -921,7 +1011,9 @@ class Download_File(Cmdlet):
table_obj = pipeline_context.get_last_result_table()
items_obj = pipeline_context.get_last_result_items()
if table_obj is not None:
pipeline_context.set_last_result_table_overlay(table_obj, items_obj)
pipeline_context.set_last_result_table_overlay(
table_obj, items_obj
)
except Exception:
pass
@@ -935,7 +1027,11 @@ class Download_File(Cmdlet):
continue
# Fallback: if we have a direct HTTP URL, download it directly
if downloaded_path is None and isinstance(target, str) and target.startswith("http"):
if (
downloaded_path is None
and isinstance(target, str)
and target.startswith("http")
):
# Guard: provider landing pages (e.g. LibGen ads.php) are HTML, not files.
# Never download these as "files".
if str(table or "").lower() == "libgen":
@@ -946,7 +1042,9 @@ class Download_File(Cmdlet):
file=sys.stderr,
)
continue
debug(f"[download-file] Provider item looks like direct URL, downloading: {target}")
debug(
f"[download-file] Provider item looks like direct URL, downloading: {target}"
)
suggested_name = str(title).strip() if title is not None else None
result_obj = _download_direct_file(
target,
@@ -958,7 +1056,10 @@ class Download_File(Cmdlet):
downloaded_path = self._path_from_download_result(result_obj)
if downloaded_path is None:
log(f"Cannot download item (no provider handler / unsupported target): {title or target}", file=sys.stderr)
log(
f"Cannot download item (no provider handler / unsupported target): {title or target}",
file=sys.stderr,
)
continue
# Allow providers to add/enrich tags and metadata during download.
@@ -1038,11 +1139,19 @@ class Download_File(Cmdlet):
# UX: In piped mode, allow a single positional arg to be the destination directory.
# Example: @1-4 | download-file "C:\\Users\\Me\\Downloads\\yoyo"
if had_piped_input and raw_url and len(raw_url) == 1 and (not parsed.get("path")) and (not parsed.get("output")):
if (
had_piped_input
and raw_url
and len(raw_url) == 1
and (not parsed.get("path"))
and (not parsed.get("output"))
):
candidate = str(raw_url[0] or "").strip()
low = candidate.lower()
looks_like_url = low.startswith(("http://", "https://", "ftp://"))
looks_like_provider = low.startswith(("magnet:", "alldebrid:", "hydrus:", "ia:", "internetarchive:"))
looks_like_provider = low.startswith(
("magnet:", "alldebrid:", "hydrus:", "ia:", "internetarchive:")
)
looks_like_windows_path = (
(len(candidate) >= 2 and candidate[1] == ":")
or candidate.startswith("\\\\")
@@ -1058,7 +1167,9 @@ class Download_File(Cmdlet):
log("No url or piped items to download", file=sys.stderr)
return 1
quiet_mode = bool(config.get("_quiet_background_output")) if isinstance(config, dict) else False
quiet_mode = (
bool(config.get("_quiet_background_output")) if isinstance(config, dict) else False
)
ia_picker_exit = self._maybe_show_internetarchive_formats(
raw_urls=raw_url,
piped_items=piped_items,
@@ -1082,7 +1193,9 @@ class Download_File(Cmdlet):
total_items = self._safe_total_items(raw_url, piped_items)
preview = self._build_preview(raw_url, piped_items, total_items)
progress.ensure_local_ui(label="download-file", total_items=total_items, items_preview=preview)
progress.ensure_local_ui(
label="download-file", total_items=total_items, items_preview=preview
)
registry = self._load_provider_registry()
@@ -1155,6 +1268,7 @@ class Download_File(Cmdlet):
# Priority 2: Config default output/temp directory
try:
from config import resolve_output_dir
final_output_dir = resolve_output_dir(config)
except Exception:
final_output_dir = Path.home() / "Downloads"
@@ -1173,6 +1287,7 @@ class Download_File(Cmdlet):
def _compute_file_hash(self, filepath: Path) -> str:
"""Compute SHA256 hash of a file."""
import hashlib
sha256_hash = hashlib.sha256()
with open(filepath, "rb") as f:
for byte_block in iter(lambda: f.read(4096), b""):