Skip to content
This repository was archived by the owner on Feb 11, 2026. It is now read-only.

Commit 07c7fd2

Browse files
committed
Обновление документации и улучшение обработки аутентификации, включая поддержку двухфакторной аутентификации и исправления для работы с сокетами.
1 parent 5054fd9 commit 07c7fd2

11 files changed

Lines changed: 440 additions & 116 deletions

File tree

redocs/source/release_notes.rst

Lines changed: 3 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -85,59 +85,7 @@ Video
8585

8686
---
8787

88-
Release Notes v1.2.3
89-
====================
90-
91-
Новые функции
92-
-------------
93-
94-
**Загрузка фотографий профиля**
95-
Профиль теперь может быть обновлен с загрузкой новой фотографии через метод ``change_profile()``.
96-
97-
**Разрешение групп по ссылке**
98-
Группы теперь могут быть разрешены (получены) прямо по их ссылке через метод ``resolve_group_by_link()``.
99-
100-
**Поддержка контактов в сообщениях**
101-
Сообщения теперь поддерживают вложения типа контакта с информацией о контакте (ContactAttach).
102-
103-
**Список контактов клиента**
104-
Клиент теперь ведет список всех контактов пользователя через свойство ``client.contacts``.
105-
106-
Новые методы
107-
------------
108-
109-
MaxClient.resolve_group_by_link(link: str) -> Chat | None
110-
Разрешает группу по ссылке. Возвращает объект чата группы или None, если не найдено.
111-
112-
MaxClient.change_profile(first_name, last_name, description, photo)
113-
Изменяет информацию профиля текущего пользователя, включая загрузку новой фотографии.
114-
115-
Новые типы
116-
----------
117-
118-
ContactAttach
119-
Представляет контакт в сообщении. Содержит информацию о контакте (ID, имя, фамилия, фото).
120-
121-
Измененные типы
122-
---------------
123-
124-
Message
125-
Теперь поддерживает вложения типа ContactAttach в список attaches.
126-
127-
Names
128-
Улучшен для работы с различными форматами имен пользователя.
129-
130-
StickerAttach
131-
Улучшено представление стикеров в сообщениях.
132-
133-
Photo
134-
Улучшено для работы с фотографиями профиля.
135-
136-
AttachType
137-
Добавлено значение CONTACT для контактов.
138-
139-
Новые параметры
140-
---------------
88+
Архив
89+
-----
14190

142-
MaxClient.contacts: list[User]
143-
Список контактов текущего пользователя.
91+
Предыдущие версии доступны в :doc:`release_notes_archive`.
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
Archive
2+
=======
3+
4+
Архив предыдущих версий.
5+
6+
v1.2.3 (24 декабря 2025)
7+
=========================
8+
9+
Новые функции
10+
-------------
11+
12+
**Загрузка фотографий профиля**
13+
Профиль теперь может быть обновлен с загрузкой новой фотографии через метод ``change_profile()``.
14+
15+
**Разрешение групп по ссылке**
16+
Группы теперь могут быть разрешены (получены) прямо по их ссылке через метод ``resolve_group_by_link()``.
17+
18+
**Поддержка контактов в сообщениях**
19+
Сообщения теперь поддерживают вложения типа контакта с информацией о контакте (ContactAttach).
20+
21+
**Список контактов клиента**
22+
Клиент теперь ведет список всех контактов пользователя через свойство ``client.contacts``.
23+
24+
Новые методы
25+
------------
26+
27+
MaxClient.resolve_group_by_link(link: str) -> Chat | None
28+
Разрешает группу по ссылке. Возвращает объект чата группы или None, если не найдено.
29+
30+
MaxClient.change_profile(first_name, last_name, description, photo)
31+
Изменяет информацию профиля текущего пользователя, включая загрузку новой фотографии.
32+
33+
Новые типы
34+
----------
35+
36+
ContactAttach
37+
Представляет контакт в сообщении. Содержит информацию о контакте (ID, имя, фамилия, фото).
38+
39+
Измененные типы
40+
---------------
41+
42+
Message
43+
Теперь поддерживает вложения типа ContactAttach в список attaches.
44+
45+
Names
46+
Улучшен для работы с различными форматами имен пользователя.
47+
48+
StickerAttach
49+
Улучшено представление стикеров в сообщениях.
50+
51+
Photo
52+
Улучшено для работы с фотографиями профиля.
53+
54+
AttachType
55+
Добавлено значение CONTACT для контактов.
56+
57+
Новые параметры
58+
---------------
59+
60+
MaxClient.contacts: list[User]
61+
Список контактов текущего пользователя.

src/pymax/core.py

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,7 @@ def __init__(
134134
self._background_tasks: set[asyncio.Task[Any]] = set()
135135
self._stop_event = asyncio.Event()
136136

137-
self._seq: int = 0
137+
self._seq: int = 255
138138
self._error_count: int = 0
139139
self._circuit_breaker: bool = False
140140
self._last_error_time: float = 0.0
@@ -252,7 +252,15 @@ async def login_with_code(self, temp_token: str, code: str, start: bool = False)
252252
:rtype: None
253253
"""
254254
resp = await self._send_code(code, temp_token)
255-
token = resp.get("tokenAttrs", {}).get("LOGIN", {}).get("token")
255+
256+
login_attrs = resp.get("tokenAttrs", {}).get("LOGIN", {})
257+
password_challenge = resp.get("passwordChallenge")
258+
259+
if password_challenge and not login_attrs:
260+
token = await self._two_factor_auth(password_challenge)
261+
else:
262+
token = login_attrs.get("LOGIN", {}).get("token")
263+
256264
if not token:
257265
raise ValueError("Login response did not contain tokenAttrs.LOGIN.token")
258266
self._token = token

src/pymax/interfaces.py

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010

1111
from typing_extensions import Self
1212

13-
from pymax.exceptions import WebSocketNotConnectedError
13+
from pymax.exceptions import SocketNotConnectedError, WebSocketNotConnectedError
1414
from pymax.filters import BaseFilter
1515
from pymax.formatter import ColoredFormatter
1616
from pymax.payloads import BaseWebSocketMessage, SyncPayload, UserAgentPayload
@@ -188,6 +188,7 @@ def _make_message(
188188
self._seq += 1
189189

190190
msg = BaseWebSocketMessage(
191+
ver=11,
191192
cmd=cmd,
192193
seq=self._seq,
193194
opcode=opcode.value,
@@ -206,8 +207,11 @@ async def _send_interactive_ping(self) -> None:
206207
cmd=0,
207208
)
208209
self.logger.debug("Interactive ping sent successfully")
210+
except SocketNotConnectedError:
211+
self.logger.debug("Socket disconnected, exiting ping loop")
212+
break
209213
except Exception:
210-
self.logger.warning("Interactive ping failed", exc_info=True)
214+
self.logger.warning("Interactive ping failed")
211215
await asyncio.sleep(DEFAULT_PING_INTERVAL)
212216

213217
async def _handshake(self, user_agent: UserAgentPayload) -> dict[str, Any]:
@@ -283,6 +287,8 @@ async def _handle_file_upload(self, data: dict[str, Any]) -> None:
283287
self.logger.debug("Fulfilled file upload waiter for %s=%s", key, id_)
284288

285289
async def _send_notification_response(self, chat_id: int, message_id: str) -> None:
290+
if self._socket is not None and self.is_connected:
291+
return
286292
await self._send_and_wait(
287293
opcode=Opcode.NOTIF_MESSAGE,
288294
payload={"chatId": chat_id, "messageId": message_id},

0 commit comments

Comments
 (0)