Files
groovy-zilean/config.py

199 lines
5.8 KiB
Python

# config.py
# Modern configuration management using environment variables
import os
import discord
from discord import Color
from dotenv import load_dotenv
from typing import Optional
# Load environment variables from .env file
load_dotenv()
# ===================================
# Environment Detection
# ===================================
ENVIRONMENT = os.getenv("ENVIRONMENT", "dev").lower()
IS_PRODUCTION = ENVIRONMENT == "live"
IS_DEVELOPMENT = ENVIRONMENT == "dev"
# ===================================
# Discord Configuration
# ===================================
def get_discord_token() -> str:
"""Get the appropriate Discord token based on environment"""
if IS_PRODUCTION:
token = os.getenv("DISCORD_TOKEN_LIVE")
if not token:
raise ValueError("DISCORD_TOKEN_LIVE not found in environment!")
return token
else:
token = os.getenv("DISCORD_TOKEN_DEV")
if not token:
raise ValueError("DISCORD_TOKEN_DEV not found in environment!")
return token
def get_prefix() -> str:
"""Get command prefix (default: =)"""
return os.getenv("DISCORD_PREFIX", "=")
# ===================================
# Spotify Configuration
# ===================================
def get_spotify_creds() -> tuple[str, str]:
"""Get Spotify API credentials"""
client_id = os.getenv("SPOTIFY_CLIENT_ID")
client_secret = os.getenv("SPOTIFY_CLIENT_SECRET")
if not client_id or not client_secret:
raise ValueError("Spotify credentials not found in environment!")
return client_id, client_secret
# ===================================
# Database Configuration
# ===================================
def get_db_path() -> str:
"""Get SQLite database path"""
return os.getenv("DB_PATH", "./data/music.db")
# Future PostgreSQL config
def get_postgres_url() -> Optional[str]:
"""Get PostgreSQL connection URL (for future migration)"""
host = os.getenv("DB_HOST")
port = os.getenv("DB_PORT", "5432")
name = os.getenv("DB_NAME")
user = os.getenv("DB_USER")
password = os.getenv("DB_PASSWORD")
if all([host, name, user, password]):
return f"postgresql://{user}:{password}@{host}:{port}/{name}"
return None
# ===================================
# Bot Status/Presence
# ===================================
def get_status() -> discord.Activity:
"""Get bot status/presence"""
status_type = os.getenv("STATUS_TYPE", "listening").lower()
status_text = os.getenv("STATUS_TEXT", "Zilean's Theme")
status_url = os.getenv("STATUS_URL")
return translate_status(status_type, status_text, status_url)
def translate_status(
status_type: str,
status_text: str,
status_url: Optional[str] = None
) -> discord.Activity:
"""Convert status type string to Discord Activity"""
status_map = {
"playing": discord.ActivityType.playing,
"streaming": discord.ActivityType.streaming,
"listening": discord.ActivityType.listening,
"watching": discord.ActivityType.watching,
"competing": discord.ActivityType.competing,
}
activity_type = status_map.get(status_type)
if not activity_type:
raise ValueError(f"Invalid status type: {status_type}")
# Streaming requires URL
if status_type == "streaming":
if not status_url:
raise ValueError("Streaming status requires STATUS_URL")
return discord.Activity(
type=activity_type,
name=status_text,
url=status_url
)
return discord.Activity(type=activity_type, name=status_text)
# ===================================
# Color Scheme
# ===================================
def get_color(color_name: str) -> Color:
"""Get color from environment (hex format)"""
color_map = {
"primary": os.getenv("COLOR_PRIMARY", "#7289DA"),
"success": os.getenv("COLOR_SUCCESS", "#43B581"),
"error": os.getenv("COLOR_ERROR", "#F04747"),
"warning": os.getenv("COLOR_WARNING", "#FAA61A"),
}
hex_value = color_map.get(color_name.lower())
if not hex_value:
# Default to Discord blurple
hex_value = "#7289DA"
return Color.from_str(hex_value)
# ===================================
# Logging Configuration
# ===================================
def get_log_level() -> str:
"""Get logging level from environment"""
return os.getenv("LOG_LEVEL", "INFO").upper()
# ===================================
# Legacy Support (for backward compatibility)
# ===================================
def get_login(bot: str) -> str:
"""Legacy function - maps to new get_discord_token()"""
# Ignore the 'bot' parameter, use ENVIRONMENT instead
return get_discord_token()
# ===================================
# Validation
# ===================================
def validate_config():
"""Validate that all required config is present"""
errors = []
# Check Discord token
try:
get_discord_token()
except ValueError as e:
errors.append(str(e))
# Check Spotify creds
try:
get_spotify_creds()
except ValueError as e:
errors.append(str(e))
if errors:
error_msg = "\n".join(errors)
raise ValueError(f"Configuration errors:\n{error_msg}")
print(f"✅ Configuration validated (Environment: {ENVIRONMENT})")
# ===================================
# Startup Info
# ===================================
def print_config_info():
"""Print configuration summary (without secrets!)"""
print("=" * 50)
print("🎵 Groovy-Zilean Configuration")
print("=" * 50)
print(f"Environment: {ENVIRONMENT.upper()}")
print(f"Prefix: {get_prefix()}")
print(f"Database: {get_db_path()}")
print(f"Log Level: {get_log_level()}")
print(f"Spotify: {'Configured ✅' if os.getenv('SPOTIFY_CLIENT_ID') else 'Not configured ❌'}")
print("=" * 50)