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

Commit 7c7fcd3

Browse files
committed
фиксы сокета (не опять а снова)
1 parent defa27f commit 7c7fcd3

5 files changed

Lines changed: 45 additions & 13 deletions

File tree

src/pymax/core.py

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -234,13 +234,7 @@ async def _post_login_tasks(self, sync: bool = True) -> None:
234234
if sync:
235235
await self._sync()
236236

237-
self.logger.debug("is_connected=%s before starting ping", self.is_connected)
238-
ping_task = self._create_safe_task(
239-
self._send_interactive_ping(),
240-
name="interactive_ping",
241-
)
242-
243-
start_scheduled_task = self._create_safe_task(
237+
start_scheaduled_task = self._create_safe_task(
244238
self._start_scheduled_tasks(),
245239
name="start_scheduled_tasks",
246240
)

src/pymax/exceptions.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,8 +35,11 @@ class SocketSendError(Exception):
3535
Исключение, вызываемое при ошибке отправки данных через сокет.
3636
"""
3737

38-
def __init__(self) -> None:
39-
super().__init__("Send and wait failed (socket)")
38+
def __init__(self, message: str | None = None) -> None:
39+
if not message:
40+
super().__init__("Send and wait failed (socket)")
41+
else:
42+
super().__init__(message)
4043

4144

4245
class ResponseError(Exception):

src/pymax/mixins/channel.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ async def resolve_channel_by_name(self, name: str) -> Channel | None:
3030
).model_dump(by_alias=True)
3131

3232
data = await self._send_and_wait(opcode=Opcode.LINK_INFO, payload=payload)
33+
3334
if data.get("payload", {}).get("error"):
3435
MixinsUtils.handle_error(data)
3536

src/pymax/mixins/socket.py

Lines changed: 27 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -145,7 +145,7 @@ def _create_socket_with_proxy(self, proxy: str) -> socket.socket:
145145
auth_req = b"\x01" + bytes([len(u)]) + u + bytes([len(p)]) + p
146146
sock.sendall(auth_req)
147147

148-
auth_resp = self._ssl_read_exactly(sock, 2)
148+
auth_resp = self._recv_exactly_plain(sock, 2)
149149
if auth_resp != b"\x01\x00":
150150
sock.close()
151151
raise ConnectionError("SOCKS5 authentication failed")
@@ -220,6 +220,7 @@ async def connect(self, user_agent: UserAgentPayload | None = None) -> dict[str,
220220
:rtype: dict[str, Any] | None
221221
"""
222222
if user_agent is None or self.headers is None:
223+
self.logger.debug("No user agent provided, using default")
223224
user_agent = self.headers or UserAgentPayload()
224225

225226
if sys.version_info[:2] == (3, 12):
@@ -253,6 +254,11 @@ async def connect(self, user_agent: UserAgentPayload | None = None) -> dict[str,
253254
self.logger.error("SSL handshake timeout")
254255
raise
255256

257+
for fut in list(self._pending.values()):
258+
if not fut.done():
259+
fut.set_exception(SocketNotConnectedError())
260+
self._pending.clear()
261+
256262
self.is_connected = True
257263
self._incoming = asyncio.Queue()
258264
self._outgoing = asyncio.Queue()
@@ -273,6 +279,12 @@ async def connect(self, user_agent: UserAgentPayload | None = None) -> dict[str,
273279
)
274280
)
275281

282+
self.logger.debug("is_connected=%s before starting ping", self.is_connected)
283+
ping_task = self._create_safe_task(
284+
self._send_interactive_ping(),
285+
name="interactive_ping",
286+
)
287+
276288
self._outgoing_task = self._create_safe_task(
277289
self._outgoing_loop(), name="outgoing_loop socket task"
278290
)
@@ -384,6 +396,12 @@ async def _recv_loop(self) -> None:
384396
)
385397
self.is_connected = False
386398

399+
for fut in list(self._pending.values()):
400+
if not fut.done():
401+
fut.set_exception(SocketNotConnectedError())
402+
403+
self._pending.clear()
404+
387405
self._socket = None
388406

389407
if self.reconnect and consecutive_errors < max_consecutive_errors:
@@ -462,8 +480,13 @@ async def _send_and_wait(
462480
return data
463481

464482
except (ssl.SSLEOFError, ssl.SSLError, ConnectionError, BrokenPipeError) as conn_err:
465-
self.logger.warning("Connection lost: %s, attempting reconnect...", conn_err)
483+
self.logger.warning("Connection lost while sending: %s", conn_err)
466484
self.is_connected = False
485+
if not fut.done():
486+
fut.set_exception(SocketSendError("connection lost during send"))
487+
488+
self._socket = None
489+
raise SocketSendError("Connection lost during send") from conn_err
467490

468491
except asyncio.TimeoutError:
469492
self.logger.exception("Send and wait failed (opcode=%s, seq=%s)", opcode, msg["seq"])
@@ -473,7 +496,7 @@ async def _send_and_wait(
473496
raise SocketSendError from exc
474497

475498
finally:
476-
self._pending.pop(msg["seq"], None)
499+
self._pending.pop(seq_key, None)
477500

478501
@override
479502
async def _get_chat(self, chat_id: int) -> Chat | None:
@@ -498,4 +521,4 @@ async def send_task():
498521
loop = asyncio.get_running_loop()
499522
await loop.run_in_executor(None, lambda: self._socket.sendall(packet))
500523

501-
asyncio.create_task(send_task())
524+
self._create_safe_task(send_task())

src/pymax/mixins/websocket.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,12 @@ async def connect(self, user_agent: UserAgentPayload | None = None) -> dict[str,
5151
user_agent_header=user_agent.header_user_agent,
5252
proxy=self.proxy,
5353
)
54+
55+
for fut in list(self._pending.values()):
56+
if not fut.done():
57+
fut.set_exception(WebSocketNotConnectedError())
58+
self._pending.clear()
59+
5460
self.is_connected = True
5561
self._incoming = asyncio.Queue()
5662
self._outgoing = asyncio.Queue()
@@ -61,6 +67,11 @@ async def connect(self, user_agent: UserAgentPayload | None = None) -> dict[str,
6167
self._outgoing_task = self._create_safe_task(
6268
self._outgoing_loop(), name="outgoing_loop websocket task"
6369
)
70+
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+
)
6475
self.logger.info("WebSocket connected, starting handshake")
6576
return await self._handshake(user_agent)
6677

0 commit comments

Comments
 (0)