""" Configuration management for Twitch Archive. Handles loading global and per-streamer configuration files. """ import json import pathlib from typing import Dict, Any from colorama import Fore, Style from .constants import DEFAULT_CONFIG class ConfigManager: """ Manages global and per-streamer configurations. Loads global defaults from config/global.json and merges with per-streamer configs from config/streamers/*.json. """ def __init__(self): """Initialize the configuration manager.""" self.config_dir = pathlib.Path(__file__).parent.parent / "config" self.streamers_dir = self.config_dir / "streamers" self.global_config = self._load_global_config() def _load_global_config(self) -> Dict[str, Any]: """ Load global configuration from config/global.json. Returns: dict: Global configuration with defaults """ global_file = self.config_dir / "global.json" # Start with DEFAULT_CONFIG as ultimate fallback config = DEFAULT_CONFIG.copy() # Try to load global config if global_file.exists(): try: with open(global_file, 'r', encoding='utf-8') as f: user_config = json.load(f) # Filter out comment fields and schema references user_config = {k: v for k, v in user_config.items() if not k.startswith('_') and k != '$schema'} config.update(user_config) print(f'{Fore.GREEN}✓ Global configuration loaded from config/global.json{Style.RESET_ALL}') except json.JSONDecodeError as e: print(f'{Fore.YELLOW}⚠ Warning: Invalid JSON in config/global.json: {e}{Style.RESET_ALL}') print(f'{Fore.YELLOW} Using default configuration{Style.RESET_ALL}') except Exception as e: print(f'{Fore.YELLOW}⚠ Warning: Could not load config/global.json: {e}{Style.RESET_ALL}') else: print(f'{Fore.YELLOW}⚠ Warning: config/global.json not found{Style.RESET_ALL}') print(f'{Fore.CYAN} → Create config/global.json with default settings{Style.RESET_ALL}') return config def load_streamer_config(self, username: str) -> Dict[str, Any]: """ Load configuration for a specific streamer. Merges global config with streamer-specific overrides. Args: username: Twitch username Returns: dict: Complete configuration for the streamer """ # Start with global config config = self.global_config.copy() # Load streamer-specific config streamer_file = self.streamers_dir / f"{username}.json" if streamer_file.exists(): try: with open(streamer_file, 'r', encoding='utf-8') as f: streamer_config = json.load(f) # Filter out comments and schema references streamer_config = {k: v for k, v in streamer_config.items() if not k.startswith('_') and k != '$schema'} # Merge streamer config (overrides global) config.update(streamer_config) print(f'{Fore.GREEN}✓ Loaded config for {username}{Style.RESET_ALL}') except json.JSONDecodeError as e: print(f'{Fore.YELLOW}⚠ Warning: Invalid JSON in {streamer_file}: {e}{Style.RESET_ALL}') except Exception as e: print(f'{Fore.YELLOW}⚠ Warning: Could not load {streamer_file}: {e}{Style.RESET_ALL}') else: # Create default config for new streamer print(f'{Fore.CYAN}→ Creating default config for new streamer: {username}{Style.RESET_ALL}') self.create_default_streamer_config(username) config['username'] = username config['enabled'] = True # Ensure username is set config['username'] = username return config def create_default_streamer_config(self, username: str) -> None: """ Create a default configuration file for a new streamer. Args: username: Twitch username """ # Ensure streamers directory exists self.streamers_dir.mkdir(parents=True, exist_ok=True) streamer_file = self.streamers_dir / f"{username}.json" default_config = { "$schema": "../streamer.schema.json", "username": username, "enabled": True } try: with open(streamer_file, 'w', encoding='utf-8') as f: json.dump(default_config, f, indent=2) print(f'{Fore.GREEN}✓ Created config file: config/streamers/{username}.json{Style.RESET_ALL}') print(f'{Fore.CYAN} → Edit the file to add custom settings or overrides{Style.RESET_ALL}') except Exception as e: print(f'{Fore.RED}✗ Could not create config file for {username}: {e}{Style.RESET_ALL}') def get_all_enabled_streamers(self) -> list: """ Get list of all enabled streamers. Returns: list: List of usernames configured and enabled """ if not self.streamers_dir.exists(): return [] enabled_streamers = [] for config_file in self.streamers_dir.glob("*.json"): try: with open(config_file, 'r', encoding='utf-8') as f: config = json.load(f) # Filter comments and schema references config = {k: v for k, v in config.items() if not k.startswith('_') and k != '$schema'} if config.get('enabled', False): username = config.get('username') or config_file.stem enabled_streamers.append(username) except Exception as e: print(f'{Fore.YELLOW}⚠ Warning: Could not read {config_file}: {e}{Style.RESET_ALL}') return enabled_streamers