From 797b5fee402ef4376940cdfebcf4705ac2c217fa Mon Sep 17 00:00:00 2001 From: Nose Date: Fri, 23 Jan 2026 15:02:19 -0800 Subject: [PATCH] j --- SYS/config.py | 5 +- TUI/modalscreen/config_modal.py | 9 ++++ scripts/hydrusnetwork.py | 86 ++++++++++++++++++--------------- 3 files changed, 58 insertions(+), 42 deletions(-) diff --git a/SYS/config.py b/SYS/config.py index 9dd21d4..a9e7518 100644 --- a/SYS/config.py +++ b/SYS/config.py @@ -368,8 +368,8 @@ def save_config( from SYS.database import db, save_config_value with db.transaction(): - # We want to clear and re-save or just update? - # For simplicity, we'll iterate and update. + # Replace the table contents so removed entries disappear from the DB. + db.execute("DELETE FROM config") for key, value in config.items(): if key in ('store', 'provider', 'tool'): if isinstance(value, dict): @@ -393,6 +393,7 @@ def save_config( log(f"Failed to save config to database: {e}") cache_key = _make_cache_key(config_dir, filename, config_path) + clear_config_cache() _CONFIG_CACHE[cache_key] = config diff --git a/TUI/modalscreen/config_modal.py b/TUI/modalscreen/config_modal.py index 508bd09..cc63d86 100644 --- a/TUI/modalscreen/config_modal.py +++ b/TUI/modalscreen/config_modal.py @@ -544,14 +544,23 @@ class ConfigModal(ModalScreen): self.editing_item_name = name self.refresh_view() elif action == "del": + removed = False if itype.startswith("store-"): stype = itype.replace("store-", "") if "store" in self.config_data and stype in self.config_data["store"]: if name in self.config_data["store"][stype]: del self.config_data["store"][stype][name] + removed = True elif itype == "provider": if "provider" in self.config_data and name in self.config_data["provider"]: del self.config_data["provider"][name] + removed = True + if removed: + try: + self.save_all() + self.notify("Configuration saved!") + except Exception as exc: + self.notify(f"Save failed: {exc}", severity="error", timeout=10) self.refresh_view() elif bid == "add-store-btn": all_classes = _discover_store_classes() diff --git a/scripts/hydrusnetwork.py b/scripts/hydrusnetwork.py index 338801d..e3b4f22 100644 --- a/scripts/hydrusnetwork.py +++ b/scripts/hydrusnetwork.py @@ -159,56 +159,62 @@ def run_git_pull(git: str, dest: Path) -> None: subprocess.run([git, "-C", str(dest), "pull"], check=True) +def _sanitize_store_name(name: str) -> str: + clean = "".join(ch for ch in name if ch.isalnum() or ch in {"-", "_"}) + return clean or "hydrus" + + def update_medios_config(hydrus_path: Path) -> bool: """Attempt to update Medios-Macina root configuration with the hydrus path. - This helps link the newly installed Hydrus instance with the main project. - We check for medios.db first, then fall back to config.conf. + We look for an existing hydrusnetwork backend entry and attach the gitclone + path to that backend. This avoids hard-coded store names such as "hydrus" or + "hn-local" so users can pick their own alias. """ script_dir = Path(__file__).resolve().parent root = script_dir.parent db_path = root / "medios.db" - config_path = root / "config.conf" - hydrus_abs_path = str(hydrus_path.resolve()) - # Try database first - if db_path.exists(): - try: - import sqlite3 - import json - with sqlite3.connect(str(db_path), timeout=30.0) as conn: - conn.row_factory = sqlite3.Row - cur = conn.cursor() - - # We want to set store.hydrusnetwork.hydrus.gitclone - # First check if hydrusnetwork store exists - cur.execute("SELECT 1 FROM config WHERE category='store' AND subtype='hydrusnetwork'") - if cur.fetchone(): - # Update or insert gitclone for the hydrus subtype - # Note: we assume the name is 'hydrus' or 'hn-local' or something. - # Usually it's 'hydrus' if newly created. - cur.execute( - "INSERT OR REPLACE INTO config (category, subtype, item_name, key, value) VALUES (?, ?, ?, ?, ?)", - ('store', 'hydrusnetwork', 'hydrus', 'gitclone', hydrus_abs_path) - ) - else: - # Create the section - cur.execute( - "INSERT OR REPLACE INTO config (category, subtype, item_name, key, value) VALUES (?, ?, ?, ?, ?)", - ('store', 'hydrusnetwork', 'hydrus', 'name', 'hydrus') - ) - cur.execute( - "INSERT OR REPLACE INTO config (category, subtype, item_name, key, value) VALUES (?, ?, ?, ?, ?)", - ('store', 'hydrusnetwork', 'hydrus', 'gitclone', hydrus_abs_path) - ) - conn.commit() - logging.info("✅ Linked Hydrus installation in medios.db (gitclone=\"%s\")", hydrus_abs_path) - return True - except Exception as e: - logging.error("Failed to update medios.db: %s", e) + if not db_path.exists(): + return False - return False + try: + import sqlite3 + + with sqlite3.connect(str(db_path), timeout=30.0) as conn: + conn.row_factory = sqlite3.Row + cur = conn.cursor() + + cur.execute( + "SELECT DISTINCT item_name FROM config WHERE category='store' AND subtype='hydrusnetwork'" + ) + rows = [row[0] for row in cur.fetchall() if row[0]] + + if not rows: + store_name = _sanitize_store_name(hydrus_path.name) + cur.execute( + "INSERT OR REPLACE INTO config (category, subtype, item_name, key, value) VALUES (?, ?, ?, ?, ?)", + ('store', 'hydrusnetwork', store_name, 'name', store_name) + ) + rows = [store_name] + + for name in rows: + cur.execute( + "INSERT OR REPLACE INTO config (category, subtype, item_name, key, value) VALUES (?, ?, ?, ?, ?)", + ('store', 'hydrusnetwork', name, 'gitclone', hydrus_abs_path) + ) + + conn.commit() + logging.info( + "✅ Linked Hydrus installation in medios.db for [%s] (gitclone=\"%s\")", + rows, + hydrus_abs_path, + ) + return True + except Exception as e: + logging.error("Failed to update medios.db: %s", e) + return False def download_and_extract_zip(