Files
X25020501_card_book/core/routers/chat/handlers.py
2025-04-16 14:44:52 +08:00

127 lines
3.8 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 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'})