maxapi-python 2.0.1__py3-none-any.whl → 2.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.
- {maxapi_python-2.0.1.dist-info → maxapi_python-2.1.1.dist-info}/METADATA +4 -1
- {maxapi_python-2.0.1.dist-info → maxapi_python-2.1.1.dist-info}/RECORD +62 -55
- pymax/__init__.py +1 -1
- pymax/api/auth/enums.py +13 -2
- pymax/api/auth/payloads.py +10 -6
- pymax/api/auth/service.py +75 -12
- pymax/api/bots/__init__.py +1 -0
- pymax/api/bots/payloads.py +7 -0
- pymax/api/bots/service.py +35 -0
- pymax/api/chats/enums.py +1 -0
- pymax/api/chats/payloads.py +14 -0
- pymax/api/chats/service.py +112 -12
- pymax/api/facade.py +2 -0
- pymax/api/messages/payloads.py +5 -1
- pymax/api/messages/service.py +36 -11
- pymax/api/self/service.py +29 -10
- pymax/api/session/payloads.py +9 -2
- pymax/api/uploads/models.py +1 -4
- pymax/api/uploads/payloads.py +9 -3
- pymax/api/uploads/service.py +107 -37
- pymax/api/users/service.py +15 -5
- pymax/app.py +19 -5
- pymax/auth/qr.py +11 -6
- pymax/auth/sms.py +13 -4
- pymax/base.py +1 -0
- pymax/client.py +4 -1
- pymax/client_web.py +4 -2
- pymax/config.py +11 -3
- pymax/connection/connection.py +15 -5
- pymax/connection/readers/tcp.py +4 -2
- pymax/dispatch/dispatcher.py +28 -10
- pymax/dispatch/mapping.py +9 -2
- pymax/dispatch/router.py +2 -0
- pymax/files/base.py +6 -1
- pymax/formatting/markdown.py +4 -1
- pymax/infra/auth.py +42 -0
- pymax/infra/base.py +2 -0
- pymax/infra/bots.py +33 -0
- pymax/infra/chat.py +102 -1
- pymax/infra/self.py +2 -6
- pymax/protocol/tcp/compression.py +3 -1
- pymax/protocol/tcp/framing.py +6 -11
- pymax/protocol/tcp/payload.py +3 -2
- pymax/protocol/tcp/protocol.py +13 -3
- pymax/protocol/ws/protocol.py +9 -3
- pymax/session/protocol.py +6 -2
- pymax/session/store.py +24 -8
- pymax/telemetry/navigation.py +3 -1
- pymax/telemetry/service.py +9 -3
- pymax/transport/tcp.py +14 -6
- pymax/transport/websocket.py +0 -2
- pymax/types/domain/__init__.py +3 -0
- pymax/types/domain/bots.py +14 -0
- pymax/types/domain/error.py +3 -3
- pymax/types/domain/folder.py +1 -1
- pymax/types/domain/login.py +18 -6
- pymax/types/domain/member.py +16 -0
- pymax/types/domain/presence.py +15 -0
- pymax/types/domain/sync.py +21 -5
- pymax/types/domain/user.py +12 -0
- {maxapi_python-2.0.1.dist-info → maxapi_python-2.1.1.dist-info}/WHEEL +0 -0
- {maxapi_python-2.0.1.dist-info → maxapi_python-2.1.1.dist-info}/licenses/LICENSE +0 -0
pymax/transport/tcp.py
CHANGED
|
@@ -10,7 +10,9 @@ logger = get_logger(__name__)
|
|
|
10
10
|
|
|
11
11
|
|
|
12
12
|
class TCPTransport(Transport):
|
|
13
|
-
def __init__(
|
|
13
|
+
def __init__(
|
|
14
|
+
self, host: str, port: int, proxy: str | None, use_ssl: bool = True
|
|
15
|
+
) -> None:
|
|
14
16
|
self._host = host
|
|
15
17
|
self._port = port
|
|
16
18
|
self._proxy = proxy
|
|
@@ -31,10 +33,12 @@ class TCPTransport(Transport):
|
|
|
31
33
|
sock = await proxy.connect(
|
|
32
34
|
dest_host=self._host,
|
|
33
35
|
dest_port=self._port,
|
|
34
|
-
ssl=self._use_ssl,
|
|
35
36
|
)
|
|
37
|
+
server_hostname = self._host if self._use_ssl else None
|
|
36
38
|
self._reader, self._writer = await asyncio.open_connection(
|
|
37
|
-
sock=sock,
|
|
39
|
+
sock=sock,
|
|
40
|
+
ssl=self._use_ssl,
|
|
41
|
+
server_hostname=server_hostname,
|
|
38
42
|
)
|
|
39
43
|
logger.info(
|
|
40
44
|
"tcp connected via proxy %s host=%s port=%s ssl=%s",
|
|
@@ -57,10 +61,14 @@ class TCPTransport(Transport):
|
|
|
57
61
|
)
|
|
58
62
|
|
|
59
63
|
async def close(self) -> None:
|
|
60
|
-
|
|
64
|
+
writer = self._writer
|
|
65
|
+
self._reader = None
|
|
66
|
+
self._writer = None
|
|
67
|
+
|
|
68
|
+
if writer:
|
|
61
69
|
logger.debug("tcp close")
|
|
62
|
-
|
|
63
|
-
await
|
|
70
|
+
writer.close()
|
|
71
|
+
await writer.wait_closed()
|
|
64
72
|
logger.debug("tcp closed")
|
|
65
73
|
|
|
66
74
|
async def send(self, data: bytes | str) -> None:
|
pymax/transport/websocket.py
CHANGED
pymax/types/domain/__init__.py
CHANGED
|
@@ -1,10 +1,13 @@
|
|
|
1
1
|
from .attachments import *
|
|
2
|
+
from .bots import InitData
|
|
2
3
|
from .chat import Chat
|
|
3
4
|
from .error import MaxApiError
|
|
4
5
|
from .folder import Folder, FolderList, FolderUpdate
|
|
5
6
|
from .login import LoginResponse
|
|
7
|
+
from .member import Member
|
|
6
8
|
from .message import Message, ReactionCounter, ReactionInfo, ReadState
|
|
7
9
|
from .name import Name
|
|
10
|
+
from .presence import Presence
|
|
8
11
|
from .profile import Profile
|
|
9
12
|
from .session import Session
|
|
10
13
|
from .sync import SyncOverrides, SyncState
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
from .base import CamelModel
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
class InitData(CamelModel):
|
|
5
|
+
"""Начальные данные web app-бота.
|
|
6
|
+
|
|
7
|
+
:ivar query_id: ID запроса инициализации.
|
|
8
|
+
:vartype query_id: str
|
|
9
|
+
:ivar url: URL для открытия web app-бота.
|
|
10
|
+
:vartype url: str
|
|
11
|
+
"""
|
|
12
|
+
|
|
13
|
+
query_id: str
|
|
14
|
+
url: str
|
pymax/types/domain/error.py
CHANGED
|
@@ -9,12 +9,12 @@ class MaxApiError(CamelModel):
|
|
|
9
9
|
:ivar message: Сообщение ошибки.
|
|
10
10
|
:vartype message: str
|
|
11
11
|
:ivar title: Заголовок ошибки.
|
|
12
|
-
:vartype title: str
|
|
12
|
+
:vartype title: str | None
|
|
13
13
|
:ivar localized_message: Локализованное сообщение ошибки.
|
|
14
14
|
:vartype localized_message: str | None
|
|
15
15
|
"""
|
|
16
16
|
|
|
17
17
|
error: str
|
|
18
18
|
message: str
|
|
19
|
-
title: str
|
|
20
|
-
localized_message: str | None
|
|
19
|
+
title: str | None = None
|
|
20
|
+
localized_message: str | None = None
|
pymax/types/domain/folder.py
CHANGED
pymax/types/domain/login.py
CHANGED
|
@@ -16,7 +16,9 @@ class LoginConfig(CamelModel):
|
|
|
16
16
|
class LoginResponse(CamelModel):
|
|
17
17
|
chats: list[Chat] = Field(default_factory=list)
|
|
18
18
|
profile: Profile
|
|
19
|
-
messages: dict[int, list[Message]] = Field(
|
|
19
|
+
messages: dict[int, list[Message]] = Field(
|
|
20
|
+
default_factory=dict
|
|
21
|
+
) # chat_id -> [message]
|
|
20
22
|
contacts: list[User | None] = Field(default_factory=list)
|
|
21
23
|
token: str
|
|
22
24
|
time: int | None = None
|
|
@@ -27,9 +29,19 @@ class LoginResponse(CamelModel):
|
|
|
27
29
|
config_hash = self.config.hash if self.config is not None else None
|
|
28
30
|
|
|
29
31
|
return SyncState(
|
|
30
|
-
chats_sync=(
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
32
|
+
chats_sync=(
|
|
33
|
+
sync_time if sync_time is not None else current.chats_sync
|
|
34
|
+
),
|
|
35
|
+
contacts_sync=(
|
|
36
|
+
sync_time if sync_time is not None else current.contacts_sync
|
|
37
|
+
),
|
|
38
|
+
drafts_sync=(
|
|
39
|
+
sync_time if sync_time is not None else current.drafts_sync
|
|
40
|
+
),
|
|
41
|
+
presence_sync=(
|
|
42
|
+
sync_time if sync_time is not None else current.presence_sync
|
|
43
|
+
),
|
|
44
|
+
config_hash=(
|
|
45
|
+
config_hash if config_hash is not None else current.config_hash
|
|
46
|
+
),
|
|
35
47
|
)
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
from .base import CamelModel
|
|
2
|
+
from .presence import Presence
|
|
3
|
+
from .user import User
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class Member(CamelModel):
|
|
7
|
+
"""Пользователь из списка участников или заявок на вступление.
|
|
8
|
+
|
|
9
|
+
:ivar contact: Данные пользователя.
|
|
10
|
+
:vartype contact: User
|
|
11
|
+
:ivar presence: Информация о присутствии пользователя.
|
|
12
|
+
:vartype presence: Presence
|
|
13
|
+
"""
|
|
14
|
+
|
|
15
|
+
contact: User
|
|
16
|
+
presence: Presence
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
from .base import CamelModel
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
class Presence(CamelModel):
|
|
5
|
+
"""Состояние присутствия пользователя.
|
|
6
|
+
|
|
7
|
+
:ivar seen: Время последней активности в формате Unix time, если оно
|
|
8
|
+
передано сервером.
|
|
9
|
+
:vartype seen: int | None
|
|
10
|
+
:ivar status: Код статуса присутствия Max.
|
|
11
|
+
:vartype status: int
|
|
12
|
+
"""
|
|
13
|
+
|
|
14
|
+
seen: int | None = None
|
|
15
|
+
status: int
|
pymax/types/domain/sync.py
CHANGED
|
@@ -68,13 +68,29 @@ class SyncOverrides(BaseModel):
|
|
|
68
68
|
:rtype: SyncState
|
|
69
69
|
"""
|
|
70
70
|
return SyncState(
|
|
71
|
-
chats_sync=(
|
|
71
|
+
chats_sync=(
|
|
72
|
+
self.chats_sync
|
|
73
|
+
if self.chats_sync is not None
|
|
74
|
+
else saved.chats_sync
|
|
75
|
+
),
|
|
72
76
|
contacts_sync=(
|
|
73
|
-
self.contacts_sync
|
|
77
|
+
self.contacts_sync
|
|
78
|
+
if self.contacts_sync is not None
|
|
79
|
+
else saved.contacts_sync
|
|
80
|
+
),
|
|
81
|
+
drafts_sync=(
|
|
82
|
+
self.drafts_sync
|
|
83
|
+
if self.drafts_sync is not None
|
|
84
|
+
else saved.drafts_sync
|
|
74
85
|
),
|
|
75
|
-
drafts_sync=(self.drafts_sync if self.drafts_sync is not None else saved.drafts_sync),
|
|
76
86
|
presence_sync=(
|
|
77
|
-
self.presence_sync
|
|
87
|
+
self.presence_sync
|
|
88
|
+
if self.presence_sync is not None
|
|
89
|
+
else saved.presence_sync
|
|
90
|
+
),
|
|
91
|
+
config_hash=(
|
|
92
|
+
self.config_hash
|
|
93
|
+
if self.config_hash is not None
|
|
94
|
+
else saved.config_hash
|
|
78
95
|
),
|
|
79
|
-
config_hash=(self.config_hash if self.config_hash is not None else saved.config_hash),
|
|
80
96
|
)
|
pymax/types/domain/user.py
CHANGED
|
@@ -18,6 +18,10 @@ class User(CamelModel):
|
|
|
18
18
|
:vartype id: int
|
|
19
19
|
:ivar account_status: Статус аккаунта в кодировке Max.
|
|
20
20
|
:vartype account_status: int | None
|
|
21
|
+
:ivar registration_time: Время регистрации в формате Unix time.
|
|
22
|
+
:vartype registration_time: int | None
|
|
23
|
+
:ivar country: Код страны пользователя.
|
|
24
|
+
:vartype country: str | None
|
|
21
25
|
:ivar base_raw_url: Исходный URL аватара.
|
|
22
26
|
:vartype base_raw_url: str | None
|
|
23
27
|
:ivar base_url: URL аватара.
|
|
@@ -30,6 +34,10 @@ class User(CamelModel):
|
|
|
30
34
|
:vartype photo_id: int | None
|
|
31
35
|
:ivar update_time: Время обновления в формате Unix time.
|
|
32
36
|
:vartype update_time: int | None
|
|
37
|
+
:ivar phone: Телефон пользователя, если возвращен API.
|
|
38
|
+
:vartype phone: int | None
|
|
39
|
+
:ivar status: Статус контакта, если возвращен API.
|
|
40
|
+
:vartype status: str | None
|
|
33
41
|
:ivar description: Описание профиля.
|
|
34
42
|
:vartype description: str | None
|
|
35
43
|
:ivar gender: Пол пользователя.
|
|
@@ -44,12 +52,16 @@ class User(CamelModel):
|
|
|
44
52
|
|
|
45
53
|
id: int
|
|
46
54
|
account_status: int | None = None
|
|
55
|
+
registration_time: int | None = None
|
|
56
|
+
country: str | None = None
|
|
47
57
|
base_raw_url: str | None = None
|
|
48
58
|
base_url: str | None = None
|
|
49
59
|
names: list[Name] = Field(default_factory=list)
|
|
50
60
|
options: list[str] = Field(default_factory=list)
|
|
51
61
|
photo_id: int | None = None
|
|
52
62
|
update_time: int | None = None
|
|
63
|
+
phone: int | None = None
|
|
64
|
+
status: str | None = None
|
|
53
65
|
description: str | None = None
|
|
54
66
|
gender: str | None = None
|
|
55
67
|
link: str | None = None
|
|
File without changes
|
|
File without changes
|