# -*- coding = utf-8 -*- # @Time : 2025/3/1 下午4:40 # @File : handlers.py # @Software : PyCharm # @Author : xingc # @Desc : import logging from datetime import datetime from typing import List, Dict import redis.asyncio as aioredis from fastapi import WebSocket from sqlalchemy import select 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 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}) # 判断是否为新聊天 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() # await db_session.refresh(message, attribute_names=["user", "chat"]) # await db_session.refresh(chat, attribute_names=["users"]) 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_json(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'})