Fix all activity system edge cases
Critical fixes: - Add threading.Lock for all shared mutable state (override, cache, current activity) - Atomic YAML writes (temp file + os.replace) to prevent corruption on crash - Deep-copy cache on reads to prevent callers from mutating shared state High-severity fixes: - Validate entries in pick_activity_for_mood() — skip/log malformed instead of KeyError - Log warning on unrecognized activity type fallback - Normalize empty-string state to None (avoid 'None' display) - release_manual_override() now uses force=True so bot always shows activity - Add try/except in release_manual_override() to handle failures gracefully Medium fixes: - Remove dead 'test' mood from activities.yaml - Validate name length (128 char Discord limit) in CRUD and manual set - Validate streaming entries have URL in CRUD path - Add JSON parse error handling in API routes - on_ready preserves active manual override instead of overwriting - Log override expiry timestamp (HH:MM:SS) for easier debugging - exc_info=True on presence update errors for full stack traces Low fixes: - JS activitySetFromEntry() shows notification on parse error
This commit is contained in:
@@ -41,7 +41,11 @@ async def set_mood_activities(section: str, mood: str, request: Request):
|
||||
if section not in ("normal", "evil"):
|
||||
return JSONResponse(status_code=400, content={"error": "Section must be 'normal' or 'evil'"})
|
||||
|
||||
data = await request.json()
|
||||
try:
|
||||
data = await request.json()
|
||||
except Exception:
|
||||
return JSONResponse(status_code=400, content={"error": "Invalid JSON body"})
|
||||
|
||||
activities = data.get("activities")
|
||||
|
||||
if activities is None:
|
||||
@@ -97,12 +101,24 @@ async def set_current_activity(request: Request):
|
||||
Body: {"type": "listening"|"playing"|"watching"|"competing"|"streaming",
|
||||
"name": "...", "state": "..." (optional), "url": "..." (required for streaming)}
|
||||
"""
|
||||
data = await request.json()
|
||||
try:
|
||||
data = await request.json()
|
||||
except Exception:
|
||||
return JSONResponse(status_code=400, content={"error": "Invalid JSON body"})
|
||||
|
||||
activity_type = data.get("type", "").lower().strip()
|
||||
name = data.get("name", "").strip()
|
||||
state = data.get("state") or None
|
||||
url = data.get("url") or None
|
||||
|
||||
# Pre-validate before passing to activity module
|
||||
if not activity_type:
|
||||
return JSONResponse(status_code=400, content={"error": "'type' is required"})
|
||||
if not name:
|
||||
return JSONResponse(status_code=400, content={"error": "'name' is required"})
|
||||
if len(name) > 128:
|
||||
return JSONResponse(status_code=400, content={"error": f"'name' exceeds 128 characters ({len(name)})"})
|
||||
|
||||
try:
|
||||
from utils.activities import set_activity_manual
|
||||
await set_activity_manual(activity_type, name, state=state, url=url)
|
||||
|
||||
Reference in New Issue
Block a user