NoahsKI / settings_manager.py
noah33565's picture
Upload 221 files
8d3de43 verified
"""
SETTINGS & CONFIGURATION MANAGEMENT
Handles user preferences, system settings, Discord bot configuration, etc.
"""
import json
import os
from datetime import datetime
from typing import Dict, Optional, Any
from pathlib import Path
import logging
logger = logging.getLogger(__name__)
class SettingsManager:
"""Manages all application and user settings"""
def __init__(self, data_dir='noahski_data'):
self.data_dir = Path(data_dir)
self.settings_dir = self.data_dir / 'settings'
self.settings_dir.mkdir(parents=True, exist_ok=True)
# Global settings file
self.global_settings_file = self.settings_dir / 'global_settings.json'
# User settings directory
self.user_settings_dir = self.settings_dir / 'users'
self.user_settings_dir.mkdir(parents=True, exist_ok=True)
# Load or create global settings
self.global_settings = self._load_global_settings()
logger.info("✅ Settings Manager initialized")
def _load_global_settings(self) -> Dict:
"""Load global settings from file"""
if self.global_settings_file.exists():
try:
with open(self.global_settings_file, 'r', encoding='utf-8') as f:
return json.load(f)
except Exception as e:
logger.error(f"Failed to load global settings: {e}")
# Default global settings
defaults = {
'app_name': 'NoahsKI',
'version': '6.0',
'timezone': 'UTC',
'max_users': 100,
'debug_mode': False,
'enable_logging': True,
'enable_cache': True,
'cache_ttl': 86400,
'rate_limit_enabled': True,
'rate_limit_requests': 100,
'rate_limit_window': 3600,
'image_generation_enabled': True,
'web_search_enabled': True,
'code_generation_enabled': True,
'file_processing_enabled': True,
'features': {
'discord_bot': True,
'web_search': True,
'image_generation': True,
'code_execution': False,
'voice_synthesis': False,
'speech_recognition': False,
'video_processing': False
}
}
self._save_global_settings(defaults)
return defaults
def _save_global_settings(self, settings: Dict):
"""Save global settings to file"""
try:
with open(self.global_settings_file, 'w', encoding='utf-8') as f:
json.dump(settings, f, indent=2, ensure_ascii=False)
except Exception as e:
logger.error(f"Failed to save global settings: {e}")
def get_global_setting(self, key: str, default=None) -> Any:
"""Get a global setting"""
return self.global_settings.get(key, default)
def set_global_setting(self, key: str, value: Any) -> bool:
"""Set a global setting"""
try:
self.global_settings[key] = value
self._save_global_settings(self.global_settings)
logger.info(f"✅ Global setting '{key}' updated")
return True
except Exception as e:
logger.error(f"Failed to set global setting '{key}': {e}")
return False
def get_user_settings(self, email: str) -> Dict:
"""Get all settings for a user"""
user_settings_file = self.user_settings_dir / f"{email}.json"
if user_settings_file.exists():
try:
with open(user_settings_file, 'r', encoding='utf-8') as f:
return json.load(f)
except Exception as e:
logger.error(f"Failed to load user settings for {email}: {e}")
# Default user settings
defaults = {
'email': email,
'created_at': datetime.now().isoformat(),
'theme': 'dark',
'language': 'de',
'timezone': 'UTC',
'notifications_enabled': True,
'email_notifications': False,
'auto_save': True,
'discord_bot': {
'enabled': False,
'prefix': '!',
'status': 'online',
'status_text': 'mit NoahsKI',
'intents': ['messages', 'reactions', 'guild_messages']
},
'chat': {
'theme': 'dark',
'font_size': 16,
'show_timestamps': True,
'show_sources': True,
'auto_scroll': True
},
'privacy': {
'save_chat_history': True,
'allow_feedback': True,
'allow_analytics': False,
'data_retention_days': 90
},
'preferences': {
'agi_enabled': True,
'show_reasoning': False,
'auto_complete': True,
'spell_check': True
},
'developer': {
'show_logs': False,
'show_debug': False,
'api_key': None,
'webhook_url': None
}
}
self._save_user_settings(email, defaults)
return defaults
def _save_user_settings(self, email: str, settings: Dict):
"""Save user settings to file"""
try:
user_settings_file = self.user_settings_dir / f"{email}.json"
with open(user_settings_file, 'w', encoding='utf-8') as f:
json.dump(settings, f, indent=2, ensure_ascii=False)
except Exception as e:
logger.error(f"Failed to save user settings for {email}: {e}")
def update_user_settings(self, email: str, updates: Dict) -> Dict:
"""Update specific user settings"""
try:
settings = self.get_user_settings(email)
# Deep update for nested dicts
for key, value in updates.items():
if key in settings and isinstance(settings[key], dict) and isinstance(value, dict):
settings[key].update(value)
else:
settings[key] = value
settings['updated_at'] = datetime.now().isoformat()
self._save_user_settings(email, settings)
logger.info(f"✅ Settings updated for user: {email}")
return {'success': True, 'settings': settings}
except Exception as e:
logger.error(f"Failed to update settings for {email}: {e}")
return {'success': False, 'error': str(e)}
def get_user_setting(self, email: str, key: str, default=None) -> Any:
"""Get a specific user setting"""
settings = self.get_user_settings(email)
# Support nested keys like "discord_bot.enabled"
if '.' in key:
keys = key.split('.')
value = settings
for k in keys:
if isinstance(value, dict):
value = value.get(k)
else:
return default
return value if value is not None else default
return settings.get(key, default)
def set_user_setting(self, email: str, key: str, value: Any) -> bool:
"""Set a specific user setting"""
try:
settings = self.get_user_settings(email)
# Support nested keys
if '.' in key:
keys = key.split('.')
current = settings
for k in keys[:-1]:
if k not in current:
current[k] = {}
current = current[k]
current[keys[-1]] = value
else:
settings[key] = value
self._save_user_settings(email, settings)
return True
except Exception as e:
logger.error(f"Failed to set user setting '{key}' for {email}: {e}")
return False
def apply_discord_settings(self, email: str, discord_settings: Dict) -> Dict:
"""Apply Discord bot settings"""
try:
result = self.update_user_settings(email, {
'discord_bot': discord_settings
})
if result['success']:
logger.info(f"✅ Discord settings applied for: {email}")
# TODO: Actually start/update Discord bot with these settings
return result
except Exception as e:
logger.error(f"Failed to apply Discord settings: {e}")
return {'success': False, 'error': str(e)}
def apply_theme(self, email: str, theme: str) -> bool:
"""Apply theme setting"""
if theme not in ['light', 'dark', 'auto']:
logger.warning(f"Invalid theme: {theme}")
return False
return self.set_user_setting(email, 'theme', theme)
def apply_language(self, email: str, language: str) -> bool:
"""Apply language setting"""
if language not in ['de', 'en', 'fr', 'es', 'ja', 'zh']:
logger.warning(f"Invalid language: {language}")
return False
return self.set_user_setting(email, 'language', language)
def apply_chat_settings(self, email: str, chat_settings: Dict) -> bool:
"""Apply chat UI settings"""
return self.update_user_settings(email, {
'chat': chat_settings
}).get('success', False)
def apply_privacy_settings(self, email: str, privacy_settings: Dict) -> bool:
"""Apply privacy settings"""
return self.update_user_settings(email, {
'privacy': privacy_settings
}).get('success', False)
def export_user_data(self, email: str) -> Dict:
"""Export all user data"""
try:
settings = self.get_user_settings(email)
return {
'success': True,
'email': email,
'exported_at': datetime.now().isoformat(),
'settings': settings
}
except Exception as e:
logger.error(f"Failed to export user data for {email}: {e}")
return {'success': False, 'error': str(e)}
def reset_user_settings(self, email: str) -> bool:
"""Reset user settings to defaults"""
try:
user_settings_file = self.user_settings_dir / f"{email}.json"
if user_settings_file.exists():
user_settings_file.unlink()
# Recreate defaults
self.get_user_settings(email)
logger.info(f"✅ Settings reset for user: {email}")
return True
except Exception as e:
logger.error(f"Failed to reset settings for {email}: {e}")
return False
def get_all_user_emails(self) -> list:
"""Get list of all users with settings"""
try:
emails = [f.stem for f in self.user_settings_dir.glob('*.json')]
return emails
except Exception as e:
logger.error(f"Failed to get user list: {e}")
return []
def get_settings_summary(self) -> Dict:
"""Get summary of all settings"""
return {
'global_settings_file': str(self.global_settings_file),
'user_settings_dir': str(self.user_settings_dir),
'total_users': len(self.get_all_user_emails()),
'global_settings_keys': list(self.global_settings.keys()),
'timestamp': datetime.now().isoformat()
}
# Global instance
_settings_manager = None
def get_settings_manager() -> SettingsManager:
"""Get singleton settings manager"""
global _settings_manager
if _settings_manager is None:
_settings_manager = SettingsManager()
return _settings_manager
def init_settings_manager(data_dir='noahski_data') -> SettingsManager:
"""Initialize settings manager with custom data directory"""
global _settings_manager
_settings_manager = SettingsManager(data_dir)
return _settings_manager