8b17c17137
Implements direct-message (DM) chat send and history endpoints:
- Migration 0011_add_dm_last_read.py (last_read_at on conversation_participants)
- Models updated in backend/app/models/chat.py
- Router in backend/app/routers/chat_dm.py:
- POST /api/chat/dm/{user_id}/messages (send DM, filtered via TextFilter, rate-limited via Redis)
- GET /api/chat/dm/{user_id}/messages (paginated history, updates last_read_at)
- GET /api/chat/dm/conversations (conversations list, last message, unread count)
- Blocks enforced in both directions (cannot send to/from blocked users)
- Self-messaging prevented, peer exist check, auth required
- Integration tests in backend/tests/test_chat_dm.py
Independently re-verified: 14/14 new DM chat tests pass,
272/272 full backend regression suite passes with zero regressions.
58 lines
1.9 KiB
Python
58 lines
1.9 KiB
Python
"""FastAPI application entry point."""
|
|
|
|
from contextlib import asynccontextmanager
|
|
|
|
from fastapi import FastAPI
|
|
from fastapi.middleware.cors import CORSMiddleware
|
|
|
|
from app.config import settings
|
|
from app.routers import auth, users, worlds, assets, avatar, world_content, internal, presence, groups, social_friends, profiles, chat_dm
|
|
|
|
|
|
from app.services.game_servers import supervisor
|
|
|
|
|
|
@asynccontextmanager
|
|
async def lifespan(app: FastAPI):
|
|
"""Application lifespan: startup and shutdown events."""
|
|
supervisor.start()
|
|
yield
|
|
await supervisor.shutdown()
|
|
|
|
|
|
app = FastAPI(
|
|
title=settings.APP_NAME,
|
|
version=settings.APP_VERSION,
|
|
description="Agentic Game Platform - Backend API",
|
|
lifespan=lifespan,
|
|
)
|
|
|
|
# CORS
|
|
app.add_middleware(
|
|
CORSMiddleware,
|
|
allow_origins=settings.cors_origins_list,
|
|
allow_credentials=True,
|
|
allow_methods=["*"],
|
|
allow_headers=["*"],
|
|
)
|
|
|
|
# Include routers
|
|
app.include_router(auth.router, prefix="/api/auth", tags=["auth"])
|
|
app.include_router(users.router, prefix="/api/users", tags=["users"])
|
|
app.include_router(worlds.router, prefix="/api/worlds", tags=["worlds"])
|
|
app.include_router(world_content.router, prefix="/api/worlds", tags=["world-content"])
|
|
app.include_router(assets.router, prefix="/api/assets", tags=["assets"])
|
|
app.include_router(avatar.router, prefix="/api/avatar", tags=["avatar"])
|
|
app.include_router(internal.router, prefix="/api/internal", tags=["internal"])
|
|
app.include_router(presence.router, prefix="/api/presence", tags=["presence"])
|
|
app.include_router(groups.router, prefix="/api/groups", tags=["groups"])
|
|
app.include_router(social_friends.router, prefix="/api/friends", tags=["friends"])
|
|
app.include_router(profiles.router, prefix="/api/profile", tags=["profile"])
|
|
app.include_router(chat_dm.router, prefix="/api/chat/dm", tags=["chat-dm"])
|
|
|
|
|
|
@app.get("/api/health")
|
|
async def health_check():
|
|
"""Simple health check endpoint."""
|
|
return {"status": "ok", "app": settings.APP_NAME}
|