From db1c7a10fd76ba48fb841a2ef95038e7dfaaec12 Mon Sep 17 00:00:00 2001 From: sn0w <105451515+sn0w12@users.noreply.github.com> Date: Fri, 31 Oct 2025 15:48:33 +0100 Subject: [PATCH] Update visible character manager --- __init__.py | 143 ++------------------------------------ sn0w.py | 78 +++++++++++++++++---- web/characters/index.html | 99 ++++++++++++++++++++++++++ 3 files changed, 171 insertions(+), 149 deletions(-) create mode 100644 web/characters/index.html diff --git a/__init__.py b/__init__.py index d7d87a7..643a34f 100644 --- a/__init__.py +++ b/__init__.py @@ -172,12 +172,9 @@ async def series_endpoint(request): @PromptServer.instance.routes.get(f"{API_PREFIX}/visible_series") async def get_visible_series(request): - path = os.path.join(os.path.dirname(os.path.realpath(__file__)), "web/settings/visible_series.json") - if os.path.exists(path): - with open(path, "r", encoding="utf-8") as f: - data = json.load(f) - return web.json_response({"visible_series": data}) - return web.json_response({"visible_series": []}) + db = CharacterDBLoader() + visible_series = db.load_visible_series() + return web.json_response({"visible_series": list(visible_series) if visible_series else []}) @PromptServer.instance.routes.post(f"{API_PREFIX}/visible_series") @@ -201,135 +198,7 @@ async def get_characters_by_series_endpoint(request): @PromptServer.instance.routes.get(f"{API_PREFIX}/series_selector") async def serve_series_selector(request): - html = """ - - - Select Series - - - -
-

Select Series to Show in Dropdown

-
- -
-
- - - - """ + path = os.path.join(os.path.dirname(os.path.realpath(__file__)), "web", "characters", "index.html") + with open(path, "r", encoding="utf-8") as f: + html = f.read() return web.Response(text=html, content_type="text/html") diff --git a/sn0w.py b/sn0w.py index da64e80..b372033 100644 --- a/sn0w.py +++ b/sn0w.py @@ -438,6 +438,7 @@ class MessageHolder: class CharacterDBLoader: def __init__(self): + start = time.perf_counter() self.logger = Logger() self.db_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), "web", "characters", "characters.db") self.conn = sqlite3.connect(self.db_path, check_same_thread=False) # Allow multi-thread access @@ -446,8 +447,11 @@ class CharacterDBLoader: self.logger.log(f"Connected to database at {self.db_path}", "DEBUG") self._ensure_table() self._custom_characters = self._load_custom_characters() + duration = time.perf_counter() - start + self.logger.log(f"CharacterDBLoader __init__ took {duration:.4f} seconds", "DEBUG") def _ensure_table(self): + start = time.perf_counter() with self.lock: self.cursor.execute(""" CREATE TABLE IF NOT EXISTS characters ( @@ -461,9 +465,12 @@ class CharacterDBLoader: ) """) self.conn.commit() + duration = time.perf_counter() - start + self.logger.log(f"CharacterDBLoader _ensure_table took {duration:.4f} seconds", "DEBUG") def _load_custom_characters(self): """Load custom characters from JSON and return as dict.""" + start = time.perf_counter() base_dir = os.path.dirname(os.path.dirname(self.db_path)) custom_json_path = os.path.join(base_dir, "settings/custom_characters.json") custom_dict = {} @@ -490,6 +497,8 @@ class CharacterDBLoader: self.logger.log(f"Error loading custom characters: {e}", "ERROR") else: self.logger.log("Custom characters JSON file not found", "DEBUG") + duration = time.perf_counter() - start + self.logger.log(f"CharacterDBLoader _load_custom_characters took {duration:.4f} seconds", "DEBUG") return custom_dict def _extract_series_name(self, character_name): @@ -504,10 +513,11 @@ class CharacterDBLoader: def _get_db_characters(self): """Get characters from DB.""" + start = time.perf_counter() with self.lock: self.cursor.execute("SELECT * FROM characters") rows = self.cursor.fetchall() - return { + result = { row[0]: { "gender": row[1], "series": row[2], @@ -518,9 +528,13 @@ class CharacterDBLoader: } for row in rows } + duration = time.perf_counter() - start + self.logger.log(f"CharacterDBLoader _get_db_characters took {duration:.4f} seconds", "DEBUG") + return result def get_all_characters(self): """Get all characters from DB and custom merged.""" + start = time.perf_counter() db_chars = self._get_db_characters() merged = db_chars.copy() for name, char in self._custom_characters.items(): @@ -540,55 +554,90 @@ class CharacterDBLoader: self.logger.log( f"Merged {len(db_chars)} DB characters with {len(self._custom_characters)} custom characters", "DEBUG" ) + duration = time.perf_counter() - start + self.logger.log(f"CharacterDBLoader get_all_characters took {duration:.4f} seconds", "DEBUG") return merged def get_characters_by_series(self, series_name): """Get characters by series from merged data.""" + start = time.perf_counter() all_chars = self.get_all_characters() - return {name: char for name, char in all_chars.items() if char["series"] == series_name} + result = {name: char for name, char in all_chars.items() if char["series"] == series_name} + duration = time.perf_counter() - start + self.logger.log(f"CharacterDBLoader get_characters_by_series took {duration:.4f} seconds", "DEBUG") + return result def get_all_series(self): """Get all series from merged data.""" + start = time.perf_counter() all_chars = self.get_all_characters() series_set = set(char["series"] for char in all_chars.values() if char["series"]) - return sorted(series_set) + result = sorted(series_set) + duration = time.perf_counter() - start + self.logger.log(f"CharacterDBLoader get_all_series took {duration:.4f} seconds", "DEBUG") + return result def get_filtered_characters(self, visible_series=None): """Get filtered characters from merged data.""" + start = time.perf_counter() all_chars = self.get_all_characters() if visible_series: - return { + result = { name: char for name, char in all_chars.items() if char.get("is_custom") or char["series"] in visible_series } - return all_chars + else: + result = all_chars + duration = time.perf_counter() - start + self.logger.log(f"CharacterDBLoader get_filtered_characters took {duration:.4f} seconds", "DEBUG") + return result def load_visible_series(self): """Load visible series from JSON file""" + start = time.perf_counter() base_dir = os.path.dirname(os.path.dirname(self.db_path)) visible_series_path = os.path.join(base_dir, "settings/visible_series.json") try: with open(visible_series_path, "r", encoding="utf-8") as f: - visible_series = json.load(f) + content = f.read().strip() + if not content: + raise FileNotFoundError("File is empty") + visible_series = json.loads(content) self.logger.log(f"Loaded {len(visible_series) if visible_series else 0} visible series", "DEBUG") - return set(visible_series) if visible_series else None + result = set(visible_series) if visible_series else None except FileNotFoundError: - self.logger.log(f"Visible series file not found at: {visible_series_path}", "WARNING") - return None + self.logger.log(f"Visible series file not found or empty at: {visible_series_path}", "WARNING") + all_series = self.get_all_series() + os.makedirs(os.path.dirname(visible_series_path), exist_ok=True) + with open(visible_series_path, "w", encoding="utf-8") as f: + json.dump(all_series, f) + result = set(all_series) except Exception as e: self.logger.log(f"Error reading visible series file: {e}", "ERROR") - return None + all_series = self.get_all_series() + os.makedirs(os.path.dirname(visible_series_path), exist_ok=True) + with open(visible_series_path, "w", encoding="utf-8") as f: + json.dump(all_series, f) + result = set(all_series) + duration = time.perf_counter() - start + self.logger.log(f"CharacterDBLoader load_visible_series took {duration:.4f} seconds", "DEBUG") + return result def get_visible_characters(self, include_default=True): """Get characters filtered by visible series or only custom if include_default is False""" + start = time.perf_counter() if not include_default: - return self._custom_characters + result = self._custom_characters else: visible_series = self.load_visible_series() - return self.get_filtered_characters(visible_series) + result = self.get_filtered_characters(visible_series) + duration = time.perf_counter() - start + self.logger.log(f"CharacterDBLoader get_visible_characters took {duration:.4f} seconds", "DEBUG") + return result def insert_character(self, name, gender, series="", associated_string="", prompt="", clothing_tags="", is_custom=0): + start = time.perf_counter() # Only insert if not custom, or handle custom separately if is_custom: self.logger.log(f"Skipping insert for custom character: {name}", "DEBUG") @@ -606,11 +655,16 @@ class CharacterDBLoader: (name, gender, series, associated_string, prompt, clothing_tags, is_custom), ) self.conn.commit() + duration = time.perf_counter() - start + self.logger.log(f"CharacterDBLoader insert_character took {duration:.4f} seconds", "DEBUG") def close(self): + start = time.perf_counter() self.logger.log("Closing database connection", "DEBUG") with self.lock: self.conn.close() + duration = time.perf_counter() - start + self.logger.log(f"CharacterDBLoader close took {duration:.4f} seconds", "DEBUG") API_PREFIX = "/sn0w" diff --git a/web/characters/index.html b/web/characters/index.html new file mode 100644 index 0000000..68e2a3f --- /dev/null +++ b/web/characters/index.html @@ -0,0 +1,99 @@ + + + + + + series-select + + + + +
+ +