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