maxapi-python 1.2.3__py3-none-any.whl → 1.2.5__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/static/constant.py CHANGED
@@ -1,10 +1,73 @@
1
+ from random import choice, randint
1
2
  from re import Pattern, compile
2
3
  from typing import Final
3
4
 
5
+ import ua_generator
4
6
  from websockets.typing import Origin
5
7
 
8
+ from pymax.utils import MixinsUtils
9
+
10
+ DEVICE_NAMES: Final[list[str]] = [
11
+ "Chrome",
12
+ "Firefox",
13
+ "Edge",
14
+ "Safari",
15
+ "Opera",
16
+ "Vivaldi",
17
+ "Brave",
18
+ "Chromium",
19
+ # os
20
+ "Windows 10",
21
+ "Windows 11",
22
+ "macOS Big Sur",
23
+ "macOS Monterey",
24
+ "macOS Ventura",
25
+ "Ubuntu 20.04",
26
+ "Ubuntu 22.04",
27
+ "Fedora 35",
28
+ "Fedora 36",
29
+ "Debian 11",
30
+ ]
31
+ SCREEN_SIZES: Final[list[str]] = [
32
+ "1920x1080 1.0x",
33
+ "1366x768 1.0x",
34
+ "1440x900 1.0x",
35
+ "1536x864 1.0x",
36
+ "1280x720 1.0x",
37
+ "1600x900 1.0x",
38
+ "1680x1050 1.0x",
39
+ "2560x1440 1.0x",
40
+ "3840x2160 1.0x",
41
+ ]
42
+ OS_VERSIONS: Final[list[str]] = [
43
+ "Windows 10",
44
+ "Windows 11",
45
+ "macOS Big Sur",
46
+ "macOS Monterey",
47
+ "macOS Ventura",
48
+ "Ubuntu 20.04",
49
+ "Ubuntu 22.04",
50
+ "Fedora 35",
51
+ "Fedora 36",
52
+ "Debian 11",
53
+ ]
54
+ TIMEZONES: Final[list[str]] = [
55
+ "Europe/Moscow",
56
+ "Europe/Kaliningrad",
57
+ "Europe/Samara",
58
+ "Asia/Yekaterinburg",
59
+ "Asia/Omsk",
60
+ "Asia/Krasnoyarsk",
61
+ "Asia/Irkutsk",
62
+ "Asia/Yakutsk",
63
+ "Asia/Vladivostok",
64
+ "Asia/Kamchatka",
65
+ ]
66
+
67
+
6
68
  PHONE_REGEX: Final[Pattern[str]] = compile(r"^\+?\d{10,15}$")
7
69
  WEBSOCKET_URI: Final[str] = "wss://ws-api.oneme.ru/websocket"
70
+ SESSION_STORAGE_DB = "session.db"
8
71
  WEBSOCKET_ORIGIN: Final[Origin] = Origin("https://web.max.ru")
9
72
  HOST: Final[str] = "api.oneme.ru"
10
73
  PORT: Final[int] = 443
@@ -12,17 +75,22 @@ DEFAULT_TIMEOUT: Final[float] = 20.0
12
75
  DEFAULT_DEVICE_TYPE: Final[str] = "DESKTOP"
13
76
  DEFAULT_LOCALE: Final[str] = "ru"
14
77
  DEFAULT_DEVICE_LOCALE: Final[str] = "ru"
15
- DEFAULT_DEVICE_NAME: Final[str] = "Chrome"
16
- DEFAULT_APP_VERSION: Final[str] = "25.12.13"
78
+ DEFAULT_DEVICE_NAME: Final[str] = choice(DEVICE_NAMES)
79
+ DEFAULT_APP_VERSION: Final[str] = "25.12.14"
17
80
  DEFAULT_SCREEN: Final[str] = "1080x1920 1.0x"
18
- DEFAULT_OS_VERSION: Final[str] = "Linux"
19
- DEFAULT_USER_AGENT: Final[str] = (
20
- "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/141.0.0.0 Safari/537.36"
21
- )
81
+ DEFAULT_OS_VERSION: Final[str] = choice(OS_VERSIONS)
82
+ DEFAULT_USER_AGENT: Final[str] = ua_generator.generate().text
22
83
  DEFAULT_BUILD_NUMBER: Final[int] = 0x97CB
