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.
- {maxapi_python-1.2.3.dist-info → maxapi_python-1.2.5.dist-info}/METADATA +9 -7
- maxapi_python-1.2.5.dist-info/RECORD +33 -0
- pymax/core.py +63 -38
- pymax/files.py +28 -7
- pymax/interfaces.py +417 -116
- pymax/mixins/auth.py +231 -5
- pymax/mixins/channel.py +3 -5
- pymax/mixins/group.py +2 -2
- pymax/mixins/handler.py +4 -10
- pymax/mixins/message.py +64 -88
- pymax/mixins/scheduler.py +1 -1
- pymax/mixins/self.py +2 -2
- pymax/mixins/socket.py +16 -340
- pymax/mixins/telemetry.py +10 -6
- pymax/mixins/user.py +3 -5
- pymax/mixins/websocket.py +16 -365
- pymax/payloads.py +44 -1
- pymax/protocols.py +123 -0
- pymax/static/constant.py +76 -8
- pymax/static/enum.py +65 -52
- pymax/types.py +25 -0
- pymax/utils.py +90 -0
- maxapi_python-1.2.3.dist-info/RECORD +0 -32
- pymax/mixins/utils.py +0 -27
- {maxapi_python-1.2.3.dist-info → maxapi_python-1.2.5.dist-info}/WHEEL +0 -0
- {maxapi_python-1.2.3.dist-info → maxapi_python-1.2.5.dist-info}/licenses/LICENSE +0 -0
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] =
|
|
16
|
-
DEFAULT_APP_VERSION: Final[str] = "25.12.
|
|
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] =
|
|
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] =
|
|
24
|
-
DEFAULT_TIMEZONE: Final[str] =
|
|
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
|
-
)
|
|
File without changes
|
|
File without changes
|