import json import os from app.utils.logger import logger DEFAULT_SYNC_MODE = "merge_local_primary" DEFAULT_PATH_MAPPING = { "mode": "SIMPLE", "simple": [], "regex": { "local_pre": [], "local_post": [], "remote_pre": [], "remote_post": [] } } CONFIG_PATH = os.path.abspath( os.path.join(os.path.dirname(__file__), "..", "config.json") ) class ServerConfig: def __init__(self): self.theme = "auto" self.token = "" self.url = "" self.scheme = "https" self.port = "32400" self.timeout = 9 self.library_name = "" self.sync_mode = DEFAULT_SYNC_MODE self.local_path = "playlist" self.path_rules: list[dict[str, str]] = [] # Legacy field for backward compatibility self.path_mapping: dict = DEFAULT_PATH_MAPPING.copy() self.schedule_mode = "DISABLED" self.schedule_cron = "" self.schedule_daily_time = "02:00" self.schedule_weekly_days = [0] self.schedule_weekly_time = "03:00" self.schedule_auto_watch = False self.backup_enabled = False self.backup_retention_count = 5 self.load() def load(self) -> None: try: with open(CONFIG_PATH, "r", encoding="utf-8") as f: config = json.load(f) logger.debug(f"Loaded server config: {config}") except FileNotFoundError: # 如果配置文件不存在,使用默认值 self.save() logger.debug("Config file not found, using default values.") return except json.JSONDecodeError: # 如果配置文件格式错误,使用默认值 self.save() logger.debug("Config file is invalid, using default values.") return self.theme = config.get("theme", "auto") self.token = config.get("token", "") self.url = config.get("server_url", "") self.scheme = config.get("server_scheme", "https") self.port = config.get("server_port", "32400") self.timeout = config.get("timeout", 9) self.library_name = config.get("library_name", "") self.sync_mode = config.get("sync_mode", DEFAULT_SYNC_MODE) self.local_path = config.get("local_path", "playlist") self.path_rules = config.get("path_rules", []) or [] # Load path_mapping with default fallback path_mapping_config = config.get("path_mapping") if path_mapping_config: self.path_mapping = { "mode": path_mapping_config.get("mode", "SIMPLE"), "simple": path_mapping_config.get("simple", []), "regex": { "local_pre": path_mapping_config.get("regex", {}).get("local_pre", []), "local_post": path_mapping_config.get("regex", {}).get("local_post", []), "remote_pre": path_mapping_config.get("regex", {}).get("remote_pre", []), "remote_post": path_mapping_config.get("regex", {}).get("remote_post", []) } } else: self.path_mapping = DEFAULT_PATH_MAPPING.copy() self.schedule_mode = config.get("schedule_mode", "DISABLED") self.schedule_cron = config.get("schedule_cron", "") self.schedule_daily_time = config.get("schedule_daily_time", "02:00") self.schedule_weekly_days = config.get("schedule_weekly_days", [0]) self.schedule_weekly_time = config.get("schedule_weekly_time", "03:00") self.schedule_auto_watch = config.get("schedule_auto_watch", False) self.backup_enabled = config.get("backup_enabled", False) self.backup_retention_count = config.get("backup_retention_count", 5) logger.info(f"Server config loaded.") logger.debug(f"Current server config: {self.__dict__}") def save(self): config = { "theme": self.theme, "token": self.token, "server_url": self.url, "server_scheme": self.scheme, "server_port": self.port, "timeout": self.timeout, "library_name": self.library_name, "sync_mode": self.sync_mode, "local_path": self.local_path, "path_rules": self.path_rules, "path_mapping": self.path_mapping, "schedule_mode": self.schedule_mode, "schedule_cron": self.schedule_cron, "schedule_daily_time": self.schedule_daily_time, "schedule_weekly_days": self.schedule_weekly_days, "schedule_weekly_time": self.schedule_weekly_time, "schedule_auto_watch": self.schedule_auto_watch, "backup_enabled": self.backup_enabled, "backup_retention_count": self.backup_retention_count, } with open(CONFIG_PATH, "w", encoding="utf-8") as f: json.dump(config, f, indent=4, ensure_ascii=False) logger.info(f"Server config saved: {config}") def set_url(self, url: str) -> None: self.url = url def set_scheme(self, scheme: str) -> None: self.scheme = scheme def set_port(self, port: str) -> None: self.port = port def set_timeout(self, timeout: int) -> None: self.timeout = timeout if timeout and timeout > 0 else 9 def set_token(self, token: str) -> None: self.token = token def set_library(self, library_name: str) -> None: self.library_name = library_name or "" def set_sync_mode(self, sync_mode: str) -> None: self.sync_mode = sync_mode def set_local_path(self, local_path: str) -> None: self.local_path = local_path or "playlist" def set_theme(self, theme: str) -> None: # check theme is valid if theme not in ["auto", "dark", "light"]: logger.error(f"Invalid theme: {theme}") raise ValueError("Invalid theme. Must be 'auto', 'dark', or 'light'.") self.theme = theme def set_path_rules(self, path_rules: list[dict[str, str]]) -> None: self.path_rules = path_rules or [] def set_path_mapping(self, path_mapping: dict) -> None: if path_mapping: self.path_mapping = { "mode": path_mapping.get("mode", "SIMPLE"), "simple": path_mapping.get("simple", []), "regex": { "local_pre": path_mapping.get("regex", {}).get("local_pre", []), "local_post": path_mapping.get("regex", {}).get("local_post", []), "remote_pre": path_mapping.get("regex", {}).get("remote_pre", []), "remote_post": path_mapping.get("regex", {}).get("remote_post", []) } } else: self.path_mapping = DEFAULT_PATH_MAPPING.copy() def set_schedule( self, mode: str, cron: str, daily_time: str, weekly_days: list[int], weekly_time: str, auto_watch: bool, ) -> None: self.schedule_mode = mode self.schedule_cron = cron self.schedule_daily_time = daily_time self.schedule_weekly_days = weekly_days self.schedule_weekly_time = weekly_time self.schedule_auto_watch = auto_watch self.save() def set_backup( self, enabled: bool, retention_count: int, ) -> None: self.backup_enabled = enabled self.backup_retention_count = retention_count self.save() def set_and_save_config( self, theme: str = None, token: str = None, url: str = None, scheme: str = None, port: str = None, timeout: int | None = None, library_name: str | None = None, sync_mode: str | None = None, local_path: str | None = None, path_rules: list[dict[str, str]] | None = None, path_mapping: dict | None = None, ) -> None: if theme is not None: self.set_theme(theme) if token is not None: self.set_token(token) if url is not None: self.set_url(url) if scheme is not None: self.set_scheme(scheme) if port is not None: self.set_port(port) if timeout is not None: self.set_timeout(timeout) if library_name is not None: self.set_library(library_name) if sync_mode is not None: self.set_sync_mode(sync_mode) if local_path is not None: self.set_local_path(local_path) if path_rules is not None: self.set_path_rules(path_rules) if path_mapping is not None: self.set_path_mapping(path_mapping) self.save() server_config = ServerConfig()