feat(chat): 聊天功能
This commit is contained in:
90
core/routers/chat/services.py
Normal file
90
core/routers/chat/services.py
Normal file
@@ -0,0 +1,90 @@
|
||||
# -*- coding = utf-8 -*-
|
||||
# @Time : 2025/3/1 下午4:44
|
||||
# @File : services.py
|
||||
# @Software : PyCharm
|
||||
# @Author : xingc
|
||||
# @Desc :
|
||||
from typing import Dict
|
||||
|
||||
from sqlalchemy import select, and_, func
|
||||
from sqlalchemy.ext.asyncio import AsyncSession
|
||||
from sqlalchemy.orm import aliased, selectinload
|
||||
|
||||
from core.base.exceptions import WebsocketTooManyRequests
|
||||
from core.db.models import User, Chat, ReadStatus, Message
|
||||
from core.routers.auth.schema import LoginUser
|
||||
from core.utils.helper import format_date
|
||||
|
||||
from .schema import ChatUnreadOut
|
||||
|
||||
|
||||
async def websocket_callback(ws, pexpire):
|
||||
raise WebsocketTooManyRequests("Too many requests")
|
||||
|
||||
|
||||
async def get_user_active_direct_chats(
|
||||
db_session: AsyncSession, current_user: User
|
||||
) -> Dict[str, int] | None:
|
||||
"""获取活跃聊天"""
|
||||
direct_chats_dict = dict()
|
||||
query = (
|
||||
select(Chat)
|
||||
.where(and_(Chat.is_deleted.is_(False), Chat.users.contains(current_user)))
|
||||
.options(selectinload(Chat.users))
|
||||
)
|
||||
result = await db_session.execute(query)
|
||||
direct_chats: list[Chat] = result.scalars().all()
|
||||
|
||||
if direct_chats:
|
||||
for direct_chat in direct_chats:
|
||||
direct_chats_dict[str(direct_chat.guid)] = direct_chat.id
|
||||
return direct_chats_dict
|
||||
|
||||
|
||||
async def get_unread_messages_per_chat(
|
||||
db_session: AsyncSession, chats: list[Chat], login_user: LoginUser
|
||||
) -> list[dict]:
|
||||
"""获取聊天未读消息数"""
|
||||
unread_messages_info_per_chat = {chat.id: {'message_count': 0} for chat in chats}
|
||||
|
||||
# 查询消息情况
|
||||
read_status_alias = aliased(ReadStatus)
|
||||
query = (
|
||||
select(Message.chat_id, Message.content, func.count().label("message_count"))
|
||||
.join(
|
||||
read_status_alias,
|
||||
and_(read_status_alias.user_id == login_user.user_id, read_status_alias.chat_id == Message.chat_id),
|
||||
)
|
||||
.where(
|
||||
and_(
|
||||
Message.user_id != login_user.user_id,
|
||||
Message.id > func.coalesce(read_status_alias.last_read_message_id, 0),
|
||||
Message.chat_id.in_(unread_messages_info_per_chat),
|
||||
)
|
||||
)
|
||||
.order_by(Message.created_at.desc())
|
||||
.group_by(Message.chat_id)
|
||||
)
|
||||
result = await db_session.execute(query)
|
||||
unread_messages_info = result.fetchall()
|
||||
|
||||
for messages_info in unread_messages_info:
|
||||
unread_messages_info_per_chat[messages_info[0]] = {
|
||||
'message': messages_info[1],
|
||||
'message_count': messages_info[2],
|
||||
}
|
||||
|
||||
results = []
|
||||
for chat in chats:
|
||||
users = [user for user in await chat.awaitable_attrs.users if user.user_id != login_user.user_id]
|
||||
messages_info = unread_messages_info_per_chat[chat.id]
|
||||
results.append(dict(
|
||||
chat_guid=chat.guid,
|
||||
created_at=format_date(chat.created_at),
|
||||
updated_at=format_date(chat.updated_at),
|
||||
recipient_user=users[0],
|
||||
last_message=messages_info.get('message'),
|
||||
unread_messages_count=messages_info.get('message_count'),
|
||||
))
|
||||
|
||||
return results
|
||||
Reference in New Issue
Block a user