This commit is contained in:
2026-01-23 18:40:00 -08:00
parent 883ac2a283
commit b79e3b309b
4 changed files with 57 additions and 37 deletions

View File

@@ -339,7 +339,7 @@
"(file\\.al/[0-9a-zA-Z]{12})" "(file\\.al/[0-9a-zA-Z]{12})"
], ],
"regexp": "(file\\.al/[0-9a-zA-Z]{12})", "regexp": "(file\\.al/[0-9a-zA-Z]{12})",
"status": true "status": false
}, },
"filedot": { "filedot": {
"name": "filedot", "name": "filedot",
@@ -477,7 +477,7 @@
"isra\\.cloud/\\?op=report_file&id=([0-9a-zA-Z]{12})" "isra\\.cloud/\\?op=report_file&id=([0-9a-zA-Z]{12})"
], ],
"regexp": "((isra\\.cloud/[0-9a-zA-Z]{12}))|(isra\\.cloud/\\?op=report_file&id=([0-9a-zA-Z]{12}))", "regexp": "((isra\\.cloud/[0-9a-zA-Z]{12}))|(isra\\.cloud/\\?op=report_file&id=([0-9a-zA-Z]{12}))",
"status": true, "status": false,
"hardRedirect": [ "hardRedirect": [
"isra\\.cloud/([0-9a-zA-Z]{12})" "isra\\.cloud/([0-9a-zA-Z]{12})"
] ]
@@ -507,7 +507,7 @@
"mediafire\\.com/(\\?|download/|file/|download\\.php\\?)([0-9a-z]{15})" "mediafire\\.com/(\\?|download/|file/|download\\.php\\?)([0-9a-z]{15})"
], ],
"regexp": "mediafire\\.com/(\\?|download/|file/|download\\.php\\?)([0-9a-z]{15})", "regexp": "mediafire\\.com/(\\?|download/|file/|download\\.php\\?)([0-9a-z]{15})",
"status": false "status": true
}, },
"mexashare": { "mexashare": {
"name": "mexashare", "name": "mexashare",

View File

@@ -557,24 +557,7 @@ def _load_config_best_effort() -> dict:
try: try:
from SYS.config import load_config from SYS.config import load_config
# `SYS.config.load_config()` defaults to loading `config.conf` from the cfg = load_config()
# SYS/ directory, but this repo keeps `config.conf` at the repo root.
# MPV.lyric is often spawned from mpv (not the CLI), so we must locate
# the repo root ourselves.
try:
repo_root = Path(__file__).resolve().parent.parent
except Exception:
repo_root = None
cfg = None
if repo_root is not None:
try:
cfg = load_config(config_dir=repo_root)
except Exception:
cfg = None
if cfg is None:
cfg = load_config()
return cfg if isinstance(cfg, dict) else {} return cfg if isinstance(cfg, dict) else {}
except Exception: except Exception:

View File

@@ -2,13 +2,12 @@
from __future__ import annotations from __future__ import annotations
import re
import tempfile
import json import json
import sqlite3 import sqlite3
import time import time
from copy import deepcopy
from pathlib import Path from pathlib import Path
from typing import Any, Dict, Optional, List from typing import Any, Dict, List, Optional, Tuple
from SYS.logger import log from SYS.logger import log
from SYS.utils import expand_path from SYS.utils import expand_path
from SYS.database import db, get_config_all, save_config_value from SYS.database import db, get_config_all, save_config_value
@@ -16,6 +15,7 @@ from SYS.database import db, get_config_all, save_config_value
SCRIPT_DIR = Path(__file__).resolve().parent SCRIPT_DIR = Path(__file__).resolve().parent
_CONFIG_CACHE: Dict[str, Any] = {} _CONFIG_CACHE: Dict[str, Any] = {}
_LAST_SAVED_CONFIG: Dict[str, Any] = {}
_CONFIG_SAVE_MAX_RETRIES = 5 _CONFIG_SAVE_MAX_RETRIES = 5
_CONFIG_SAVE_RETRY_DELAY = 0.15 _CONFIG_SAVE_RETRY_DELAY = 0.15
@@ -39,9 +39,10 @@ def global_config() -> List[Dict[str, Any]]:
def clear_config_cache() -> None: def clear_config_cache() -> None:
"""Clear the configuration cache.""" """Clear the configuration cache and baseline snapshot."""
global _CONFIG_CACHE global _CONFIG_CACHE, _LAST_SAVED_CONFIG
_CONFIG_CACHE = {} _CONFIG_CACHE = {}
_LAST_SAVED_CONFIG = {}
def get_hydrus_instance( def get_hydrus_instance(
@@ -334,8 +335,37 @@ def resolve_debug_log(config: Dict[str, Any]) -> Optional[Path]:
return path return path
def _flatten_config_entries(config: Dict[str, Any]) -> Dict[Tuple[str, str, str, str], Any]:
entries: Dict[Tuple[str, str, str, str], Any] = {}
for key, value in config.items():
if key in ('store', 'provider', 'tool') and isinstance(value, dict):
for subtype, instances in value.items():
if not isinstance(instances, dict):
continue
if key == 'store':
for name, settings in instances.items():
if not isinstance(settings, dict):
continue
for k, v in settings.items():
entries[(key, subtype, name, k)] = v
else:
for k, v in instances.items():
entries[(key, subtype, 'default', k)] = v
elif not key.startswith('_') and value is not None:
entries[('global', 'none', 'none', key)] = value
return entries
def _count_changed_entries(old_config: Dict[str, Any], new_config: Dict[str, Any]) -> int:
old_entries = _flatten_config_entries(old_config or {})
new_entries = _flatten_config_entries(new_config or {})
changed = {k for k, v in new_entries.items() if old_entries.get(k) != v}
removed = {k for k in old_entries if k not in new_entries}
return len(changed) + len(removed)
def load_config() -> Dict[str, Any]: def load_config() -> Dict[str, Any]:
global _CONFIG_CACHE global _CONFIG_CACHE, _LAST_SAVED_CONFIG
if _CONFIG_CACHE: if _CONFIG_CACHE:
return _CONFIG_CACHE return _CONFIG_CACHE
@@ -343,8 +373,10 @@ def load_config() -> Dict[str, Any]:
db_config = get_config_all() db_config = get_config_all()
if db_config: if db_config:
_CONFIG_CACHE = db_config _CONFIG_CACHE = db_config
_LAST_SAVED_CONFIG = deepcopy(db_config)
return db_config return db_config
_LAST_SAVED_CONFIG = {}
return {} return {}
@@ -354,6 +386,10 @@ def reload_config() -> Dict[str, Any]:
def save_config(config: Dict[str, Any]) -> int: def save_config(config: Dict[str, Any]) -> int:
global _CONFIG_CACHE, _LAST_SAVED_CONFIG
previous_config = deepcopy(_LAST_SAVED_CONFIG)
changed_count = _count_changed_entries(previous_config, config)
def _write_entries() -> int: def _write_entries() -> int:
count = 0 count = 0
with db.transaction(): with db.transaction():
@@ -384,7 +420,10 @@ def save_config(config: Dict[str, Any]) -> int:
while True: while True:
try: try:
saved_entries = _write_entries() saved_entries = _write_entries()
log(f"Synced {saved_entries} entries to {db.db_path}") log(
f"Synced {saved_entries} entries to {db.db_path} "
f"({changed_count} changed entries)"
)
break break
except sqlite3.OperationalError as exc: except sqlite3.OperationalError as exc:
attempts += 1 attempts += 1
@@ -400,8 +439,8 @@ def save_config(config: Dict[str, Any]) -> int:
raise raise
clear_config_cache() clear_config_cache()
global _CONFIG_CACHE
_CONFIG_CACHE = config _CONFIG_CACHE = config
_LAST_SAVED_CONFIG = deepcopy(config)
return saved_entries return saved_entries

View File

@@ -182,11 +182,9 @@ def _strip_value_quotes(value: str) -> str:
def _run(piped_result: Any, args: List[str], config: Dict[str, Any]) -> int: def _run(piped_result: Any, args: List[str], config: Dict[str, Any]) -> int:
import sys import sys
from pathlib import Path
# Load configuration from the database
# Load from workspace root, not SYS directory current_config = load_config()
workspace_root = Path(__file__).resolve().parent.parent
current_config = load_config(config_dir=workspace_root)
selection_key = _get_selected_config_key() selection_key = _get_selected_config_key()
value_from_args = _extract_value_arg(args) if selection_key else None value_from_args = _extract_value_arg(args) if selection_key else None
@@ -202,7 +200,7 @@ def _run(piped_result: Any, args: List[str], config: Dict[str, Any]) -> int:
new_value = _strip_value_quotes(new_value) new_value = _strip_value_quotes(new_value)
try: try:
set_nested_config(current_config, selection_key, new_value) set_nested_config(current_config, selection_key, new_value)
save_config(current_config, config_dir=workspace_root) save_config(current_config)
print(f"Updated '{selection_key}' to '{new_value}'") print(f"Updated '{selection_key}' to '{new_value}'")
return 0 return 0
except Exception as exc: except Exception as exc:
@@ -235,7 +233,7 @@ def _run(piped_result: Any, args: List[str], config: Dict[str, Any]) -> int:
from cmdlet._shared import SharedArgs from cmdlet._shared import SharedArgs
from cmdnat.status import CMDLET as STATUS_CMDLET from cmdnat.status import CMDLET as STATUS_CMDLET
# We reload the config one more time because it might have changed on disk # We reload the config one more time because it might have changed on disk
fresh_config = load_config(config_dir=workspace_root) fresh_config = load_config()
# Force refresh of shared caches (especially stores) # Force refresh of shared caches (especially stores)
SharedArgs._refresh_store_choices_cache(fresh_config) SharedArgs._refresh_store_choices_cache(fresh_config)
@@ -261,7 +259,7 @@ def _run(piped_result: Any, args: List[str], config: Dict[str, Any]) -> int:
value = _strip_value_quotes(" ".join(args[1:])) value = _strip_value_quotes(" ".join(args[1:]))
try: try:
set_nested_config(current_config, key, value) set_nested_config(current_config, key, value)
save_config(current_config, config_dir=workspace_root) save_config(current_config)
print(f"Updated '{key}' to '{value}'") print(f"Updated '{key}' to '{value}'")
return 0 return 0
except Exception as exc: except Exception as exc: