ТамТам: реализация 32 опкода. Надеюсь, будет работать

This commit is contained in:
Alexey Polyakov 2026-03-22 16:59:13 +03:00
parent 8d7a1dacb5
commit f2e7e37592
4 changed files with 75 additions and 2 deletions

View File

@ -31,4 +31,7 @@ class FinalAuthPayloadModel(pydantic.BaseModel):
class LoginPayloadModel(pydantic.BaseModel):
interactive: bool
token: str
token: str
class SearchUsersPayloadModel(pydantic.BaseModel):
contactIds: list

View File

@ -1,5 +1,6 @@
from .main import MainProcessors
from .auth import AuthProcessors
from .search import SearchProcessors
class Processors(MainProcessors, AuthProcessors):
class Processors(MainProcessors, AuthProcessors, SearchProcessors):
pass

View File

@ -0,0 +1,63 @@
import json, pydantic
from classes.baseprocessor import BaseProcessor
from tamtam.models import SearchUsersPayloadModel
class SearchProcessors(BaseProcessor):
async def contact_info(self, payload, seq, writer):
"""Поиск пользователей по ID"""
# Валидируем данные пакета
try:
SearchUsersPayloadModel.model_validate(payload)
except pydantic.ValidationError as error:
self.logger.error(f"Возникли ошибки при валидации пакета: {error}")
await self._send_error(seq, self.opcodes.CONTACT_INFO, self.error_types.INVALID_PAYLOAD, writer)
return
# Итоговый список пользователей
users = []
# ID пользователей, которые нам предстоит найти
contactIds = payload.get("contactIds")
# Ищем пользователей в бд
async with self.db_pool.acquire() as conn:
async with conn.cursor() as cursor:
for contactId in contactIds:
await cursor.execute("SELECT * FROM users WHERE id = %s", (contactId,))
user = await cursor.fetchone()
# Если такой пользователь есть, добавляем его в список
if user:
# Аватарка с биографией
photo_id = None if not user.get("avatar_id") else int(user.get("avatar_id"))
avatar_url = None if not photo_id else self.config.avatar_base_url + photo_id
description = None if not user.get("description") else user.get("description")
# Генерируем профиль
users.append(
self.tools.generate_profile_tt(
id=user.get("id"),
phone=int(user.get("phone")),
avatarUrl=avatar_url,
photoId=photo_id,
updateTime=int(user.get("updatetime")),
firstName=user.get("firstname"),
lastName=user.get("lastname"),
options=json.loads(user.get("options")),
description=description,
username=user.get("username")
)
)
# Создаем данные пакета
payload = {
"contacts": users
}
# Создаем пакет
response = self.proto.pack_packet(
seq=seq, opcode=self.opcodes.CONTACT_INFO, payload=payload
)
# Отправляем
await self._send(writer, response)

View File

@ -3,6 +3,7 @@ from common.proto_tcp import MobileProto
from tamtam.processors import Processors
from common.rate_limiter import RateLimiter
from common.opcodes import Opcodes
from common.tools import Tools
class TTMobileServer:
def __init__(self, host="0.0.0.0", port=443, ssl_context=None, db_pool=None, clients={}, send_event=None):
@ -18,6 +19,7 @@ class TTMobileServer:
self.proto = MobileProto()
self.processors = Processors(db_pool=db_pool, clients=clients, send_event=send_event)
self.auth_required = Tools().auth_required
# rate limiter
self.auth_rate_limiter = RateLimiter(max_attempts=5, window_seconds=60)
@ -97,6 +99,10 @@ class TTMobileServer:
if userPhone:
await self._finish_auth(writer, address, userPhone, userId)
case self.opcodes.CONTACT_INFO:
await self.auth_required(
userPhone, self.processors.contact_info, payload, seq, writer
)
case _:
self.logger.warning(f"Неизвестный опкод {opcode}")
except Exception as e: