diff --git a/src/oneme/processors.py b/src/oneme/processors.py index 6cb6008..2b76391 100644 --- a/src/oneme/processors.py +++ b/src/oneme/processors.py @@ -1148,7 +1148,7 @@ class Processors: if getMessages: if backward > 0: await cursor.execute( - "SELECT * FROM messages WHERE chat_id = %s AND time < %s ORDER BY id DESC LIMIT %s", + "SELECT * FROM messages WHERE chat_id = %s AND time < %s ORDER BY time ASC LIMIT %s", (chatId, from_time, backward) ) @@ -1168,7 +1168,7 @@ class Processors: if forward > 0: await cursor.execute( - "SELECT * FROM messages WHERE chat_id = %s AND time > %s ORDER BY id ASC LIMIT %s", + "SELECT * FROM messages WHERE chat_id = %s AND time > %s ORDER BY time ASC LIMIT %s", (chatId, from_time, forward) ) @@ -1186,6 +1186,9 @@ class Processors: "reactionInfo": {} }) + # Сортируем сообщения по времени + messages.sort(key=lambda x: x["time"]) + # Формируем ответ payload = { "messages": messages diff --git a/src/tamtam/models.py b/src/tamtam/models.py index 7d72e59..63eefdf 100644 --- a/src/tamtam/models.py +++ b/src/tamtam/models.py @@ -37,4 +37,8 @@ class SearchUsersPayloadModel(pydantic.BaseModel): contactIds: list class PingPayloadModel(pydantic.BaseModel): - interactive: bool \ No newline at end of file + interactive: bool + +class ChatHistoryPayloadModel(pydantic.BaseModel): + chatId: int + backward: int \ No newline at end of file diff --git a/src/tamtam/processors/__init__.py b/src/tamtam/processors/__init__.py index 4c798db..de52007 100644 --- a/src/tamtam/processors/__init__.py +++ b/src/tamtam/processors/__init__.py @@ -1,6 +1,10 @@ from .main import MainProcessors from .auth import AuthProcessors from .search import SearchProcessors +from .history import HistoryProcessors -class Processors(MainProcessors, AuthProcessors, SearchProcessors): +class Processors(MainProcessors, + AuthProcessors, + SearchProcessors, + HistoryProcessors): pass \ No newline at end of file diff --git a/src/tamtam/processors/history.py b/src/tamtam/processors/history.py new file mode 100644 index 0000000..4d5d74c --- /dev/null +++ b/src/tamtam/processors/history.py @@ -0,0 +1,98 @@ +import pydantic +import json +from classes.baseprocessor import BaseProcessor +from tamtam.models import ChatHistoryPayloadModel + +class HistoryProcessors(BaseProcessor): + async def 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.opcodes.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.opcodes.CHAT_HISTORY, 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.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 time ASC 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 time 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": {} + }) + + # Сортируем сообщения по времени + messages.sort(key=lambda x: x["time"]) + + # Формируем ответ + payload = { + "messages": messages + } + + # Собираем пакет + packet = self.proto.pack_packet( + cmd=self.proto.CMD_OK, seq=seq, opcode=self.opcodes.CHAT_HISTORY, payload=payload + ) + + # Отправялем + await self._send(writer, packet) \ No newline at end of file diff --git a/src/tamtam/websocket.py b/src/tamtam/websocket.py index 7a20da1..2a260fc 100644 --- a/src/tamtam/websocket.py +++ b/src/tamtam/websocket.py @@ -95,6 +95,10 @@ class TTWebSocketServer: await self.auth_required( userPhone, self.processors.contact_info, payload, seq, websocket ) + case self.opcodes.CHAT_HISTORY: + await self.auth_required( + userPhone, self.processors.chat_history, payload, seq, websocket, userId + ) case _: self.logger.warning(f"Неизвестный опкод {opcode}") except websockets.exceptions.ConnectionClosed: