Описание
При повторном запуске клиента, когда work_dir/session.db уже содержит валидный токен (т.е. SMS-авторизация была пройдена ранее), pymax падает с pydantic_core._pydantic_core.ValidationError на этапе Opcode.LOGIN. Сервер Max API в ответе на повторный login не возвращает поле token, а pydantic-модель LoginResponse в pymax объявляет его обязательным.
Сравнение ответов сервера:
- Через SMS + 2FA:
['chats', 'config', 'contacts', 'messages', 'presence', 'profile', 'time', 'token', 'updates']
- Через token из session.db:
['chats', 'config', 'contacts', 'messages', 'presence', 'profile', 'time', 'updates']
Похоже, сервер Max выдаёт новый token только при первичной авторизации, а на повторных логинах (включая вариант с chatsSync=-1 для полной синхронизации) отдаёт payload без него - т.к. старый токен всё ещё валиден.
Шаги для воспроизведения
- Сбросить кэш.
- Пройти авторизацию: ввести SMS-код и 2FA-пароль. Дождаться, пока бот стартует и отправит тестовое сообщение.
- Завершить процесс.
- Снова запустить скрипт.
Ожидаемый результат
Клиент успешно проходит Opcode.LOGIN по сохранённому токену, поднимает сессию, вызывает on_start и продолжает работу. Токен при необходимости продлевается.
Фактический результат
pydantic_core._pydantic_core.ValidationError: 1 validation error for LoginResponse
token
Field required [type=missing, input_value={'profile': {'contact': {...}, 'updates': 1}, input_type=dict]
For further information visit https://errors.pydantic.dev/2.12/v/missing
Стек:
File "pymax\app.py", line 134, in start
response = await self.api.auth.login(self.config.device.user_agent)
File "pymax\api\auth\service.py", line 112, in login
return await self.mobile_login()
File "pymax\api\auth\service.py", line 131, in mobile_login
login_response = require_payload_model(response, LoginResponse)
File "pymax\api\response.py", line 94, in require_payload_model
return model.model_validate(response.payload)
После этого срабатывает await self.close() в base.py:start(), что даёт вторичный ssl.SSLError: [SSL: APPLICATION_DATA_AFTER_CLOSE_NOTIFY].
Дополнительно
- pymax:
2.1.1
- Python: 3.13
- Client:
Client(phone, work_dir, session_name, extra_config=ExtraConfig(...))
user_agent зафиксирован через ExtraConfig(user_agent=MobileUserAgentPayload(...)), но проблема воспроизводится и с рандомным UA из generate_user_agent().
SyncOverrides(chats_sync=-1) для принудительной полной синхронизации не помогает - сервер всё равно не возвращает token.
device_id и userAgent в handshake совпадают между запусками
Описание
При повторном запуске клиента, когда
work_dir/session.dbуже содержит валидный токен (т.е. SMS-авторизация была пройдена ранее), pymax падает сpydantic_core._pydantic_core.ValidationErrorна этапеOpcode.LOGIN. Сервер Max API в ответе на повторный login не возвращает полеtoken, а pydantic-модельLoginResponseв pymax объявляет его обязательным.Сравнение ответов сервера:
['chats', 'config', 'contacts', 'messages', 'presence', 'profile', 'time', 'token', 'updates']['chats', 'config', 'contacts', 'messages', 'presence', 'profile', 'time', 'updates']Похоже, сервер Max выдаёт новый
tokenтолько при первичной авторизации, а на повторных логинах (включая вариант сchatsSync=-1для полной синхронизации) отдаёт payload без него - т.к. старый токен всё ещё валиден.Шаги для воспроизведения
Ожидаемый результат
Клиент успешно проходит
Opcode.LOGINпо сохранённому токену, поднимает сессию, вызываетon_startи продолжает работу. Токен при необходимости продлевается.Фактический результат
Стек:
После этого срабатывает
await self.close()вbase.py:start(), что даёт вторичныйssl.SSLError: [SSL: APPLICATION_DATA_AFTER_CLOSE_NOTIFY].Дополнительно
2.1.1Client(phone, work_dir, session_name, extra_config=ExtraConfig(...))user_agentзафиксирован черезExtraConfig(user_agent=MobileUserAgentPayload(...)), но проблема воспроизводится и с рандомным UA изgenerate_user_agent().SyncOverrides(chats_sync=-1)для принудительной полной синхронизации не помогает - сервер всё равно не возвращает token.device_idиuserAgentв handshake совпадают между запусками