mirror of
https://github.com/openmax-server/server.git
synced 2026-05-22 19:41:41 +03:00
188 lines
8.0 KiB
Python
188 lines
8.0 KiB
Python
import pydantic
|
||
import json
|
||
from classes.baseprocessor import BaseProcessor
|
||
from oneme.models import (
|
||
HelloPayloadModel,
|
||
PingPayloadModel,
|
||
UpdateProfilePayloadModel
|
||
)
|
||
|
||
|
||
class MainProcessors(BaseProcessor):
|
||
def __init__(self, db_pool=None, clients=None, send_event=None, type="socket"):
|
||
super().__init__(db_pool, clients, send_event, type)
|
||
|
||
async def session_init(self, payload, seq, writer):
|
||
"""Обработчик приветствия"""
|
||
# Валидируем данные пакета
|
||
try:
|
||
HelloPayloadModel.model_validate(payload)
|
||
except pydantic.ValidationError as error:
|
||
self.logger.error(f"Возникли ошибки при валидации пакета: {error}")
|
||
await self._send_error(seq, self.opcodes.SESSION_INIT, self.error_types.INVALID_PAYLOAD, writer)
|
||
return None, None
|
||
|
||
# Получаем данные из пакета
|
||
deviceType = payload.get("userAgent").get("deviceType")
|
||
deviceName = payload.get("userAgent").get("deviceName")
|
||
|
||
# Данные пакета
|
||
payload = {
|
||
"location": "RU",
|
||
"app-update-type": 0, # 1 = принудительное обновление
|
||
"reg-country-code": self.static.REG_COUNTRY_CODES,
|
||
"phone-auto-complete-enabled": False,
|
||
"qr-auth-enabled": False,
|
||
"lang": True
|
||
}
|
||
|
||
# Собираем пакет
|
||
packet = self.proto.pack_packet(
|
||
cmd=self.proto.CMD_OK, seq=seq, opcode=self.opcodes.SESSION_INIT, payload=payload
|
||
)
|
||
|
||
# Отправляем
|
||
await self._send(writer, packet)
|
||
return deviceType, deviceName
|
||
|
||
async def ping(self, payload, seq, writer):
|
||
"""Обработчик пинга"""
|
||
# Валидируем данные пакета
|
||
try:
|
||
PingPayloadModel.model_validate(payload)
|
||
except pydantic.ValidationError as error:
|
||
self.logger.error(f"Возникли ошибки при валидации пакета: {error}")
|
||
await self._send_error(seq, self.opcodes.PING, self.error_types.INVALID_PAYLOAD, writer)
|
||
return
|
||
|
||
# Собираем пакет
|
||
response = self.proto.pack_packet(
|
||
cmd=self.proto.CMD_OK, seq=seq, opcode=self.opcodes.PING, payload=None
|
||
)
|
||
|
||
# Отправляем
|
||
await self._send(writer, response)
|
||
|
||
async def log(self, payload, seq, writer):
|
||
"""Обработчик телеметрии"""
|
||
# TODO: можно было бы реализовать валидацию телеметрии, но сейчас это не особо важно
|
||
|
||
# Собираем пакет
|
||
response = self.proto.pack_packet(
|
||
cmd=self.proto.CMD_OK, seq=seq, opcode=self.opcodes.LOG, payload=None
|
||
)
|
||
|
||
# Отправляем
|
||
await self._send(writer, response)
|
||
|
||
async def profile(self, payload, seq, writer, userId):
|
||
# Валидируем входные данные
|
||
try:
|
||
UpdateProfilePayloadModel.model_validate(payload)
|
||
except pydantic.ValidationError as error:
|
||
self.logger.error(f"Возникли ошибки при валидации пакета: {error}")
|
||
await self._send_error(seq, self.opcodes.PROFILE, self.error_types.INVALID_PAYLOAD, writer)
|
||
return
|
||
|
||
# Ищем пользователя в бд
|
||
async with self.db_pool.acquire() as conn:
|
||
async with conn.cursor() as cursor:
|
||
await cursor.execute("SELECT * FROM users WHERE id = %s", (userId,))
|
||
user = await cursor.fetchone()
|
||
|
||
# Если пользователь не найден
|
||
if not user:
|
||
await self._send_error(seq, self.opcodes.PROFILE, self.error_types.USER_NOT_FOUND, writer)
|
||
return
|
||
|
||
# Аватарка с биографией
|
||
photoId = None if not user.get("avatar_id") else int(user.get("avatar_id"))
|
||
avatar_url = None if not photoId else self.config.avatar_base_url + photoId
|
||
description = None if not user.get("description") else user.get("description")
|
||
|
||
# Генерируем профиль
|
||
profile = self.tools.generate_profile(
|
||
id=user.get("id"),
|
||
phone=int(user.get("phone")),
|
||
avatarUrl=avatar_url,
|
||
photoId=photoId,
|
||
updateTime=int(user.get("updatetime")),
|
||
firstName=user.get("firstname"),
|
||
lastName=user.get("lastname"),
|
||
options=json.loads(user.get("options")),
|
||
description=description,
|
||
accountStatus=int(user.get("accountstatus")),
|
||
profileOptions=json.loads(user.get("profileoptions")),
|
||
includeProfileOptions=True,
|
||
username=user.get("username")
|
||
)
|
||
|
||
# Создаем данные пакета
|
||
payload = {
|
||
"profile": profile
|
||
}
|
||
|
||
# Собираем пакет
|
||
response = self.proto.pack_packet(
|
||
cmd=self.proto.CMD_OK, seq=seq, opcode=self.opcodes.PROFILE, payload=payload
|
||
)
|
||
|
||
# Отправляем
|
||
await self._send(writer, response)
|
||
|
||
async def update_config(self, payload, seq, writer, userPhone, hashedToken=None):
|
||
"""
|
||
Обработчик 22 опкода (config)
|
||
Он отвечает за обновление настроек приватности
|
||
и пуш токена для пушей
|
||
"""
|
||
# Пейлоад, который отдадим клиенту
|
||
# а отдавать его нужно только при изменении настроек приватности
|
||
result_payload = None
|
||
|
||
if payload.get("pushToken"):
|
||
push_token = payload.get("pushToken")
|
||
async with self.db_pool.acquire() as conn:
|
||
async with conn.cursor() as cursor:
|
||
await cursor.execute(
|
||
"UPDATE tokens SET push_token = %s WHERE phone = %s AND token_hash = %s",
|
||
(push_token, str(userPhone), hashedToken)
|
||
)
|
||
elif payload.get("settings") and payload.get("settings").get("user"):
|
||
"""Обновление настроек приватности"""
|
||
new_settings = payload.get("settings").get("user")
|
||
|
||
async with self.db_pool.acquire() as conn:
|
||
async with conn.cursor() as cursor:
|
||
# Получаем текущий конфиг
|
||
await cursor.execute(
|
||
"SELECT user_config FROM user_data WHERE phone = %s", (userPhone,)
|
||
)
|
||
row = await cursor.fetchone()
|
||
|
||
if row:
|
||
current_config = json.loads(row.get("user_config"))
|
||
|
||
# Обновляем настройки
|
||
for key, value in new_settings.items():
|
||
if key in current_config:
|
||
current_config[key] = value
|
||
|
||
# Сохраняем обновлённый конфиг
|
||
await cursor.execute(
|
||
"UPDATE user_data SET user_config = %s WHERE phone = %s",
|
||
(json.dumps(current_config), userPhone)
|
||
)
|
||
|
||
result_payload = {
|
||
"user": current_config,
|
||
"hash": "0"
|
||
}
|
||
|
||
# Собираем пакет
|
||
response = self.proto.pack_packet(
|
||
cmd=self.proto.CMD_OK, seq=seq, opcode=self.opcodes.CONFIG, payload=result_payload
|
||
)
|
||
|
||
# Отправляем
|
||
await self._send(writer, response) |