This commit is contained in:
2026-01-10 17:30:18 -08:00
parent 08fef4a5d3
commit c2edd5139f
10 changed files with 769 additions and 86 deletions

View File

@@ -1033,6 +1033,7 @@ class Add_File(Cmdlet):
except Exception as exc:
debug(f"[add-file] Failed to retrieve via hash+store: {exc}")
# PRIORITY 2: Try explicit path argument
if path_arg:
media_path = Path(path_arg)

View File

@@ -40,6 +40,8 @@ from tool.ytdlp import (
_format_chapters_note,
_read_text_file,
is_url_supported_by_ytdlp,
is_browseable_format,
format_for_table_selection,
list_formats,
probe_url,
)
@@ -1553,22 +1555,8 @@ class Download_File(Cmdlet):
return fmts
def _is_browseable_format(self, fmt: Any) -> bool:
if not isinstance(fmt, dict):
return False
format_id = str(fmt.get("format_id") or "").strip()
if not format_id:
return False
ext = str(fmt.get("ext") or "").strip().lower()
if ext in {"mhtml", "json"}:
return False
note = str(fmt.get("format_note") or "").lower()
if "storyboard" in note:
return False
if format_id.lower().startswith("sb"):
return False
vcodec = str(fmt.get("vcodec", "none"))
acodec = str(fmt.get("acodec", "none"))
return not (vcodec == "none" and acodec == "none")
"""Check if format is user-browseable. Delegates to ytdlp helper."""
return is_browseable_format(fmt)
def _format_id_for_query_index(
self,
@@ -2374,6 +2362,9 @@ class Download_File(Cmdlet):
table = ResultTable(title=f"Available formats for {url}", max_columns=10, preserve_order=True)
table.set_table("ytdlp.formatlist")
table.set_source_command("download-file", [url])
debug(f"[ytdlp.formatlist] Displaying format selection table for {url}")
debug(f"[ytdlp.formatlist] Provider: ytdlp (routing to download-file via TABLE_AUTO_STAGES)")
results_list: List[Dict[str, Any]] = []
for idx, fmt in enumerate(filtered_formats, 1):
@@ -2392,65 +2383,28 @@ class Download_File(Cmdlet):
except Exception:
selection_format_id = format_id
size_str = ""
size_prefix = ""
size_bytes = filesize
if not size_bytes:
size_bytes = filesize_approx
if size_bytes:
size_prefix = "~"
try:
if isinstance(size_bytes, (int, float)) and size_bytes > 0:
size_mb = float(size_bytes) / (1024 * 1024)
size_str = f"{size_prefix}{size_mb:.1f}MB"
except Exception:
size_str = ""
desc_parts: List[str] = []
if resolution and resolution != "audio only":
desc_parts.append(resolution)
if ext:
desc_parts.append(str(ext).upper())
if vcodec != "none":
desc_parts.append(f"v:{vcodec}")
if acodec != "none":
desc_parts.append(f"a:{acodec}")
if size_str:
desc_parts.append(size_str)
format_desc = " | ".join(desc_parts)
format_dict = {
"table": "download-file",
"title": f"Format {format_id}",
"url": url,
"target": url,
"detail": format_desc,
"annotations": [ext, resolution] if resolution else [ext],
"media_kind": "format",
"cmd": base_cmd,
"columns": [
("ID", format_id),
("Resolution", resolution or "N/A"),
("Ext", ext),
("Size", size_str or ""),
("Video", vcodec),
("Audio", acodec),
],
"full_metadata": {
"format_id": format_id,
"url": url,
"item_selector": selection_format_id,
},
"_selection_args": None,
}
selection_args: List[str] = ["-format", selection_format_id]
# Use ytdlp helper to format for table
format_dict = format_for_table_selection(
fmt,
url,
idx,
selection_format_id=selection_format_id,
)
# Add base command for display
format_dict["cmd"] = base_cmd
# Append clip values to selection args if needed
selection_args: List[str] = format_dict["_selection_args"].copy()
try:
if (not clip_spec) and clip_values:
selection_args.extend(["-query", f"clip:{','.join([v for v in clip_values if v])}"])
except Exception:
pass
format_dict["_selection_args"] = selection_args
# Also update in full_metadata for provider registration
format_dict["full_metadata"]["_selection_args"] = selection_args
results_list.append(format_dict)
table.add_result(format_dict)
@@ -2470,6 +2424,9 @@ class Download_File(Cmdlet):
setattr(table, "_rendered_by_cmdlet", True)
pipeline_context.set_current_stage_table(table)
pipeline_context.set_last_result_table(table, results_list)
debug(f"[ytdlp.formatlist] Format table registered with {len(results_list)} formats")
debug(f"[ytdlp.formatlist] When user selects @N, will invoke: download-file {url} -format <format_id>")
log(f"", file=sys.stderr)
return 0
@@ -3675,6 +3632,27 @@ class Download_File(Cmdlet):
raw_url = self._normalize_urls(parsed)
piped_items = self._collect_piped_items_if_no_urls(result, raw_url)
# Handle TABLE_AUTO_STAGES routing: if a piped PipeObject has _selection_args,
# re-invoke download-file with those args instead of processing the PipeObject itself
if piped_items and not raw_url:
for item in piped_items:
try:
if hasattr(item, 'metadata') and isinstance(item.metadata, dict):
selection_args = item.metadata.get('_selection_args')
if selection_args and isinstance(selection_args, (list, tuple)):
# Found selection args - extract URL and re-invoke with format args
item_url = getattr(item, 'url', None) or item.metadata.get('url')
if item_url:
debug(f"[ytdlp] Detected selection args from table selection: {selection_args}")
# Reconstruct args: URL + selection args
new_args = [str(item_url)] + [str(arg) for arg in selection_args]
debug(f"[ytdlp] Re-invoking download-file with: {new_args}")
# Recursively call _run_impl with the new args
return self._run_impl(None, new_args, config)
except Exception as e:
debug(f"[ytdlp] Error handling selection args: {e}")
pass
had_piped_input = False
try:
if isinstance(result, list):
@@ -3962,13 +3940,21 @@ class Download_File(Cmdlet):
log(f"Invalid storage location: {e}", file=sys.stderr)
return None
# Priority 2: Config default output/temp directory
# Priority 2: Config default output/temp directory, then OS temp
try:
from SYS.config import resolve_output_dir
final_output_dir = resolve_output_dir(config)
except Exception:
final_output_dir = Path.home() / "Downloads"
final_output_dir = None
# If config resolution failed, use OS temp directory
if not final_output_dir:
try:
import tempfile
final_output_dir = Path(tempfile.gettempdir()) / "Medios-Macina"
except Exception:
final_output_dir = Path.home() / ".Medios-Macina-temp"
debug(f"Using default directory: {final_output_dir}")

View File

@@ -556,6 +556,33 @@ class search_file(Cmdlet):
library_root = get_local_storage_path(config or {})
if not library_root:
log("No library root configured", file=sys.stderr)
log("", file=sys.stderr)
# Show config panel for FolderStore
try:
from SYS.rich_display import show_store_config_panel
show_store_config_panel("folder", ["NAME", "PATH"])
log("", file=sys.stderr)
except Exception:
log("Example config for FolderStore:", file=sys.stderr)
log("[store=folder]", file=sys.stderr)
log('NAME="default"', file=sys.stderr)
log('PATH="/path/to/library"', file=sys.stderr)
log("", file=sys.stderr)
# Show config panel for HydrusNetworkStore
try:
from SYS.rich_display import show_store_config_panel
show_store_config_panel("hydrusnetwork", ["NAME", "API", "URL"])
log("", file=sys.stderr)
except Exception:
log("Example config for HydrusNetworkStore:", file=sys.stderr)
log("[store=hydrusnetwork]", file=sys.stderr)
log('NAME="default"', file=sys.stderr)
log('API="your-api-key"', file=sys.stderr)
log('URL="http://localhost:45869"', file=sys.stderr)
log("", file=sys.stderr)
return 1
# Use context manager to ensure database is always closed