From 09c1f8b6f647666571764be11ec0981fcbcdef97 Mon Sep 17 00:00:00 2001 From: Alexey Polyakov Date: Wed, 18 Mar 2026 21:55:24 +0300 Subject: [PATCH] =?UTF-8?q?=D0=98=D1=81=D1=82=D0=BE=D1=80=D0=B8=D1=8F=20?= =?UTF-8?q?=D1=81=D0=BE=D0=BE=D0=B1=D1=89=D0=B5=D0=BD=D0=B8=D0=B9=20(?= =?UTF-8?q?=D0=B2=D1=80=D0=BE=D0=B4=D0=B5=20=D0=BA=D0=B0=D0=BA=20=D0=B4?= =?UTF-8?q?=D0=B0=D0=B6=D0=B5=20=D1=80=D0=B0=D0=B1=D0=BE=D1=82=D0=B0=D0=B5?= =?UTF-8?q?=D1=82)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/oneme_tcp/models.py | 6 ++- src/oneme_tcp/processors.py | 89 +++++++++++++++++++++++++++++++++++++ src/oneme_tcp/server.py | 4 ++ 3 files changed, 98 insertions(+), 1 deletion(-) diff --git a/src/oneme_tcp/models.py b/src/oneme_tcp/models.py index f8aecdd..26f5508 100644 --- a/src/oneme_tcp/models.py +++ b/src/oneme_tcp/models.py @@ -122,4 +122,8 @@ class AuthConfirmRegisterPayloadModel(pydantic.BaseModel): v = v.strip() if len(v) > 59: raise ValueError('lastName too long') - return v \ No newline at end of file + return v + +class ChatHistoryPayloadModel(pydantic.BaseModel): + chatId: int + backward: int \ No newline at end of file diff --git a/src/oneme_tcp/processors.py b/src/oneme_tcp/processors.py index d97d13a..b89f718 100644 --- a/src/oneme_tcp/processors.py +++ b/src/oneme_tcp/processors.py @@ -1063,6 +1063,95 @@ class Processors: # Отправляем пакет await self._send(writer, packet) + async def process_chat_history(self, payload, seq, writer, senderId): + """Обработчик получения истории чата""" + # Валидируем данные пакета + try: + ChatHistoryPayloadModel.model_validate(payload) + except pydantic.ValidationError as error: + self.logger.error(f"Возникли ошибки при валидации пакета: {error}") + await self._send_error(seq, self.proto.CHAT_HISTORY, self.error_types.INVALID_PAYLOAD, writer) + return + + # Извлекаем данные из пакета + chatId = payload.get("chatId") + forward = payload.get("forward", 0) + backward = payload.get("backward", 0) + from_time = payload.get("from", 0) + getMessages = payload.get("getMessages", True) + messages = [] + + # Проверяем, существует ли чат + 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.proto.CHAT_HISTORY, self.error_types.CHAT_NOT_FOUND, writer) + return + + # Проверяем, является ли пользователь участником чата + participants = json.loads(chat.get("participants")) + if int(senderId) not in participants: + await self._send_error(seq, self.proto.CHAT_HISTORY, self.error_types.CHAT_NOT_ACCESS, writer) + return + + # Если запрошены сообщения + if getMessages: + if backward > 0: + await cursor.execute( + "SELECT * FROM messages WHERE chat_id = %s AND time < %s ORDER BY id DESC LIMIT %s", + (chatId, from_time, backward) + ) + + result = await cursor.fetchall() + + for row in result: + messages.append({ + "id": row.get("id"), + "time": int(row.get("time")), + "type": row.get("type"), + "sender": row.get("sender"), + "text": row.get("text"), + "attaches": json.loads(row.get("attaches")), + "elements": json.loads(row.get("elements")), + "reactionInfo": {} + }) + + if forward > 0: + await cursor.execute( + "SELECT * FROM messages WHERE chat_id = %s AND time > %s ORDER BY id ASC LIMIT %s", + (chatId, from_time, forward) + ) + + result = await cursor.fetchall() + + for row in result: + messages.append({ + "id": row.get("id"), + "time": int(row.get("time")), + "type": row.get("type"), + "sender": row.get("sender"), + "text": row.get("text"), + "attaches": json.loads(row.get("attaches")), + "elements": json.loads(row.get("elements")), + "reactionInfo": {} + }) + + # Формируем ответ + payload = { + "messages": messages + } + + # Собираем пакет + packet = self.proto.pack_packet( + cmd=self.proto.CMD_OK, seq=seq, opcode=self.proto.CHAT_HISTORY, payload=payload + ) + + # Отправялем + await self._send(writer, packet) + async def process_update_profile(self, payload, seq, writer, userId, userPhone): # Валидируем входные данные try: diff --git a/src/oneme_tcp/server.py b/src/oneme_tcp/server.py index bc06e78..c5481ec 100644 --- a/src/oneme_tcp/server.py +++ b/src/oneme_tcp/server.py @@ -129,6 +129,10 @@ class OnemeMobileServer: await self.auth_required( userPhone, self.processors.process_search_chats, payload, seq, writer, userId ) + case self.proto.CHAT_HISTORY: + await self.auth_required( + userPhone, self.processors.process_chat_history, payload, seq, writer, userId + ) case self.proto.CONTACT_INFO_BY_PHONE: await self.auth_required( userPhone, self.processors.process_search_by_phone, payload, seq, writer, userId