maxapi-python 2.4.0__py3-none-any.whl → 2.5.0__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.4.0.dist-info → maxapi_python-2.5.0.dist-info}/METADATA +22 -12
- maxapi_python-2.5.0.dist-info/RECORD +195 -0
- {maxapi_python-2.4.0.dist-info → maxapi_python-2.5.0.dist-info}/WHEEL +1 -1
- pymax/__init__.py +8 -2
- pymax/_data/apk_fingerprints.json +374 -17
- pymax/_data/rootca_ssl_rsa2022.crt +33 -0
- pymax/api/auth/service.py +15 -2
- pymax/api/auth/types.py +3 -0
- pymax/api/bots/payloads.py +8 -0
- pymax/api/bots/service.py +13 -1
- pymax/api/chats/enums.py +1 -0
- pymax/api/chats/payloads.py +21 -1
- pymax/api/chats/service.py +41 -0
- pymax/api/facade.py +2 -0
- pymax/api/messages/__init__.py +1 -1
- pymax/api/messages/enums.py +1 -0
- pymax/api/messages/payloads.py +56 -4
- pymax/api/messages/service.py +405 -27
- pymax/api/response.py +1 -1
- pymax/api/stories/__init__.py +2 -0
- pymax/api/stories/enums.py +19 -0
- pymax/api/stories/payloads.py +64 -0
- pymax/api/stories/service.py +198 -0
- pymax/api/uploads/payloads.py +42 -1
- pymax/api/uploads/service.py +171 -69
- pymax/app.py +39 -8
- pymax/auth/__init__.py +2 -0
- pymax/auth/exceptions.py +9 -0
- pymax/auth/providers.py +6 -2
- pymax/auth/qr.py +11 -1
- pymax/auth/sms.py +11 -1
- pymax/base.py +146 -27
- pymax/client.py +39 -11
- pymax/client_web.py +15 -12
- pymax/config.py +101 -53
- pymax/di/__init__.py +2 -0
- pymax/di/context.py +18 -0
- pymax/di/resolver.py +38 -0
- pymax/dispatch/__init__.py +7 -0
- pymax/dispatch/dispatcher.py +143 -40
- pymax/dispatch/enums.py +1 -0
- pymax/dispatch/mapping.py +23 -3
- pymax/dispatch/middleware.py +32 -0
- pymax/dispatch/resolvers.py +4 -0
- pymax/dispatch/router.py +86 -34
- pymax/files/base.py +58 -1
- pymax/files/video.py +32 -40
- pymax/files/voice.py +18 -4
- pymax/filters/__init__.py +15 -0
- pymax/filters/base.py +218 -0
- pymax/filters/containers/__init__.py +2 -0
- pymax/filters/containers/chat.py +240 -0
- pymax/filters/containers/message.py +147 -0
- pymax/filters/filters.py +211 -0
- pymax/filters/magic.py +13 -0
- pymax/filters/presets.py +88 -0
- pymax/filters/refs.py +56 -0
- pymax/fingerprint/fingerprint.py +5 -22
- pymax/fingerprint/models.py +1 -0
- pymax/formatting/markdown.py +55 -1
- pymax/fsm/__init__.py +3 -0
- pymax/fsm/context.py +30 -0
- pymax/fsm/protocol.py +14 -0
- pymax/fsm/state.py +70 -0
- pymax/fsm/storage.py +151 -0
- pymax/infra/base.py +2 -0
- pymax/infra/bots.py +20 -0
- pymax/infra/chat.py +37 -5
- pymax/infra/message.py +204 -9
- pymax/infra/protocol.py +5 -1
- pymax/infra/stories.py +205 -0
- pymax/integrations/__init__.py +0 -0
- pymax/integrations/dishka.py +109 -0
- pymax/protocol/enums.py +2 -0
- pymax/protocol/tcp/payload.py +0 -2
- pymax/session/__init__.py +1 -1
- pymax/session/models.py +30 -0
- pymax/session/protocol.py +33 -7
- pymax/session/store.py +73 -5
- pymax/transport/tcp.py +11 -3
- pymax/types/domain/__init__.py +23 -1
- pymax/types/domain/attachments/__init__.py +1 -1
- pymax/types/domain/attachments/call.py +7 -1
- pymax/types/domain/attachments/contact.py +3 -3
- pymax/types/domain/attachments/control.py +3 -0
- pymax/types/domain/attachments/enums.py +16 -0
- pymax/types/domain/attachments/keyboards/__init__.py +1 -1
- pymax/types/domain/attachments/keyboards/enums.py +12 -0
- pymax/types/domain/attachments/keyboards/inline.py +74 -3
- pymax/types/domain/attachments/video.py +3 -3
- pymax/types/domain/callback.py +19 -0
- pymax/types/domain/comment.py +24 -0
- pymax/types/domain/enums.py +7 -0
- pymax/types/domain/message.py +158 -9
- pymax/types/domain/story.py +126 -0
- pymax/types/events/reaction.py +28 -4
- pymax/versions/__init__.py +2 -0
- pymax/versions/catalog.py +104 -0
- pymax/versions/exceptions.py +10 -0
- maxapi_python-2.4.0.dist-info/RECORD +0 -161
- {maxapi_python-2.4.0.dist-info → maxapi_python-2.5.0.dist-info}/licenses/LICENSE +0 -0
pymax/filters/base.py
ADDED
|
@@ -0,0 +1,218 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from abc import ABC, abstractmethod
|
|
4
|
+
from inspect import isawaitable
|
|
5
|
+
from typing import TYPE_CHECKING, Any, Generic, TypeVar
|
|
6
|
+
|
|
7
|
+
if TYPE_CHECKING:
|
|
8
|
+
from collections.abc import Awaitable
|
|
9
|
+
|
|
10
|
+
from pymax.base import BaseClient
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
MISSING = object()
|
|
14
|
+
|
|
15
|
+
EventT = TypeVar("EventT")
|
|
16
|
+
ClientT = TypeVar("ClientT", bound="BaseClient")
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
class Filter(ABC, Generic[EventT, ClientT]):
|
|
20
|
+
"""Базовый класс фильтра событий.
|
|
21
|
+
|
|
22
|
+
Реализуйте ``__call__(event, client)`` с результатом ``bool`` или
|
|
23
|
+
``Awaitable[bool]`` и передайте экземпляр в декоратор роутера. Фильтры
|
|
24
|
+
объединяются через ``&``, ``|`` и ``~``; составной фильтр при ручном вызове
|
|
25
|
+
нужно ожидать через ``await``.
|
|
26
|
+
"""
|
|
27
|
+
|
|
28
|
+
@abstractmethod
|
|
29
|
+
def __call__(
|
|
30
|
+
self,
|
|
31
|
+
event: EventT,
|
|
32
|
+
client: ClientT,
|
|
33
|
+
/,
|
|
34
|
+
) -> bool | Awaitable[bool]: ...
|
|
35
|
+
def __and__(self, other: Filter[EventT, ClientT]) -> AndFilter:
|
|
36
|
+
return AndFilter(self, other)
|
|
37
|
+
|
|
38
|
+
def __or__(self, value: Filter[EventT, ClientT]) -> OrFilter:
|
|
39
|
+
return OrFilter(self, value)
|
|
40
|
+
|
|
41
|
+
def __invert__(self) -> NotFilter:
|
|
42
|
+
return NotFilter(self)
|
|
43
|
+
|
|
44
|
+
async def resolve_filter_result(
|
|
45
|
+
self,
|
|
46
|
+
result: bool | Awaitable[bool],
|
|
47
|
+
) -> bool:
|
|
48
|
+
if isawaitable(result):
|
|
49
|
+
return await result
|
|
50
|
+
|
|
51
|
+
return result
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
class PathResolver:
|
|
55
|
+
def __init__(self, path: list[str]) -> None:
|
|
56
|
+
self.path = path
|
|
57
|
+
|
|
58
|
+
def resolve_path(self, event: Any) -> Any | None:
|
|
59
|
+
value = event
|
|
60
|
+
|
|
61
|
+
for attr in self.path:
|
|
62
|
+
value = getattr(value, attr, MISSING)
|
|
63
|
+
|
|
64
|
+
if value is MISSING:
|
|
65
|
+
return MISSING
|
|
66
|
+
|
|
67
|
+
return value
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
class IsNoneFilter(Filter[EventT, ClientT], PathResolver):
|
|
71
|
+
def __init__(
|
|
72
|
+
self,
|
|
73
|
+
path: list[str],
|
|
74
|
+
expected_type: type[EventT],
|
|
75
|
+
) -> None:
|
|
76
|
+
super().__init__(path)
|
|
77
|
+
self.expected_type = expected_type
|
|
78
|
+
self.path = path
|
|
79
|
+
|
|
80
|
+
def __call__(self, event: EventT, _: ClientT) -> bool:
|
|
81
|
+
if not isinstance(event, self.expected_type):
|
|
82
|
+
return False
|
|
83
|
+
|
|
84
|
+
value = self.resolve_path(event)
|
|
85
|
+
|
|
86
|
+
if value is MISSING:
|
|
87
|
+
return False
|
|
88
|
+
|
|
89
|
+
return value is None
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
class IsEmptyFilter(Filter[EventT, ClientT], PathResolver):
|
|
93
|
+
def __init__(
|
|
94
|
+
self,
|
|
95
|
+
path: list[str],
|
|
96
|
+
expected_type: type[EventT],
|
|
97
|
+
) -> None:
|
|
98
|
+
super().__init__(path)
|
|
99
|
+
self.expected_type = expected_type
|
|
100
|
+
self.path = path
|
|
101
|
+
|
|
102
|
+
def __call__(self, event: EventT, _: ClientT) -> bool:
|
|
103
|
+
if not isinstance(event, self.expected_type):
|
|
104
|
+
return False
|
|
105
|
+
|
|
106
|
+
value = self.resolve_path(event)
|
|
107
|
+
|
|
108
|
+
return value == []
|
|
109
|
+
|
|
110
|
+
|
|
111
|
+
class FieldRef(Filter[EventT, ClientT], PathResolver):
|
|
112
|
+
def __init__(self, path: list[str], expected_type: type[EventT]) -> None:
|
|
113
|
+
super().__init__(path)
|
|
114
|
+
self.expected_type: type[EventT] = expected_type
|
|
115
|
+
self.path = path
|
|
116
|
+
|
|
117
|
+
def __eq__(self, value: object) -> EqFilter: # pyright: ignore[reportIncompatibleMethodOverride] # ty: ignore[invalid-method-override]
|
|
118
|
+
return EqFilter(self.path, self.expected_type, value)
|
|
119
|
+
|
|
120
|
+
def __ne__(self, value: object) -> NeFilter: # pyright: ignore[reportIncompatibleMethodOverride] # ty: ignore[invalid-method-override]
|
|
121
|
+
return NeFilter(self.path, self.expected_type, value)
|
|
122
|
+
|
|
123
|
+
def is_none(self) -> IsNoneFilter:
|
|
124
|
+
return IsNoneFilter(self.path, expected_type=self.expected_type)
|
|
125
|
+
|
|
126
|
+
def is_empty(self) -> IsEmptyFilter:
|
|
127
|
+
return IsEmptyFilter(self.path, expected_type=self.expected_type)
|
|
128
|
+
|
|
129
|
+
def __call__(self, event: EventT, _: ClientT, /) -> bool:
|
|
130
|
+
if not isinstance(event, self.expected_type):
|
|
131
|
+
return False
|
|
132
|
+
|
|
133
|
+
value = self.resolve_path(event)
|
|
134
|
+
|
|
135
|
+
if value is MISSING:
|
|
136
|
+
return False
|
|
137
|
+
|
|
138
|
+
return bool(value)
|
|
139
|
+
|
|
140
|
+
|
|
141
|
+
class BinaryFilter(Filter[EventT, ClientT]):
|
|
142
|
+
def __init__(self, left: Filter[EventT, ClientT], right: Filter[EventT, ClientT]) -> None:
|
|
143
|
+
self.left = left
|
|
144
|
+
self.right = right
|
|
145
|
+
|
|
146
|
+
|
|
147
|
+
class NotFilter(Filter[EventT, ClientT]):
|
|
148
|
+
def __init__(self, filter_instance: Filter[EventT, ClientT]) -> None:
|
|
149
|
+
self.filter = filter_instance
|
|
150
|
+
|
|
151
|
+
async def __call__(self, event: EventT, client: ClientT) -> bool:
|
|
152
|
+
return not await self.resolve_filter_result(self.filter(event, client))
|
|
153
|
+
|
|
154
|
+
|
|
155
|
+
class NeFilter(Filter[EventT, ClientT], PathResolver):
|
|
156
|
+
def __init__(
|
|
157
|
+
self,
|
|
158
|
+
path: list[str],
|
|
159
|
+
expected_type: type[EventT],
|
|
160
|
+
expected: object,
|
|
161
|
+
) -> None:
|
|
162
|
+
self.path: list[str] = path
|
|
163
|
+
self.expected_type = expected_type
|
|
164
|
+
self.expected: object = expected
|
|
165
|
+
|
|
166
|
+
def __call__(self, event: EventT, _: ClientT) -> bool:
|
|
167
|
+
if not isinstance(event, self.expected_type):
|
|
168
|
+
return False
|
|
169
|
+
|
|
170
|
+
value = self.resolve_path(event)
|
|
171
|
+
|
|
172
|
+
if value is MISSING:
|
|
173
|
+
return False
|
|
174
|
+
|
|
175
|
+
return value != self.expected
|
|
176
|
+
|
|
177
|
+
|
|
178
|
+
class AndFilter(BinaryFilter[EventT, ClientT]):
|
|
179
|
+
async def __call__(self, event: EventT, client: ClientT) -> bool:
|
|
180
|
+
left = await self.resolve_filter_result(self.left(event, client))
|
|
181
|
+
|
|
182
|
+
if not left:
|
|
183
|
+
return False
|
|
184
|
+
|
|
185
|
+
return await self.resolve_filter_result(self.right(event, client))
|
|
186
|
+
|
|
187
|
+
|
|
188
|
+
class OrFilter(BinaryFilter[EventT, ClientT]):
|
|
189
|
+
async def __call__(self, event: EventT, client: ClientT) -> bool:
|
|
190
|
+
left = await self.resolve_filter_result(self.left(event, client))
|
|
191
|
+
|
|
192
|
+
if left:
|
|
193
|
+
return True
|
|
194
|
+
|
|
195
|
+
return await self.resolve_filter_result(self.right(event, client))
|
|
196
|
+
|
|
197
|
+
|
|
198
|
+
class EqFilter(Filter[EventT, ClientT], PathResolver):
|
|
199
|
+
def __init__(
|
|
200
|
+
self,
|
|
201
|
+
path: list[str],
|
|
202
|
+
expected_type: type[EventT],
|
|
203
|
+
expected: object,
|
|
204
|
+
) -> None:
|
|
205
|
+
self.path: list[str] = path
|
|
206
|
+
self.expected_type = expected_type
|
|
207
|
+
self.expected: object = expected
|
|
208
|
+
|
|
209
|
+
def __call__(self, event: EventT, _: ClientT) -> bool:
|
|
210
|
+
if not isinstance(event, self.expected_type):
|
|
211
|
+
return False
|
|
212
|
+
|
|
213
|
+
value = self.resolve_path(event)
|
|
214
|
+
|
|
215
|
+
if value is MISSING:
|
|
216
|
+
return False
|
|
217
|
+
|
|
218
|
+
return value == self.expected
|
|
@@ -0,0 +1,240 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import builtins
|
|
4
|
+
from typing import TYPE_CHECKING, Any, TypeVar
|
|
5
|
+
|
|
6
|
+
from pymax.filters.base import ClientT, Filter, PathResolver
|
|
7
|
+
from pymax.filters.refs import FieldRef, NumberFieldRef, TextFieldRef
|
|
8
|
+
|
|
9
|
+
from .message import MessageContainer
|
|
10
|
+
|
|
11
|
+
if TYPE_CHECKING:
|
|
12
|
+
pass
|
|
13
|
+
|
|
14
|
+
EventT = TypeVar("EventT")
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class ChatContainer(Filter[EventT, ClientT], PathResolver):
|
|
18
|
+
def __init__(
|
|
19
|
+
self,
|
|
20
|
+
expected_type: builtins.type[EventT],
|
|
21
|
+
path: list[str] | None = None,
|
|
22
|
+
) -> None:
|
|
23
|
+
self.expected_type: type[EventT] = expected_type
|
|
24
|
+
self.path = path or []
|
|
25
|
+
|
|
26
|
+
@property
|
|
27
|
+
def id(self) -> NumberFieldRef:
|
|
28
|
+
return NumberFieldRef(
|
|
29
|
+
path=[*self.path, "id"],
|
|
30
|
+
expected_type=self.expected_type,
|
|
31
|
+
)
|
|
32
|
+
|
|
33
|
+
@property
|
|
34
|
+
def type(self) -> TextFieldRef:
|
|
35
|
+
return TextFieldRef(
|
|
36
|
+
path=[*self.path, "type"],
|
|
37
|
+
expected_type=self.expected_type,
|
|
38
|
+
)
|
|
39
|
+
|
|
40
|
+
@property
|
|
41
|
+
def status(self) -> TextFieldRef:
|
|
42
|
+
return TextFieldRef(
|
|
43
|
+
path=[*self.path, "status"],
|
|
44
|
+
expected_type=self.expected_type,
|
|
45
|
+
)
|
|
46
|
+
|
|
47
|
+
@property
|
|
48
|
+
def owner(self) -> NumberFieldRef:
|
|
49
|
+
return NumberFieldRef(
|
|
50
|
+
path=[*self.path, "owner"],
|
|
51
|
+
expected_type=self.expected_type,
|
|
52
|
+
)
|
|
53
|
+
|
|
54
|
+
@property
|
|
55
|
+
def participants(self) -> FieldRef:
|
|
56
|
+
return FieldRef(
|
|
57
|
+
path=[*self.path, "participants"],
|
|
58
|
+
expected_type=self.expected_type,
|
|
59
|
+
)
|
|
60
|
+
|
|
61
|
+
@property
|
|
62
|
+
def title(self) -> TextFieldRef:
|
|
63
|
+
return TextFieldRef(
|
|
64
|
+
path=[*self.path, "title"],
|
|
65
|
+
expected_type=self.expected_type,
|
|
66
|
+
)
|
|
67
|
+
|
|
68
|
+
@property
|
|
69
|
+
def base_raw_icon_url(self) -> TextFieldRef:
|
|
70
|
+
return TextFieldRef(
|
|
71
|
+
path=[*self.path, "base_raw_icon_url"],
|
|
72
|
+
expected_type=self.expected_type,
|
|
73
|
+
)
|
|
74
|
+
|
|
75
|
+
@property
|
|
76
|
+
def base_icon_url(self) -> TextFieldRef:
|
|
77
|
+
return TextFieldRef(
|
|
78
|
+
path=[*self.path, "base_icon_url"],
|
|
79
|
+
expected_type=self.expected_type,
|
|
80
|
+
)
|
|
81
|
+
|
|
82
|
+
@property
|
|
83
|
+
def last_message(self) -> MessageContainer:
|
|
84
|
+
return MessageContainer(
|
|
85
|
+
path=[*self.path, "last_message"],
|
|
86
|
+
expected_type=self.expected_type,
|
|
87
|
+
)
|
|
88
|
+
|
|
89
|
+
@property
|
|
90
|
+
def last_event_time(self) -> NumberFieldRef:
|
|
91
|
+
return NumberFieldRef(
|
|
92
|
+
path=[*self.path, "last_event_time"],
|
|
93
|
+
expected_type=self.expected_type,
|
|
94
|
+
)
|
|
95
|
+
|
|
96
|
+
@property
|
|
97
|
+
def last_delayed_update_time(self) -> NumberFieldRef:
|
|
98
|
+
return NumberFieldRef(
|
|
99
|
+
path=[*self.path, "last_delayed_update_time"],
|
|
100
|
+
expected_type=self.expected_type,
|
|
101
|
+
)
|
|
102
|
+
|
|
103
|
+
@property
|
|
104
|
+
def last_fire_delayed_error_time(self) -> NumberFieldRef:
|
|
105
|
+
return NumberFieldRef(
|
|
106
|
+
path=[*self.path, "last_fire_delayed_error_time"],
|
|
107
|
+
expected_type=self.expected_type,
|
|
108
|
+
)
|
|
109
|
+
|
|
110
|
+
@property
|
|
111
|
+
def created(self) -> NumberFieldRef:
|
|
112
|
+
return NumberFieldRef(
|
|
113
|
+
path=[*self.path, "created"],
|
|
114
|
+
expected_type=self.expected_type,
|
|
115
|
+
)
|
|
116
|
+
|
|
117
|
+
@property
|
|
118
|
+
def new_messages(self) -> NumberFieldRef:
|
|
119
|
+
return NumberFieldRef(
|
|
120
|
+
path=[*self.path, "new_messages"],
|
|
121
|
+
expected_type=self.expected_type,
|
|
122
|
+
)
|
|
123
|
+
|
|
124
|
+
@property
|
|
125
|
+
def link(self) -> TextFieldRef:
|
|
126
|
+
return TextFieldRef(
|
|
127
|
+
path=[*self.path, "link"],
|
|
128
|
+
expected_type=self.expected_type,
|
|
129
|
+
)
|
|
130
|
+
|
|
131
|
+
@property
|
|
132
|
+
def access(self) -> TextFieldRef:
|
|
133
|
+
return TextFieldRef(
|
|
134
|
+
path=[*self.path, "access"],
|
|
135
|
+
expected_type=self.expected_type,
|
|
136
|
+
)
|
|
137
|
+
|
|
138
|
+
@property
|
|
139
|
+
def restrictions(self) -> NumberFieldRef:
|
|
140
|
+
return NumberFieldRef(
|
|
141
|
+
path=[*self.path, "restrictions"],
|
|
142
|
+
expected_type=self.expected_type,
|
|
143
|
+
)
|
|
144
|
+
|
|
145
|
+
@property
|
|
146
|
+
def pinned_message(self) -> MessageContainer:
|
|
147
|
+
return MessageContainer(
|
|
148
|
+
path=[*self.path, "pinned_message"],
|
|
149
|
+
expected_type=self.expected_type,
|
|
150
|
+
)
|
|
151
|
+
|
|
152
|
+
@property
|
|
153
|
+
def participants_count(self) -> NumberFieldRef:
|
|
154
|
+
return NumberFieldRef(
|
|
155
|
+
path=[*self.path, "participants_count"],
|
|
156
|
+
expected_type=self.expected_type,
|
|
157
|
+
)
|
|
158
|
+
|
|
159
|
+
@property
|
|
160
|
+
def description(self) -> TextFieldRef:
|
|
161
|
+
return TextFieldRef(
|
|
162
|
+
path=[*self.path, "description"],
|
|
163
|
+
expected_type=self.expected_type,
|
|
164
|
+
)
|
|
165
|
+
|
|
166
|
+
@property
|
|
167
|
+
def options(self) -> FieldRef:
|
|
168
|
+
return FieldRef(
|
|
169
|
+
path=[*self.path, "options"],
|
|
170
|
+
expected_type=self.expected_type,
|
|
171
|
+
)
|
|
172
|
+
|
|
173
|
+
@property
|
|
174
|
+
def join_time(self) -> NumberFieldRef:
|
|
175
|
+
return NumberFieldRef(
|
|
176
|
+
path=[*self.path, "join_time"],
|
|
177
|
+
expected_type=self.expected_type,
|
|
178
|
+
)
|
|
179
|
+
|
|
180
|
+
@property
|
|
181
|
+
def invited_by(self) -> NumberFieldRef:
|
|
182
|
+
return NumberFieldRef(
|
|
183
|
+
path=[*self.path, "invited_by"],
|
|
184
|
+
expected_type=self.expected_type,
|
|
185
|
+
)
|
|
186
|
+
|
|
187
|
+
@property
|
|
188
|
+
def modified(self) -> NumberFieldRef:
|
|
189
|
+
return NumberFieldRef(
|
|
190
|
+
path=[*self.path, "modified"],
|
|
191
|
+
expected_type=self.expected_type,
|
|
192
|
+
)
|
|
193
|
+
|
|
194
|
+
@property
|
|
195
|
+
def messages_count(self) -> NumberFieldRef:
|
|
196
|
+
return NumberFieldRef(
|
|
197
|
+
path=[*self.path, "messages_count"],
|
|
198
|
+
expected_type=self.expected_type,
|
|
199
|
+
)
|
|
200
|
+
|
|
201
|
+
@property
|
|
202
|
+
def has_bots(self) -> FieldRef:
|
|
203
|
+
return FieldRef(
|
|
204
|
+
path=[*self.path, "has_bots"],
|
|
205
|
+
expected_type=self.expected_type,
|
|
206
|
+
)
|
|
207
|
+
|
|
208
|
+
@property
|
|
209
|
+
def prev_message_id(self) -> NumberFieldRef:
|
|
210
|
+
return NumberFieldRef(
|
|
211
|
+
path=[*self.path, "prev_message_id"],
|
|
212
|
+
expected_type=self.expected_type,
|
|
213
|
+
)
|
|
214
|
+
|
|
215
|
+
@property
|
|
216
|
+
def admin_participants(self) -> FieldRef:
|
|
217
|
+
return FieldRef(
|
|
218
|
+
path=[*self.path, "admin_participants"],
|
|
219
|
+
expected_type=self.expected_type,
|
|
220
|
+
)
|
|
221
|
+
|
|
222
|
+
@property
|
|
223
|
+
def admins(self) -> FieldRef:
|
|
224
|
+
return FieldRef(
|
|
225
|
+
path=[*self.path, "admins"],
|
|
226
|
+
expected_type=self.expected_type,
|
|
227
|
+
)
|
|
228
|
+
|
|
229
|
+
@property
|
|
230
|
+
def cid(self) -> NumberFieldRef:
|
|
231
|
+
return NumberFieldRef(
|
|
232
|
+
path=[*self.path, "cid"],
|
|
233
|
+
expected_type=self.expected_type,
|
|
234
|
+
)
|
|
235
|
+
|
|
236
|
+
def __call__(self, event: Any, client: ClientT) -> bool:
|
|
237
|
+
if not isinstance(event, self.expected_type):
|
|
238
|
+
return False
|
|
239
|
+
|
|
240
|
+
return bool(self.resolve_path(event))
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import builtins
|
|
4
|
+
from typing import TYPE_CHECKING, Any, TypeVar
|
|
5
|
+
|
|
6
|
+
from pymax.filters.base import ClientT, Filter, PathResolver
|
|
7
|
+
from pymax.filters.refs import FieldRef, NumberFieldRef, TextFieldRef
|
|
8
|
+
|
|
9
|
+
if TYPE_CHECKING:
|
|
10
|
+
pass
|
|
11
|
+
|
|
12
|
+
EventT = TypeVar("EventT")
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class MessageContainer(Filter[EventT, ClientT], PathResolver):
|
|
16
|
+
def __init__(
|
|
17
|
+
self,
|
|
18
|
+
expected_type: builtins.type[EventT],
|
|
19
|
+
path: list[str] | None = None,
|
|
20
|
+
) -> None:
|
|
21
|
+
self.expected_type: type[EventT] = expected_type
|
|
22
|
+
self.path = path or []
|
|
23
|
+
|
|
24
|
+
@property
|
|
25
|
+
def text(self) -> TextFieldRef:
|
|
26
|
+
return TextFieldRef(
|
|
27
|
+
path=[*self.path, "text"],
|
|
28
|
+
expected_type=self.expected_type,
|
|
29
|
+
)
|
|
30
|
+
|
|
31
|
+
@property
|
|
32
|
+
def id(self) -> NumberFieldRef:
|
|
33
|
+
return NumberFieldRef(
|
|
34
|
+
path=[*self.path, "id"],
|
|
35
|
+
expected_type=self.expected_type,
|
|
36
|
+
)
|
|
37
|
+
|
|
38
|
+
@property
|
|
39
|
+
def chat_id(self) -> NumberFieldRef:
|
|
40
|
+
return NumberFieldRef(
|
|
41
|
+
path=[*self.path, "chat_id"],
|
|
42
|
+
expected_type=self.expected_type,
|
|
43
|
+
)
|
|
44
|
+
|
|
45
|
+
@property
|
|
46
|
+
def sender(self) -> NumberFieldRef:
|
|
47
|
+
return NumberFieldRef(
|
|
48
|
+
path=[*self.path, "sender"],
|
|
49
|
+
expected_type=self.expected_type,
|
|
50
|
+
)
|
|
51
|
+
|
|
52
|
+
@property
|
|
53
|
+
def time(self) -> NumberFieldRef:
|
|
54
|
+
return NumberFieldRef(
|
|
55
|
+
path=[*self.path, "time"],
|
|
56
|
+
expected_type=self.expected_type,
|
|
57
|
+
)
|
|
58
|
+
|
|
59
|
+
@property
|
|
60
|
+
def type(self) -> TextFieldRef:
|
|
61
|
+
return TextFieldRef(
|
|
62
|
+
path=[*self.path, "type"],
|
|
63
|
+
expected_type=self.expected_type,
|
|
64
|
+
)
|
|
65
|
+
|
|
66
|
+
@property
|
|
67
|
+
def cid(self) -> NumberFieldRef:
|
|
68
|
+
return NumberFieldRef(
|
|
69
|
+
path=[*self.path, "cid"],
|
|
70
|
+
expected_type=self.expected_type,
|
|
71
|
+
)
|
|
72
|
+
|
|
73
|
+
@property
|
|
74
|
+
def attaches(self) -> FieldRef:
|
|
75
|
+
return FieldRef(
|
|
76
|
+
path=[*self.path, "attaches"],
|
|
77
|
+
expected_type=self.expected_type,
|
|
78
|
+
)
|
|
79
|
+
|
|
80
|
+
@property
|
|
81
|
+
def stats(self) -> FieldRef:
|
|
82
|
+
return FieldRef(
|
|
83
|
+
path=[*self.path, "stats"],
|
|
84
|
+
expected_type=self.expected_type,
|
|
85
|
+
)
|
|
86
|
+
|
|
87
|
+
@property
|
|
88
|
+
def status(self) -> TextFieldRef:
|
|
89
|
+
return TextFieldRef(
|
|
90
|
+
path=[*self.path, "status"],
|
|
91
|
+
expected_type=self.expected_type,
|
|
92
|
+
)
|
|
93
|
+
|
|
94
|
+
@property
|
|
95
|
+
def reaction_info(self) -> FieldRef:
|
|
96
|
+
return FieldRef(
|
|
97
|
+
path=[*self.path, "reaction_info"],
|
|
98
|
+
expected_type=self.expected_type,
|
|
99
|
+
)
|
|
100
|
+
|
|
101
|
+
@property
|
|
102
|
+
def options(self) -> FieldRef:
|
|
103
|
+
return FieldRef(
|
|
104
|
+
path=[*self.path, "options"],
|
|
105
|
+
expected_type=self.expected_type,
|
|
106
|
+
)
|
|
107
|
+
|
|
108
|
+
@property
|
|
109
|
+
def prev_message_id(self) -> NumberFieldRef:
|
|
110
|
+
return NumberFieldRef(
|
|
111
|
+
path=[*self.path, "prev_message_id"],
|
|
112
|
+
expected_type=self.expected_type,
|
|
113
|
+
)
|
|
114
|
+
|
|
115
|
+
@property
|
|
116
|
+
def ttl(self) -> FieldRef:
|
|
117
|
+
return FieldRef(
|
|
118
|
+
path=[*self.path, "ttl"],
|
|
119
|
+
expected_type=self.expected_type,
|
|
120
|
+
)
|
|
121
|
+
|
|
122
|
+
@property
|
|
123
|
+
def unread(self) -> NumberFieldRef:
|
|
124
|
+
return NumberFieldRef(
|
|
125
|
+
path=[*self.path, "unread"],
|
|
126
|
+
expected_type=self.expected_type,
|
|
127
|
+
)
|
|
128
|
+
|
|
129
|
+
@property
|
|
130
|
+
def mark(self) -> NumberFieldRef:
|
|
131
|
+
return NumberFieldRef(
|
|
132
|
+
path=[*self.path, "mark"],
|
|
133
|
+
expected_type=self.expected_type,
|
|
134
|
+
)
|
|
135
|
+
|
|
136
|
+
@property
|
|
137
|
+
def elements(self) -> FieldRef:
|
|
138
|
+
return FieldRef(
|
|
139
|
+
path=[*self.path, "elements"],
|
|
140
|
+
expected_type=self.expected_type,
|
|
141
|
+
)
|
|
142
|
+
|
|
143
|
+
def __call__(self, event: Any, client: ClientT) -> bool:
|
|
144
|
+
if not isinstance(event, self.expected_type):
|
|
145
|
+
return False
|
|
146
|
+
|
|
147
|
+
return bool(self.resolve_path(event))
|