23
- DEFAULT_CLIENT_SESSION_ID: Final[int] = 14
24
- DEFAULT_TIMEZONE: Final[str] = "Europe/Moscow"
84
+ DEFAULT_CLIENT_SESSION_ID: Final[int] = randint(1, 15)
85
+ DEFAULT_TIMEZONE: Final[str] = choice(TIMEZONES)
25
86
  DEFAULT_CHAT_MEMBERS_LIMIT: Final[int] = 50
26
87
  DEFAULT_MARKER_VALUE: Final[int] = 0
27
88
  DEFAULT_PING_INTERVAL: Final[float] = 30.0
28
89
  RECV_LOOP_BACKOFF_DELAY: Final[float] = 0.5
90
+
91
+
92
+ class _Unset:
93
+ pass
94
+
95
+
96
+ UNSET = _Unset()
pymax/static/enum.py CHANGED
@@ -2,28 +2,28 @@ from enum import Enum
2
2
 
3
3
 
4
4
  class Opcode(int, Enum):
5
- PING = 1
5
+ PING = 1 # ✅
6
6
  DEBUG = 2
7
7
  RECONNECT = 3
8
- LOG = 5
9
- SESSION_INIT = 6
10
- PROFILE = 16
11
- AUTH_REQUEST = 17
12
- AUTH = 18
13
- LOGIN = 19
14
- LOGOUT = 20
8
+ LOG = 5 # ✅
9
+ SESSION_INIT = 6 # ✅
10
+ PROFILE = 16 # ✅
11
+ AUTH_REQUEST = 17 # ✅
12
+ AUTH = 18 # ✅
13
+ LOGIN = 19 # ✅
14
+ LOGOUT = 20 # ✅
15
15
  SYNC = 21
16
16
  CONFIG = 22
17
- AUTH_CONFIRM = 23
17
+ AUTH_CONFIRM = 23 # ✅
18
18
  PRESET_AVATARS = 25
19
19
  ASSETS_GET = 26
20
20
  ASSETS_UPDATE = 27
21
21
  ASSETS_GET_BY_IDS = 28
22
22
  ASSETS_ADD = 29
23
23
  SEARCH_FEEDBACK = 31
24
- CONTACT_INFO = 32
24
+ CONTACT_INFO = 32 # ✅
25
25
  CONTACT_ADD = 33
26
- CONTACT_UPDATE = 34
26
+ CONTACT_UPDATE = 34 # ✅
27
27
  CONTACT_PRESENCE = 35
28
28
  CONTACT_LIST = 36
29
29
  CONTACT_SEARCH = 37
@@ -32,26 +32,26 @@ class Opcode(int, Enum):
32
32
  CONTACT_SORT = 40
33
33
  CONTACT_VERIFY = 42
34
34
  REMOVE_CONTACT_PHOTO = 43
35
- CONTACT_INFO_BY_PHONE = 46
36
- CHAT_INFO = 48
37
- CHAT_HISTORY = 49
38
- CHAT_MARK = 50
35
+ CONTACT_INFO_BY_PHONE = 46 # ✅
36
+ CHAT_INFO = 48 # ✅
37
+ CHAT_HISTORY = 49 # ✅
38
+ CHAT_MARK = 50 # ✅
39
39
  CHAT_MEDIA = 51
40
40
  CHAT_DELETE = 52
41
- CHATS_LIST = 53
41
+ CHATS_LIST = 53 # ✅
42
42
  CHAT_CLEAR = 54
43
- CHAT_UPDATE = 55
43
+ CHAT_UPDATE = 55 # ✅
44
44
  CHAT_CHECK_LINK = 56
45
- CHAT_JOIN = 57
46
- CHAT_LEAVE = 58
47
- CHAT_MEMBERS = 59
45
+ CHAT_JOIN = 57 # ✅
46
+ CHAT_LEAVE = 58 # ✅
47
+ CHAT_MEMBERS = 59 # ✅
48
48
  PUBLIC_SEARCH = 60
49
49
  CHAT_CLOSE = 61
50
50
  CHAT_CREATE = 63
51
- MSG_SEND = 64
51
+ MSG_SEND = 64 # ✅
52
52
  MSG_TYPING = 65
53
- MSG_DELETE = 66
54
- MSG_EDIT = 67
53
+ MSG_DELETE = 66 # ✅
54
+ MSG_EDIT = 67 # ✅
55
55
  CHAT_SEARCH = 68
