Files
PlexPlaylistSync/app/utils/config.py
T
2025-12-04 23:21:26 +00:00

240 lines
8.6 KiB
Python

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()