Refactor activity system: energy-based probability, manual override, all 5 activity types
- Rewrite utils/activities.py with mood energy-driven activity probability (high-energy moods like excited/bubbly show activity ~80-85% of the time, low-energy moods like sleepy/melancholy only ~15-25%) - Add manual override system with 30-min auto-expiry for Web UI control - Support all 5 Discord activity types: listening, playing, watching, competing, streaming (with purple LIVE badge via discord.Streaming) - Add current activity tracking (get_current_activity) - Add force=True param to update_bot_presence for on_ready (bot.py) - Add 4 new API routes for manual override: GET/POST/DELETE /activities/current, POST /activities/current/auto - Expand activities.yaml from 139 to 157 entries, adding watching, competing, and streaming entries across 11 moods - Update Web UI: activity type dropdown with all 5 types, conditional URL field for streaming, 'Current Activity' override panel with set/clear/auto controls, type-aware icons and labels
This commit is contained in:
@@ -71,3 +71,70 @@ def reload_activities():
|
||||
evil_count = sum(len(v) for v in data.get("evil", {}).values())
|
||||
logger.info(f"Force-reloaded activities: {normal_count} normal entries, {evil_count} evil entries")
|
||||
return {"status": "ok", "normal_entries": normal_count, "evil_entries": evil_count}
|
||||
|
||||
|
||||
# ══════════════════════════════════════════════════════════════════════════════
|
||||
# Manual Override — set / clear / release current activity
|
||||
# ══════════════════════════════════════════════════════════════════════════════
|
||||
|
||||
@router.get("/activities/current")
|
||||
def get_current_activity():
|
||||
"""Return the bot's current activity and override status."""
|
||||
from utils.activities import get_current_activity, is_manual_override_active
|
||||
activity = get_current_activity()
|
||||
override = is_manual_override_active()
|
||||
result = {
|
||||
"activity": activity, # dict or null
|
||||
"manual_override": override,
|
||||
}
|
||||
return result
|
||||
|
||||
|
||||
@router.post("/activities/current")
|
||||
async def set_current_activity(request: Request):
|
||||
"""Manually set the bot's activity (bypasses mood system for 30 min).
|
||||
|
||||
Body: {"type": "listening"|"playing"|"watching"|"competing"|"streaming",
|
||||
"name": "...", "state": "..." (optional), "url": "..." (required for streaming)}
|
||||
"""
|
||||
data = await request.json()
|
||||
activity_type = data.get("type", "").lower().strip()
|
||||
name = data.get("name", "").strip()
|
||||
state = data.get("state") or None
|
||||
url = data.get("url") or None
|
||||
|
||||
try:
|
||||
from utils.activities import set_activity_manual
|
||||
await set_activity_manual(activity_type, name, state=state, url=url)
|
||||
return {"status": "ok", "activity": {"type": activity_type, "name": name, "state": state, "url": url}}
|
||||
except ValueError as e:
|
||||
return JSONResponse(status_code=400, content={"error": str(e)})
|
||||
except RuntimeError as e:
|
||||
return JSONResponse(status_code=503, content={"error": str(e)})
|
||||
except Exception as e:
|
||||
logger.error(f"Failed to set manual activity: {e}")
|
||||
return JSONResponse(status_code=500, content={"error": "Internal server error"})
|
||||
|
||||
|
||||
@router.delete("/activities/current")
|
||||
async def clear_current_activity():
|
||||
"""Manually clear the bot's activity (stays idle, override stays active)."""
|
||||
try:
|
||||
from utils.activities import clear_activity_manual
|
||||
await clear_activity_manual()
|
||||
return {"status": "ok", "activity": None, "manual_override": True}
|
||||
except Exception as e:
|
||||
logger.error(f"Failed to clear manual activity: {e}")
|
||||
return JSONResponse(status_code=500, content={"error": "Internal server error"})
|
||||
|
||||
|
||||
@router.post("/activities/current/auto")
|
||||
async def release_to_auto():
|
||||
"""Release manual override and return to automatic mood-based activity."""
|
||||
try:
|
||||
from utils.activities import release_manual_override
|
||||
await release_manual_override()
|
||||
return {"status": "ok", "manual_override": False}
|
||||
except Exception as e:
|
||||
logger.error(f"Failed to release manual override: {e}")
|
||||
return JSONResponse(status_code=500, content={"error": "Internal server error"})
|
||||
|
||||
Reference in New Issue
Block a user