56
56
  MSG_SHARE_PREVIEW = 70
57
57
  MSG_GET = 71
@@ -60,31 +60,31 @@ class Opcode(int, Enum):
60
60
  MSG_GET_STAT = 74
61
61
  CHAT_SUBSCRIBE = 75
62
62
  VIDEO_CHAT_START = 76
63
- CHAT_MEMBERS_UPDATE = 77
63
+ CHAT_MEMBERS_UPDATE = 77 # ✅
64
64
  VIDEO_CHAT_HISTORY = 79
65
- PHOTO_UPLOAD = 80
65
+ PHOTO_UPLOAD = 80 # ✅
66
66
  STICKER_UPLOAD = 81
67
- VIDEO_UPLOAD = 82
68
- VIDEO_PLAY = 83
67
+ VIDEO_UPLOAD = 82 # ✅
68
+ VIDEO_PLAY = 83 # ✅
69
69
  CHAT_PIN_SET_VISIBILITY = 86
70
- FILE_UPLOAD = 87
71
- FILE_DOWNLOAD = 88
72
- LINK_INFO = 89
70
+ FILE_UPLOAD = 87 # ✅
71
+ FILE_DOWNLOAD = 88 # ✅
72
+ LINK_INFO = 89 # ✅
73
73
  MSG_DELETE_RANGE = 92
74
- SESSIONS_INFO = 96
75
- SESSIONS_CLOSE = 97
74
+ SESSIONS_INFO = 96 # ✅
75
+ SESSIONS_CLOSE = 97 # ✅
76
76
  PHONE_BIND_REQUEST = 98
77
77
  PHONE_BIND_CONFIRM = 99
78
78
  CONFIRM_PRESENT = 101
79
79
  GET_INBOUND_CALLS = 103
80
80
  EXTERNAL_CALLBACK = 105
81
- AUTH_VALIDATE_PASSWORD = 107
82
- AUTH_VALIDATE_HINT = 108
83
- AUTH_VERIFY_EMAIL = 109
84
- AUTH_CHECK_EMAIL = 110
85
- AUTH_SET_2FA = 111
86
- AUTH_CREATE_TRACK = 112
87
- AUTH_LOGIN_CHECK_PASSWORD = 115
81
+ AUTH_VALIDATE_PASSWORD = 107 # ✅
82
+ AUTH_VALIDATE_HINT = 108 # ✅
83
+ AUTH_VERIFY_EMAIL = 109 # ✅
84
+ AUTH_CHECK_EMAIL = 110 # ✅
85
+ AUTH_SET_2FA = 111 # ✅
86
+ AUTH_CREATE_TRACK = 112 # ✅
87
+ AUTH_LOGIN_CHECK_PASSWORD = 115 # ✅
88
88
  CHAT_COMPLAIN = 117
89
89
  MSG_SEND_CALLBACK = 118
90
90
  SUSPEND_BOT = 119
@@ -92,14 +92,14 @@ class Opcode(int, Enum):
92
92
  LOCATION_SEND = 125
93
93
  LOCATION_REQUEST = 126
94
94
  GET_LAST_MENTIONS = 127
95
- NOTIF_MESSAGE = 128
95
+ NOTIF_MESSAGE = 128 # ✅
96
96
  NOTIF_TYPING = 129
97
97
  NOTIF_MARK = 130
98
98
  NOTIF_CONTACT = 131
99
99
  NOTIF_PRESENCE = 132
100
100
  NOTIF_CONFIG = 134
101
- NOTIF_CHAT = 135
102
- NOTIF_ATTACH = 136
101
+ NOTIF_CHAT = 135 # ✅
102
+ NOTIF_ATTACH = 136 # ✅
103
103
  NOTIF_CALL_START = 137
104
104
  NOTIF_CONTACT_SORT = 139
105
105
  NOTIF_MSG_DELETE_RANGE = 140
@@ -113,16 +113,16 @@ class Opcode(int, Enum):
113
113
  NOTIF_DRAFT = 152
114
114
  NOTIF_DRAFT_DISCARD = 153
115
115
  NOTIF_MSG_DELAYED = 154
116
- NOTIF_MSG_REACTIONS_CHANGED = 155
116
+ NOTIF_MSG_REACTIONS_CHANGED = 155 # ✅
117
117
  NOTIF_MSG_YOU_REACTED = 156
