feat: add activities API routes and register in api.py
New endpoints:
- GET /activities — full data (normal + evil)
- GET /activities/{section}/{mood} — per-mood activities
- POST /activities/{section}/{mood} — update activities with validation
- POST /activities/reload — force reload from disk
This commit is contained in:
@@ -101,6 +101,7 @@ from routes.config import router as config_router
|
|||||||
from routes.logging_config import router as logging_config_router
|
from routes.logging_config import router as logging_config_router
|
||||||
from routes.voice import router as voice_router
|
from routes.voice import router as voice_router
|
||||||
from routes.memory import router as memory_router
|
from routes.memory import router as memory_router
|
||||||
|
from routes.activities import router as activities_router
|
||||||
|
|
||||||
app.include_router(core_router)
|
app.include_router(core_router)
|
||||||
app.include_router(mood_router)
|
app.include_router(mood_router)
|
||||||
@@ -121,6 +122,7 @@ app.include_router(config_router)
|
|||||||
app.include_router(logging_config_router)
|
app.include_router(logging_config_router)
|
||||||
app.include_router(voice_router)
|
app.include_router(voice_router)
|
||||||
app.include_router(memory_router)
|
app.include_router(memory_router)
|
||||||
|
app.include_router(activities_router)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
73
bot/routes/activities.py
Normal file
73
bot/routes/activities.py
Normal file
@@ -0,0 +1,73 @@
|
|||||||
|
"""Activities API routes — CRUD for mood-based song/game activity lists."""
|
||||||
|
|
||||||
|
from fastapi import APIRouter, Request
|
||||||
|
from fastapi.responses import JSONResponse
|
||||||
|
from utils.logger import get_logger
|
||||||
|
|
||||||
|
logger = get_logger('api')
|
||||||
|
|
||||||
|
router = APIRouter()
|
||||||
|
|
||||||
|
|
||||||
|
@router.get("/activities")
|
||||||
|
def get_all_activities():
|
||||||
|
"""Return the full activities data (normal + evil sections, all moods)."""
|
||||||
|
from utils.activities import get_all_activities
|
||||||
|
return get_all_activities()
|
||||||
|
|
||||||
|
|
||||||
|
@router.get("/activities/{section}/{mood}")
|
||||||
|
def get_mood_activities(section: str, mood: str):
|
||||||
|
"""Return activities for a specific mood.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
section: "normal" or "evil"
|
||||||
|
mood: mood name (e.g. "bubbly", "aggressive")
|
||||||
|
"""
|
||||||
|
if section not in ("normal", "evil"):
|
||||||
|
return JSONResponse(status_code=400, content={"error": "Section must be 'normal' or 'evil'"})
|
||||||
|
|
||||||
|
from utils.activities import get_activities_for_mood
|
||||||
|
activities = get_activities_for_mood(mood, is_evil=(section == "evil"))
|
||||||
|
return {"section": section, "mood": mood, "activities": activities}
|
||||||
|
|
||||||
|
|
||||||
|
@router.post("/activities/{section}/{mood}")
|
||||||
|
async def set_mood_activities(section: str, mood: str, request: Request):
|
||||||
|
"""Update activities for a specific mood.
|
||||||
|
|
||||||
|
Body: {"activities": [{"type": "listening"|"playing", "name": "...", "weight": 1}]}
|
||||||
|
"""
|
||||||
|
if section not in ("normal", "evil"):
|
||||||
|
return JSONResponse(status_code=400, content={"error": "Section must be 'normal' or 'evil'"})
|
||||||
|
|
||||||
|
data = await request.json()
|
||||||
|
activities = data.get("activities")
|
||||||
|
|
||||||
|
if activities is None:
|
||||||
|
return JSONResponse(status_code=400, content={"error": "Request body must include 'activities' list"})
|
||||||
|
|
||||||
|
if not isinstance(activities, list):
|
||||||
|
return JSONResponse(status_code=400, content={"error": "'activities' must be a list"})
|
||||||
|
|
||||||
|
try:
|
||||||
|
from utils.activities import set_activities_for_mood
|
||||||
|
set_activities_for_mood(mood, is_evil=(section == "evil"), activities=activities)
|
||||||
|
logger.info(f"Updated activities for {section}/{mood}: {len(activities)} entries")
|
||||||
|
return {"status": "ok", "section": section, "mood": mood, "count": len(activities)}
|
||||||
|
except ValueError as e:
|
||||||
|
return JSONResponse(status_code=400, content={"error": str(e)})
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"Failed to save activities for {section}/{mood}: {e}")
|
||||||
|
return JSONResponse(status_code=500, content={"error": "Internal server error"})
|
||||||
|
|
||||||
|
|
||||||
|
@router.post("/activities/reload")
|
||||||
|
def reload_activities():
|
||||||
|
"""Force reload activities from disk (useful after hand-editing the YAML)."""
|
||||||
|
from utils.activities import _load_activities
|
||||||
|
data = _load_activities(force=True)
|
||||||
|
normal_count = sum(len(v) for v in data.get("normal", {}).values())
|
||||||
|
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}
|
||||||
Reference in New Issue
Block a user