update commit prev
This commit is contained in:
+82
-3
@@ -93,7 +93,10 @@ def clear_config_cache() -> None:
|
||||
|
||||
def _log_config_load_summary(config: Dict[str, Any]) -> None:
|
||||
try:
|
||||
provs = list(config.get("provider", {}).keys()) if isinstance(config.get("provider"), dict) else []
|
||||
plugin_block = config.get("plugin")
|
||||
if not isinstance(plugin_block, dict):
|
||||
plugin_block = config.get("provider")
|
||||
provs = list(plugin_block.keys()) if isinstance(plugin_block, dict) else []
|
||||
stores = list(config.get("store", {}).keys()) if isinstance(config.get("store"), dict) else []
|
||||
mtime = None
|
||||
try:
|
||||
@@ -101,7 +104,7 @@ def _log_config_load_summary(config: Dict[str, Any]) -> None:
|
||||
except Exception:
|
||||
mtime = None
|
||||
summary = (
|
||||
f"Loaded config from {db.db_path.name}: providers={len(provs)} ({', '.join(provs[:10])}{'...' if len(provs)>10 else ''}), "
|
||||
f"Loaded config from {db.db_path.name}: plugins={len(provs)} ({', '.join(provs[:10])}{'...' if len(provs)>10 else ''}), "
|
||||
f"stores={len(stores)} ({', '.join(stores[:10])}{'...' if len(stores)>10 else ''}), mtime={mtime}"
|
||||
)
|
||||
log(summary)
|
||||
@@ -325,6 +328,7 @@ def get_hydrus_url(config: Dict[str, Any], instance_name: str = "home") -> Optio
|
||||
|
||||
|
||||
def get_provider_block(config: Dict[str, Any], name: str) -> Dict[str, Any]:
|
||||
_normalize_plugin_config_aliases(config)
|
||||
provider_cfg = config.get("provider")
|
||||
if not isinstance(provider_cfg, dict):
|
||||
return {}
|
||||
@@ -518,7 +522,7 @@ def resolve_cookies_path(
|
||||
except Exception as exc:
|
||||
logger.debug("resolve_cookies_path: failed to read tool.ytdlp cookies: %s", exc, exc_info=True)
|
||||
|
||||
base_dir = script_dir or SCRIPT_DIR
|
||||
base_dir = _resolve_app_root(script_dir)
|
||||
for value in values:
|
||||
if not value:
|
||||
continue
|
||||
@@ -528,6 +532,10 @@ def resolve_cookies_path(
|
||||
if candidate.is_file():
|
||||
return candidate
|
||||
|
||||
plugin_cookie = resolve_plugin_asset_path("ytdlp", "cookies.txt", script_dir=base_dir)
|
||||
if plugin_cookie is not None:
|
||||
return plugin_cookie
|
||||
|
||||
default_path = base_dir / "cookies.txt"
|
||||
if default_path.is_file():
|
||||
return default_path
|
||||
@@ -547,6 +555,70 @@ def _normalize_provider_name(value: Any) -> Optional[str]:
|
||||
candidate = str(value or "").strip().lower()
|
||||
return candidate if candidate else None
|
||||
|
||||
|
||||
def _resolve_app_root(script_dir: Optional[Path] = None) -> Path:
|
||||
if script_dir is not None:
|
||||
try:
|
||||
candidate = expand_path(script_dir)
|
||||
except Exception:
|
||||
candidate = Path(script_dir)
|
||||
return candidate if candidate.is_dir() else candidate.parent
|
||||
return SCRIPT_DIR.parent
|
||||
|
||||
|
||||
def resolve_plugin_asset_path(
|
||||
plugin_name: str,
|
||||
*relative_parts: str,
|
||||
script_dir: Optional[Path] = None,
|
||||
) -> Optional[Path]:
|
||||
normalized = _normalize_provider_name(plugin_name)
|
||||
if not normalized:
|
||||
return None
|
||||
|
||||
plugin_dir = _resolve_app_root(script_dir) / "plugins" / normalized
|
||||
if not plugin_dir.is_dir():
|
||||
return None
|
||||
|
||||
for part in relative_parts:
|
||||
text = str(part or "").strip().strip("/\\")
|
||||
if not text:
|
||||
continue
|
||||
candidate = plugin_dir / text
|
||||
if candidate.is_file():
|
||||
return candidate
|
||||
return None
|
||||
|
||||
|
||||
def _normalize_plugin_config_aliases(config: Dict[str, Any]) -> None:
|
||||
if not isinstance(config, dict):
|
||||
return
|
||||
|
||||
plugin_block = config.get("plugin")
|
||||
provider_block = config.get("provider")
|
||||
|
||||
normalized_provider: Dict[str, Any] = {}
|
||||
|
||||
if isinstance(provider_block, dict):
|
||||
for key, value in provider_block.items():
|
||||
normalized_key = _normalize_provider_name(key)
|
||||
if normalized_key and normalized_key not in normalized_provider:
|
||||
normalized_provider[normalized_key] = value
|
||||
|
||||
if isinstance(plugin_block, dict):
|
||||
for key, value in plugin_block.items():
|
||||
normalized_key = _normalize_provider_name(key)
|
||||
if normalized_key and normalized_key not in normalized_provider:
|
||||
normalized_provider[normalized_key] = value
|
||||
|
||||
if normalized_provider:
|
||||
config["provider"] = normalized_provider
|
||||
config["plugin"] = normalized_provider
|
||||
else:
|
||||
if isinstance(provider_block, dict):
|
||||
config["plugin"] = provider_block
|
||||
elif isinstance(plugin_block, dict):
|
||||
config["provider"] = plugin_block
|
||||
|
||||
def _extract_api_key(value: Any) -> Optional[str]:
|
||||
if isinstance(value, dict):
|
||||
for key in ("api_key", "API_KEY", "apikey", "APIKEY"):
|
||||
@@ -564,6 +636,8 @@ def _sync_alldebrid_api_key(config: Dict[str, Any]) -> None:
|
||||
if not isinstance(config, dict):
|
||||
return
|
||||
|
||||
_normalize_plugin_config_aliases(config)
|
||||
|
||||
providers = config.get("provider")
|
||||
if not isinstance(providers, dict):
|
||||
providers = {}
|
||||
@@ -617,7 +691,10 @@ def _sync_alldebrid_api_key(config: Dict[str, Any]) -> None:
|
||||
|
||||
def _flatten_config_entries(config: Dict[str, Any]) -> Dict[Tuple[str, str, str, str], Any]:
|
||||
entries: Dict[Tuple[str, str, str, str], Any] = {}
|
||||
_normalize_plugin_config_aliases(config)
|
||||
for key, value in config.items():
|
||||
if key == 'plugin':
|
||||
continue
|
||||
if key in ('store', 'provider', 'tool') and isinstance(value, dict):
|
||||
for subtype, instances in value.items():
|
||||
if not isinstance(instances, dict):
|
||||
@@ -655,6 +732,7 @@ def load_config(*, emit_summary: bool = True) -> Dict[str, Any]:
|
||||
# Load strictly from database
|
||||
db_config = get_config_all()
|
||||
if db_config:
|
||||
_normalize_plugin_config_aliases(db_config)
|
||||
_sync_alldebrid_api_key(db_config)
|
||||
_CONFIG_CACHE = db_config
|
||||
_LAST_SAVED_CONFIG = deepcopy(db_config)
|
||||
@@ -742,6 +820,7 @@ def _release_save_lock(lock_dir: Path) -> None:
|
||||
|
||||
def save_config(config: Dict[str, Any]) -> int:
|
||||
global _CONFIG_CACHE, _LAST_SAVED_CONFIG
|
||||
_normalize_plugin_config_aliases(config)
|
||||
_sync_alldebrid_api_key(config)
|
||||
|
||||
# Acquire cross-process save lock to avoid concurrent saves from different
|
||||
|
||||
+27
-15
@@ -61,11 +61,15 @@ def get_store_schema(store_type: str) -> List[ConfigField]:
|
||||
return _call_schema(cls, f"store '{store_type}'")
|
||||
|
||||
|
||||
def get_provider_schema(provider_name: str) -> List[ConfigField]:
|
||||
plugin_class = get_plugin_class(str(provider_name or "").strip())
|
||||
def get_plugin_schema(plugin_name: str) -> List[ConfigField]:
|
||||
plugin_class = get_plugin_class(str(plugin_name or "").strip())
|
||||
if plugin_class is None:
|
||||
return []
|
||||
return _call_schema(plugin_class, f"provider '{provider_name}'")
|
||||
return _call_schema(plugin_class, f"plugin '{plugin_name}'")
|
||||
|
||||
|
||||
def get_provider_schema(provider_name: str) -> List[ConfigField]:
|
||||
return get_plugin_schema(provider_name)
|
||||
|
||||
|
||||
def get_tool_schema(tool_name: str) -> List[ConfigField]:
|
||||
@@ -85,8 +89,8 @@ def get_item_schema(item_type: str, item_name: str) -> List[ConfigField]:
|
||||
normalized_name = str(item_name or "").strip()
|
||||
if normalized_type.startswith("store-"):
|
||||
return get_store_schema(normalized_type.replace("store-", "", 1))
|
||||
if normalized_type == "provider":
|
||||
return get_provider_schema(normalized_name)
|
||||
if normalized_type in {"provider", "plugin"}:
|
||||
return get_plugin_schema(normalized_name)
|
||||
if normalized_type == "tool":
|
||||
return get_tool_schema(normalized_name)
|
||||
return []
|
||||
@@ -126,25 +130,29 @@ def build_default_store_config(store_type: str, instance_name: str) -> Dict[str,
|
||||
return config
|
||||
|
||||
|
||||
def build_default_provider_config(provider_name: str) -> Dict[str, Any]:
|
||||
def build_default_plugin_config(plugin_name: str) -> Dict[str, Any]:
|
||||
config: Dict[str, Any] = {}
|
||||
schema = get_provider_schema(provider_name)
|
||||
schema = get_plugin_schema(plugin_name)
|
||||
if schema:
|
||||
for field in schema:
|
||||
config[field["key"]] = field.get("default", "")
|
||||
return config
|
||||
|
||||
plugin_class = get_plugin_class(str(provider_name or "").strip())
|
||||
plugin_class = get_plugin_class(str(plugin_name or "").strip())
|
||||
if plugin_class is None:
|
||||
return config
|
||||
try:
|
||||
for required_key in plugin_class.required_config_keys():
|
||||
config[str(required_key)] = ""
|
||||
except Exception:
|
||||
logger.exception("Failed to load legacy required config keys for provider '%s'", provider_name)
|
||||
logger.exception("Failed to load legacy required config keys for plugin '%s'", plugin_name)
|
||||
return config
|
||||
|
||||
|
||||
def build_default_provider_config(provider_name: str) -> Dict[str, Any]:
|
||||
return build_default_plugin_config(provider_name)
|
||||
|
||||
|
||||
def build_default_tool_config(tool_name: str) -> Dict[str, Any]:
|
||||
config: Dict[str, Any] = {}
|
||||
for field in get_tool_schema(tool_name):
|
||||
@@ -179,14 +187,14 @@ def get_required_config_keys(item_type: str, item_name: str) -> List[str]:
|
||||
if cls is not None:
|
||||
for required_key in _required_keys_for(cls):
|
||||
_add_key(required_key)
|
||||
elif normalized_type == "provider":
|
||||
elif normalized_type in {"provider", "plugin"}:
|
||||
plugin_class = get_plugin_class(normalized_name)
|
||||
if plugin_class is not None:
|
||||
try:
|
||||
for required_key in plugin_class.required_config_keys():
|
||||
_add_key(required_key)
|
||||
except Exception:
|
||||
logger.exception("Failed to load required config keys for provider '%s'", normalized_name)
|
||||
logger.exception("Failed to load required config keys for plugin '%s'", normalized_name)
|
||||
|
||||
return required_keys
|
||||
|
||||
@@ -199,14 +207,18 @@ def get_configurable_store_types() -> List[str]:
|
||||
return sorted(set(options))
|
||||
|
||||
|
||||
def get_configurable_provider_types() -> List[str]:
|
||||
def get_configurable_plugin_types() -> List[str]:
|
||||
options: List[str] = []
|
||||
for provider_name in list_plugins().keys():
|
||||
if get_provider_schema(provider_name):
|
||||
options.append(str(provider_name))
|
||||
for plugin_name in list_plugins().keys():
|
||||
if get_plugin_schema(plugin_name):
|
||||
options.append(str(plugin_name))
|
||||
return sorted(set(options))
|
||||
|
||||
|
||||
def get_configurable_provider_types() -> List[str]:
|
||||
return get_configurable_plugin_types()
|
||||
|
||||
|
||||
def get_configurable_tool_types() -> List[str]:
|
||||
options: List[str] = []
|
||||
try:
|
||||
|
||||
Reference in New Issue
Block a user