118
118
  CALLS_TOKEN = 158
119
119
  NOTIF_PROFILE = 159
120
120
  WEB_APP_INIT_DATA = 160
121
121
  DRAFT_SAVE = 176
122
122
  DRAFT_DISCARD = 177
123
- MSG_REACTION = 178
124
- MSG_CANCEL_REACTION = 179
125
- MSG_GET_REACTIONS = 180
123
+ MSG_REACTION = 178 # ✅
124
+ MSG_CANCEL_REACTION = 179 # ✅
125
+ MSG_GET_REACTIONS = 180 # ✅
126
126
  MSG_GET_DETAILED_REACTIONS = 181
127
127
  STICKER_CREATE = 193
128
128
  STICKER_SUGGEST = 194
@@ -134,16 +134,16 @@ class Opcode(int, Enum):
134
134
  ASSETS_REMOVE = 259
135
135
  ASSETS_MOVE = 260
136
136
  ASSETS_LIST_MODIFY = 261
137
- FOLDERS_GET = 272
137
+ FOLDERS_GET = 272 # ✅
138
138
  FOLDERS_GET_BY_ID = 273
139
- FOLDERS_UPDATE = 274
139
+ FOLDERS_UPDATE = 274 # ✅
140
140
  FOLDERS_REORDER = 275
141
- FOLDERS_DELETE = 276
141
+ FOLDERS_DELETE = 276 # ✅
142
142
  NOTIF_FOLDERS = 277
143
143
 
144
- GET_QR = 288
145
- GET_QR_STATUS = 289
146
- LOGIN_BY_QR = 291
144
+ GET_QR = 288 # ✅
145
+ GET_QR_STATUS = 289 # ✅
146
+ LOGIN_BY_QR = 291 # ✅
147
147
 
148
148
 
149
149
  class ChatType(str, Enum):
@@ -216,3 +216,16 @@ class MarkupType(str, Enum):
216
216
  class ContactAction(str, Enum):
217
217
  ADD = "ADD"
218
218
  REMOVE = "REMOVE"
219
+
220
+
221
+ class ReadAction(str, Enum):
222
+ READ_MESSAGE = "READ_MESSAGE"
223
+ READ_REACTION = "READ_REACTION"
224
+
225
+
226
+ class Capability(int, Enum):
227
+ DEFAULT = 0 # В душе не чаю что это такое но при первой установке 2фа там 0 3 4 так что пусть будет дефолт
228
+ ESIA_VERIFIED_FLAG = 1
229
+ SECOND_FACTOR_PASSWORD_ENABLED = 2
230
+ SECOND_FACTOR_HAS_EMAIL = 3
231
+ SECOND_FACTOR_HAS_HINT = 4
pymax/types.py CHANGED
@@ -1193,3 +1193,28 @@ class FolderList:
1193
1193
  @override
1194
1194
  def __str__(self) -> str:
1195
1195
  return f"FolderList: {len(self.folders)} folders"
