158 lines
6.2 KiB
Python
158 lines
6.2 KiB
Python
"""
|
|
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
|