mirror of
https://github.com/openmax-server/server.git
synced 2026-05-23 03:51:43 +03:00
TT: регистрация через клиент
This commit is contained in:
@@ -118,12 +118,29 @@ class Tools:
|
|||||||
options=[],
|
options=[],
|
||||||
description=None,
|
description=None,
|
||||||
username=None,
|
username=None,
|
||||||
|
custom_firstname=None,
|
||||||
|
custom_lastname=None
|
||||||
):
|
):
|
||||||
|
# Так как TT не поддерживает фамилию, и если нам ее не передали в функцию
|
||||||
|
# то используем только имя, чтобы избежать None в фамилии
|
||||||
|
if firstName and lastName:
|
||||||
|
name = f"{firstName} {lastName}",
|
||||||
|
else:
|
||||||
|
name = firstName
|
||||||
|
|
||||||
|
# Используем такой же костыль, как и выше
|
||||||
|
if custom_firstname:
|
||||||
|
custom_name = custom_firstname
|
||||||
|
elif custom_firstname and custom_lastname:
|
||||||
|
custom_name = f"{custom_firstname} {custom_lastname}"
|
||||||
|
else:
|
||||||
|
custom_name = None
|
||||||
|
|
||||||
contact = {
|
contact = {
|
||||||
"id": id,
|
"id": id,
|
||||||
"updateTime": updateTime,
|
"updateTime": updateTime,
|
||||||
"phone": phone,
|
"phone": phone,
|
||||||
"names": [{"name": f"{firstName} {lastName}", "type": "TT"}],
|
"names": [{"name": name, "type": "TT"}],
|
||||||
"options": options,
|
"options": options,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -135,8 +152,16 @@ class Tools:
|
|||||||
if description:
|
if description:
|
||||||
contact["description"] = description
|
contact["description"] = description
|
||||||
|
|
||||||
|
# NOTE: официальный сервер вроде как отдавал tt.me, но клиент примет любую ссылку
|
||||||
|
# можно потом как нибудь сделать возможность редактирования этого момента, но это
|
||||||
|
# позже, так как по юзернейму искать пока нельзя
|
||||||
if username:
|
if username:
|
||||||
contact["link"] = "https://tamtam.chat/" + username
|
contact["link"] = "https://tt.me/" + username
|
||||||
|
|
||||||
|
if custom_firstname:
|
||||||
|
contact["names"].append(
|
||||||
|
{"name": custom_name, "type": "CUSTOM"}
|
||||||
|
)
|
||||||
|
|
||||||
return contact
|
return contact
|
||||||
|
|
||||||
|
|||||||
@@ -76,7 +76,7 @@ class ContactPresencePayloadModel(pydantic.BaseModel):
|
|||||||
class ContactUpdatePayloadModel(pydantic.BaseModel):
|
class ContactUpdatePayloadModel(pydantic.BaseModel):
|
||||||
action: str
|
action: str
|
||||||
contactId: int
|
contactId: int
|
||||||
firstName: str
|
firstName: str = None
|
||||||
lastName: str = None
|
lastName: str = None
|
||||||
|
|
||||||
class TypingPayloadModel(pydantic.BaseModel):
|
class TypingPayloadModel(pydantic.BaseModel):
|
||||||
@@ -94,4 +94,20 @@ class MessageModel(pydantic.BaseModel):
|
|||||||
class SendMessagePayloadModel(pydantic.BaseModel):
|
class SendMessagePayloadModel(pydantic.BaseModel):
|
||||||
userId: int = None
|
userId: int = None
|
||||||
chatId: int = None
|
chatId: int = None
|
||||||
message: MessageModel
|
message: MessageModel
|
||||||
|
|
||||||
|
class AuthConfirmRegisterPayloadModel(pydantic.BaseModel):
|
||||||
|
token: str
|
||||||
|
name: str
|
||||||
|
tokenType: str
|
||||||
|
deviceType: str
|
||||||
|
deviceId: str = None
|
||||||
|
|
||||||
|
@pydantic.field_validator('name')
|
||||||
|
def validate_name(cls, v):
|
||||||
|
v = v.strip()
|
||||||
|
if not v:
|
||||||
|
raise ValueError('name must not be empty')
|
||||||
|
if len(v) > 59:
|
||||||
|
raise ValueError('name too long')
|
||||||
|
return v
|
||||||
|
|||||||
@@ -4,10 +4,12 @@ import time
|
|||||||
import json
|
import json
|
||||||
import re
|
import re
|
||||||
from classes.baseprocessor import BaseProcessor
|
from classes.baseprocessor import BaseProcessor
|
||||||
|
from common.sms import send_sms_code
|
||||||
from tamtam.models import (
|
from tamtam.models import (
|
||||||
RequestCodePayloadModel,
|
RequestCodePayloadModel,
|
||||||
VerifyCodePayloadModel,
|
VerifyCodePayloadModel,
|
||||||
FinalAuthPayloadModel,
|
FinalAuthPayloadModel,
|
||||||
|
AuthConfirmRegisterPayloadModel,
|
||||||
LoginPayloadModel,
|
LoginPayloadModel,
|
||||||
)
|
)
|
||||||
from tamtam.config import TTConfig
|
from tamtam.config import TTConfig
|
||||||
@@ -17,6 +19,172 @@ class AuthProcessors(BaseProcessor):
|
|||||||
super().__init__(db_pool, clients, send_event, type)
|
super().__init__(db_pool, clients, send_event, type)
|
||||||
self.server_config = TTConfig().SERVER_CONFIG
|
self.server_config = TTConfig().SERVER_CONFIG
|
||||||
|
|
||||||
|
async def _finish_auth(self, payload, seq, writer, cursor, phone, hashed_token, hashed_login, account, deviceType, deviceName, ip, login):
|
||||||
|
"""Завершение существующего пользователя"""
|
||||||
|
# Валидируем данные пакета
|
||||||
|
try:
|
||||||
|
FinalAuthPayloadModel.model_validate(payload)
|
||||||
|
except Exception as e:
|
||||||
|
await self._send_error(seq, self.opcodes.AUTH_CONFIRM,
|
||||||
|
self.error_types.INVALID_PAYLOAD, writer)
|
||||||
|
return None
|
||||||
|
|
||||||
|
# Удаляем токен
|
||||||
|
await cursor.execute("DELETE FROM auth_tokens WHERE token_hash = %s", (hashed_token,))
|
||||||
|
|
||||||
|
# Создаем сессию
|
||||||
|
await cursor.execute(
|
||||||
|
"INSERT INTO tokens (phone, token_hash, device_type, device_name, location, time) VALUES (%s, %s, %s, %s, %s, %s)",
|
||||||
|
(
|
||||||
|
phone,
|
||||||
|
hashed_login,
|
||||||
|
deviceType,
|
||||||
|
deviceName,
|
||||||
|
self.tools.get_geo(
|
||||||
|
ip=ip, db_path=self.config.geo_db_path
|
||||||
|
),
|
||||||
|
int(time.time() * 1000)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
# Аватарка с биографией
|
||||||
|
photo_id = None if not account.get("avatar_id") else int(account.get("avatar_id"))
|
||||||
|
avatar_url = None if not photo_id else self.config.avatar_base_url + str(photo_id)
|
||||||
|
description = None if not account.get("description") else account.get("description")
|
||||||
|
|
||||||
|
# Собираем данные пакета
|
||||||
|
return {
|
||||||
|
"userToken": str(account.get("id")),
|
||||||
|
"profile": self.tools.generate_profile_tt(
|
||||||
|
id=account.get("id"),
|
||||||
|
phone=int(account.get("phone")),
|
||||||
|
avatarUrl=avatar_url,
|
||||||
|
photoId=photo_id,
|
||||||
|
updateTime=int(account.get("updatetime")),
|
||||||
|
firstName=account.get("firstname"),
|
||||||
|
lastName=account.get("lastname"),
|
||||||
|
options=json.loads(account.get("options")),
|
||||||
|
description=description,
|
||||||
|
username=account.get("username")
|
||||||
|
),
|
||||||
|
"tokenType": "LOGIN",
|
||||||
|
"token": login
|
||||||
|
}
|
||||||
|
|
||||||
|
async def _finish_reg(self, payload, seq, writer, cursor, phone, hashed_token, hashed_login, deviceType, deviceName, ip, login):
|
||||||
|
"""Регистрация пользователя во время авторизации"""
|
||||||
|
# Валидируем данные пакета
|
||||||
|
try:
|
||||||
|
AuthConfirmRegisterPayloadModel.model_validate(payload)
|
||||||
|
except Exception as e:
|
||||||
|
await self._send_error(seq, self.opcodes.AUTH_CONFIRM,
|
||||||
|
self.error_types.INVALID_PAYLOAD, writer)
|
||||||
|
return None
|
||||||
|
|
||||||
|
name = payload.get("name", "").strip()
|
||||||
|
|
||||||
|
now_ms = int(time.time() * 1000)
|
||||||
|
now_s = int(time.time())
|
||||||
|
|
||||||
|
# Генерируем ID пользователя
|
||||||
|
user_id = await self.tools.generate_user_id(self.db_pool)
|
||||||
|
|
||||||
|
# Создаем пользователя
|
||||||
|
|
||||||
|
# NOTE: На бумаге у нас как бы полная поддержка ТТ (ну, все функции, в которые может макс),
|
||||||
|
# а клиенты тамтама не знают, что такое фамилия в аккаунтах тамтама (оно предназначено только для ОК)
|
||||||
|
# по этому просто не писать указывать фамилию в бд, ее клиент и так не отдаст
|
||||||
|
|
||||||
|
await cursor.execute(
|
||||||
|
"""
|
||||||
|
INSERT INTO users
|
||||||
|
(id, phone, telegram_id, firstname, lastname, username,
|
||||||
|
profileoptions, options, accountstatus, updatetime, lastseen)
|
||||||
|
VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)
|
||||||
|
""",
|
||||||
|
(
|
||||||
|
user_id,
|
||||||
|
phone,
|
||||||
|
None,
|
||||||
|
name,
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
json.dumps([]),
|
||||||
|
json.dumps(["TT", "ONEME"]),
|
||||||
|
0,
|
||||||
|
str(now_ms),
|
||||||
|
str(now_s),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
# Добавляем данные аккаунта
|
||||||
|
await cursor.execute(
|
||||||
|
"""
|
||||||
|
INSERT INTO user_data
|
||||||
|
(phone, user_config, chat_config)
|
||||||
|
VALUES (%s, %s, %s)
|
||||||
|
""",
|
||||||
|
(
|
||||||
|
phone,
|
||||||
|
json.dumps(self.static.USER_SETTINGS),
|
||||||
|
json.dumps({}),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
# Добавляем дефолтную папку
|
||||||
|
await cursor.execute(
|
||||||
|
"""
|
||||||
|
INSERT INTO user_folders
|
||||||
|
(id, phone, title, sort_order)
|
||||||
|
VALUES ('all.chat.folder', %s, 'Все', 0)
|
||||||
|
""",
|
||||||
|
(phone,),
|
||||||
|
)
|
||||||
|
|
||||||
|
# Удаляем токен
|
||||||
|
await cursor.execute("DELETE FROM auth_tokens WHERE token_hash = %s", (hashed_token,))
|
||||||
|
|
||||||
|
# Создаем сессию
|
||||||
|
await cursor.execute(
|
||||||
|
"INSERT INTO tokens (phone, token_hash, device_type, device_name, location, time) VALUES (%s, %s, %s, %s, %s, %s)",
|
||||||
|
(
|
||||||
|
phone,
|
||||||
|
hashed_login,
|
||||||
|
deviceType or "ANDROID",
|
||||||
|
deviceName or "Unknown",
|
||||||
|
self.tools.get_geo(
|
||||||
|
ip=ip, db_path=self.config.geo_db_path
|
||||||
|
),
|
||||||
|
now_ms,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
# Генерируем профиль
|
||||||
|
profile = self.tools.generate_profile_tt(
|
||||||
|
id=user_id,
|
||||||
|
phone=int(phone),
|
||||||
|
avatarUrl=None,
|
||||||
|
photoId=None,
|
||||||
|
updateTime=now_ms,
|
||||||
|
firstName=name,
|
||||||
|
lastName="",
|
||||||
|
options=["TT", "ONEME"],
|
||||||
|
description=None,
|
||||||
|
username=None,
|
||||||
|
)
|
||||||
|
|
||||||
|
self.logger.info(
|
||||||
|
f"Новый пользователь зарегистрирован: phone={phone} id={user_id} name={name}"
|
||||||
|
)
|
||||||
|
|
||||||
|
# Собираем данные пакета
|
||||||
|
return {
|
||||||
|
"userToken": "0",
|
||||||
|
"profile": profile,
|
||||||
|
"tokenType": "LOGIN",
|
||||||
|
"token": login,
|
||||||
|
}
|
||||||
|
|
||||||
async def auth_request(self, payload, seq, writer):
|
async def auth_request(self, payload, seq, writer):
|
||||||
"""Обработчик запроса кода"""
|
"""Обработчик запроса кода"""
|
||||||
# Валидируем данные пакета
|
# Валидируем данные пакета
|
||||||
@@ -30,29 +198,51 @@ class AuthProcessors(BaseProcessor):
|
|||||||
# Извлекаем телефон из пакета
|
# Извлекаем телефон из пакета
|
||||||
phone = re.sub(r'\D', '', payload.get("phone", ""))
|
phone = re.sub(r'\D', '', payload.get("phone", ""))
|
||||||
|
|
||||||
# Генерируем токен с кодом
|
# Генерируем токен
|
||||||
code = f"{secrets.randbelow(1_000_000):06d}"
|
|
||||||
token = secrets.token_urlsafe(128)
|
token = secrets.token_urlsafe(128)
|
||||||
|
|
||||||
# Хешируем
|
|
||||||
code_hash = hashlib.sha256(code.encode()).hexdigest()
|
|
||||||
token_hash = hashlib.sha256(token.encode()).hexdigest()
|
token_hash = hashlib.sha256(token.encode()).hexdigest()
|
||||||
|
|
||||||
# Срок жизни токена (5 минут)
|
# Срок жизни токена (5 минут)
|
||||||
expires = int(time.time()) + 300
|
expires = int(time.time()) + 300
|
||||||
|
|
||||||
# Ищем пользователя, и если он существует, сохраняем токен
|
user_exists = False
|
||||||
|
|
||||||
|
# Ищем пользователя
|
||||||
async with self.db_pool.acquire() as conn:
|
async with self.db_pool.acquire() as conn:
|
||||||
async with conn.cursor() as cursor:
|
async with conn.cursor() as cursor:
|
||||||
await cursor.execute("SELECT * FROM users WHERE phone = %s", (phone,))
|
await cursor.execute("SELECT * FROM users WHERE phone = %s", (phone,))
|
||||||
user = await cursor.fetchone()
|
user = await cursor.fetchone()
|
||||||
|
|
||||||
# Если пользователь существует, сохраняем токен
|
# Получаем код через SMS шлюз или генерируем локально
|
||||||
|
local_fallback_code = False
|
||||||
|
if self.config.sms_gateway_url:
|
||||||
|
code = await send_sms_code(self.config.sms_gateway_url, phone)
|
||||||
|
|
||||||
|
if code is None:
|
||||||
|
code = f"{secrets.randbelow(1_000_000):06d}"
|
||||||
|
local_fallback_code = True
|
||||||
|
else:
|
||||||
|
code = f"{secrets.randbelow(1_000_000):06d}"
|
||||||
|
local_fallback_code = True
|
||||||
|
|
||||||
|
# Хешируем
|
||||||
|
code_hash = hashlib.sha256(code.encode()).hexdigest()
|
||||||
|
|
||||||
|
# Сохраняем токен
|
||||||
|
async with self.db_pool.acquire() as conn:
|
||||||
|
async with conn.cursor() as cursor:
|
||||||
if user:
|
if user:
|
||||||
|
user_exists = True
|
||||||
await cursor.execute(
|
await cursor.execute(
|
||||||
"INSERT INTO auth_tokens (phone, token_hash, code_hash, expires, state) VALUES (%s, %s, %s, %s, %s)",
|
"INSERT INTO auth_tokens (phone, token_hash, code_hash, expires, state) VALUES (%s, %s, %s, %s, %s)",
|
||||||
(phone, token_hash, code_hash, expires, "started")
|
(phone, token_hash, code_hash, expires, "started")
|
||||||
)
|
)
|
||||||
|
else:
|
||||||
|
# Пользователь не найден - сохраняем токен в register
|
||||||
|
await cursor.execute(
|
||||||
|
"INSERT INTO auth_tokens (phone, token_hash, code_hash, expires, state) VALUES (%s, %s, %s, %s, %s)",
|
||||||
|
(phone, token_hash, code_hash, expires, "register")
|
||||||
|
)
|
||||||
|
|
||||||
# Данные пакета
|
# Данные пакета
|
||||||
payload = {
|
payload = {
|
||||||
@@ -71,7 +261,7 @@ class AuthProcessors(BaseProcessor):
|
|||||||
|
|
||||||
# Отправляем
|
# Отправляем
|
||||||
await self._send(writer, packet)
|
await self._send(writer, packet)
|
||||||
self.logger.debug(f"Код для {phone}: {code}")
|
self.logger.debug(f"Код для {phone}: {code} (существующий={user_exists})")
|
||||||
|
|
||||||
async def auth(self, payload, seq, writer):
|
async def auth(self, payload, seq, writer):
|
||||||
"""Обработчик проверки кода"""
|
"""Обработчик проверки кода"""
|
||||||
@@ -112,13 +302,32 @@ class AuthProcessors(BaseProcessor):
|
|||||||
self.error_types.INVALID_CODE, writer)
|
self.error_types.INVALID_CODE, writer)
|
||||||
return
|
return
|
||||||
|
|
||||||
|
# Если это новый пользователь - переводим токен в verified
|
||||||
|
# и отдаём клиенту NEW токен, чтобы он показал экран ввода имени
|
||||||
|
if stored_token.get("state") == "register":
|
||||||
|
await cursor.execute(
|
||||||
|
"UPDATE auth_tokens SET state = %s WHERE token_hash = %s",
|
||||||
|
("verified", hashed_token)
|
||||||
|
)
|
||||||
|
packet = self.proto.pack_packet(
|
||||||
|
cmd=self.proto.CMD_OK,
|
||||||
|
seq=seq,
|
||||||
|
opcode=self.opcodes.AUTH,
|
||||||
|
payload={
|
||||||
|
"tokenAttrs": {"NEW": {"token": token}},
|
||||||
|
"tokenTypes": {"NEW": token},
|
||||||
|
},
|
||||||
|
)
|
||||||
|
await self._send(writer, packet)
|
||||||
|
return
|
||||||
|
|
||||||
# Ищем аккаунт
|
# Ищем аккаунт
|
||||||
await cursor.execute("SELECT * FROM users WHERE phone = %s", (stored_token.get("phone"),))
|
await cursor.execute("SELECT * FROM users WHERE phone = %s", (stored_token.get("phone"),))
|
||||||
account = await cursor.fetchone()
|
account = await cursor.fetchone()
|
||||||
|
|
||||||
# Обновляем состояние токена
|
# Обновляем состояние токена
|
||||||
await cursor.execute(
|
await cursor.execute(
|
||||||
"UPDATE auth_tokens set state = %s WHERE token_hash = %s",
|
"UPDATE auth_tokens SET state = %s WHERE token_hash = %s",
|
||||||
("verified", hashed_token)
|
("verified", hashed_token)
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -159,15 +368,7 @@ class AuthProcessors(BaseProcessor):
|
|||||||
await self._send(writer, packet)
|
await self._send(writer, packet)
|
||||||
|
|
||||||
async def auth_confirm(self, payload, seq, writer, deviceType, deviceName, ip):
|
async def auth_confirm(self, payload, seq, writer, deviceType, deviceName, ip):
|
||||||
"""Обработчик финальной аутентификации"""
|
"""Обработчик финальной аутентификации / регистрации"""
|
||||||
# Валидируем данные пакета
|
|
||||||
try:
|
|
||||||
FinalAuthPayloadModel.model_validate(payload)
|
|
||||||
except Exception as e:
|
|
||||||
await self._send_error(seq, self.opcodes.AUTH_CONFIRM,
|
|
||||||
self.error_types.INVALID_PAYLOAD, writer)
|
|
||||||
return
|
|
||||||
|
|
||||||
# Извлекаем данные из пакета
|
# Извлекаем данные из пакета
|
||||||
token = payload.get("token")
|
token = payload.get("token")
|
||||||
|
|
||||||
@@ -184,10 +385,9 @@ class AuthProcessors(BaseProcessor):
|
|||||||
login = secrets.token_urlsafe(128)
|
login = secrets.token_urlsafe(128)
|
||||||
hashed_login = hashlib.sha256(login.encode()).hexdigest()
|
hashed_login = hashlib.sha256(login.encode()).hexdigest()
|
||||||
|
|
||||||
# Ищем токен с кодом
|
# Ищем токен
|
||||||
async with self.db_pool.acquire() as conn:
|
async with self.db_pool.acquire() as conn:
|
||||||
async with conn.cursor() as cursor:
|
async with conn.cursor() as cursor:
|
||||||
# Ищем токен
|
|
||||||
await cursor.execute(
|
await cursor.execute(
|
||||||
"SELECT * FROM auth_tokens WHERE token_hash = %s AND expires > UNIX_TIMESTAMP()",
|
"SELECT * FROM auth_tokens WHERE token_hash = %s AND expires > UNIX_TIMESTAMP()",
|
||||||
(hashed_token,)
|
(hashed_token,)
|
||||||
@@ -199,63 +399,36 @@ class AuthProcessors(BaseProcessor):
|
|||||||
self.error_types.INVALID_TOKEN, writer)
|
self.error_types.INVALID_TOKEN, writer)
|
||||||
return
|
return
|
||||||
|
|
||||||
# Если авторизация только началась - отдаем ошибку
|
# Если авторизация только началась (код ещё не проверен) - отдаем ошибку
|
||||||
if stored_token.get("state") == "started":
|
if stored_token.get("state") == "started" or stored_token.get("state") == "register":
|
||||||
await self._send_error(seq, self.opcodes.AUTH_CONFIRM,
|
await self._send_error(seq, self.opcodes.AUTH_CONFIRM,
|
||||||
self.error_types.INVALID_TOKEN, writer)
|
self.error_types.INVALID_TOKEN, writer)
|
||||||
return
|
return
|
||||||
|
|
||||||
# Ищем аккаунт
|
phone = stored_token.get("phone")
|
||||||
await cursor.execute("SELECT * FROM users WHERE phone = %s", (stored_token.get("phone"),))
|
|
||||||
|
# Проверяем, существует ли пользователь
|
||||||
|
await cursor.execute("SELECT * FROM users WHERE phone = %s", (phone,))
|
||||||
account = await cursor.fetchone()
|
account = await cursor.fetchone()
|
||||||
|
|
||||||
# Удаляем токен
|
# Если пользователь есть, производим создание сессии
|
||||||
await cursor.execute("DELETE FROM auth_tokens WHERE token_hash = %s", (hashed_token,))
|
if account:
|
||||||
|
resp_payload = await self._finish_auth(
|
||||||
# Создаем сессию
|
payload, seq, writer, cursor, phone, hashed_token,
|
||||||
await cursor.execute(
|
hashed_login, account, deviceType, deviceName, ip, login
|
||||||
"INSERT INTO tokens (phone, token_hash, device_type, device_name, location, time) VALUES (%s, %s, %s, %s, %s, %s)",
|
)
|
||||||
(
|
else: # в ином случае производим регистрацию
|
||||||
stored_token.get("phone"),
|
resp_payload = await self._finish_reg(
|
||||||
hashed_login,
|
payload, seq, writer, cursor, phone, hashed_token,
|
||||||
deviceType,
|
hashed_login, deviceType, deviceName, ip, login
|
||||||
deviceName,
|
|
||||||
self.tools.get_geo(
|
|
||||||
ip=ip, db_path=self.config.geo_db_path
|
|
||||||
),
|
|
||||||
int(time.time() * 1000)
|
|
||||||
)
|
)
|
||||||
)
|
|
||||||
|
|
||||||
# Аватарка с биографией
|
if resp_payload is None:
|
||||||
photo_id = None if not account.get("avatar_id") else int(account.get("avatar_id"))
|
return
|
||||||
avatar_url = None if not photo_id else self.config.avatar_base_url + str(photo_id)
|
|
||||||
description = None if not account.get("description") else account.get("description")
|
|
||||||
|
|
||||||
# Собираем данные пакета
|
|
||||||
payload = {
|
|
||||||
# Я хз че сюда вставлять)
|
|
||||||
# ребята из одноклассников, может быть вы подскажете?
|
|
||||||
"userToken": str(account.get("id")),
|
|
||||||
"profile": self.tools.generate_profile_tt(
|
|
||||||
id=account.get("id"),
|
|
||||||
phone=int(account.get("phone")),
|
|
||||||
avatarUrl=avatar_url,
|
|
||||||
photoId=photo_id,
|
|
||||||
updateTime=int(account.get("updatetime")),
|
|
||||||
firstName=account.get("firstname"),
|
|
||||||
lastName=account.get("lastname"),
|
|
||||||
options=json.loads(account.get("options")),
|
|
||||||
description=description,
|
|
||||||
username=account.get("username")
|
|
||||||
),
|
|
||||||
"tokenType": "LOGIN",
|
|
||||||
"token": login
|
|
||||||
}
|
|
||||||
|
|
||||||
# Создаем пакет
|
# Создаем пакет
|
||||||
packet = self.proto.pack_packet(
|
packet = self.proto.pack_packet(
|
||||||
cmd=self.proto.CMD_OK, seq=seq, opcode=self.opcodes.AUTH_CONFIRM, payload=payload
|
cmd=self.proto.CMD_OK, seq=seq, opcode=self.opcodes.AUTH_CONFIRM, payload=resp_payload
|
||||||
)
|
)
|
||||||
|
|
||||||
# Отправляем
|
# Отправляем
|
||||||
|
|||||||
Reference in New Issue
Block a user