1196
+
1197
+
1198
+ class ReadState:
1199
+ def __init__(
1200
+ self,
1201
+ unread: int,
1202
+ mark: int,
1203
+ ) -> None:
1204
+ self.unread = unread
1205
+ self.mark = mark
1206
+
1207
+ @classmethod
1208
+ def from_dict(cls, data: dict[str, Any]) -> Self:
1209
+ return cls(
1210
+ unread=data["unread"],
1211
+ mark=data["mark"],
1212
+ )
1213
+
1214
+ @override
1215
+ def __repr__(self) -> str:
1216
+ return f"ReadState(unread={self.unread!r}, mark={self.mark!r})"
1217
+
1218
+ @override
1219
+ def __str__(self) -> str:
1220
+ return f"ReadState: unread={self.unread}, mark={self.mark}"
pymax/utils.py ADDED
@@ -0,0 +1,90 @@
1
+ import re
2
+ import time
3
+ from concurrent.futures import ThreadPoolExecutor, as_completed
4
+ from typing import Any, NoReturn
5
+
6
+ import requests
7
+
8
+ from pymax.exceptions import Error, RateLimitError
9
+
10
+
11
+ class MixinsUtils:
12
+ @staticmethod
13
+ def handle_error(data: dict[str, Any]) -> NoReturn:
14
+ error = data.get("payload", {}).get("error")
15
+ localized_message = data.get("payload", {}).get("localizedMessage")
16
+ title = data.get("payload", {}).get("title")
17
+ message = data.get("payload", {}).get("message")
18
+
19
+ if error == "too.many.requests": # TODO: вынести в статик
20
+ raise RateLimitError(
21
+ error=error,
22
+ message=message,
23
+ title=title,
24
+ localized_message=localized_message,
25
+ )
26
+
27
+ raise Error(
28
+ error=error,
29
+ message=message,
30
+ title=title,
31
+ localized_message=localized_message,
32
+ )
33
+
34
+ @staticmethod
35
+ def _fetch_and_extract(url: str, session: requests.Session) -> str | None:
36
+ try:
37
+ js_code = session.get(url, timeout=10).text
38
+ except requests.RequestException:
39
+ return None
40
+ return MixinsUtils._extract_version(js_code)
41
+
42
+ @staticmethod
43
+ def _extract_version(js_code: str) -> str | None:
44
+ ws_anchor = "wss://ws-api.oneme.ru/websocket"
45
+ pos = js_code.find(ws_anchor)
46
+ if pos == -1:
47
+ return None
48
+
49
+ snippet = js_code[pos : pos + 2000]
50
+
51
+ match = re.search(r'[:=]\s*"(\d{1,2}\.\d{1,2}\.\d{1,2})"', snippet)
52
+ if match:
53
+ version = match.group(1)
54
+ return version
55
+
56
+ return None
57
+
58
+ @staticmethod
59
+ def get_current_web_version() -> str | None:
60
+ try:
61
+ html = requests.get("https://web.max.ru/", timeout=10).text
62
+ except requests.RequestException:
63
+ return None
64
+
65
+ main_chunk_import = html.split("import(")[2].split(")")[0].strip("\"'")
66
+ main_chunk_url = f"https://web.max.ru{main_chunk_import}"
67
+ try:
68
+ main_chunk_code = requests.get(main_chunk_url, timeout=10).text
69
+ except requests.exceptions.RequestException as e:
70
+ return None
71
+
72
+ arr = main_chunk_code.split("\n")[0].split("[")[1].split("]")[0].split(",")
73
+ urls = []
74
+ for i in arr:
75
+ if "/chunks/" in i:
76
+ url = "https://web.max.ru/_app/immutable" + i[3 : len(i) - 1]
77
+ urls.append(url)
78
+
79
+ session = requests.Session()
80
+ session.headers["User-Agent"] = "Mozilla/5.0"
81
+ if urls:
82
+ with ThreadPoolExecutor(max_workers=8) as pool:
83
+ futures = [
84
+ pool.submit(MixinsUtils._fetch_and_extract, url, session) for url in urls
85
+ ]
86
+ for f in as_completed(futures):
87
+ ver = f.result()
88
+ if ver:
89
+ return ver
90
+ return None
@@ -1,32 +0,0 @@
1
- pymax/__init__.py,sha256=6wUKKwsyxFpWG3b7kwptOvHd-w78C-ygw42iCDBYQvc,1915
2
- pymax/core.py,sha256=S5el07cMcqIyXOI25G0a2XtVJSz2_AltmKN7ZW6LEeg,14946
3
- pymax/crud.py,sha256=YC92TyhA2mr1tJCcfd-tvh8umtXKgqJfgiLo7nXUl3Q,3076
4
- pymax/exceptions.py,sha256=nDUNx7bM-Yjugj-qfIllcrnwLg9JpZroYqfXapjYbMQ,3178
5
- pymax/files.py,sha256=bSjP1m-dLPJCN8HPZtjrLLp0Oc7OxdGxI6U1K2rQzUA,3587
6
- pymax/filters.py,sha256=gSHPJ1Vi37HKPxf0jRRv9Q3iGwhiQjw1MGrCaouqHzs,4325
7
- pymax/formatter.py,sha256=RJ_5VbY7Li8UM3xL1AvcXo8v1iYnY8GvDDkreaFqtnY,860
8
- pymax/formatting.py,sha256=XRtuXJGweuNZevJFdPxksDftIrfuMGEA-AOUc_v6IhQ,2484
9
- pymax/interfaces.py,sha256=5-0RM0tH3eBJrVZkjL494lKTTwvIVmOTJiQxDWZo-7A,8829
10
- pymax/models.py,sha256=PsPGbOkERxesZZltjNrmqhOfRcO44Is2ThbEToREcB8,201
11
- pymax/navigation.py,sha256=4ia6RGY2pXMArboNhHkbWlWX7LtcYK1VGVXorPX0Pb4,5747
12
- pymax/payloads.py,sha256=tlqPT-JFexfklp9idSrbpU3bALcQuiDne9H9vTnwL4w,8022
13
- pymax/types.py,sha256=_Ee1aycVwe4nfBO_hGMnpm9lQDGzkPOkT9vME8OL-sA,36650
14
- pymax/mixins/__init__.py,sha256=5sXJME34S1EssuDETaN4DLRH7vhMw_Q3Jmay9myAIZM,775
15
- pymax/mixins/auth.py,sha256=e90vIpEOwAjUxgYMYaG7R6jR_5t9rKsei_mTBQUirL4,14716
16
- pymax/mixins/channel.py,sha256=W52YnBay1sUYXxF9oAWsz44ZUh_s45jSvKmAyjTbULM,5357
17
- pymax/mixins/group.py,sha256=MaiZCQ9R-wWbuEPXyqf4JZAGNmxu_tXCs8qU3JEoYek,15911
18
- pymax/mixins/handler.py,sha256=ETnI8fA386LYJGjWtUhhWzQHREUA78di1aO1oWwtscA,12523
19
- pymax/mixins/message.py,sha256=AznKKmTMxdzsYl8IecT43RjWpGvlQM85GzSNGFbI8BA,33279
20
- pymax/mixins/scheduler.py,sha256=rcMfgfZnzu5V6MkcCg6uRgbi-jkc7UyqOjemulydWbc,964
21
- pymax/mixins/self.py,sha256=27ranVw5rdv1qSplhV5mdUvHc4qSxHi63f1gWOjR9B4,9182
22
- pymax/mixins/socket.py,sha256=tk2puQPsT2Dltg1j6kUSHIbXs64p6q-jiIIcs73Y1Sk,23174
23
- pymax/mixins/telemetry.py,sha256=LWr68DNQkPhAjGRDYQ5lORXxC3Yw6M9E8sF0TCNISTE,3609
24
- pymax/mixins/user.py,sha256=RSZd4t-aq8P2k3cVzNVWBkUf-_xTWILrBzwxLRgk1pw,9450
25
- pymax/mixins/utils.py,sha256=s3FUf3i_wjn2Gbg5YY1rWZB-90ZEGrrcUuND_MqqSTE,853
26
- pymax/mixins/websocket.py,sha256=fL8IcsLkvksizSAg98UaFlDPZGyGbYtbtdHnlDzfR9g,18056
27
- pymax/static/constant.py,sha256=nM0svv3VpsVxK-RqoADn9qsTdQvB-IYv0Sgv-bQcWs4,1116
28
- pymax/static/enum.py,sha256=mraN6FK_gcVXdTHBdK8Zf6-92AzVFGAWRnQLA4rzYBA,4672
29
- maxapi_python-1.2.3.dist-info/METADATA,sha256=0NSb43LEMf9-M1KLeETofzdcjsGJ68lpZ15xP9GouI0,6753
30
- maxapi_python-1.2.3.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
31
- maxapi_python-1.2.3.dist-info/licenses/LICENSE,sha256=hOR249ItqMdcly1A0amqEWRNRTq4Gv5NJtmQ3A5qK4E,1070
32
- maxapi_python-1.2.3.dist-info/RECORD,,
pymax/mixins/utils.py DELETED
@@ -1,27 +0,0 @@
1
- from typing import Any, NoReturn
2
-
3
- from pymax.exceptions import Error, RateLimitError
4
-
5
-
6
- class MixinsUtils:
7
- @staticmethod
8
- def handle_error(data: dict[str, Any]) -> NoReturn:
9
- error = data.get("payload", {}).get("error")
10
- localized_message = data.get("payload", {}).get("localizedMessage")
11
- title = data.get("payload", {}).get("title")
12
- message = data.get("payload", {}).get("message")
13
-
14
- if error == "too.many.requests": # TODO: вынести в статик
15
- raise RateLimitError(
16
- error=error,
17
- message=message,
18
- title=title,
19
- localized_message=localized_message,
20
- )
21
-
22
- raise Error(
23
- error=error,
24
- message=message,
25
- title=title,
26
- localized_message=localized_message,
27
- )