df
Some checks failed
smoke-mm / Install & smoke test mm --help (push) Has been cancelled
Some checks failed
smoke-mm / Install & smoke test mm --help (push) Has been cancelled
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
"""search-provider cmdlet: Search external providers (bandcamp, libgen, soulseek, youtube, alldebrid)."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import Any, Dict, List, Sequence, Optional
|
||||
@@ -25,37 +26,54 @@ try:
|
||||
except Exception: # pragma: no cover
|
||||
get_local_storage_path = None # type: ignore
|
||||
|
||||
|
||||
class Search_Provider(Cmdlet):
|
||||
"""Search external content providers."""
|
||||
|
||||
|
||||
def __init__(self):
|
||||
super().__init__(
|
||||
name="search-provider",
|
||||
summary="Search external providers (bandcamp, libgen, soulseek, youtube, alldebrid, loc, internetarchive)",
|
||||
usage="search-provider -provider <provider> <query> [-limit N] [-open ID]",
|
||||
arg=[
|
||||
CmdletArg("provider", type="string", required=True, description="Provider name: bandcamp, libgen, soulseek, youtube, alldebrid, loc, internetarchive"),
|
||||
CmdletArg("query", type="string", required=True, description="Search query (supports provider-specific syntax)"),
|
||||
CmdletArg("limit", type="int", description="Maximum results to return (default: 50)"),
|
||||
CmdletArg("open", type="int", description="(alldebrid) Open folder/magnet by ID and list its files"),
|
||||
CmdletArg(
|
||||
"provider",
|
||||
type="string",
|
||||
required=True,
|
||||
description="Provider name: bandcamp, libgen, soulseek, youtube, alldebrid, loc, internetarchive",
|
||||
),
|
||||
CmdletArg(
|
||||
"query",
|
||||
type="string",
|
||||
required=True,
|
||||
description="Search query (supports provider-specific syntax)",
|
||||
),
|
||||
CmdletArg(
|
||||
"limit", type="int", description="Maximum results to return (default: 50)"
|
||||
),
|
||||
CmdletArg(
|
||||
"open",
|
||||
type="int",
|
||||
description="(alldebrid) Open folder/magnet by ID and list its files",
|
||||
),
|
||||
],
|
||||
detail=[
|
||||
"Search external content providers:",
|
||||
"- alldebrid: List your AllDebrid account folders (magnets). Select @N to view files.",
|
||||
" Example: search-provider -provider alldebrid \"*\"",
|
||||
" Example: search-provider -provider alldebrid -open 123 \"*\"",
|
||||
' Example: search-provider -provider alldebrid "*"',
|
||||
' Example: search-provider -provider alldebrid -open 123 "*"',
|
||||
"- bandcamp: Search for music albums/tracks",
|
||||
" Example: search-provider -provider bandcamp \"artist:altrusian grace\"",
|
||||
' Example: search-provider -provider bandcamp "artist:altrusian grace"',
|
||||
"- libgen: Search Library Genesis for books",
|
||||
" Example: search-provider -provider libgen \"python programming\"",
|
||||
' Example: search-provider -provider libgen "python programming"',
|
||||
"- loc: Search Library of Congress (Chronicling America)",
|
||||
" Example: search-provider -provider loc \"lincoln\"",
|
||||
' Example: search-provider -provider loc "lincoln"',
|
||||
"- soulseek: Search P2P network for music",
|
||||
" Example: search-provider -provider soulseek \"pink floyd\"",
|
||||
' Example: search-provider -provider soulseek "pink floyd"',
|
||||
"- youtube: Search YouTube for videos",
|
||||
" Example: search-provider -provider youtube \"tutorial\"",
|
||||
' Example: search-provider -provider youtube "tutorial"',
|
||||
"- internetarchive: Search archive.org items (advancedsearch syntax)",
|
||||
" Example: search-provider -provider internetarchive \"title:(lincoln) AND mediatype:texts\"",
|
||||
' Example: search-provider -provider internetarchive "title:(lincoln) AND mediatype:texts"',
|
||||
"",
|
||||
"Query syntax:",
|
||||
"- bandcamp: Use 'artist:Name' to search by artist",
|
||||
@@ -65,12 +83,12 @@ class Search_Provider(Cmdlet):
|
||||
"- internetarchive: Archive.org advancedsearch query syntax",
|
||||
"",
|
||||
"Results can be piped to other cmdlet:",
|
||||
" search-provider -provider bandcamp \"artist:grace\" | @1 | download-file",
|
||||
' search-provider -provider bandcamp "artist:grace" | @1 | download-file',
|
||||
],
|
||||
exec=self.run
|
||||
exec=self.run,
|
||||
)
|
||||
self.register()
|
||||
|
||||
|
||||
def run(self, result: Any, args: Sequence[str], config: Dict[str, Any]) -> int:
|
||||
"""Execute search-provider cmdlet."""
|
||||
if should_show_help(args):
|
||||
@@ -81,7 +99,9 @@ class Search_Provider(Cmdlet):
|
||||
|
||||
# Dynamic flag variants from cmdlet arg definitions.
|
||||
flag_registry = self.build_flag_registry()
|
||||
provider_flags = {f.lower() for f in (flag_registry.get("provider") or {"-provider", "--provider"})}
|
||||
provider_flags = {
|
||||
f.lower() for f in (flag_registry.get("provider") or {"-provider", "--provider"})
|
||||
}
|
||||
query_flags = {f.lower() for f in (flag_registry.get("query") or {"-query", "--query"})}
|
||||
limit_flags = {f.lower() for f in (flag_registry.get("limit") or {"-limit", "--limit"})}
|
||||
open_flags = {f.lower() for f in (flag_registry.get("open") or {"-open", "--open"})}
|
||||
@@ -106,14 +126,20 @@ class Search_Provider(Cmdlet):
|
||||
try:
|
||||
limit = int(args_list[i + 1])
|
||||
except ValueError:
|
||||
log(f"Warning: Invalid limit value '{args_list[i + 1]}', using default 50", file=sys.stderr)
|
||||
log(
|
||||
f"Warning: Invalid limit value '{args_list[i + 1]}', using default 50",
|
||||
file=sys.stderr,
|
||||
)
|
||||
limit = 50
|
||||
i += 2
|
||||
elif low in open_flags and i + 1 < len(args_list):
|
||||
try:
|
||||
open_id = int(args_list[i + 1])
|
||||
except ValueError:
|
||||
log(f"Warning: Invalid open value '{args_list[i + 1]}', ignoring", file=sys.stderr)
|
||||
log(
|
||||
f"Warning: Invalid open value '{args_list[i + 1]}', ignoring",
|
||||
file=sys.stderr,
|
||||
)
|
||||
open_id = None
|
||||
i += 2
|
||||
elif not token.startswith("-"):
|
||||
@@ -139,9 +165,9 @@ class Search_Provider(Cmdlet):
|
||||
status = "✓" if available else "✗"
|
||||
log(f" {status} {name}", file=sys.stderr)
|
||||
return 1
|
||||
|
||||
|
||||
debug(f"[search-provider] provider={provider_name}, query={query}, limit={limit}")
|
||||
|
||||
|
||||
# Get provider
|
||||
provider = get_search_provider(provider_name, config)
|
||||
if not provider:
|
||||
@@ -160,6 +186,7 @@ class Search_Provider(Cmdlet):
|
||||
if library_root:
|
||||
try:
|
||||
from API.folder import API_folder_store
|
||||
|
||||
db = API_folder_store(library_root)
|
||||
except Exception:
|
||||
db = None
|
||||
@@ -178,6 +205,7 @@ class Search_Provider(Cmdlet):
|
||||
|
||||
results_list = []
|
||||
import result_table
|
||||
|
||||
importlib.reload(result_table)
|
||||
from result_table import ResultTable
|
||||
|
||||
@@ -190,7 +218,9 @@ class Search_Provider(Cmdlet):
|
||||
elif provider_lower == "loc":
|
||||
provider_label = "LoC"
|
||||
else:
|
||||
provider_label = provider_text[:1].upper() + provider_text[1:] if provider_text else "Provider"
|
||||
provider_label = (
|
||||
provider_text[:1].upper() + provider_text[1:] if provider_text else "Provider"
|
||||
)
|
||||
|
||||
if provider_lower == "alldebrid" and open_id is not None:
|
||||
table_title = f"{provider_label} Files: {open_id}".strip().rstrip(":")
|
||||
@@ -205,7 +235,9 @@ class Search_Provider(Cmdlet):
|
||||
if provider_lower == "alldebrid":
|
||||
if open_id is not None:
|
||||
# Second-stage: show files for selected folder/magnet.
|
||||
results = provider.search(query, limit=limit, filters={"view": "files", "magnet_id": open_id})
|
||||
results = provider.search(
|
||||
query, limit=limit, filters={"view": "files", "magnet_id": open_id}
|
||||
)
|
||||
else:
|
||||
# Default: show folders (magnets) so user can select @N.
|
||||
results = provider.search(query, limit=limit, filters={"view": "folders"})
|
||||
@@ -222,7 +254,11 @@ class Search_Provider(Cmdlet):
|
||||
|
||||
# Emit results for pipeline
|
||||
for search_result in results:
|
||||
item_dict = search_result.to_dict() if hasattr(search_result, "to_dict") else dict(search_result)
|
||||
item_dict = (
|
||||
search_result.to_dict()
|
||||
if hasattr(search_result, "to_dict")
|
||||
else dict(search_result)
|
||||
)
|
||||
|
||||
# Ensure table field is set (should be by provider, but just in case)
|
||||
if "table" not in item_dict:
|
||||
@@ -233,13 +269,18 @@ class Search_Provider(Cmdlet):
|
||||
|
||||
# For AllDebrid folder rows, allow @N to open and show files.
|
||||
try:
|
||||
if provider_lower == "alldebrid" and getattr(search_result, "media_kind", "") == "folder":
|
||||
if (
|
||||
provider_lower == "alldebrid"
|
||||
and getattr(search_result, "media_kind", "") == "folder"
|
||||
):
|
||||
magnet_id = None
|
||||
meta = getattr(search_result, "full_metadata", None)
|
||||
if isinstance(meta, dict):
|
||||
magnet_id = meta.get("magnet_id")
|
||||
if magnet_id is not None:
|
||||
table.set_row_selection_args(row_index, ["-open", str(magnet_id), "-query", "*"])
|
||||
table.set_row_selection_args(
|
||||
row_index, ["-open", str(magnet_id), "-query", "*"]
|
||||
)
|
||||
except Exception:
|
||||
pass
|
||||
results_list.append(item_dict)
|
||||
|
||||
Reference in New Issue
Block a user