# -*- coding: utf-8 -*- """JSON 持久化:设置 / 播放列表 / URL 媒体(对齐原 Rust storage 语义)""" import json import threading import time from pathlib import Path from .config import settings DEFAULT_SETTINGS = { "username": "admin", "password": "123456", "volume": 80, "sfx_volume": 60, "auto_play": True, "play_mode": "sequential", "image_duration": 5, "fullscreen": True, "autostart": False, } class Storage: def __init__(self, data_file: Path): self.data_file = data_file self._lock = threading.RLock() self._data = self._load() # ---------- 底层 ---------- def _load(self): if self.data_file.exists(): try: data = json.loads(self.data_file.read_text("utf-8")) # 规范化:URL 来源自动标记(兼容旧数据 source=None 的 URL 条目) for it in data.setdefault("playlist", []): p = it.get("path", "") if p.startswith(("http://", "https://")) and not it.get("source"): it["source"] = "url" return data except Exception: pass return {"settings": dict(DEFAULT_SETTINGS), "playlist": [], "url_media": []} def _save(self): self.data_file.parent.mkdir(parents=True, exist_ok=True) tmp = self.data_file.with_suffix(".tmp") tmp.write_text(json.dumps(self._data, ensure_ascii=False, indent=2), "utf-8") tmp.replace(self.data_file) # ---------- 设置 ---------- def get_settings(self): with self._lock: s = dict(DEFAULT_SETTINGS) s.update(self._data.get("settings", {})) return s def update_settings(self, **kw): with self._lock: s = dict(DEFAULT_SETTINGS) s.update(self._data.get("settings", {})) for k, v in kw.items(): if v is not None and k in s: s[k] = v self._data["settings"] = s self._save() # ---------- 播放列表 ---------- def get_playlist(self): with self._lock: return list(self._data.get("playlist", [])) def add_to_playlist(self, path): with self._lock: items = self._data.setdefault("playlist", []) if not any(it.get("path") == path for it in items): # URL 来源自动标记,避免被当作本地文件过滤 source = "url" if path.startswith(("http://", "https://")) else None items.append({"path": path, "source": source, "name": None}) self._save() def remove_from_playlist(self, path): with self._lock: self._data.setdefault("playlist", []) self._data["playlist"] = [it for it in self._data["playlist"] if it.get("path") != path] self._save() # ---------- URL 媒体 ---------- def get_url_media(self): with self._lock: return list(self._data.get("url_media", [])) def add_url_media(self, url, name, media_type): """返回 True 表示新增,False 表示已存在(重复)""" with self._lock: items = self._data.setdefault("url_media", []) if any(it.get("url") == url for it in items): return False items.append({ "url": url, "name": name, "type": media_type, "added_at": time.strftime("%Y-%m-%d %H:%M:%S"), }) self._save() return True def delete_media(self, path): with self._lock: self._data.setdefault("url_media", []) self._data["url_media"] = [it for it in self._data["url_media"] if it.get("url") != path] self._data.setdefault("playlist", []) self._data["playlist"] = [it for it in self._data["playlist"] if it.get("path") != path] self._save() storage = Storage(settings.DATA_FILE)