from functools import lru_cache from pydantic_settings import BaseSettings class Settings(BaseSettings): """Application settings""" # Application app_env: str = "development" debug: bool = True secret_key: str # Database database_url: str db_pool_size: int = 20 db_max_overflow: int = 10 # Redis redis_url: str = "redis://localhost:6379/0" # Discord OAuth discord_client_id: str discord_client_secret: str discord_redirect_uri: str # Legacy frontend callback discord_server_redirect_uri: str = "" # Server-side callback URL frontend_url: str = "http://localhost:3000" # Frontend base URL for redirects # Access Control - Comma-separated list of allowed Discord user IDs # Leave empty or set to "*" to allow all users (NOT recommended for production) allowed_discord_ids: str = "" # League APIs sba_api_url: str sba_api_key: str pd_api_url: str pd_api_key: str # WebSocket ws_heartbeat_interval: int = 30 ws_connection_timeout: int = 60 # CORS cors_origins: list[str] = ["http://localhost:3000", "http://localhost:3001"] # Game settings max_concurrent_games: int = 20 game_idle_timeout: int = 86400 # 24 hours # Game eviction settings (memory management) game_idle_timeout_hours: int = 24 # Evict games idle > 24 hours game_eviction_interval_minutes: int = 60 # Check every hour game_max_in_memory: int = 500 # Hard limit on in-memory games # Rate limiting settings rate_limit_websocket_per_minute: int = 120 # Events per minute per connection rate_limit_api_per_minute: int = 100 # API calls per minute per user rate_limit_decision_per_game: int = 20 # Decisions per minute per game rate_limit_roll_per_game: int = 30 # Rolls per minute per game rate_limit_substitution_per_game: int = 15 # Substitutions per minute per game rate_limit_cleanup_interval: int = 300 # Cleanup stale buckets every 5 min class Config: env_file = ".env" case_sensitive = False @lru_cache def get_settings() -> Settings: """Get cached settings instance""" return Settings()