# -*- 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 ReadStatus, 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 CRUD(db_session, Chat).get(filters={'guid': chat_guid, 'is_deleted': False} 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(), ) send_status_replay = schema.WSMessageOut( type='chat.send_status_reply', message_id=message.id, message_guid=message.guid, message_type=message.message_type, chat_guid=chat.guid, ) await socket_manager.broadcast_to_chat(chat_guid, send_message_schema.model_dump_json()) await websocket.send_text(send_status_replay.model_dump_json()) @socket_manager.handler('chat.message_read') async def read_message( websocket: WebSocket, db_session: AsyncSession, current_user: User, 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, ReadStatus) condition = { 'user_id': current_user.user_id, 'chat_guid': incoming_message.chat_guid, } 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'})