From c5721f3f9ef752e9210fa09d41c8158eb18b2be5 Mon Sep 17 00:00:00 2001 From: Alexey Polyakov Date: Wed, 13 May 2026 18:56:27 +0300 Subject: [PATCH] =?UTF-8?q?=D0=92=D1=80=D0=BE=D0=B4=D0=B5=20=D0=BA=D0=B0?= =?UTF-8?q?=D0=BA=20=D0=BD=D0=BE=D1=80=D0=BC=D0=B0=D0=BB=D1=8C=D0=BD=D1=8B?= =?UTF-8?q?=D0=B5=20=D0=B7=D0=B0=D0=B3=D0=BB=D1=83=D1=88=D0=BA=D0=B8=20?= =?UTF-8?q?=D0=BF=D0=BE=D0=B4=20=D0=B0=D1=81=D1=81=D0=B5=D1=82=D1=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/oneme/models.py | 26 +++++ src/oneme/processors/assets.py | 162 +++++++++++++++++++++++++++++--- src/oneme/socket.py | 48 ++++++++++ src/oneme/websocket.py | 48 ++++++++++ src/tamtam/models.py | 26 +++++ src/tamtam/processors/assets.py | 159 ++++++++++++++++++++++++++++--- src/tamtam/socket.py | 24 +++++ src/tamtam/websocket.py | 24 +++++ 8 files changed, 491 insertions(+), 26 deletions(-) diff --git a/src/oneme/models.py b/src/oneme/models.py index ee4ccc3..8bd57e2 100644 --- a/src/oneme/models.py +++ b/src/oneme/models.py @@ -54,6 +54,32 @@ class AssetsPayloadModel(pydantic.BaseModel): sync: int type: str +class AssetsGetPayloadModel(pydantic.BaseModel): + type: str + count: int = 100 + query: str = None + +class AssetsGetByIdsPayloadModel(pydantic.BaseModel): + type: str + ids: list + +class AssetsAddPayloadModel(pydantic.BaseModel): + type: str + id: int = None + +class AssetsRemovePayloadModel(pydantic.BaseModel): + type: str + ids: list + +class AssetsMovePayloadModel(pydantic.BaseModel): + type: str + id: int + position: int + +class AssetsListModifyPayloadModel(pydantic.BaseModel): + type: str + ids: list + class GetCallHistoryPayloadModel(pydantic.BaseModel): forward: bool count: int diff --git a/src/oneme/processors/assets.py b/src/oneme/processors/assets.py index 45e1c15..78c39ae 100644 --- a/src/oneme/processors/assets.py +++ b/src/oneme/processors/assets.py @@ -1,31 +1,167 @@ import pydantic import time from classes.baseprocessor import BaseProcessor -from oneme.models import AssetsPayloadModel +from oneme.models import ( + AssetsPayloadModel, + AssetsGetPayloadModel, + AssetsGetByIdsPayloadModel, + AssetsAddPayloadModel, + AssetsRemovePayloadModel, + AssetsMovePayloadModel, + AssetsListModifyPayloadModel, +) class AssetsProcessors(BaseProcessor): async def assets_update(self, payload, seq, writer): - """Обработчик запроса ассетов клиента на сервере""" - # Валидируем данные пакета try: AssetsPayloadModel.model_validate(payload) except pydantic.ValidationError as error: self.logger.error(f"Возникли ошибки при валидации пакета: {error}") await self._send_error(seq, self.opcodes.ASSETS_UPDATE, self.error_types.INVALID_PAYLOAD, writer) return - - # TODO: сейчас это заглушка, а попозже нужно сделать полноценную реализацию - # Данные пакета - payload = { - "sections": [], - "sync": int(time.time() * 1000) + response = { + "sync": int(time.time() * 1000), + "stickerSetsUpdates": {}, + "stickersUpdates": {}, + "stickersOrder": [ + "RECENT", + "FAVORITE_STICKERS", + "FAVORITE_STICKER_SETS", + "TOP", + "NEW", + "NEW_STICKER_SETS", + ], + "sections": [ + { + "id": "RECENT", + "type": "RECENTS", + "recentsList": [], + }, + { + "id": "FAVORITE_STICKERS", + "type": "STICKERS", + "stickers": [], + "marker": None, + }, + { + "id": "FAVORITE_STICKER_SETS", + "type": "STICKER_SETS", + "stickerSets": [], + "marker": None, + }, + { + "id": "TOP", + "type": "STICKERS", + "stickers": [], + "marker": None, + }, + { + "id": "NEW", + "type": "STICKERS", + "stickers": [], + "marker": None, + }, + { + "id": "NEW_STICKER_SETS", + "type": "STICKER_SETS", + "stickerSets": [], + "marker": None, + }, + ], } - # Собираем пакет packet = self.proto.pack_packet( - cmd=self.proto.CMD_OK, seq=seq, opcode=self.opcodes.ASSETS_UPDATE, payload=payload + cmd=self.proto.CMD_OK, seq=seq, opcode=self.opcodes.ASSETS_UPDATE, payload=response ) + await self._send(writer, packet) - # Отправляем - await self._send(writer, packet) \ No newline at end of file + async def assets_get(self, payload, seq, writer): + try: + data = AssetsGetPayloadModel.model_validate(payload) + except pydantic.ValidationError as error: + self.logger.error(f"Возникли ошибки при валидации пакета: {error}") + await self._send_error(seq, self.opcodes.ASSETS_GET, self.error_types.INVALID_PAYLOAD, writer) + return + + asset_type = data.type + if asset_type == "STICKER_SET": + response = {"stickerSets": [], "marker": None} + else: + response = {"stickers": [], "marker": None} + + packet = self.proto.pack_packet( + cmd=self.proto.CMD_OK, seq=seq, opcode=self.opcodes.ASSETS_GET, payload=response + ) + await self._send(writer, packet) + + async def assets_get_by_ids(self, payload, seq, writer): + try: + data = AssetsGetByIdsPayloadModel.model_validate(payload) + except pydantic.ValidationError as error: + self.logger.error(f"Возникли ошибки при валидации пакета: {error}") + await self._send_error(seq, self.opcodes.ASSETS_GET_BY_IDS, self.error_types.INVALID_PAYLOAD, writer) + return + + asset_type = data.type + if asset_type == "STICKER_SET": + response = {"stickerSets": []} + else: + response = {"stickers": []} + + packet = self.proto.pack_packet( + cmd=self.proto.CMD_OK, seq=seq, opcode=self.opcodes.ASSETS_GET_BY_IDS, payload=response + ) + await self._send(writer, packet) + + async def assets_add(self, payload, seq, writer): + try: + AssetsAddPayloadModel.model_validate(payload) + except pydantic.ValidationError as error: + self.logger.error(f"Возникли ошибки при валидации пакета: {error}") + await self._send_error(seq, self.opcodes.ASSETS_ADD, self.error_types.INVALID_PAYLOAD, writer) + return + + packet = self.proto.pack_packet( + cmd=self.proto.CMD_OK, seq=seq, opcode=self.opcodes.ASSETS_ADD, payload={} + ) + await self._send(writer, packet) + + async def assets_remove(self, payload, seq, writer): + try: + AssetsRemovePayloadModel.model_validate(payload) + except pydantic.ValidationError as error: + self.logger.error(f"Возникли ошибки при валидации пакета: {error}") + await self._send_error(seq, self.opcodes.ASSETS_REMOVE, self.error_types.INVALID_PAYLOAD, writer) + return + + packet = self.proto.pack_packet( + cmd=self.proto.CMD_OK, seq=seq, opcode=self.opcodes.ASSETS_REMOVE, payload={} + ) + await self._send(writer, packet) + + async def assets_move(self, payload, seq, writer): + try: + AssetsMovePayloadModel.model_validate(payload) + except pydantic.ValidationError as error: + self.logger.error(f"Возникли ошибки при валидации пакета: {error}") + await self._send_error(seq, self.opcodes.ASSETS_MOVE, self.error_types.INVALID_PAYLOAD, writer) + return + + packet = self.proto.pack_packet( + cmd=self.proto.CMD_OK, seq=seq, opcode=self.opcodes.ASSETS_MOVE, payload={} + ) + await self._send(writer, packet) + + async def assets_list_modify(self, payload, seq, writer): + try: + AssetsListModifyPayloadModel.model_validate(payload) + except pydantic.ValidationError as error: + self.logger.error(f"Возникли ошибки при валидации пакета: {error}") + await self._send_error(seq, self.opcodes.ASSETS_LIST_MODIFY, self.error_types.INVALID_PAYLOAD, writer) + return + + packet = self.proto.pack_packet( + cmd=self.proto.CMD_OK, seq=seq, opcode=self.opcodes.ASSETS_LIST_MODIFY, payload={} + ) + await self._send(writer, packet) diff --git a/src/oneme/socket.py b/src/oneme/socket.py index 2945ca3..bcaa3af 100644 --- a/src/oneme/socket.py +++ b/src/oneme/socket.py @@ -168,6 +168,54 @@ class OnemeMobile: seq, writer, ) + case self.opcodes.ASSETS_GET: + await self.auth_required( + userPhone, + self.processors.assets_get, + payload, + seq, + writer, + ) + case self.opcodes.ASSETS_GET_BY_IDS: + await self.auth_required( + userPhone, + self.processors.assets_get_by_ids, + payload, + seq, + writer, + ) + case self.opcodes.ASSETS_ADD: + await self.auth_required( + userPhone, + self.processors.assets_add, + payload, + seq, + writer, + ) + case self.opcodes.ASSETS_REMOVE: + await self.auth_required( + userPhone, + self.processors.assets_remove, + payload, + seq, + writer, + ) + case self.opcodes.ASSETS_MOVE: + await self.auth_required( + userPhone, + self.processors.assets_move, + payload, + seq, + writer, + ) + case self.opcodes.ASSETS_LIST_MODIFY: + await self.auth_required( + userPhone, + self.processors.assets_list_modify, + payload, + seq, + writer, + ) case self.opcodes.VIDEO_CHAT_HISTORY: await self.auth_required( userPhone, diff --git a/src/oneme/websocket.py b/src/oneme/websocket.py index ea5beaa..63e852d 100644 --- a/src/oneme/websocket.py +++ b/src/oneme/websocket.py @@ -151,6 +151,54 @@ class OnemeWS: seq, websocket, ) + case self.opcodes.ASSETS_GET: + await self.auth_required( + userPhone, + self.processors.assets_get, + payload, + seq, + websocket, + ) + case self.opcodes.ASSETS_GET_BY_IDS: + await self.auth_required( + userPhone, + self.processors.assets_get_by_ids, + payload, + seq, + websocket, + ) + case self.opcodes.ASSETS_ADD: + await self.auth_required( + userPhone, + self.processors.assets_add, + payload, + seq, + websocket, + ) + case self.opcodes.ASSETS_REMOVE: + await self.auth_required( + userPhone, + self.processors.assets_remove, + payload, + seq, + websocket, + ) + case self.opcodes.ASSETS_MOVE: + await self.auth_required( + userPhone, + self.processors.assets_move, + payload, + seq, + websocket, + ) + case self.opcodes.ASSETS_LIST_MODIFY: + await self.auth_required( + userPhone, + self.processors.assets_list_modify, + payload, + seq, + websocket, + ) case self.opcodes.VIDEO_CHAT_HISTORY: await self.auth_required( userPhone, diff --git a/src/tamtam/models.py b/src/tamtam/models.py index 05cae0a..5a20d99 100644 --- a/src/tamtam/models.py +++ b/src/tamtam/models.py @@ -54,6 +54,32 @@ class AssetsPayloadModel(pydantic.BaseModel): type: str = None userId: int = None +class AssetsGetPayloadModel(pydantic.BaseModel): + type: str + count: int = 100 + query: str = None + +class AssetsGetByIdsPayloadModel(pydantic.BaseModel): + type: str + ids: list + +class AssetsAddPayloadModel(pydantic.BaseModel): + type: str + id: int = None + +class AssetsRemovePayloadModel(pydantic.BaseModel): + type: str + ids: list + +class AssetsMovePayloadModel(pydantic.BaseModel): + type: str + id: int + position: int + +class AssetsListModifyPayloadModel(pydantic.BaseModel): + type: str + ids: list + class GetCallTokenPayloadModel(pydantic.BaseModel): userId: int value: str diff --git a/src/tamtam/processors/assets.py b/src/tamtam/processors/assets.py index dcce8e1..6b2d15e 100644 --- a/src/tamtam/processors/assets.py +++ b/src/tamtam/processors/assets.py @@ -1,34 +1,167 @@ import pydantic import time from classes.baseprocessor import BaseProcessor -from tamtam.models import AssetsPayloadModel +from tamtam.models import ( + AssetsPayloadModel, + AssetsGetPayloadModel, + AssetsGetByIdsPayloadModel, + AssetsAddPayloadModel, + AssetsRemovePayloadModel, + AssetsMovePayloadModel, + AssetsListModifyPayloadModel, +) class AssetsProcessors(BaseProcessor): async def assets_update(self, payload, seq, writer): - """Обработчик запроса ассетов клиента на сервере""" - # Валидируем данные пакета try: AssetsPayloadModel.model_validate(payload) except pydantic.ValidationError as error: self.logger.error(f"Возникли ошибки при валидации пакета: {error}") await self._send_error(seq, self.opcodes.ASSETS_UPDATE, self.error_types.INVALID_PAYLOAD, writer) return - - # TODO: сейчас это заглушка, а попозже нужно сделать полноценную реализацию - # Данные пакета - payload = { + response = { "sync": int(time.time() * 1000), "stickerSetsUpdates": {}, "stickersUpdates": {}, - "sections": [], - "stickersOrder": [] + "stickersOrder": [ + "RECENT", + "FAVORITE_STICKERS", + "FAVORITE_STICKER_SETS", + "TOP", + "NEW", + "NEW_STICKER_SETS", + ], + "sections": [ + { + "id": "RECENT", + "type": "RECENTS", + "recentsList": [], + }, + { + "id": "FAVORITE_STICKERS", + "type": "STICKERS", + "stickers": [], + "marker": None, + }, + { + "id": "FAVORITE_STICKER_SETS", + "type": "STICKER_SETS", + "stickerSets": [], + "marker": None, + }, + { + "id": "TOP", + "type": "STICKERS", + "stickers": [], + "marker": None, + }, + { + "id": "NEW", + "type": "STICKERS", + "stickers": [], + "marker": None, + }, + { + "id": "NEW_STICKER_SETS", + "type": "STICKER_SETS", + "stickerSets": [], + "marker": None, + }, + ], } - # Собираем пакет packet = self.proto.pack_packet( - cmd=self.proto.CMD_OK, seq=seq, opcode=self.opcodes.ASSETS_UPDATE, payload=payload + cmd=self.proto.CMD_OK, seq=seq, opcode=self.opcodes.ASSETS_UPDATE, payload=response ) + await self._send(writer, packet) - # Отправляем - await self._send(writer, packet) \ No newline at end of file + async def assets_get(self, payload, seq, writer): + try: + data = AssetsGetPayloadModel.model_validate(payload) + except pydantic.ValidationError as error: + self.logger.error(f"Возникли ошибки при валидации пакета: {error}") + await self._send_error(seq, self.opcodes.ASSETS_GET, self.error_types.INVALID_PAYLOAD, writer) + return + + asset_type = data.type + if asset_type == "STICKER_SET": + response = {"stickerSets": [], "marker": None} + else: + response = {"stickers": [], "marker": None} + + packet = self.proto.pack_packet( + cmd=self.proto.CMD_OK, seq=seq, opcode=self.opcodes.ASSETS_GET, payload=response + ) + await self._send(writer, packet) + + async def assets_get_by_ids(self, payload, seq, writer): + try: + data = AssetsGetByIdsPayloadModel.model_validate(payload) + except pydantic.ValidationError as error: + self.logger.error(f"Возникли ошибки при валидации пакета: {error}") + await self._send_error(seq, self.opcodes.ASSETS_GET_BY_IDS, self.error_types.INVALID_PAYLOAD, writer) + return + + asset_type = data.type + if asset_type == "STICKER_SET": + response = {"stickerSets": []} + else: + response = {"stickers": []} + + packet = self.proto.pack_packet( + cmd=self.proto.CMD_OK, seq=seq, opcode=self.opcodes.ASSETS_GET_BY_IDS, payload=response + ) + await self._send(writer, packet) + + async def assets_add(self, payload, seq, writer): + try: + AssetsAddPayloadModel.model_validate(payload) + except pydantic.ValidationError as error: + self.logger.error(f"Возникли ошибки при валидации пакета: {error}") + await self._send_error(seq, self.opcodes.ASSETS_ADD, self.error_types.INVALID_PAYLOAD, writer) + return + + packet = self.proto.pack_packet( + cmd=self.proto.CMD_OK, seq=seq, opcode=self.opcodes.ASSETS_ADD, payload={} + ) + await self._send(writer, packet) + + async def assets_remove(self, payload, seq, writer): + try: + AssetsRemovePayloadModel.model_validate(payload) + except pydantic.ValidationError as error: + self.logger.error(f"Возникли ошибки при валидации пакета: {error}") + await self._send_error(seq, self.opcodes.ASSETS_REMOVE, self.error_types.INVALID_PAYLOAD, writer) + return + + packet = self.proto.pack_packet( + cmd=self.proto.CMD_OK, seq=seq, opcode=self.opcodes.ASSETS_REMOVE, payload={} + ) + await self._send(writer, packet) + + async def assets_move(self, payload, seq, writer): + try: + AssetsMovePayloadModel.model_validate(payload) + except pydantic.ValidationError as error: + self.logger.error(f"Возникли ошибки при валидации пакета: {error}") + await self._send_error(seq, self.opcodes.ASSETS_MOVE, self.error_types.INVALID_PAYLOAD, writer) + return + + packet = self.proto.pack_packet( + cmd=self.proto.CMD_OK, seq=seq, opcode=self.opcodes.ASSETS_MOVE, payload={} + ) + await self._send(writer, packet) + + async def assets_list_modify(self, payload, seq, writer): + try: + AssetsListModifyPayloadModel.model_validate(payload) + except pydantic.ValidationError as error: + self.logger.error(f"Возникли ошибки при валидации пакета: {error}") + await self._send_error(seq, self.opcodes.ASSETS_LIST_MODIFY, self.error_types.INVALID_PAYLOAD, writer) + return + + packet = self.proto.pack_packet( + cmd=self.proto.CMD_OK, seq=seq, opcode=self.opcodes.ASSETS_LIST_MODIFY, payload={} + ) + await self._send(writer, packet) diff --git a/src/tamtam/socket.py b/src/tamtam/socket.py index e0c8886..8f9c037 100644 --- a/src/tamtam/socket.py +++ b/src/tamtam/socket.py @@ -122,6 +122,30 @@ class TamTamMobile: await self.auth_required( userPhone, self.processors.assets_update, payload, seq, writer ) + case self.opcodes.ASSETS_GET: + await self.auth_required( + userPhone, self.processors.assets_get, payload, seq, writer + ) + case self.opcodes.ASSETS_GET_BY_IDS: + await self.auth_required( + userPhone, self.processors.assets_get_by_ids, payload, seq, writer + ) + case self.opcodes.ASSETS_ADD: + await self.auth_required( + userPhone, self.processors.assets_add, payload, seq, writer + ) + case self.opcodes.ASSETS_REMOVE: + await self.auth_required( + userPhone, self.processors.assets_remove, payload, seq, writer + ) + case self.opcodes.ASSETS_MOVE: + await self.auth_required( + userPhone, self.processors.assets_move, payload, seq, writer + ) + case self.opcodes.ASSETS_LIST_MODIFY: + await self.auth_required( + userPhone, self.processors.assets_list_modify, payload, seq, writer + ) case self.opcodes.VIDEO_CHAT_HISTORY: await self.auth_required( userPhone, self.processors.video_chat_history, payload, seq, writer diff --git a/src/tamtam/websocket.py b/src/tamtam/websocket.py index b146188..37124d6 100644 --- a/src/tamtam/websocket.py +++ b/src/tamtam/websocket.py @@ -109,6 +109,30 @@ class TamTamWS: await self.auth_required( userPhone, self.processors.assets_update, payload, seq, websocket ) + case self.opcodes.ASSETS_GET: + await self.auth_required( + userPhone, self.processors.assets_get, payload, seq, websocket + ) + case self.opcodes.ASSETS_GET_BY_IDS: + await self.auth_required( + userPhone, self.processors.assets_get_by_ids, payload, seq, websocket + ) + case self.opcodes.ASSETS_ADD: + await self.auth_required( + userPhone, self.processors.assets_add, payload, seq, websocket + ) + case self.opcodes.ASSETS_REMOVE: + await self.auth_required( + userPhone, self.processors.assets_remove, payload, seq, websocket + ) + case self.opcodes.ASSETS_MOVE: + await self.auth_required( + userPhone, self.processors.assets_move, payload, seq, websocket + ) + case self.opcodes.ASSETS_LIST_MODIFY: + await self.auth_required( + userPhone, self.processors.assets_list_modify, payload, seq, websocket + ) case self.opcodes.VIDEO_CHAT_HISTORY: await self.auth_required( userPhone, self.processors.video_chat_history, payload, seq, websocket