Config page for adding tokens and settings

This commit is contained in:
2026-01-26 15:20:55 -05:00
parent 64749f4743
commit 1754cf8023
9 changed files with 531 additions and 33 deletions

105
main.py
View File

@@ -39,6 +39,10 @@ async def dashboard(request: Request):
print(">>> DASHBOARD ROUTE LOADED")
return templates.TemplateResponse("dashboard.html", {"request": request})
@app.get("/config", response_class=HTMLResponse)
async def config_page(request: Request):
return templates.TemplateResponse("config.html", {"request": request})
# ============================================================
# Pydantic models for JSON POST input
# ============================================================
@@ -61,6 +65,10 @@ class DiscordMappingRequest(BaseModel):
torn_id: int
discord_id: int
class ConfigUpdateRequest(BaseModel):
key: str
value: Optional[str | int]
# ================================
# Helper: load JSON file into STATE
# ================================
@@ -298,6 +306,103 @@ async def remove_discord_mapping(torn_id: int):
else:
raise HTTPException(status_code=404, detail="Mapping not found")
# =============================
# Config endpoints
# =============================
def reload_config_from_file():
"""Reload config values from JSON into module globals"""
path = Path("data/config.json")
if not path.exists():
return
try:
with open(path, "r", encoding="utf-8") as f:
data = json.load(f)
# Update config module globals
import config
for key, value in data.get("config", {}).items():
if hasattr(config, key):
setattr(config, key, value)
except Exception as e:
print(f"Error reloading config from file: {e}")
@app.get("/api/config")
async def get_config():
"""Get all config values (with sensitive values masked)"""
import config
path = Path("data/config.json")
if not path.exists():
# Return defaults from config.py (masked)
config_values = {
"TORN_API_KEY": config.TORN_API_KEY,
"FFSCOUTER_KEY": config.FFSCOUTER_KEY,
"DISCORD_TOKEN": config.DISCORD_TOKEN,
"ALLOWED_CHANNEL_ID": config.ALLOWED_CHANNEL_ID,
"POLL_INTERVAL": config.POLL_INTERVAL,
"HIT_CHECK_INTERVAL": config.HIT_CHECK_INTERVAL,
"REASSIGN_DELAY": config.REASSIGN_DELAY,
"ASSIGNMENT_TIMEOUT": config.ASSIGNMENT_TIMEOUT,
"ASSIGNMENT_REMINDER": config.ASSIGNMENT_REMINDER
}
else:
with open(path, "r", encoding="utf-8") as f:
data = json.load(f)
config_values = data.get("config", {})
# Mask sensitive values
masked_config = config_values.copy()
sensitive = ["TORN_API_KEY", "FFSCOUTER_KEY", "DISCORD_TOKEN"]
for key in sensitive:
if key in masked_config and masked_config[key]:
val = str(masked_config[key])
masked_config[key] = "****" + val[-4:] if len(val) > 4 else "****"
return {"config": masked_config, "sensitive_fields": sensitive}
@app.post("/api/config")
async def update_config(req: ConfigUpdateRequest):
"""Update a single config value"""
path = Path("data/config.json")
# Load existing or create from current config
if path.exists():
with open(path, "r", encoding="utf-8") as f:
data = json.load(f)
else:
import config
data = {
"comment": "Application configuration settings",
"config": {
"TORN_API_KEY": config.TORN_API_KEY,
"FFSCOUTER_KEY": config.FFSCOUTER_KEY,
"DISCORD_TOKEN": config.DISCORD_TOKEN,
"ALLOWED_CHANNEL_ID": config.ALLOWED_CHANNEL_ID,
"POLL_INTERVAL": config.POLL_INTERVAL,
"HIT_CHECK_INTERVAL": config.HIT_CHECK_INTERVAL,
"REASSIGN_DELAY": config.REASSIGN_DELAY,
"ASSIGNMENT_TIMEOUT": config.ASSIGNMENT_TIMEOUT,
"ASSIGNMENT_REMINDER": config.ASSIGNMENT_REMINDER
}
}
# Validate key exists
if req.key not in data["config"]:
raise HTTPException(status_code=400, detail="Invalid config key")
# Update value
data["config"][req.key] = req.value
# Save to file
with open(path, "w", encoding="utf-8") as f:
json.dump(data, f, indent=2)
# Reload config in memory
reload_config_from_file()
return {"status": "ok", "key": req.key}
# ============================================================
# Reset Groups Endpoint