mirror of
https://github.com/openmax-server/server.git
synced 2026-05-22 19:41:41 +03:00
168 lines
7.0 KiB
Python
168 lines
7.0 KiB
Python
import pydantic
|
||
from classes.baseprocessor import BaseProcessor
|
||
from oneme.models import (
|
||
TypingPayloadModel,
|
||
SendMessagePayloadModel
|
||
)
|
||
|
||
class MessagesProcessors(BaseProcessor):
|
||
async def msg_typing(self, payload, seq, writer, senderId):
|
||
"""Обработчик события печатания"""
|
||
# Валидируем данные пакета
|
||
try:
|
||
TypingPayloadModel.model_validate(payload)
|
||
except pydantic.ValidationError as error:
|
||
self.logger.error(f"Возникли ошибки при валидации пакета: {error}")
|
||
await self._send_error(seq, self.opcodes.MSG_TYPING, self.error_types.INVALID_PAYLOAD, writer)
|
||
return
|
||
|
||
# Извлекаем данные из пакета
|
||
chatId = payload.get("chatId")
|
||
type = payload.get("type") or "TYPING"
|
||
|
||
# Ищем чат в базе данных
|
||
async with self.db_pool.acquire() as conn:
|
||
async with conn.cursor() as cursor:
|
||
await cursor.execute("SELECT * FROM chats WHERE id = %s", (chatId,))
|
||
chat = await cursor.fetchone()
|
||
|
||
# Если чат не найден, отправляем ошибку
|
||
if not chat:
|
||
await self._send_error(seq, self.opcodes.MSG_TYPING, self.error_types.CHAT_NOT_FOUND, writer)
|
||
return
|
||
|
||
# Участники чата
|
||
participants = await self.tools.get_chat_participants(chatId, self.db_pool)
|
||
|
||
# Проверяем, является ли отправитель участником чата
|
||
if int(senderId) not in participants:
|
||
await self._send_error(seq, self.opcodes.MSG_TYPING, self.error_types.CHAT_NOT_ACCESS, writer)
|
||
return
|
||
|
||
# Рассылаем событие участникам чата
|
||
for participant in participants:
|
||
if participant != senderId:
|
||
# Если участник не является отправителем, отправляем
|
||
await self.event(
|
||
participant,
|
||
{
|
||
"eventType": "typing",
|
||
"chatId": chatId,
|
||
"type": type,
|
||
"userId": senderId,
|
||
"writer": writer,
|
||
}
|
||
)
|
||
|
||
# Создаем пакет
|
||
packet = self.proto.pack_packet(
|
||
seq=seq, opcode=self.opcodes.MSG_TYPING
|
||
)
|
||
|
||
# Отправляем пакет
|
||
await self._send(writer, packet)
|
||
|
||
async def msg_send(self, payload, seq, writer, senderId, db_pool):
|
||
"""Функция отправки сообщения"""
|
||
# Валидируем данные пакета
|
||
try:
|
||
SendMessagePayloadModel.model_validate(payload)
|
||
except pydantic.ValidationError as error:
|
||
self.logger.error(f"Возникли ошибки при валидации пакета: {error}")
|
||
await self._send_error(seq, self.opcodes.MSG_SEND, self.error_types.INVALID_PAYLOAD, writer)
|
||
return
|
||
|
||
# Извлекаем данные из пакета
|
||
userId = payload.get("userId")
|
||
chatId = payload.get("chatId")
|
||
message = payload.get("message")
|
||
|
||
elements = message.get("elements") or []
|
||
attaches = message.get("attaches") or []
|
||
cid = message.get("cid") or 0
|
||
text = message.get("text") or ""
|
||
|
||
# Вычисляем ID чата по ID пользователя и ID отправителя,
|
||
# в случае отсутствия ID чата
|
||
if chatId is None:
|
||
chatId = userId ^ senderId
|
||
|
||
# Если клиент хочет отправить сообщение в избранное,
|
||
# то выставляем в качестве ID чата отрицательный ID отправителя
|
||
if chatId == (senderId ^ senderId):
|
||
chatId = -senderId
|
||
participants = [senderId]
|
||
else:
|
||
# Если все таки клиент хочет отправить сообщение в нормальный чат,
|
||
# то ищем его в базе данных (извлекать список участников все таки тоже надо)
|
||
async with db_pool.acquire() as db_connection:
|
||
async with db_connection.cursor() as cursor:
|
||
await cursor.execute("SELECT * FROM chats WHERE id = %s", (chatId,))
|
||
chat = await cursor.fetchone()
|
||
|
||
# Если нет такого чата - выбрасываем ошибку
|
||
if not chat:
|
||
await self._send_error(seq, self.opcodes.MSG_SEND, self.error_types.CHAT_NOT_FOUND, writer)
|
||
return
|
||
|
||
# Список участников
|
||
participants = await self.tools.get_chat_participants(chatId, db_pool)
|
||
|
||
# Проверяем, является ли отправитель участником чата
|
||
if int(senderId) not in participants:
|
||
await self._send_error(seq, self.opcodes.MSG_SEND, self.error_types.CHAT_NOT_ACCESS, writer)
|
||
return
|
||
|
||
# Добавляем сообщение в историю
|
||
messageId, lastMessageId, messageTime = await self.tools.insert_message(
|
||
chatId=chatId,
|
||
senderId=senderId,
|
||
text=text,
|
||
attaches=attaches,
|
||
elements=elements,
|
||
cid=cid,
|
||
type="USER",
|
||
db_pool=self.db_pool
|
||
)
|
||
|
||
# Готовое тело сообщения
|
||
bodyMessage = {
|
||
"id": messageId,
|
||
"time": messageTime,
|
||
"type": "USER",
|
||
"sender": senderId,
|
||
"cid": cid,
|
||
"text": text,
|
||
"attaches": attaches,
|
||
"elements": elements
|
||
}
|
||
|
||
# Отправляем событие всем участникам чата
|
||
for participant in participants:
|
||
await self.event(
|
||
participant,
|
||
{
|
||
"eventType": "new_msg",
|
||
"chatId": 0 if chatId == -senderId else chatId,
|
||
"message": bodyMessage,
|
||
"prevMessageId": lastMessageId,
|
||
"time": messageTime,
|
||
"writer": writer
|
||
}
|
||
)
|
||
|
||
# Данные пакета
|
||
payload = {
|
||
"chatId": 0 if chatId == -senderId else chatId,
|
||
"message": bodyMessage,
|
||
"unread": 0,
|
||
"mark": messageTime
|
||
}
|
||
|
||
# Собираем пакет
|
||
packet = self.proto.pack_packet(
|
||
cmd=self.proto.CMD_OK, seq=seq, opcode=self.opcodes.MSG_SEND, payload=payload
|
||
)
|
||
|
||
# Отправляем
|
||
await self._send(writer, packet) |