Files

120 lines
3.5 KiB
Python

# -*- coding = utf-8 -*-
# @Time : 2025/3/1 下午4:40
# @File : handlers.py
# @Software : PyCharm
# @Author : xingc
# @Desc :
import logging
from datetime import datetime
from fastapi import WebSocket
from sqlalchemy.ext.asyncio import AsyncSession
from core.db.crud import CRUD
from core.db.models import ChatParticipant, User, Chat, Message
from .managers import SocketManager
from . import schema
from .services import get_chat
logger = logging.getLogger(__name__)
socket_manager = SocketManager()
@socket_manager.handler('chat.new_message')
async def send_new_message(
websocket: WebSocket,
db_session: AsyncSession,
chats: dict,
current_user: User,
incoming_message: schema.WSMessage,
):
chat_guid: str = str(incoming_message.chat_guid)
chat: Chat | None = await get_chat(chat_guid, current_user, db_session)
# 判断是否为新聊天
if not chats or chat_guid not in chats:
if chat:
chats[chat_guid] = chat.id
await socket_manager.add_user_to_chat(chat_guid, websocket)
else:
logger.warning(f'chat {chat_guid} not found')
await socket_manager.send_error('聊天尚未添加', websocket)
return
chat_id = chats.get(chat_guid)
try:
message = Message(
guid=incoming_message.message_guid,
user_id=current_user.user_id,
chat_id=chat_id,
message_type=incoming_message.message_type,
content=incoming_message.content,
)
db_session.add(message)
chat.updated_at = datetime.now()
db_session.add(chat)
await db_session.flush()
await db_session.commit()
except Exception as exc_info:
await db_session.rollback()
logger.exception(f"[new_message] Exception, rolling back session, detail: {exc_info}")
raise exc_info
send_message_schema = schema.WSMessageOut(
type='chat.new_message',
message_id=message.id,
message_guid=message.guid,
message_type=message.message_type,
chat_guid=chat.guid,
content=message.content,
friend_user=current_user.dict(),
)
await socket_manager.broadcast_to_chat(chat_guid, send_message_schema.model_dump_json())
@socket_manager.handler('chat.message_read')
async def read_message(
websocket: WebSocket,
db_session: AsyncSession,
current_user: User,
chats: dict,
incoming_message: schema.WSMessage,
):
last_read_message_id: str | None = incoming_message.content
if not last_read_message_id:
return
db_crud = CRUD(db_session, ChatParticipant)
chat_guid: str = str(incoming_message.chat_guid)
chat: Chat | None = await get_chat(chat_guid, current_user, db_session)
if chat is None:
await socket_manager.send_error('聊天尚未添加', websocket)
return
condition = {
'user_id': current_user.user_id,
'chat_id': chat.id,
}
result = await db_crud.update(filters=condition, data={'last_read_message_id': last_read_message_id})
if result is None:
await db_crud.create(
data={
**condition,
'last_read_message_id': last_read_message_id
},
filters=condition
)
@socket_manager.handler('chat.ping')
async def ping(
websocket: WebSocket,
db_session: AsyncSession,
current_user: User,
incoming_message: schema.WSMessage,
):
await websocket.send_json({'type': 'chat.send_status_reply', 'status': 'ok'})