dynamic config reloading
This commit is contained in:
149
config.py
149
config.py
@@ -6,57 +6,118 @@ from dotenv import load_dotenv
|
||||
# Load environment variables from .env file (if it exists)
|
||||
load_dotenv()
|
||||
|
||||
def load_from_json():
|
||||
#Load config from JSON file if it exists
|
||||
path = Path("data/config.json")
|
||||
if not path.exists():
|
||||
return {}
|
||||
|
||||
try:
|
||||
with open(path, "r", encoding="utf-8") as f:
|
||||
data = json.load(f)
|
||||
return data.get("config", {})
|
||||
except Exception as e:
|
||||
print(f"Error loading config from JSON: {e}")
|
||||
return {}
|
||||
class DynamicConfig:
|
||||
"""Dynamic configuration that reloads from JSON on each access"""
|
||||
|
||||
# Load from JSON or use defaults
|
||||
_config = load_from_json()
|
||||
def __init__(self):
|
||||
self._json_cache = None
|
||||
self._cache_time = 0
|
||||
|
||||
# Helper function to get config value from environment, then JSON, then default
|
||||
def get_config(key: str, default, is_int: bool = False):
|
||||
# 1. Try environment variable first
|
||||
env_val = os.getenv(key)
|
||||
if env_val is not None:
|
||||
return int(env_val) if is_int else env_val
|
||||
# 2. Try JSON config
|
||||
json_val = _config.get(key)
|
||||
if json_val is not None:
|
||||
return json_val
|
||||
# 3. Use default
|
||||
return default
|
||||
def _load_from_json(self):
|
||||
"""Load config from JSON file if it exists"""
|
||||
path = Path("data/config.json")
|
||||
if not path.exists():
|
||||
return {}
|
||||
|
||||
# Torn API
|
||||
TORN_API_KEY = get_config("TORN_API_KEY", "YOUR_TORN_API_KEY_HERE")
|
||||
try:
|
||||
with open(path, "r", encoding="utf-8") as f:
|
||||
data = json.load(f)
|
||||
return data.get("config", {})
|
||||
except Exception as e:
|
||||
print(f"Error loading config from JSON: {e}")
|
||||
return {}
|
||||
|
||||
# FFScouter API
|
||||
FFSCOUTER_KEY = get_config("FFSCOUTER_KEY", "YOUR_FFSCOUTER_KEY_HERE")
|
||||
def _get_value(self, key: str, default, is_int: bool = False):
|
||||
"""Get config value with priority: env vars > json > defaults"""
|
||||
# 1. Try environment variable first (highest priority)
|
||||
env_val = os.getenv(key)
|
||||
if env_val is not None:
|
||||
return int(env_val) if is_int else env_val
|
||||
|
||||
# Discord Bot
|
||||
DISCORD_TOKEN = get_config("DISCORD_TOKEN", "YOUR_DISCORD_BOT_TOKEN_HERE")
|
||||
ALLOWED_CHANNEL_ID = get_config("ALLOWED_CHANNEL_ID", 0, is_int=True)
|
||||
# 2. Try JSON config (reload from file each time)
|
||||
json_config = self._load_from_json()
|
||||
json_val = json_config.get(key)
|
||||
if json_val is not None:
|
||||
return json_val
|
||||
|
||||
# Intervals
|
||||
HIT_CHECK_INTERVAL = get_config("HIT_CHECK_INTERVAL", 60, is_int=True)
|
||||
REASSIGN_DELAY = get_config("REASSIGN_DELAY", 120, is_int=True)
|
||||
# 3. Use default
|
||||
return default
|
||||
|
||||
# Bot Assignment Settings
|
||||
ASSIGNMENT_TIMEOUT = get_config("ASSIGNMENT_TIMEOUT", 60, is_int=True) # Seconds before reassigning a target
|
||||
ASSIGNMENT_REMINDER = get_config("ASSIGNMENT_REMINDER", 45, is_int=True) # Seconds before sending reminder message
|
||||
def reload(self):
|
||||
"""Force reload of JSON config (called after settings update)"""
|
||||
# Just clear cache - next access will reload
|
||||
self._json_cache = None
|
||||
print("[CONFIG] Configuration reloaded from file")
|
||||
|
||||
# Chain Timer Settings
|
||||
CHAIN_TIMER_THRESHOLD = get_config("CHAIN_TIMER_THRESHOLD", 5, is_int=True) # Minutes - start assigning hits when chain timer is at or below this
|
||||
# Torn API
|
||||
@property
|
||||
def TORN_API_KEY(self):
|
||||
return self._get_value("TORN_API_KEY", "YOUR_TORN_API_KEY_HERE")
|
||||
|
||||
# Authentication
|
||||
AUTH_PASSWORD = get_config("AUTH_PASSWORD", "YOUR_AUTH_PASSWORD_HERE") # Universal password for all users
|
||||
JWT_SECRET = get_config("JWT_SECRET", "your-secret-key-change-this") # Secret key for JWT tokens
|
||||
# FFScouter API
|
||||
@property
|
||||
def FFSCOUTER_KEY(self):
|
||||
return self._get_value("FFSCOUTER_KEY", "YOUR_FFSCOUTER_KEY_HERE")
|
||||
|
||||
# Discord Bot
|
||||
@property
|
||||
def DISCORD_TOKEN(self):
|
||||
return self._get_value("DISCORD_TOKEN", "YOUR_DISCORD_BOT_TOKEN_HERE")
|
||||
|
||||
@property
|
||||
def ALLOWED_CHANNEL_ID(self):
|
||||
return self._get_value("ALLOWED_CHANNEL_ID", 0, is_int=True)
|
||||
|
||||
# Intervals
|
||||
@property
|
||||
def HIT_CHECK_INTERVAL(self):
|
||||
return self._get_value("HIT_CHECK_INTERVAL", 60, is_int=True)
|
||||
|
||||
@property
|
||||
def REASSIGN_DELAY(self):
|
||||
return self._get_value("REASSIGN_DELAY", 120, is_int=True)
|
||||
|
||||
# Bot Assignment Settings
|
||||
@property
|
||||
def ASSIGNMENT_TIMEOUT(self):
|
||||
return self._get_value("ASSIGNMENT_TIMEOUT", 60, is_int=True)
|
||||
|
||||
@property
|
||||
def ASSIGNMENT_REMINDER(self):
|
||||
return self._get_value("ASSIGNMENT_REMINDER", 45, is_int=True)
|
||||
|
||||
# Chain Timer Settings
|
||||
@property
|
||||
def CHAIN_TIMER_THRESHOLD(self):
|
||||
return self._get_value("CHAIN_TIMER_THRESHOLD", 5, is_int=True)
|
||||
|
||||
# Authentication
|
||||
@property
|
||||
def AUTH_PASSWORD(self):
|
||||
return self._get_value("AUTH_PASSWORD", "YOUR_AUTH_PASSWORD_HERE")
|
||||
|
||||
@property
|
||||
def JWT_SECRET(self):
|
||||
return self._get_value("JWT_SECRET", "your-secret-key-change-this")
|
||||
|
||||
|
||||
# Create global config instance
|
||||
config = DynamicConfig()
|
||||
|
||||
# Export reload function
|
||||
def reload_config():
|
||||
"""Reload configuration from file"""
|
||||
config.reload()
|
||||
|
||||
# For backward compatibility, access config properties directly
|
||||
# Code using "from config import TORN_API_KEY" needs to be changed to use config.TORN_API_KEY
|
||||
# But we can't do that without breaking existing code, so we need a different approach
|
||||
|
||||
# Instead, we'll make these read from the config instance each time they're accessed
|
||||
# by using __getattr__ at the module level
|
||||
def __getattr__(name):
|
||||
"""Dynamically fetch config values when accessed as module attributes"""
|
||||
if hasattr(config, name):
|
||||
return getattr(config, name)
|
||||
raise AttributeError(f"module '{__name__}' has no attribute '{name}'")
|
||||
|
||||
Reference in New Issue
Block a user