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

Commit 06fb6d6

Browse files
committed
изменил структуру _pending для хранения дополнительных данных и обновил обработку исключений
1 parent 5081fb7 commit 06fb6d6

File tree

5 files changed

+70
-50
lines changed

5 files changed

+70
-50
lines changed

src/pymax/core.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -137,7 +137,7 @@ def __init__(
137137
self._outgoing: asyncio.Queue[dict[str, Any]] | None = None
138138
self._recv_task: asyncio.Task[Any] | None = None
139139
self._outgoing_task: asyncio.Task[Any] | None = None
140-
self._pending: dict[int, asyncio.Future[dict[str, Any]]] = {}
140+
self._pending: dict[int, tuple[asyncio.Future[dict[str, Any]], int, int | None]] = {}
141141
self._file_upload_waiters: dict[int, asyncio.Future[dict[str, Any]]] = {}
142142
self._background_tasks: set[asyncio.Task[Any]] = set()
143143
self._stop_event = asyncio.Event()
@@ -414,8 +414,9 @@ async def _cleanup_client(self):
414414
self._outgoing_task = None
415415

416416
for fut in self._pending.values():
417-
if not fut.done():
418-
fut.set_exception(SocketNotConnectedError())
417+
old_fut = fut[0]
418+
if not old_fut.done():
419+
old_fut.set_exception(SocketNotConnectedError())
419420
self._pending.clear()
420421

421422
if self._socket:

src/pymax/interfaces.py

Lines changed: 35 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -114,10 +114,11 @@ async def _cleanup_client(self) -> None:
114114
await self._outgoing_task
115115
self._outgoing_task = None
116116

117-
for fut in self._pending.values():
118-
if not fut.done():
119-
fut.set_exception(WebSocketNotConnectedError())
120-
self._pending.clear()
117+
for pending in self._pending.values():
118+
fut = pending[0]
119+
if not fut.done():
120+
fut.set_exception(WebSocketNotConnectedError())
121+
self._pending.clear()
121122

122123
if self._ws:
123124
try:
@@ -281,14 +282,30 @@ def _parse_json(self, raw: Any) -> dict[str, Any] | None:
281282
self.logger.warning("JSON parse error", exc_info=True)
282283
return None
283284

284-
def _handle_pending(self, seq: int | None, data: dict) -> bool:
285-
if isinstance(seq, int):
286-
fut = self._pending.get(seq)
287-
if fut and not fut.done():
288-
fut.set_result(data)
289-
self.logger.debug("Matched response for pending seq=%s", seq)
290-
return True
291-
return False
285+
def _handle_pending(self, seq: int | None, data: dict[str, Any]) -> bool:
286+
if seq is None:
287+
return False
288+
289+
pending = self._pending.get(seq)
290+
if not pending:
291+
return False
292+
293+
fut, expected_cmd, expected_opcode = pending
294+
295+
cmd = data.get("cmd")
296+
opcode = data.get("opcode")
297+
298+
if cmd != expected_cmd:
299+
return False
300+
301+
if expected_opcode is not None and opcode != expected_opcode:
302+
return False
303+
304+
if not fut.done():
305+
fut.set_result(data)
306+
307+
self.logger.debug("Matched response for pending seq=%s", seq)
308+
return True
292309

293310
async def _handle_incoming_queue(self, data: dict[str, Any]) -> None:
294311
if self._incoming:
@@ -311,18 +328,6 @@ async def _handle_file_upload(self, data: dict[str, Any]) -> None:
311328
fut.set_result(data)
312329
self.logger.debug("Fulfilled file upload waiter for %s=%s", key, id_)
313330

314-
async def _send_notification_response(self, chat_id: int, message_id: str) -> None:
315-
if self._socket is not None:
316-
return
317-
await self._queue_message(
318-
opcode=Opcode.NOTIF_MESSAGE,
319-
payload={"chatId": chat_id, "messageId": message_id},
320-
cmd=1,
321-
)
322-
self.logger.debug(
323-
"Sent NOTIF_MESSAGE_RECEIVED for chat_id=%s message_id=%s", chat_id, message_id
324-
)
325-
326331
async def _handle_message_notifications(self, data: dict) -> None:
327332
if data.get("opcode") != Opcode.NOTIF_MESSAGE.value:
328333
return
@@ -331,9 +336,6 @@ async def _handle_message_notifications(self, data: dict) -> None:
331336
if not msg:
332337
return
333338

334-
if msg.chat_id and msg.id:
335-
await self._send_notification_response(msg.chat_id, str(msg.id))
336-
337339
handlers_map = {
338340
MessageStatus.EDITED: self._on_message_edit_handlers,
339341
MessageStatus.REMOVED: self._on_message_delete_handlers,
@@ -538,6 +540,12 @@ async def _sync(self, user_agent: UserAgentPayload | None = None) -> None:
538540

539541
if error := raw_payload.get("error"):
540542
MixinsUtils.handle_error(data)
543+
544+
ping_task = self._create_safe_task(
545+
self._send_interactive_ping(),
546+
name="interactive_ping",
547+
)
548+
541549
chat_marker = raw_payload.get("chatMarker")
542550
if chat_marker:
543551
self.chat_marker = chat_marker

src/pymax/mixins/socket.py

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -274,8 +274,9 @@ async def connect(self, user_agent: UserAgentPayload | None = None) -> dict[str,
274274
raise
275275

276276
for fut in list(self._pending.values()):
277-
if not fut.done():
278-
fut.set_exception(SocketNotConnectedError())
277+
old_fut = fut[0]
278+
if not old_fut.done():
279+
old_fut.set_exception(SocketNotConnectedError())
279280
self._pending.clear()
280281

281282
self.is_connected = True
@@ -419,8 +420,9 @@ async def _recv_loop(self) -> None:
419420
self.is_connected = False
420421

421422
for fut in list(self._pending.values()):
422-
if not fut.done():
423-
fut.set_exception(SocketNotConnectedError())
423+
old_fut = fut[0]
424+
if not old_fut.done():
425+
old_fut.set_exception(SocketNotConnectedError())
424426

425427
self._pending.clear()
426428

@@ -513,8 +515,9 @@ async def _send_and_wait(
513515
self.logger.warning("Connection lost while sending: %s", conn_err)
514516
self.is_connected = False
515517
for pending_fut in list(self._pending.values()):
516-
if not pending_fut.done():
517-
pending_fut.set_exception(SocketNotConnectedError())
518+
old_fut = pending_fut[0]
519+
if not old_fut.done():
520+
old_fut.set_exception(SocketNotConnectedError())
518521
self._pending.clear()
519522

520523
if not fut.done():

src/pymax/mixins/websocket.py

Lines changed: 21 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -49,12 +49,18 @@ async def connect(self, user_agent: UserAgentPayload | None = None) -> dict[str,
4949
self.uri,
5050
origin=WEBSOCKET_ORIGIN,
5151
user_agent_header=user_agent.header_user_agent,
52+
compression="deflate",
53+
ping_interval=None,
54+
open_timeout=10,
55+
close_timeout=10,
5256
proxy=self.proxy,
57+
max_size=None,
5358
)
5459

5560
for fut in list(self._pending.values()):
56-
if not fut.done():
57-
fut.set_exception(WebSocketNotConnectedError())
61+
old_fut = fut[0]
62+
if not old_fut.done():
63+
old_fut.set_exception(WebSocketNotConnectedError())
5864
self._pending.clear()
5965

6066
self.is_connected = True
@@ -68,12 +74,11 @@ async def connect(self, user_agent: UserAgentPayload | None = None) -> dict[str,
6874
self._outgoing_loop(), name="outgoing_loop websocket task"
6975
)
7076
self.logger.debug("is_connected=%s before starting ping", self.is_connected)
71-
ping_task = self._create_safe_task(
72-
self._send_interactive_ping(),
73-
name="interactive_ping",
74-
)
77+
7578
self.logger.info("WebSocket connected, starting handshake")
76-
return await self._handshake(user_agent)
79+
resp = await self._handshake(user_agent)
80+
81+
return resp
7782

7883
async def _recv_loop(self) -> None:
7984
if self._ws is None:
@@ -101,9 +106,10 @@ async def _recv_loop(self) -> None:
101106
self.logger.exception(
102107
f"WebSocket connection closed with error: {e.code}, {e.reason}; exiting recv loop"
103108
)
104-
for fut in self._pending.values():
109+
for pending in self._pending.values():
110+
fut = pending[0]
105111
if not fut.done():
106-
fut.set_exception(WebSocketNotConnectedError)
112+
fut.set_exception(WebSocketNotConnectedError())
107113
self._pending.clear()
108114

109115
self.is_connected = False
@@ -130,11 +136,13 @@ async def _send_and_wait(
130136
fut: asyncio.Future[dict[str, Any]] = loop.create_future()
131137
seq_key = msg["seq"]
132138

133-
old_fut = self._pending.get(seq_key)
134-
if old_fut and not old_fut.done():
135-
old_fut.cancel()
139+
old = self._pending.get(seq_key)
140+
if old:
141+
old_fut = old[0]
142+
if not old_fut.done():
143+
old_fut.cancel()
136144

137-
self._pending[seq_key] = fut
145+
self._pending[seq_key] = (fut, 1, int(opcode))
138146

139147
try:
140148
self.logger.debug(

src/pymax/protocols.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ def __init__(self, logger: Logger) -> None:
6060
self.reconnect_delay: float
6161
self._ws: websockets.ClientConnection | None = None
6262
self._seq: int = 0
63-
self._pending: dict[int, asyncio.Future[dict[str, Any]]] = {}
63+
self._pending: dict[int, tuple[asyncio.Future[dict[str, Any]], int, int | None]] = {}
6464
self._recv_task: asyncio.Task[Any] | None = None
6565
self._incoming: asyncio.Queue[dict[str, Any]] | None = None
6666
self._file_upload_waiters: dict[

0 commit comments

Comments
 (0)