huge refactor of the entire codebase, with the goal of improving maintainability, readability, and extensibility. This commit includes changes to almost every file in the project, including:

This commit is contained in:
2026-04-19 00:41:09 -07:00
parent d9e736172a
commit bafd37fdfb
50 changed files with 3258 additions and 4177 deletions
+31 -85
View File
@@ -15,7 +15,7 @@ from urllib.parse import urlparse, parse_qs, unquote, urljoin
from SYS.logger import log, debug
from SYS.payload_builders import build_file_result_payload, normalize_file_extension
from ProviderCore.registry import get_search_provider, list_search_providers
from ProviderCore.registry import get_search_plugin, list_search_plugins
from SYS.rich_display import (
show_provider_config_panel,
show_store_config_panel,
@@ -169,8 +169,8 @@ class search_file(Cmdlet):
def __init__(self) -> None:
super().__init__(
name="search-file",
summary="Search storage backends (Hydrus) or external providers (via -provider).",
usage="search-file [-query <query>] [-store BACKEND] [-limit N] [-provider NAME]",
summary="Search storage backends (Hydrus) or external plugins (via -plugin).",
usage="search-file [-query <query>] [-store BACKEND] [-limit N] [-plugin NAME]",
arg=[
CmdletArg(
"limit",
@@ -179,11 +179,7 @@ class search_file(Cmdlet):
),
SharedArgs.STORE,
SharedArgs.QUERY,
CmdletArg(
"provider",
type="string",
description="External provider name (e.g., tidal, youtube, soulseek, etc)",
),
SharedArgs.PLUGIN,
CmdletArg(
"open",
type="integer",
@@ -209,10 +205,10 @@ class search_file(Cmdlet):
"search-file 'example.com/path' -query 'ext:pdf' # Web: site:example.com filetype:pdf",
"search-file -query 'site:example.com filetype:epub history' # Web: site-scoped search",
"",
"Provider search (-provider):",
"search-file -provider youtube 'tutorial' # Search YouTube provider",
"search-file -provider alldebrid '*' # List AllDebrid magnets",
"search-file -provider alldebrid -open 123 '*' # Show files for a magnet",
"Plugin search (-plugin):",
"search-file -plugin youtube 'tutorial' # Search YouTube plugin",
"search-file -plugin alldebrid '*' # List AllDebrid magnets",
"search-file -plugin alldebrid -open 123 '*' # Show files for a magnet",
],
exec=self.run,
)
@@ -1451,10 +1447,10 @@ class search_file(Cmdlet):
self._set_storage_display_columns(payload)
return payload
def _run_provider_search(
def _run_plugin_search(
self,
*,
provider_name: str,
plugin_name: str,
query: str,
limit: int,
limit_set: bool,
@@ -1463,9 +1459,9 @@ class search_file(Cmdlet):
refresh_mode: bool,
config: Dict[str, Any],
) -> int:
"""Execute external provider search."""
"""Execute external plugin search."""
if not provider_name or not query:
if not plugin_name or not query:
from SYS import pipeline as ctx_mod
progress = None
if hasattr(ctx_mod, "get_pipeline_state"):
@@ -1476,10 +1472,10 @@ class search_file(Cmdlet):
except Exception:
pass
log("Error: search-file -provider requires both provider and query", file=sys.stderr)
log("Error: search-file -plugin requires both plugin and query", file=sys.stderr)
log(f"Usage: {self.usage}", file=sys.stderr)
providers_map = list_search_providers(config)
providers_map = list_search_plugins(config)
available = [n for n, a in providers_map.items() if a]
unconfigured = [n for n, a in providers_map.items() if not a]
@@ -1500,7 +1496,7 @@ class search_file(Cmdlet):
if hasattr(ctx_mod, "get_pipeline_state"):
progress = ctx_mod.get_pipeline_state().live_progress
provider = get_search_provider(provider_name, config)
provider = get_search_plugin(plugin_name, config)
if not provider:
if progress:
try:
@@ -1508,9 +1504,9 @@ class search_file(Cmdlet):
except Exception:
pass
show_provider_config_panel([provider_name])
show_provider_config_panel([plugin_name])
providers_map = list_search_providers(config)
providers_map = list_search_plugins(config)
available = [n for n, a in providers_map.items() if a]
if available:
show_available_providers_panel(available)
@@ -1522,7 +1518,7 @@ class search_file(Cmdlet):
worker_id,
"search-file",
title=f"Search: {query}",
description=f"Provider: {provider_name}, Query: {query}",
description=f"Plugin: {plugin_name}, Query: {query}",
)
except Exception:
pass
@@ -1532,7 +1528,7 @@ class search_file(Cmdlet):
from SYS.result_table import Table
provider_text = str(provider_name or "").strip()
provider_text = str(plugin_name or "").strip()
provider_lower = provider_text.lower()
# Dynamic query/filter extraction via provider
@@ -1564,9 +1560,9 @@ class search_file(Cmdlet):
source_cmd, source_args = provider.get_source_command(args_list)
table.set_source_command(source_cmd, source_args)
debug(f"[search-file] Calling {provider_name}.search(filters={search_filters})")
debug(f"[search-file] Calling {plugin_name}.search(filters={search_filters})")
results = provider.search(query, limit=limit, filters=search_filters or None)
debug(f"[search-file] {provider_name} -> {len(results or [])} result(s)")
debug(f"[search-file] {plugin_name} -> {len(results or [])} result(s)")
# Allow providers to apply provider-specific UX transforms (e.g. auto-expansion)
try:
@@ -1615,7 +1611,7 @@ class search_file(Cmdlet):
# Ensure provider source is present so downstream cmdlets (select) can resolve provider
if "source" not in item_dict:
item_dict["source"] = provider_name
item_dict["source"] = plugin_name
row_index = len(table.rows)
table.add_result(search_result)
@@ -1636,7 +1632,7 @@ class search_file(Cmdlet):
return 0
except Exception as exc:
log(f"Error searching provider '{provider_name}': {exc}", file=sys.stderr)
log(f"Error searching plugin '{plugin_name}': {exc}", file=sys.stderr)
import traceback
debug(traceback.format_exc())
@@ -1728,9 +1724,9 @@ class search_file(Cmdlet):
f.lower()
for f in (flag_registry.get("limit") or {"-limit", "--limit"})
}
provider_flags = {
plugin_flags = {
f.lower()
for f in (flag_registry.get("provider") or {"-provider", "--provider"})
for f in (flag_registry.get("plugin") or {"-plugin", "--plugin"})
}
open_flags = {
f.lower()
@@ -1740,7 +1736,7 @@ class search_file(Cmdlet):
# Parse arguments
query = ""
storage_backend: Optional[str] = None
provider_name: Optional[str] = None
plugin_name: Optional[str] = None
open_id: Optional[int] = None
limit = 100
limit_set = False
@@ -1756,8 +1752,8 @@ class search_file(Cmdlet):
query = f"{query} {chunk}".strip() if query else chunk
i += 2
continue
if low in provider_flags and i + 1 < len(args_list):
provider_name = args_list[i + 1]
if low in plugin_flags and i + 1 < len(args_list):
plugin_name = args_list[i + 1]
i += 2
continue
if low in open_flags and i + 1 < len(args_list):
@@ -1790,9 +1786,9 @@ class search_file(Cmdlet):
query = query.strip()
if provider_name:
return self._run_provider_search(
provider_name=provider_name,
if plugin_name:
return self._run_plugin_search(
plugin_name=plugin_name,
query=query,
limit=limit,
limit_set=limit_set,
@@ -1814,56 +1810,6 @@ class search_file(Cmdlet):
if store_filter and not storage_backend:
storage_backend = store_filter
# If the user accidentally used `-store <provider>` or `store:<provider>`,
# prefer to treat it as a provider search (providers like 'alldebrid' are not store backends).
try:
from Store.registry import list_configured_backend_names
providers_map = list_search_providers(config)
configured = list_configured_backend_names(config or {})
if storage_backend:
matched = None
storage_hint = self._normalize_lookup_target(storage_backend)
if storage_hint:
for p in (providers_map or {}):
if self._normalize_lookup_target(p) == storage_hint:
matched = p
break
if matched and str(storage_backend) not in configured:
log(f"Note: Treating '-store {storage_backend}' as provider search for '{matched}'", file=sys.stderr)
return self._run_provider_search(
provider_name=matched,
query=query,
limit=limit,
limit_set=limit_set,
open_id=open_id,
args_list=args_list,
refresh_mode=refresh_mode,
config=config,
)
elif store_filter:
matched = None
store_hint = self._normalize_lookup_target(store_filter)
if store_hint:
for p in (providers_map or {}):
if self._normalize_lookup_target(p) == store_hint:
matched = p
break
if matched and str(store_filter) not in configured:
log(f"Note: Treating 'store:{store_filter}' as provider search for '{matched}'", file=sys.stderr)
return self._run_provider_search(
provider_name=matched,
query=query,
limit=limit,
limit_set=limit_set,
open_id=open_id,
args_list=args_list,
refresh_mode=refresh_mode,
config=config,
)
except Exception:
# Be conservative: if provider detection fails, fall back to store behaviour
pass
hash_query = parse_hash_query(query)
web_plan = self._build_web_search_plan(