Files
Pterodisbot/generate_config.py
T
k.eaven bec06bd909 feat: Multi-guild support implementation
- Added multi-guild support with comma-separated AllowedGuildIDs config
- Per-guild embed tracking with isolated state
- Per-server action locking to prevent race conditions across guilds
- Cross-guild embed updates after power actions
- Debug logging for embed update triggers
- Fixed resource usage field formatting (brackets now properly closed)
- Updated config.ini.sample, generate_config.py for backward compatibility
- Updated README.md with multi-guild documentation
- Updated tests for multi-guild support
2026-10-30 10:37:13 +00:00

130 lines
4.3 KiB
Python

import os
import configparser
from pathlib import Path
from dotenv import load_dotenv
REQUIRED_VARS = [
'DISCORD_TOKEN',
'ALLOWED_GUILD_ID', # Legacy
'ALLOWED_GUILD_IDS', # New
'PANEL_URL',
'CLIENT_API_KEY',
'APPLICATION_API_KEY'
]
def validate_env_vars():
"""Validate that required environment variables are set and non-empty."""
# Check for either legacy or new guild ID variable
has_guild_id = bool(os.getenv('ALLOWED_GUILD_ID'))
has_guild_ids = bool(os.getenv('ALLOWED_GUILD_IDS'))
if not has_guild_id and not has_guild_ids:
raise ValueError(
"Missing required environment variable: ALLOWED_GUILD_IDS (or legacy ALLOWED_GUILD_ID)"
)
# Check other required vars
missing_vars = [
var for var in ['DISCORD_TOKEN', 'PANEL_URL', 'CLIENT_API_KEY', 'APPLICATION_API_KEY']
if not os.getenv(var)
]
if missing_vars:
raise ValueError(f"Missing required environment variables: {', '.join(missing_vars)}")
def get_env_config():
"""Extract configuration from environment variables."""
# Support both new ALLOWED_GUILD_IDS and legacy ALLOWED_GUILD_ID
allowed_guild_ids = os.getenv('ALLOWED_GUILD_IDS', '')
if not allowed_guild_ids:
allowed_guild_ids = os.getenv('ALLOWED_GUILD_ID', '')
return {
'Discord': {
'Token': os.getenv('DISCORD_TOKEN'),
'AllowedGuildIDs': allowed_guild_ids
},
'Pterodactyl': {
'PanelURL': os.getenv('PANEL_URL'),
'ClientAPIKey': os.getenv('CLIENT_API_KEY'),
'ApplicationAPIKey': os.getenv('APPLICATION_API_KEY')
}
}
def configs_match(existing_config, env_config):
"""Compare existing config with environment variables."""
for section, values in env_config.items():
if not existing_config.has_section(section):
return False
for key, env_value in values.items():
if env_value is None:
# Environment variable not set, don't require match
continue
# For AllowedGuildIDs, also check legacy AllowedGuildID key
check_keys = [key]
if key == 'AllowedGuildIDs':
check_keys.append('AllowedGuildID')
matched = False
for check_key in check_keys:
existing_value = existing_config.get(section, check_key, fallback=None)
if existing_value == env_value:
matched = True
break
if not matched:
return False
return True
def generate_config():
"""
Generate config.ini from environment variables if:
1. No config file exists, OR
2. Config file exists but values don't match environment variables
Environment variables always take priority.
"""
config_path = Path(os.getenv('CONFIG_PATH', 'config.ini'))
# Check if config file exists
if not config_path.exists():
print(f"No config file found at {config_path}, generating from environment variables...")
validate_env_vars()
_write_config(config_path, get_env_config())
return
# Config file exists, read it and compare with environment
existing_config = configparser.ConfigParser()
existing_config.read(config_path)
env_config = get_env_config()
if not configs_match(existing_config, env_config):
print(f"Config file at {config_path} differs from environment variables, regenerating...")
# Validate that required env vars are present for regeneration
validate_env_vars()
_write_config(config_path, env_config)
return
print(f"Config file at {config_path} matches environment variables, using existing config.")
def _write_config(config_path, config_dict):
"""Write config dictionary to file."""
config = configparser.ConfigParser()
for section, values in config_dict.items():
config[section] = {k: str(v) for k, v in values.items() if v is not None}
config_path.parent.mkdir(exist_ok=True, parents=True)
with open(config_path, 'w') as configfile:
config.write(configfile)
print(f"Config file written to {config_path}")
if __name__ == "__main__":
load_dotenv()
generate_config()