"""Configuration and persistence for the Excommunicado bot.""" import json from pathlib import Path from typing import Any, Dict, Optional DATA_DIR = Path(__file__).parent.parent / "data" CONFIG_FILE = DATA_DIR / "xcom_config.json" def _ensure_data_dir() -> None: DATA_DIR.mkdir(parents=True, exist_ok=True) def load_config() -> Dict[str, Any]: """Load the entire config dict.""" _ensure_data_dir() if not CONFIG_FILE.exists(): save_config({}) return {} with open(CONFIG_FILE, "r", encoding="utf-8") as f: return json.load(f) def save_config(data: Dict[str, Any]) -> None: """Save the config dict.""" _ensure_data_dir() with open(CONFIG_FILE, "w", encoding="utf-8") as f: json.dump(data, f, indent=2, ensure_ascii=False) def get_guild_data(guild_id: int) -> Dict[str, Any]: """Get or initialize data for a specific guild.""" config = load_config() gid = str(guild_id) if gid not in config: config[gid] = { "xcom_role_id": None, "xcom_channel_id": None, "isolated_users": {} # user_id -> {"reason": str, "timestamp": str} } save_config(config) return config[gid] def update_guild_data(guild_id: int, key: str, value: Any) -> None: """Update a top-level key for the guild.""" config = load_config() gid = str(guild_id) if gid not in config: config[gid] = { "xcom_role_id": None, "xcom_channel_id": None, "isolated_users": {} } config[gid][key] = value save_config(config) def add_isolated_user(guild_id: int, user_id: int, reason: str, timestamp: str) -> None: """Record a newly isolated user (shared xcom-lounge channel).""" config = load_config() gid = str(guild_id) if gid not in config: config[gid] = {"xcom_role_id": None, "xcom_channel_id": None, "isolated_users": {}} config[gid]["isolated_users"][str(user_id)] = { "reason": reason, "timestamp": timestamp, "absolution_points": 0, "marked": True } save_config(config) def increment_absolution_points(guild_id: int, user_id: int, amount: int = 1) -> int: """Increase absolution points for a user and return the new total.""" config = load_config() gid = str(guild_id) uid = str(user_id) if gid in config and uid in config[gid].get("isolated_users", {}): current = config[gid]["isolated_users"][uid].get("absolution_points", 0) new_total = current + amount config[gid]["isolated_users"][uid]["absolution_points"] = new_total save_config(config) return new_total return 0 def remove_isolated_user(guild_id: int, user_id: int) -> Optional[Dict]: """Remove user from isolation record and return previous data or None.""" config = load_config() gid = str(guild_id) if gid in config and str(user_id) in config[gid].get("isolated_users", {}): data = config[gid]["isolated_users"].pop(str(user_id)) save_config(config) return data return None def get_isolated_users(guild_id: int) -> Dict[str, Dict]: """Return all isolated users for guild.""" data = get_guild_data(guild_id) return data.get("isolated_users", {})