File size: 3,908 Bytes
bef5e76 08df5ae bef5e76 08df5ae bef5e76 08df5ae bef5e76 08df5ae bef5e76 08df5ae bef5e76 08df5ae bef5e76 08df5ae bef5e76 08df5ae bef5e76 08df5ae bef5e76 08df5ae bef5e76 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 | """Room management API endpoints."""
from fastapi import APIRouter, Depends, HTTPException, status
from sqlalchemy.ext.asyncio import AsyncSession
from sqlalchemy import select
from sqlalchemy.orm import selectinload
from src.db.postgres.connection import get_db
from src.db.postgres.models import Room, ChatMessage
from src.middlewares.logging import get_logger, log_execution
from pydantic import BaseModel
from typing import List
from datetime import datetime
import uuid
logger = get_logger("room_api")
router = APIRouter(prefix="/api/v1", tags=["Rooms"])
class ChatMessageResponse(BaseModel):
id: str
role: str
content: str
created_at: str
class RoomResponse(BaseModel):
id: str
title: str
created_at: str
updated_at: str | None
messages: List[ChatMessageResponse] = []
class CreateRoomRequest(BaseModel):
user_id: str
title: str = "New Chat"
@router.get("/rooms/{user_id}", response_model=List[RoomResponse])
@log_execution(logger)
async def list_rooms(
user_id: str,
db: AsyncSession = Depends(get_db)
):
"""List all rooms for a user."""
result = await db.execute(
select(Room)
.where(Room.user_id == user_id, Room.status == "active")
.order_by(Room.updated_at.desc())
)
rooms = result.scalars().all()
return [
RoomResponse(
id=room.id,
title=room.title,
created_at=room.created_at.isoformat(),
updated_at=room.updated_at.isoformat() if room.updated_at else None
)
for room in rooms
]
@router.get("/room/{room_id}", response_model=RoomResponse)
@log_execution(logger)
async def get_room(
room_id: str,
db: AsyncSession = Depends(get_db)
):
"""Get a specific room with its chat history."""
result = await db.execute(
select(Room)
.where(Room.id == room_id)
.options(selectinload(Room.messages))
)
room = result.scalars().first()
if not room:
raise HTTPException(
status_code=404,
detail="Room not found"
)
messages = sorted(room.messages, key=lambda m: m.created_at)
return RoomResponse(
id=room.id,
title=room.title,
created_at=room.created_at.isoformat(),
updated_at=room.updated_at.isoformat() if room.updated_at else None,
messages=[
ChatMessageResponse(
id=msg.id,
role=msg.role,
content=msg.content,
created_at=msg.created_at.isoformat()
)
for msg in messages
]
)
@router.delete("/room/{room_id}")
@log_execution(logger)
async def delete_room(
room_id: str,
user_id: str,
db: AsyncSession = Depends(get_db)
):
"""Soft-delete a room by setting its status to inactive."""
result = await db.execute(
select(Room).where(Room.id == room_id)
)
room = result.scalars().first()
if not room:
raise HTTPException(status_code=404, detail="Room not found")
if room.user_id != user_id:
raise HTTPException(status_code=403, detail="Access denied")
room.status = "inactive"
await db.commit()
return {"status": "success", "message": "Room deleted successfully"}
@router.post("/room/create")
@log_execution(logger)
async def create_room(
request: CreateRoomRequest,
db: AsyncSession = Depends(get_db)
):
"""Create a new room."""
room = Room(
id=str(uuid.uuid4()),
user_id=request.user_id,
title=request.title
)
db.add(room)
await db.commit()
await db.refresh(room)
return {
"status": "success",
"message": "Room created successfully",
"data": RoomResponse(
id=room.id,
title=room.title,
created_at=room.created_at.isoformat(),
updated_at=None
)
}
|