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:
2026-04-28 00:18:25 +03:00
parent 2d7acd7850
commit 6080fe170f
5 changed files with 172 additions and 78 deletions

View File

@@ -138,8 +138,11 @@ async def on_ready():
# Set initial Discord presence based on current mood
try:
from utils.activities import update_bot_presence
if globals.EVIL_MODE:
from utils.activities import update_bot_presence, is_manual_override_active
# On reconnect, don't overwrite an active manual override
if is_manual_override_active():
logger.info("Manual override active on ready, preserving it")
elif globals.EVIL_MODE:
await update_bot_presence(globals.EVIL_DM_MOOD, is_evil=True, force=True)
else:
await update_bot_presence(globals.DM_MOOD, is_evil=False, force=True)