maxapi-python 0.1.3__py3-none-any.whl → 1.1.1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
pymax/mixins/__init__.py CHANGED
@@ -1,18 +1,35 @@
1
- from .auth import AuthMixin
2
- from .channel import ChannelMixin
3
- from .handler import HandlerMixin
4
- from .message import MessageMixin
5
- from .self import SelfMixin
6
- from .user import UserMixin
7
- from .websocket import WebSocketMixin
8
-
9
-
10
- class ApiMixin(
11
- AuthMixin,
12
- HandlerMixin,
13
- UserMixin,
14
- ChannelMixin,
15
- SelfMixin,
16
- MessageMixin,
17
- ):
18
- pass
1
+ from .auth import AuthMixin
2
+ from .channel import ChannelMixin
3
+ from .handler import HandlerMixin
4
+ from .message import MessageMixin
5
+ from .self import SelfMixin
6
+ from .socket import SocketMixin
7
+ from .telemetry import TelemetryMixin
8
+ from .user import UserMixin
9
+ from .websocket import WebSocketMixin
10
+
11
+
12
+ class ApiMixin(
13
+ AuthMixin,
14
+ HandlerMixin,
15
+ UserMixin,
16
+ ChannelMixin,
17
+ SelfMixin,
18
+ MessageMixin,
19
+ TelemetryMixin,
20
+ ):
21
+ pass
22
+
23
+
24
+ __all__ = [
25
+ "ApiMixin",
26
+ "AuthMixin",
27
+ "ChannelMixin",
28
+ "HandlerMixin",
29
+ "MessageMixin",
30
+ "SelfMixin",
31
+ "SocketMixin",
32
+ "TelemetryMixin",
33
+ "UserMixin",
34
+ "WebSocketMixin",
35
+ ]
pymax/mixins/auth.py CHANGED
@@ -1,81 +1,81 @@
1
- import asyncio
2
- import re
3
- from typing import Any
4
-
5
- from pymax.interfaces import ClientProtocol
6
- from pymax.payloads import RequestCodePayload, SendCodePayload
7
- from pymax.static import AuthType, Constants, Opcode
8
-
9
-
10
- class AuthMixin(ClientProtocol):
11
- def _check_phone(self) -> bool:
12
- return bool(re.match(Constants.PHONE_REGEX.value, self.phone))
13
-
14
- async def _request_code(
15
- self, phone: str, language: str = "ru"
16
- ) -> dict[str, int | str]:
17
- try:
18
- self.logger.info("Requesting auth code")
19
-
20
- payload = RequestCodePayload(
21
- phone=phone, type=AuthType.START_AUTH, language=language
22
- ).model_dump(by_alias=True)
23
-
24
- data = await self._send_and_wait(
25
- opcode=Opcode.AUTH_REQUEST, payload=payload
26
- )
27
- self.logger.debug(
28
- "Code request response opcode=%s seq=%s",
29
- data.get("opcode"),
30
- data.get("seq"),
31
- )
32
- return data.get("payload")
33
- except Exception:
34
- self.logger.error("Request code failed", exc_info=True)
35
- raise RuntimeError("Request code failed")
36
-
37
- async def _send_code(self, code: str, token: str) -> dict[str, Any]:
38
- try:
39
- self.logger.info("Sending verification code")
40
-
41
- payload = SendCodePayload(
42
- token=token,
43
- verify_code=code,
44
- auth_token_type=AuthType.CHECK_CODE,
45
- ).model_dump(by_alias=True)
46
-
47
- data = await self._send_and_wait(opcode=Opcode.AUTH, payload=payload)
48
- self.logger.debug(
49
- "Send code response opcode=%s seq=%s",
50
- data.get("opcode"),
51
- data.get("seq"),
52
- )
53
- return data.get("payload")
54
- except Exception:
55
- self.logger.error("Send code failed", exc_info=True)
56
- raise RuntimeError("Send code failed")
57
-
58
- async def _login(self) -> None:
59
- self.logger.info("Starting login flow")
60
- request_code_payload = await self._request_code(self.phone)
61
- temp_token = request_code_payload.get("token")
62
- if not temp_token or not isinstance(temp_token, str):
63
- self.logger.critical("Failed to request code: token missing")
64
- raise ValueError("Failed to request code")
65
-
66
- code = await asyncio.to_thread(input, "Введите код: ")
67
- if len(code) != 6 or not code.isdigit():
68
- self.logger.error("Invalid code format entered")
69
- raise ValueError("Invalid code format")
70
-
71
- login_resp = await self._send_code(code, temp_token)
72
- token: str | None = (
73
- login_resp.get("tokenAttrs", {}).get("LOGIN", {}).get("token")
74
- )
75
- if not token:
76
- self.logger.critical("Failed to login, token not received")
77
- raise ValueError("Failed to login, token not received")
78
-
79
- self._token = token
80
- self._database.update_auth_token(self._device_id, self._token)
81
- self.logger.info("Login successful, token saved to database")
1
+ import asyncio
2
+ import re
3
+ from typing import Any
4
+
5
+ from pymax.interfaces import ClientProtocol
6
+ from pymax.payloads import RequestCodePayload, SendCodePayload
7
+ from pymax.static import AuthType, Constants, Opcode
8
+
9
+
10
+ class AuthMixin(ClientProtocol):
11
+ def _check_phone(self) -> bool:
12
+ return bool(re.match(Constants.PHONE_REGEX.value, self.phone))
13
+
14
+ async def _request_code(
15
+ self, phone: str, language: str = "ru"
16
+ ) -> dict[str, int | str]:
17
+ try:
18
+ self.logger.info("Requesting auth code")
19
+
20
+ payload = RequestCodePayload(
21
+ phone=phone, type=AuthType.START_AUTH, language=language
22
+ ).model_dump(by_alias=True)
23
+
24
+ data = await self._send_and_wait(
25
+ opcode=Opcode.AUTH_REQUEST, payload=payload
26
+ )
27
+ self.logger.debug(
28
+ "Code request response opcode=%s seq=%s",
29
+ data.get("opcode"),
30
+ data.get("seq"),
31
+ )
32
+ return data.get("payload")
33
+ except Exception:
34
+ self.logger.error("Request code failed", exc_info=True)
35
+ raise RuntimeError("Request code failed")
36
+
37
+ async def _send_code(self, code: str, token: str) -> dict[str, Any]:
38
+ try:
39
+ self.logger.info("Sending verification code")
40
+
41
+ payload = SendCodePayload(
42
+ token=token,
43
+ verify_code=code,
44
+ auth_token_type=AuthType.CHECK_CODE,
45
+ ).model_dump(by_alias=True)
46
+
47
+ data = await self._send_and_wait(opcode=Opcode.AUTH, payload=payload)
48
+ self.logger.debug(
49
+ "Send code response opcode=%s seq=%s",
50
+ data.get("opcode"),
51
+ data.get("seq"),
52
+ )
53
+ return data.get("payload")
54
+ except Exception:
55
+ self.logger.error("Send code failed", exc_info=True)
56
+ raise RuntimeError("Send code failed")
57
+
58
+ async def _login(self) -> None:
59
+ self.logger.info("Starting login flow")
60
+ request_code_payload = await self._request_code(self.phone)
61
+ temp_token = request_code_payload.get("token")
62
+ if not temp_token or not isinstance(temp_token, str):
63
+ self.logger.critical("Failed to request code: token missing")
64
+ raise ValueError("Failed to request code")
65
+
66
+ code = await asyncio.to_thread(input, "Введите код: ")
67
+ if len(code) != 6 or not code.isdigit():
68
+ self.logger.error("Invalid code format entered")
69
+ raise ValueError("Invalid code format")
70
+
71
+ login_resp = await self._send_code(code, temp_token)
72
+ token: str | None = (
73
+ login_resp.get("tokenAttrs", {}).get("LOGIN", {}).get("token")
74
+ )
75
+ if not token:
76
+ self.logger.critical("Failed to login, token not received")
77
+ raise ValueError("Failed to login, token not received")
78
+
79
+ self._token = token
80
+ self._database.update_auth_token(self._device_id, self._token)
81
+ self.logger.info("Login successful, token saved to database")
pymax/mixins/channel.py CHANGED
@@ -1,25 +1,25 @@
1
- from pymax.interfaces import ClientProtocol
2
- from pymax.payloads import ResolveLinkPayload
3
- from pymax.static import Opcode
4
-
5
-
6
- class ChannelMixin(ClientProtocol):
7
- async def resolve_channel_by_name(self, name: str) -> bool:
8
- """
9
- Пытается найти канал по его имени
10
-
11
- Args:
12
- name (str): Имя канала
13
-
14
- Returns:
15
- bool: True, если канал найден
16
- """
17
- payload = ResolveLinkPayload(
18
- link=f"https://max.ru/{name}",
19
- ).model_dump(by_alias=True)
20
-
21
- data = await self._send_and_wait(opcode=Opcode.LINK_INFO, payload=payload)
22
- if error := data.get("payload", {}).get("error"):
23
- self.logger.error("Resolve link error: %s", error)
24
- return False
25
- return True
1
+ from pymax.interfaces import ClientProtocol
2
+ from pymax.payloads import ResolveLinkPayload
3
+ from pymax.static import Opcode
4
+
5
+
6
+ class ChannelMixin(ClientProtocol):
7
+ async def resolve_channel_by_name(self, name: str) -> bool:
8
+ """
9
+ Пытается найти канал по его имени
10
+
11
+ Args:
12
+ name (str): Имя канала
13
+
14
+ Returns:
15
+ bool: True, если канал найден
16
+ """
17
+ payload = ResolveLinkPayload(
18
+ link=f"https://max.ru/{name}",
19
+ ).model_dump(by_alias=True)
20
+
21
+ data = await self._send_and_wait(opcode=Opcode.LINK_INFO, payload=payload)
22
+ if error := data.get("payload", {}).get("error"):
23
+ self.logger.error("Resolve link error: %s", error)
24
+ return False
25
+ return True