MaiBot/src/MaiGoi/config_manager.py

101 lines
4.4 KiB
Python

import toml
# Use tomlkit for dumping to preserve comments/formatting if needed,
# but stick to `toml` for loading unless specific features are required.
import tomlkit
from pathlib import Path
from typing import Dict, Any, Optional
CONFIG_DIR = Path("config")
# Define default filenames for different config types
CONFIG_FILES = {"gui": "gui_config.toml", "lpmm": "lpmm_config.toml", "bot": "bot_config.toml"}
DEFAULT_GUI_CONFIG = {"adapters": [], "theme": "System"} # Add default theme
def get_config_path(config_type: str = "gui") -> Optional[Path]:
"""Gets the full path to the specified config file type."""
filename = CONFIG_FILES.get(config_type)
if not filename:
print(f"[Config] Error: Unknown config type '{config_type}'")
return None
# Determine the base directory relative to this file
# Assumes config_manager.py is in src/MaiGoi/
try:
script_dir = Path(__file__).parent.parent.parent # Project Root (MaiBot-Core/)
config_path = script_dir / CONFIG_DIR / filename
return config_path
except Exception as e:
print(f"[Config] Error determining config path for type '{config_type}': {e}")
return None
def load_config(config_type: str = "gui") -> Dict[str, Any]:
"""Loads the configuration from the specified TOML file type."""
config_path = get_config_path(config_type)
if not config_path:
return {} # Return empty dict if path is invalid
print(f"[Config] Loading {config_type} config from: {config_path}")
default_config_to_use = DEFAULT_GUI_CONFIG if config_type == "gui" else {}
try:
config_path.parent.mkdir(parents=True, exist_ok=True) # Ensure directory exists
if config_path.is_file():
with open(config_path, "r", encoding="utf-8") as f:
# Use standard toml for loading, it's generally more robust
config_data = toml.load(f)
print(f"[Config] {config_type} config loaded successfully.")
# Basic check for GUI config default keys
if config_type == "gui":
if "adapters" not in config_data:
config_data["adapters"] = DEFAULT_GUI_CONFIG["adapters"]
if "theme" not in config_data:
config_data["theme"] = DEFAULT_GUI_CONFIG["theme"]
return config_data
else:
print(f"[Config] {config_type} config file not found, using default.")
# Save default config only if it's the GUI config
if config_type == "gui":
save_config(default_config_to_use, config_type=config_type)
return default_config_to_use.copy() # Return a copy
except FileNotFoundError:
print(f"[Config] {config_type} config file not found (FileNotFoundError), using default.")
if config_type == "gui":
save_config(default_config_to_use, config_type=config_type) # Attempt to save default
return default_config_to_use.copy()
except toml.TomlDecodeError as e:
print(f"[Config] Error decoding {config_type} TOML file: {e}. Using default.")
return default_config_to_use.copy()
except Exception as e:
print(f"[Config] An unexpected error occurred loading {config_type} config: {e}.")
import traceback
traceback.print_exc()
return default_config_to_use.copy()
def save_config(config_data: Dict[str, Any], config_type: str = "gui") -> bool:
"""Saves the configuration dictionary to the specified TOML file type."""
config_path = get_config_path(config_type)
if not config_path:
return False # Cannot save if path is invalid
print(f"[Config] Saving {config_type} config to: {config_path}")
try:
config_path.parent.mkdir(parents=True, exist_ok=True) # Ensure directory exists
with open(config_path, "w", encoding="utf-8") as f:
# Use tomlkit.dump if preserving format/comments is important
# Otherwise, stick to toml.dump for simplicity
tomlkit.dump(config_data, f) # Using tomlkit here
print(f"[Config] {config_type} config saved successfully.")
return True
except IOError as e:
print(f"[Config] Error writing {config_type} config file (IOError): {e}")
except Exception as e:
print(f"[Config] An unexpected error occurred saving {config_type} config: {e}")
import traceback
traceback.print_exc()
return False