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:
+58
-26
@@ -74,34 +74,9 @@ def ping_url(url: str, timeout: float = 3.0) -> tuple[bool, str]:
|
||||
|
||||
def provider_display_name(key: str) -> str:
|
||||
label = (key or "").strip()
|
||||
lower = label.lower()
|
||||
if lower == "openlibrary":
|
||||
return "OpenLibrary"
|
||||
if lower == "alldebrid":
|
||||
return "AllDebrid"
|
||||
if lower == "youtube":
|
||||
return "YouTube"
|
||||
return label[:1].upper() + label[1:] if label else "Provider"
|
||||
|
||||
|
||||
def default_provider_ping_targets(provider_key: str) -> list[str]:
|
||||
provider = (provider_key or "").strip().lower()
|
||||
if provider == "openlibrary":
|
||||
return ["https://openlibrary.org"]
|
||||
if provider == "youtube":
|
||||
return ["https://www.youtube.com"]
|
||||
if provider == "bandcamp":
|
||||
return ["https://bandcamp.com"]
|
||||
if provider == "libgen":
|
||||
try:
|
||||
from Provider.libgen import MIRRORS
|
||||
|
||||
return [str(url).rstrip("/") + "/json.php" for url in (MIRRORS or []) if str(url).strip()]
|
||||
except ImportError:
|
||||
return []
|
||||
return []
|
||||
|
||||
|
||||
def ping_first(urls: list[str]) -> tuple[bool, str]:
|
||||
for url in urls:
|
||||
ok, detail = ping_url(url)
|
||||
@@ -109,4 +84,61 @@ def ping_first(urls: list[str]) -> tuple[bool, str]:
|
||||
return True, detail
|
||||
if urls:
|
||||
return ping_url(urls[0])
|
||||
return False, "No ping target"
|
||||
return False, "No ping target"
|
||||
|
||||
|
||||
def collect_plugin_startup_checks(config: dict) -> list[dict[str, Any]]:
|
||||
provider_cfg = config.get("provider") if isinstance(config, dict) else None
|
||||
if not isinstance(provider_cfg, dict) or not provider_cfg:
|
||||
return []
|
||||
|
||||
try:
|
||||
from ProviderCore.registry import get_plugin_class
|
||||
except Exception:
|
||||
return []
|
||||
|
||||
checks: list[dict[str, Any]] = []
|
||||
for plugin_name in provider_cfg.keys():
|
||||
plugin_key = str(plugin_name or "").strip().lower()
|
||||
if not plugin_key:
|
||||
continue
|
||||
|
||||
plugin_class = None
|
||||
try:
|
||||
plugin_class = get_plugin_class(plugin_key)
|
||||
except Exception:
|
||||
plugin_class = None
|
||||
|
||||
if plugin_class is None:
|
||||
checks.append(
|
||||
{
|
||||
"status": "UNKNOWN",
|
||||
"name": provider_display_name(plugin_key),
|
||||
"plugin": plugin_key,
|
||||
"detail": "Not registered",
|
||||
}
|
||||
)
|
||||
continue
|
||||
|
||||
try:
|
||||
plugin = plugin_class(config)
|
||||
summary = plugin.status_summary()
|
||||
except Exception as exc:
|
||||
summary = {
|
||||
"status": "DISABLED",
|
||||
"name": provider_display_name(plugin_key),
|
||||
"plugin": plugin_key,
|
||||
"detail": str(exc),
|
||||
}
|
||||
|
||||
checks.append(
|
||||
{
|
||||
"status": str(summary.get("status") or "UNKNOWN"),
|
||||
"name": str(summary.get("name") or provider_display_name(plugin_key)),
|
||||
"plugin": str(summary.get("plugin") or plugin_key),
|
||||
"detail": str(summary.get("detail") or ""),
|
||||
"files": summary.get("files"),
|
||||
}
|
||||
)
|
||||
|
||||
return checks
|
||||
+49
-74
@@ -15,6 +15,7 @@ from SYS.result_table import Table
|
||||
from SYS.item_accessors import get_sha256_hex
|
||||
from SYS.utils import extract_hydrus_hash_from_url
|
||||
from SYS import pipeline as ctx
|
||||
from ProviderCore.registry import get_plugin, get_plugin_for_url
|
||||
from cmdnat._parsing import (
|
||||
extract_arg_value,
|
||||
extract_piped_value as _extract_piped_value,
|
||||
@@ -29,6 +30,29 @@ _MATRIX_MENU_STATE_KEY = "matrix_menu_state"
|
||||
_MATRIX_SELECTED_SETTING_KEY_KEY = "matrix_selected_setting_key"
|
||||
|
||||
|
||||
def _get_matrix_provider(config: Dict[str, Any]) -> Any:
|
||||
provider = get_plugin("matrix", config)
|
||||
if provider is None:
|
||||
raise RuntimeError("Matrix plugin is not registered")
|
||||
return provider
|
||||
|
||||
|
||||
def _resolve_plugin_url(url: str, config: Dict[str, Any]) -> str:
|
||||
target = str(url or "").strip()
|
||||
if not target:
|
||||
return target
|
||||
|
||||
provider = get_plugin_for_url(target, config)
|
||||
if provider is None:
|
||||
return target
|
||||
|
||||
try:
|
||||
resolved = provider.resolve_url(target)
|
||||
except Exception:
|
||||
return target
|
||||
return str(resolved or target)
|
||||
|
||||
|
||||
def _extract_set_value_arg(args: Sequence[str]) -> Optional[str]:
|
||||
"""Extract the value from -set-value flag."""
|
||||
return extract_arg_value(args, flags={"-set-value"})
|
||||
@@ -212,35 +236,11 @@ def _resolve_room_identifier(value: str, config: Dict[str, Any]) -> Optional[str
|
||||
conf_ids = _parse_config_room_filter_ids(config)
|
||||
if conf_ids:
|
||||
# Attempt to fetch names for the configured IDs
|
||||
try:
|
||||
from Provider.matrix import Matrix
|
||||
# Avoid __init__ network failures by requiring homeserver+token to exist
|
||||
block = config.get("provider", {}).get("matrix", {})
|
||||
if block and block.get("homeserver") and block.get("access_token"):
|
||||
try:
|
||||
m = Matrix(config)
|
||||
rooms = m.list_rooms(room_ids=conf_ids)
|
||||
for room in rooms or []:
|
||||
name = str(room.get("name") or "").strip()
|
||||
rid = str(room.get("room_id") or "").strip()
|
||||
if name and name.lower() == cand.lower():
|
||||
return rid
|
||||
if name and cand.lower() in name.lower():
|
||||
return rid
|
||||
except Exception:
|
||||
# Best-effort; fallback below
|
||||
pass
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
# Last resort: attempt to ask the server for matching rooms (if possible)
|
||||
try:
|
||||
from Provider.matrix import Matrix
|
||||
block = config.get("provider", {}).get("matrix", {})
|
||||
if block and block.get("homeserver") and block.get("access_token"):
|
||||
try:
|
||||
m = Matrix(config)
|
||||
rooms = m.list_rooms()
|
||||
m = _get_matrix_provider(config)
|
||||
rooms = m.list_rooms(room_ids=conf_ids)
|
||||
for room in rooms or []:
|
||||
name = str(room.get("name") or "").strip()
|
||||
rid = str(room.get("room_id") or "").strip()
|
||||
@@ -250,8 +250,22 @@ def _resolve_room_identifier(value: str, config: Dict[str, Any]) -> Optional[str
|
||||
return rid
|
||||
except Exception:
|
||||
pass
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
# Last resort: attempt to ask the server for matching rooms (if possible)
|
||||
block = config.get("provider", {}).get("matrix", {})
|
||||
if block and block.get("homeserver") and block.get("access_token"):
|
||||
try:
|
||||
m = _get_matrix_provider(config)
|
||||
rooms = m.list_rooms()
|
||||
for room in rooms or []:
|
||||
name = str(room.get("name") or "").strip()
|
||||
rid = str(room.get("room_id") or "").strip()
|
||||
if name and name.lower() == cand.lower():
|
||||
return rid
|
||||
if name and cand.lower() in name.lower():
|
||||
return rid
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
return None
|
||||
except Exception:
|
||||
@@ -270,10 +284,8 @@ def _send_pending_to_rooms(config: Dict[str, Any], room_ids: List[str], args: Se
|
||||
log("No pending items to upload (use: @N | .matrix)", file=sys.stderr)
|
||||
return 1
|
||||
|
||||
from Provider.matrix import Matrix
|
||||
|
||||
try:
|
||||
provider = Matrix(config)
|
||||
provider = _get_matrix_provider(config)
|
||||
except Exception as exc:
|
||||
log(f"Matrix not available: {exc}", file=sys.stderr)
|
||||
return 1
|
||||
@@ -585,35 +597,6 @@ def _maybe_download_hydrus_file(item: Any,
|
||||
return None
|
||||
|
||||
|
||||
def _maybe_unlock_alldebrid_url(url: str, config: Dict[str, Any]) -> str:
|
||||
try:
|
||||
parsed = urlparse(url)
|
||||
host = (parsed.netloc or "").lower()
|
||||
if host != "alldebrid.com":
|
||||
return url
|
||||
if not (parsed.path or "").startswith("/f/"):
|
||||
return url
|
||||
|
||||
try:
|
||||
from Provider.alldebrid import _get_debrid_api_key # type: ignore
|
||||
|
||||
api_key = _get_debrid_api_key(config or {})
|
||||
except Exception:
|
||||
api_key = None
|
||||
if not api_key:
|
||||
return url
|
||||
|
||||
from API.alldebrid import AllDebridClient
|
||||
|
||||
client = AllDebridClient(str(api_key))
|
||||
unlocked = client.unlock_link(url)
|
||||
if isinstance(unlocked, str) and unlocked.strip():
|
||||
return unlocked.strip()
|
||||
except Exception:
|
||||
pass
|
||||
return url
|
||||
|
||||
|
||||
def _resolve_upload_path(item: Any, config: Dict[str, Any]) -> Optional[str]:
|
||||
"""Resolve a usable local file path for uploading.
|
||||
|
||||
@@ -645,7 +628,7 @@ def _resolve_upload_path(item: Any, config: Dict[str, Any]) -> Optional[str]:
|
||||
return None
|
||||
|
||||
# Best-effort: unlock AllDebrid file links (they require auth and aren't directly downloadable).
|
||||
url = _maybe_unlock_alldebrid_url(url, config)
|
||||
url = _resolve_plugin_url(url, config)
|
||||
|
||||
try:
|
||||
from API.HTTP import _download_direct_file
|
||||
@@ -851,10 +834,8 @@ def _handle_settings_edit(result: Any, args: Sequence[str], config: Dict[str, An
|
||||
|
||||
def _handle_settings_test(config: Dict[str, Any]) -> int:
|
||||
"""Test Matrix credentials and prompt for default rooms upon success."""
|
||||
from Provider.matrix import Matrix
|
||||
|
||||
try:
|
||||
provider = Matrix(config)
|
||||
provider = _get_matrix_provider(config)
|
||||
except Exception as exc:
|
||||
log(f"Matrix test failed: {exc}", file=sys.stderr)
|
||||
return 1
|
||||
@@ -863,13 +844,11 @@ def _handle_settings_test(config: Dict[str, Any]) -> int:
|
||||
return _show_default_room_picker(config, provider=provider)
|
||||
|
||||
|
||||
def _show_default_room_picker(config: Dict[str, Any], *, provider: Optional["Matrix"] = None) -> int:
|
||||
def _show_default_room_picker(config: Dict[str, Any], *, provider: Optional[Any] = None) -> int:
|
||||
"""Display joined rooms so the user can select defaults for sharing."""
|
||||
from Provider.matrix import Matrix
|
||||
|
||||
try:
|
||||
if provider is None:
|
||||
provider = Matrix(config)
|
||||
provider = _get_matrix_provider(config)
|
||||
except Exception as exc:
|
||||
log(f"Matrix not available: {exc}", file=sys.stderr)
|
||||
return 1
|
||||
@@ -977,10 +956,8 @@ def _handle_settings_rooms(result: Any, args: Sequence[str], config: Dict[str, A
|
||||
|
||||
def _show_rooms_table(config: Dict[str, Any]) -> int:
|
||||
"""Display rooms (refactored original behavior)."""
|
||||
from Provider.matrix import Matrix
|
||||
|
||||
try:
|
||||
provider = Matrix(config)
|
||||
provider = _get_matrix_provider(config)
|
||||
except Exception as exc:
|
||||
log(f"Matrix not available: {exc}", file=sys.stderr)
|
||||
return 1
|
||||
@@ -1121,10 +1098,8 @@ def _run(result: Any, args: Sequence[str], config: Dict[str, Any]) -> int:
|
||||
log("No pending items to upload (use: @N | .matrix)", file=sys.stderr)
|
||||
return 1
|
||||
|
||||
from Provider.matrix import Matrix
|
||||
|
||||
try:
|
||||
provider = Matrix(config)
|
||||
provider = _get_matrix_provider(config)
|
||||
except Exception as exc:
|
||||
log(f"Matrix not available: {exc}", file=sys.stderr)
|
||||
return 1
|
||||
|
||||
+75
-67
@@ -10,17 +10,15 @@ from datetime import datetime, timedelta
|
||||
from urllib.parse import urlparse, parse_qs
|
||||
from pathlib import Path
|
||||
from SYS.cmdlet_spec import Cmdlet, CmdletArg, parse_cmdlet_args
|
||||
from Provider.tidal_manifest import resolve_tidal_manifest_path
|
||||
from ProviderCore.registry import get_plugin_for_url
|
||||
from SYS.logger import debug, get_thread_stream, is_debug_enabled, set_debug, set_thread_stream
|
||||
from SYS.result_table import Table
|
||||
from MPV.mpv_ipc import MPV
|
||||
from SYS import pipeline as ctx
|
||||
from SYS.models import PipeObject
|
||||
|
||||
from SYS.config import get_hydrus_access_key, get_hydrus_url
|
||||
from SYS.config import get_hydrus_access_key, get_hydrus_url, resolve_cookies_path
|
||||
|
||||
_ALLDEBRID_UNLOCK_CACHE: Dict[str,
|
||||
str] = {}
|
||||
_NOTES_PREFETCH_INFLIGHT: set[str] = set()
|
||||
_NOTES_PREFETCH_LOCK = threading.Lock()
|
||||
_PLAYLIST_STORE_CACHE: Optional[Dict[str, Any]] = None
|
||||
@@ -478,73 +476,85 @@ def _try_enable_mpv_file_logging(mpv_log_path: str, *, attempts: int = 3) -> boo
|
||||
return bool(ok)
|
||||
|
||||
|
||||
def _get_alldebrid_api_key(config: Optional[Dict[str, Any]]) -> Optional[str]:
|
||||
def _iter_plugin_targets(item: Any) -> List[str]:
|
||||
values: List[str] = []
|
||||
seen: set[str] = set()
|
||||
|
||||
def _add(candidate: Any) -> None:
|
||||
text = str(candidate or "").strip()
|
||||
if not text or text in seen:
|
||||
return
|
||||
seen.add(text)
|
||||
values.append(text)
|
||||
|
||||
try:
|
||||
if not isinstance(config, dict):
|
||||
return None
|
||||
provider_cfg = config.get("provider")
|
||||
if not isinstance(provider_cfg, dict):
|
||||
return None
|
||||
ad_cfg = provider_cfg.get("alldebrid")
|
||||
if not isinstance(ad_cfg, dict):
|
||||
return None
|
||||
key = ad_cfg.get("api_key")
|
||||
if not isinstance(key, str):
|
||||
return None
|
||||
key = key.strip()
|
||||
return key or None
|
||||
if isinstance(item, dict):
|
||||
_add(item.get("path"))
|
||||
_add(item.get("url"))
|
||||
_add(item.get("source_url"))
|
||||
_add(item.get("target"))
|
||||
metadata = item.get("full_metadata") or item.get("metadata")
|
||||
else:
|
||||
_add(getattr(item, "path", None))
|
||||
_add(getattr(item, "url", None))
|
||||
_add(getattr(item, "source_url", None))
|
||||
_add(getattr(item, "target", None))
|
||||
metadata = getattr(item, "full_metadata", None) or getattr(item, "metadata", None)
|
||||
if isinstance(metadata, dict):
|
||||
_add(metadata.get("url"))
|
||||
_add(metadata.get("webpage_url"))
|
||||
_add(metadata.get("source_url"))
|
||||
extra = item.get("extra") if isinstance(item, dict) else getattr(item, "extra", None)
|
||||
if isinstance(extra, dict):
|
||||
_add(extra.get("url"))
|
||||
_add(extra.get("source_url"))
|
||||
except Exception:
|
||||
return None
|
||||
return values
|
||||
|
||||
return values
|
||||
|
||||
|
||||
def _is_alldebrid_protected_url(url: str) -> bool:
|
||||
def _resolve_plugin_url(url: str, config: Optional[Dict[str, Any]]) -> str:
|
||||
target = str(url or "").strip()
|
||||
if not target:
|
||||
return target
|
||||
|
||||
try:
|
||||
if not isinstance(url, str):
|
||||
return False
|
||||
u = url.strip()
|
||||
if not u.startswith(("http://", "https://")):
|
||||
return False
|
||||
p = urlparse(u)
|
||||
host = (p.netloc or "").lower()
|
||||
path = p.path or ""
|
||||
# AllDebrid file page links (require auth; not directly streamable by mpv)
|
||||
return host == "alldebrid.com" and path.startswith("/f/")
|
||||
plugin = get_plugin_for_url(target, config or {})
|
||||
except Exception:
|
||||
return False
|
||||
|
||||
|
||||
def _maybe_unlock_alldebrid_url(url: str, config: Optional[Dict[str, Any]]) -> str:
|
||||
"""Convert AllDebrid protected file URLs into direct streamable links.
|
||||
|
||||
When AllDebrid returns `https://alldebrid.com/f/...`, that URL typically requires
|
||||
authentication. MPV cannot access it without credentials. We transparently call
|
||||
the AllDebrid API `link/unlock` (using the configured API key) to obtain a direct
|
||||
URL that MPV can stream.
|
||||
"""
|
||||
if not _is_alldebrid_protected_url(url):
|
||||
return url
|
||||
|
||||
cached = _ALLDEBRID_UNLOCK_CACHE.get(url)
|
||||
if isinstance(cached, str) and cached:
|
||||
return cached
|
||||
|
||||
api_key = _get_alldebrid_api_key(config)
|
||||
if not api_key:
|
||||
return url
|
||||
plugin = None
|
||||
if plugin is None:
|
||||
return target
|
||||
|
||||
try:
|
||||
from API.alldebrid import AllDebridClient
|
||||
resolved = plugin.resolve_url(target)
|
||||
except Exception as exc:
|
||||
debug(f"Plugin URL resolution failed for {target}: {exc}", file=sys.stderr)
|
||||
return target
|
||||
|
||||
client = AllDebridClient(api_key)
|
||||
unlocked = client.unlock_link(url)
|
||||
if isinstance(unlocked, str) and unlocked.strip():
|
||||
unlocked = unlocked.strip()
|
||||
_ALLDEBRID_UNLOCK_CACHE[url] = unlocked
|
||||
return unlocked
|
||||
except Exception as e:
|
||||
debug(f"AllDebrid unlock failed for MPV target: {e}", file=sys.stderr)
|
||||
return str(resolved or target)
|
||||
|
||||
return url
|
||||
|
||||
def _resolve_plugin_playback_path(item: Any, config: Optional[Dict[str, Any]]) -> Optional[str]:
|
||||
for candidate in _iter_plugin_targets(item):
|
||||
try:
|
||||
plugin = get_plugin_for_url(candidate, config or {})
|
||||
except Exception:
|
||||
plugin = None
|
||||
if plugin is None:
|
||||
continue
|
||||
|
||||
try:
|
||||
resolved = plugin.resolve_playback_path(item)
|
||||
except Exception as exc:
|
||||
debug(f"Plugin playback-path resolution failed for {candidate}: {exc}", file=sys.stderr)
|
||||
continue
|
||||
|
||||
text = str(resolved or "").strip()
|
||||
if text:
|
||||
return text
|
||||
|
||||
return None
|
||||
|
||||
|
||||
def _ensure_lyric_overlay(mpv: MPV) -> None:
|
||||
@@ -1078,9 +1088,7 @@ def _ensure_ytdl_cookies(config: Optional[Dict[str, Any]] = None) -> None:
|
||||
|
||||
cookies_path = None
|
||||
try:
|
||||
from tool.ytdlp import YtDlpTool
|
||||
|
||||
cookiefile = YtDlpTool(config or {}).resolve_cookiefile()
|
||||
cookiefile = resolve_cookies_path(config or {})
|
||||
if cookiefile is not None:
|
||||
cookies_path = str(cookiefile)
|
||||
except Exception:
|
||||
@@ -1326,7 +1334,7 @@ def _get_playable_path(
|
||||
"none"}:
|
||||
path = None
|
||||
|
||||
manifest_path = resolve_tidal_manifest_path(item)
|
||||
manifest_path = _resolve_plugin_playback_path(item, config)
|
||||
if manifest_path:
|
||||
path = manifest_path
|
||||
else:
|
||||
@@ -1542,7 +1550,7 @@ def _queue_items(
|
||||
# If the target is an AllDebrid protected file URL, unlock it to a direct link for MPV.
|
||||
try:
|
||||
if isinstance(target, str):
|
||||
target = _maybe_unlock_alldebrid_url(target, config)
|
||||
target = _resolve_plugin_url(target, config)
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
@@ -2591,7 +2599,7 @@ def _start_mpv(
|
||||
try:
|
||||
needs_mpd_whitelist = False
|
||||
for it in items or []:
|
||||
mpd = resolve_tidal_manifest_path(it)
|
||||
mpd = _resolve_plugin_playback_path(it, config)
|
||||
candidate = mpd
|
||||
if not candidate:
|
||||
if isinstance(it, dict):
|
||||
|
||||
+12
-79
@@ -4,18 +4,14 @@ import shutil
|
||||
from typing import Any, Dict, List
|
||||
|
||||
from SYS.cmdlet_spec import Cmdlet
|
||||
from SYS.config import resolve_cookies_path
|
||||
from SYS import pipeline as ctx
|
||||
from SYS.result_table import Table
|
||||
from SYS.logger import set_debug, debug
|
||||
from cmdnat._status_shared import (
|
||||
add_startup_check as _add_startup_check,
|
||||
default_provider_ping_targets as _default_provider_ping_targets,
|
||||
has_provider as _has_provider,
|
||||
collect_plugin_startup_checks as _collect_plugin_startup_checks,
|
||||
has_store_subtype as _has_store_subtype,
|
||||
has_tool as _has_tool,
|
||||
ping_first as _ping_first,
|
||||
ping_url as _ping_url,
|
||||
provider_display_name as _provider_display_name,
|
||||
)
|
||||
|
||||
CMDLET = Cmdlet(
|
||||
@@ -95,82 +91,19 @@ def _run(result: Any, args: List[str], config: Dict[str, Any]) -> int:
|
||||
detail = f"{uval} - {err or 'Unavailable'}"
|
||||
_add_startup_check(startup_table, status, nkey, store="hydrusnetwork", files=files, detail=detail)
|
||||
|
||||
# Providers
|
||||
pcfg = config.get("provider", {})
|
||||
if isinstance(pcfg, dict) and pcfg:
|
||||
from ProviderCore.registry import list_providers, list_search_providers, list_file_providers
|
||||
from Provider.metadata_provider import list_metadata_providers
|
||||
|
||||
p_avail = list_providers(config) or {}
|
||||
s_avail = list_search_providers(config) or {}
|
||||
f_avail = list_file_providers(config) or {}
|
||||
m_avail = list_metadata_providers(config) or {}
|
||||
debug(f"Provider registries: providers={list(p_avail.keys())}, search={list(s_avail.keys())}, file={list(f_avail.keys())}, metadata={list(m_avail.keys())}")
|
||||
|
||||
already = {"matrix"}
|
||||
for pname in pcfg.keys():
|
||||
prov = str(pname).lower()
|
||||
if prov in already: continue
|
||||
display = _provider_display_name(prov)
|
||||
|
||||
if prov == "alldebrid":
|
||||
try:
|
||||
from Provider.alldebrid import _get_debrid_api_key
|
||||
from API.alldebrid import AllDebridClient
|
||||
api_key = _get_debrid_api_key(config)
|
||||
debug(f"AllDebrid configured: api_key_present={bool(api_key)}")
|
||||
if not api_key:
|
||||
_add_startup_check(startup_table, "DISABLED", display, provider=prov, detail="Not configured")
|
||||
else:
|
||||
client = AllDebridClient(api_key)
|
||||
_add_startup_check(startup_table, "ENABLED", display, provider=prov, detail=getattr(client, "base_url", "Connected"))
|
||||
debug(f"AllDebrid client connected: base_url={getattr(client, 'base_url', 'unknown')}")
|
||||
except Exception as exc:
|
||||
_add_startup_check(startup_table, "DISABLED", display, provider=prov, detail=str(exc))
|
||||
debug(f"AllDebrid check failed: {exc}")
|
||||
already.add(prov)
|
||||
continue
|
||||
|
||||
is_known = prov in p_avail or prov in s_avail or prov in f_avail or prov in m_avail
|
||||
if not is_known:
|
||||
_add_startup_check(startup_table, "UNKNOWN", display, provider=prov, detail="Not registered")
|
||||
debug(f"Provider {prov} not registered")
|
||||
else:
|
||||
ok_val = p_avail.get(prov) or s_avail.get(prov) or f_avail.get(prov) or m_avail.get(prov)
|
||||
detail = "Configured" if ok_val else "Not configured"
|
||||
ping_targets = _default_provider_ping_targets(prov)
|
||||
if ping_targets:
|
||||
debug(f"Provider {prov} ping targets: {ping_targets}")
|
||||
pok, pdet = _ping_first(ping_targets)
|
||||
debug(f"Provider {prov} ping result: ok={pok}, detail={pdet}")
|
||||
detail = pdet if ok_val else f"{detail} | {pdet}"
|
||||
_add_startup_check(startup_table, "ENABLED" if ok_val else "DISABLED", display, provider=prov, detail=detail)
|
||||
already.add(prov)
|
||||
|
||||
# Matrix
|
||||
if _has_provider(config, "matrix"):
|
||||
try:
|
||||
from Provider.matrix import Matrix
|
||||
m_prov = Matrix(config)
|
||||
mcfg = config.get("provider", {}).get("matrix", {})
|
||||
hs = str(mcfg.get("homeserver") or "").strip()
|
||||
rid = str(mcfg.get("room_id") or "").strip()
|
||||
detail = f"{hs} room:{rid}"
|
||||
valid = False
|
||||
try:
|
||||
valid = bool(m_prov.validate())
|
||||
except Exception as exc:
|
||||
debug(f"Matrix validate failed: {exc}")
|
||||
_add_startup_check(startup_table, "ENABLED" if valid else "DISABLED", "Matrix", provider="matrix", detail=detail)
|
||||
debug(f"Matrix check: homeserver={hs}, room_id={rid}, validate={valid}")
|
||||
except Exception as exc:
|
||||
_add_startup_check(startup_table, "DISABLED", "Matrix", provider="matrix", detail=str(exc))
|
||||
debug(f"Matrix instantiation failed: {exc}")
|
||||
for check in _collect_plugin_startup_checks(config):
|
||||
_add_startup_check(
|
||||
startup_table,
|
||||
str(check.get("status") or "UNKNOWN"),
|
||||
str(check.get("name") or "Plugin"),
|
||||
provider=str(check.get("plugin") or ""),
|
||||
files=check.get("files"),
|
||||
detail=str(check.get("detail") or ""),
|
||||
)
|
||||
|
||||
# Cookies
|
||||
try:
|
||||
from tool.ytdlp import YtDlpTool
|
||||
cf = YtDlpTool(config).resolve_cookiefile()
|
||||
cf = resolve_cookies_path(config)
|
||||
_add_startup_check(startup_table, "FOUND" if cf else "MISSING", "Cookies", detail=str(cf) if cf else "Not found")
|
||||
debug(f"Cookies: resolved cookiefile={cf}")
|
||||
except Exception as exc:
|
||||
|
||||
+9
-3
@@ -8,10 +8,18 @@ from SYS.cmdlet_spec import Cmdlet, CmdletArg
|
||||
from SYS.logger import log
|
||||
from SYS.result_table import Table
|
||||
from SYS import pipeline as ctx
|
||||
from ProviderCore.registry import get_plugin
|
||||
from cmdnat._parsing import has_flag as _has_flag, normalize_to_list as _normalize_to_list
|
||||
|
||||
_TELEGRAM_PENDING_ITEMS_KEY = "telegram_pending_items"
|
||||
|
||||
|
||||
def _get_telegram_provider(config: Dict[str, Any]) -> Any:
|
||||
provider = get_plugin("telegram", config)
|
||||
if provider is None:
|
||||
raise RuntimeError("Telegram plugin is not registered")
|
||||
return provider
|
||||
|
||||
def _extract_chat_id(chat_obj: Any) -> Optional[int]:
|
||||
try:
|
||||
if isinstance(chat_obj, dict):
|
||||
@@ -119,10 +127,8 @@ def _extract_file_path(item: Any) -> Optional[str]:
|
||||
|
||||
|
||||
def _run(_result: Any, args: Sequence[str], config: Dict[str, Any]) -> int:
|
||||
from Provider.telegram import Telegram
|
||||
|
||||
try:
|
||||
provider = Telegram(config)
|
||||
provider = _get_telegram_provider(config)
|
||||
except Exception as exc:
|
||||
log(f"Telegram not available: {exc}", file=sys.stderr)
|
||||
return 1
|
||||
|
||||
Reference in New Issue
Block a user