Files
chat/backend/app/routers/messages.py
T
2026-06-14 11:16:42 +08:00

139 lines
4.9 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""消息路由"""
from fastapi import APIRouter, Depends, HTTPException, Query
from sqlalchemy.ext.asyncio import AsyncSession
from app.dependencies import get_db, get_current_user
from app.models.user import User
from app.schemas.message import MessageSend, MessagePage, MarkReadRequest
from app.services.message_service import MessageService
from app.services.conversation_service import ConversationService
router = APIRouter()
@router.get("/{conversation_id}/messages", response_model=dict)
async def get_messages(
conversation_id: str,
before: str | None = Query(None),
limit: int = Query(50, ge=1, le=100),
user: User = Depends(get_current_user),
db: AsyncSession = Depends(get_db),
):
"""获取消息列表(游标分页)"""
service = MessageService(db)
try:
return await service.get_messages(conversation_id, user.id, before, limit)
except ValueError as e:
raise HTTPException(status_code=403, detail=str(e))
@router.get("/{conversation_id}/messages/search")
async def search_messages(
conversation_id: str,
q: str = Query(..., min_length=1, max_length=200),
limit: int = Query(20, ge=1, le=50),
user: User = Depends(get_current_user),
db: AsyncSession = Depends(get_db),
):
"""在会话内搜索消息(用户级)"""
# 验证成员身份
conv_service = ConversationService(db)
detail = await conv_service.get_conversation_detail(conversation_id, user.id)
if not detail:
raise HTTPException(status_code=403, detail="无权访问该会话")
service = MessageService(db)
results = await service.search_messages(
conversation_id=conversation_id,
keyword=q,
limit=limit,
)
return {"results": results}
@router.put("/{conversation_id}/messages/{message_id}/read")
async def mark_as_read(
conversation_id: str,
message_id: str,
user: User = Depends(get_current_user),
db: AsyncSession = Depends(get_db),
):
"""标记消息已读"""
service = MessageService(db)
await service.mark_as_read(conversation_id, user.id, message_id)
return {"success": True}
@router.delete("/{conversation_id}/messages/{message_id}")
async def delete_message(
conversation_id: str,
message_id: str,
user: User = Depends(get_current_user),
db: AsyncSession = Depends(get_db),
):
"""删除消息"""
service = MessageService(db)
try:
await service.soft_delete(message_id, user.id)
return {"success": True}
except ValueError as e:
raise HTTPException(status_code=403, detail=str(e))
@router.post("/{conversation_id}/messages/{message_id}/recall")
async def recall_message(
conversation_id: str,
message_id: str,
user: User = Depends(get_current_user),
db: AsyncSession = Depends(get_db),
):
"""撤回消息(2 分钟内)"""
service = MessageService(db)
try:
await service.recall_message(message_id, user.id)
# 广播撤回事件
from app.services.conversation_service import ConversationService
conv_service = ConversationService(db)
detail = await conv_service.get_conversation_detail(conversation_id, user.id)
if detail and "members" in detail:
from app.websocket.events import EventType
from app.websocket.manager import manager
member_ids = [m["user_id"] for m in detail["members"]]
for uid in member_ids:
await manager.send_to_user(uid, EventType.CHAT_MESSAGE_RECALLED, {
"conversation_id": conversation_id, "message_id": message_id,
"recalled_by": user.id,
})
return {"success": True}
except ValueError as e:
raise HTTPException(status_code=400, detail=str(e))
@router.post("/{conversation_id}/messages/{message_id}/reactions")
async def add_reaction(
conversation_id: str,
message_id: str,
body: dict,
user: User = Depends(get_current_user),
db: AsyncSession = Depends(get_db),
):
"""添加/取消表情回应(toggle"""
service = MessageService(db)
result = await service.react(message_id, user.id, body.get("emoji", ""))
# 广播回应变化
from app.services.conversation_service import ConversationService
from app.websocket.events import EventType
from app.websocket.manager import manager
conv_service = ConversationService(db)
detail = await conv_service.get_conversation_detail(conversation_id, user.id)
if detail and "members" in detail:
member_ids = [m["user_id"] for m in detail["members"]]
etype = EventType.CHAT_REACTION_ADDED if result["action"] == "added" else EventType.CHAT_REACTION_REMOVED
for uid in member_ids:
await manager.send_to_user(uid, etype, {
"conversation_id": conversation_id, "message_id": message_id,
"emoji": result["emoji"], "user_id": user.id,
})
return result