199 lines
5.8 KiB
Python
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)
|