telegrinder 0.3.0.post2__py3-none-any.whl → 0.3.2__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.
Potentially problematic release.
This version of telegrinder might be problematic. Click here for more details.
- telegrinder/__init__.py +144 -144
- telegrinder/api/__init__.py +8 -8
- telegrinder/api/api.py +93 -93
- telegrinder/api/error.py +16 -16
- telegrinder/api/response.py +20 -20
- telegrinder/api/token.py +36 -36
- telegrinder/bot/__init__.py +66 -66
- telegrinder/bot/bot.py +76 -76
- telegrinder/bot/cute_types/__init__.py +11 -11
- telegrinder/bot/cute_types/base.py +258 -234
- telegrinder/bot/cute_types/callback_query.py +382 -382
- telegrinder/bot/cute_types/chat_join_request.py +61 -61
- telegrinder/bot/cute_types/chat_member_updated.py +160 -160
- telegrinder/bot/cute_types/inline_query.py +53 -53
- telegrinder/bot/cute_types/message.py +2631 -2631
- telegrinder/bot/cute_types/update.py +75 -75
- telegrinder/bot/cute_types/utils.py +92 -92
- telegrinder/bot/dispatch/__init__.py +55 -55
- telegrinder/bot/dispatch/abc.py +77 -77
- telegrinder/bot/dispatch/context.py +92 -92
- telegrinder/bot/dispatch/dispatch.py +202 -201
- telegrinder/bot/dispatch/handler/__init__.py +13 -13
- telegrinder/bot/dispatch/handler/abc.py +24 -24
- telegrinder/bot/dispatch/handler/audio_reply.py +44 -44
- telegrinder/bot/dispatch/handler/base.py +57 -57
- telegrinder/bot/dispatch/handler/document_reply.py +44 -44
- telegrinder/bot/dispatch/handler/func.py +128 -123
- telegrinder/bot/dispatch/handler/media_group_reply.py +43 -43
- telegrinder/bot/dispatch/handler/message_reply.py +36 -36
- telegrinder/bot/dispatch/handler/photo_reply.py +44 -44
- telegrinder/bot/dispatch/handler/sticker_reply.py +37 -37
- telegrinder/bot/dispatch/handler/video_reply.py +44 -44
- telegrinder/bot/dispatch/middleware/__init__.py +3 -3
- telegrinder/bot/dispatch/middleware/abc.py +16 -16
- telegrinder/bot/dispatch/process.py +132 -132
- telegrinder/bot/dispatch/return_manager/__init__.py +13 -13
- telegrinder/bot/dispatch/return_manager/abc.py +108 -108
- telegrinder/bot/dispatch/return_manager/callback_query.py +20 -20
- telegrinder/bot/dispatch/return_manager/inline_query.py +15 -15
- telegrinder/bot/dispatch/return_manager/message.py +36 -36
- telegrinder/bot/dispatch/view/__init__.py +13 -13
- telegrinder/bot/dispatch/view/abc.py +41 -41
- telegrinder/bot/dispatch/view/base.py +200 -211
- telegrinder/bot/dispatch/view/box.py +129 -129
- telegrinder/bot/dispatch/view/callback_query.py +17 -17
- telegrinder/bot/dispatch/view/chat_join_request.py +16 -16
- telegrinder/bot/dispatch/view/chat_member.py +39 -39
- telegrinder/bot/dispatch/view/inline_query.py +17 -17
- telegrinder/bot/dispatch/view/message.py +44 -44
- telegrinder/bot/dispatch/view/raw.py +114 -118
- telegrinder/bot/dispatch/waiter_machine/__init__.py +17 -17
- telegrinder/bot/dispatch/waiter_machine/actions.py +13 -13
- telegrinder/bot/dispatch/waiter_machine/hasher/__init__.py +8 -8
- telegrinder/bot/dispatch/waiter_machine/hasher/callback.py +57 -57
- telegrinder/bot/dispatch/waiter_machine/hasher/hasher.py +57 -57
- telegrinder/bot/dispatch/waiter_machine/hasher/message.py +53 -53
- telegrinder/bot/dispatch/waiter_machine/hasher/state.py +19 -19
- telegrinder/bot/dispatch/waiter_machine/machine.py +168 -170
- telegrinder/bot/dispatch/waiter_machine/middleware.py +89 -89
- telegrinder/bot/dispatch/waiter_machine/short_state.py +65 -65
- telegrinder/bot/polling/__init__.py +4 -4
- telegrinder/bot/polling/abc.py +25 -25
- telegrinder/bot/polling/polling.py +131 -131
- telegrinder/bot/rules/__init__.py +62 -62
- telegrinder/bot/rules/abc.py +238 -233
- telegrinder/bot/rules/adapter/__init__.py +9 -9
- telegrinder/bot/rules/adapter/abc.py +29 -29
- telegrinder/bot/rules/adapter/errors.py +5 -5
- telegrinder/bot/rules/adapter/event.py +76 -76
- telegrinder/bot/rules/adapter/node.py +48 -48
- telegrinder/bot/rules/adapter/raw_update.py +30 -30
- telegrinder/bot/rules/callback_data.py +171 -171
- telegrinder/bot/rules/chat_join.py +48 -48
- telegrinder/bot/rules/command.py +126 -126
- telegrinder/bot/rules/enum_text.py +36 -33
- telegrinder/bot/rules/func.py +26 -26
- telegrinder/bot/rules/fuzzy.py +24 -24
- telegrinder/bot/rules/inline.py +60 -60
- telegrinder/bot/rules/integer.py +20 -20
- telegrinder/bot/rules/is_from.py +146 -146
- telegrinder/bot/rules/markup.py +43 -43
- telegrinder/bot/rules/mention.py +14 -14
- telegrinder/bot/rules/message.py +17 -17
- telegrinder/bot/rules/message_entities.py +35 -35
- telegrinder/bot/rules/node.py +27 -27
- telegrinder/bot/rules/regex.py +37 -37
- telegrinder/bot/rules/rule_enum.py +72 -72
- telegrinder/bot/rules/start.py +42 -42
- telegrinder/bot/rules/state.py +37 -37
- telegrinder/bot/rules/text.py +33 -33
- telegrinder/bot/rules/update.py +15 -15
- telegrinder/bot/scenario/__init__.py +5 -5
- telegrinder/bot/scenario/abc.py +19 -19
- telegrinder/bot/scenario/checkbox.py +167 -139
- telegrinder/bot/scenario/choice.py +46 -44
- telegrinder/client/__init__.py +4 -4
- telegrinder/client/abc.py +75 -75
- telegrinder/client/aiohttp.py +130 -130
- telegrinder/model.py +244 -244
- telegrinder/modules.py +237 -237
- telegrinder/msgspec_json.py +14 -14
- telegrinder/msgspec_utils.py +410 -410
- telegrinder/node/__init__.py +20 -20
- telegrinder/node/attachment.py +92 -92
- telegrinder/node/base.py +143 -144
- telegrinder/node/callback_query.py +14 -14
- telegrinder/node/command.py +33 -33
- telegrinder/node/composer.py +196 -184
- telegrinder/node/container.py +27 -27
- telegrinder/node/event.py +71 -73
- telegrinder/node/me.py +16 -16
- telegrinder/node/message.py +14 -14
- telegrinder/node/polymorphic.py +48 -52
- telegrinder/node/rule.py +76 -76
- telegrinder/node/scope.py +38 -38
- telegrinder/node/source.py +71 -71
- telegrinder/node/text.py +21 -21
- telegrinder/node/tools/__init__.py +3 -3
- telegrinder/node/tools/generator.py +40 -40
- telegrinder/node/update.py +15 -15
- telegrinder/rules.py +0 -0
- telegrinder/tools/__init__.py +74 -74
- telegrinder/tools/buttons.py +79 -79
- telegrinder/tools/error_handler/__init__.py +7 -7
- telegrinder/tools/error_handler/abc.py +33 -33
- telegrinder/tools/error_handler/error.py +9 -9
- telegrinder/tools/error_handler/error_handler.py +193 -193
- telegrinder/tools/formatting/__init__.py +46 -46
- telegrinder/tools/formatting/html.py +308 -308
- telegrinder/tools/formatting/links.py +33 -33
- telegrinder/tools/formatting/spec_html_formats.py +111 -111
- telegrinder/tools/functional.py +12 -12
- telegrinder/tools/global_context/__init__.py +7 -7
- telegrinder/tools/global_context/abc.py +63 -63
- telegrinder/tools/global_context/global_context.py +412 -412
- telegrinder/tools/global_context/telegrinder_ctx.py +27 -27
- telegrinder/tools/i18n/__init__.py +12 -12
- telegrinder/tools/i18n/abc.py +32 -32
- telegrinder/tools/i18n/middleware/__init__.py +3 -3
- telegrinder/tools/i18n/middleware/abc.py +25 -25
- telegrinder/tools/i18n/simple.py +43 -43
- telegrinder/tools/kb_set/__init__.py +4 -4
- telegrinder/tools/kb_set/base.py +15 -15
- telegrinder/tools/kb_set/yaml.py +63 -63
- telegrinder/tools/keyboard.py +128 -128
- telegrinder/tools/limited_dict.py +37 -37
- telegrinder/tools/loop_wrapper/__init__.py +4 -4
- telegrinder/tools/loop_wrapper/abc.py +15 -15
- telegrinder/tools/loop_wrapper/loop_wrapper.py +216 -216
- telegrinder/tools/magic.py +168 -164
- telegrinder/tools/parse_mode.py +6 -6
- telegrinder/tools/state_storage/__init__.py +4 -4
- telegrinder/tools/state_storage/abc.py +35 -35
- telegrinder/tools/state_storage/memory.py +25 -25
- telegrinder/types/__init__.py +6 -6
- telegrinder/types/enums.py +672 -672
- telegrinder/types/methods.py +4633 -4633
- telegrinder/types/objects.py +6317 -6317
- telegrinder/verification_utils.py +32 -32
- {telegrinder-0.3.0.post2.dist-info → telegrinder-0.3.2.dist-info}/LICENSE +22 -22
- {telegrinder-0.3.0.post2.dist-info → telegrinder-0.3.2.dist-info}/METADATA +1 -1
- telegrinder-0.3.2.dist-info/RECORD +164 -0
- telegrinder-0.3.0.post2.dist-info/RECORD +0 -164
- {telegrinder-0.3.0.post2.dist-info → telegrinder-0.3.2.dist-info}/WHEEL +0 -0
|
@@ -1,19 +1,19 @@
|
|
|
1
|
-
from fntypes.option import Option
|
|
2
|
-
|
|
3
|
-
from telegrinder.bot.dispatch.view import BaseStateView
|
|
4
|
-
from telegrinder.bot.dispatch.waiter_machine.hasher.hasher import ECHO, Event, Hasher
|
|
5
|
-
from telegrinder.tools.functional import from_optional
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
class StateViewHasher(Hasher[Event, int]):
|
|
9
|
-
view: BaseStateView[Event]
|
|
10
|
-
|
|
11
|
-
def __init__(self, view: BaseStateView[Event]) -> None:
|
|
12
|
-
self.view = view
|
|
13
|
-
super().__init__(view.__class__, get_hash_from_data=ECHO)
|
|
14
|
-
|
|
15
|
-
def get_data_from_event(self, event: Event) -> Option[int]:
|
|
16
|
-
return from_optional(self.view.get_state_key(event))
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
__all__ = ("StateViewHasher",)
|
|
1
|
+
from fntypes.option import Option
|
|
2
|
+
|
|
3
|
+
from telegrinder.bot.dispatch.view import BaseStateView
|
|
4
|
+
from telegrinder.bot.dispatch.waiter_machine.hasher.hasher import ECHO, Event, Hasher
|
|
5
|
+
from telegrinder.tools.functional import from_optional
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class StateViewHasher(Hasher[Event, int]):
|
|
9
|
+
view: BaseStateView[Event]
|
|
10
|
+
|
|
11
|
+
def __init__(self, view: BaseStateView[Event]) -> None:
|
|
12
|
+
self.view = view
|
|
13
|
+
super().__init__(view.__class__, get_hash_from_data=ECHO)
|
|
14
|
+
|
|
15
|
+
def get_data_from_event(self, event: Event) -> Option[int]:
|
|
16
|
+
return from_optional(self.view.get_state_key(event))
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
__all__ = ("StateViewHasher",)
|
|
@@ -1,170 +1,168 @@
|
|
|
1
|
-
import asyncio
|
|
2
|
-
import datetime
|
|
3
|
-
import typing
|
|
4
|
-
|
|
5
|
-
from telegrinder.bot.dispatch.abc import ABCDispatch
|
|
6
|
-
from telegrinder.bot.dispatch.view.base import BaseStateView, BaseView
|
|
7
|
-
from telegrinder.bot.dispatch.waiter_machine.middleware import WaiterMiddleware
|
|
8
|
-
from telegrinder.bot.dispatch.waiter_machine.short_state import (
|
|
9
|
-
EventModel,
|
|
10
|
-
ShortState,
|
|
11
|
-
ShortStateContext,
|
|
12
|
-
)
|
|
13
|
-
from telegrinder.bot.rules.abc import ABCRule
|
|
14
|
-
from telegrinder.tools.limited_dict import LimitedDict
|
|
15
|
-
|
|
16
|
-
from .actions import WaiterActions
|
|
17
|
-
from .hasher import Hasher, StateViewHasher
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
]
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
self.
|
|
39
|
-
self.
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
self.
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
)
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
__all__ = ("WaiterMachine",)
|
|
1
|
+
import asyncio
|
|
2
|
+
import datetime
|
|
3
|
+
import typing
|
|
4
|
+
|
|
5
|
+
from telegrinder.bot.dispatch.abc import ABCDispatch
|
|
6
|
+
from telegrinder.bot.dispatch.view.base import BaseStateView, BaseView
|
|
7
|
+
from telegrinder.bot.dispatch.waiter_machine.middleware import WaiterMiddleware
|
|
8
|
+
from telegrinder.bot.dispatch.waiter_machine.short_state import (
|
|
9
|
+
EventModel,
|
|
10
|
+
ShortState,
|
|
11
|
+
ShortStateContext,
|
|
12
|
+
)
|
|
13
|
+
from telegrinder.bot.rules.abc import ABCRule
|
|
14
|
+
from telegrinder.tools.limited_dict import LimitedDict
|
|
15
|
+
|
|
16
|
+
from .actions import WaiterActions
|
|
17
|
+
from .hasher import Hasher, StateViewHasher
|
|
18
|
+
|
|
19
|
+
HasherData = typing.TypeVar("HasherData")
|
|
20
|
+
|
|
21
|
+
Storage: typing.TypeAlias = dict[
|
|
22
|
+
Hasher[EventModel, HasherData], LimitedDict[typing.Hashable, ShortState[EventModel]]
|
|
23
|
+
]
|
|
24
|
+
|
|
25
|
+
WEEK: typing.Final[datetime.timedelta] = datetime.timedelta(days=7)
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
class WaiterMachine:
|
|
29
|
+
def __init__(
|
|
30
|
+
self,
|
|
31
|
+
dispatch: ABCDispatch | None = None,
|
|
32
|
+
*,
|
|
33
|
+
max_storage_size: int = 1000,
|
|
34
|
+
base_state_lifetime: datetime.timedelta = WEEK,
|
|
35
|
+
) -> None:
|
|
36
|
+
self.dispatch = dispatch
|
|
37
|
+
self.max_storage_size = max_storage_size
|
|
38
|
+
self.base_state_lifetime = base_state_lifetime
|
|
39
|
+
self.storage: Storage = {}
|
|
40
|
+
|
|
41
|
+
def __repr__(self) -> str:
|
|
42
|
+
return "<{}: max_storage_size={}, base_state_lifetime={!r}>".format(
|
|
43
|
+
self.__class__.__name__,
|
|
44
|
+
self.max_storage_size,
|
|
45
|
+
self.base_state_lifetime,
|
|
46
|
+
)
|
|
47
|
+
|
|
48
|
+
async def drop_all(self) -> None:
|
|
49
|
+
"""Drops all waiters in storage."""
|
|
50
|
+
|
|
51
|
+
for hasher in self.storage:
|
|
52
|
+
for ident, short_state in self.storage[hasher].items():
|
|
53
|
+
if short_state.context:
|
|
54
|
+
await self.drop(
|
|
55
|
+
hasher,
|
|
56
|
+
ident,
|
|
57
|
+
)
|
|
58
|
+
else:
|
|
59
|
+
short_state.cancel()
|
|
60
|
+
|
|
61
|
+
async def drop(
|
|
62
|
+
self,
|
|
63
|
+
hasher: Hasher[EventModel, HasherData],
|
|
64
|
+
id: HasherData,
|
|
65
|
+
**context: typing.Any,
|
|
66
|
+
) -> None:
|
|
67
|
+
if hasher not in self.storage:
|
|
68
|
+
raise LookupError("No record of hasher {!r} found.".format(hasher))
|
|
69
|
+
|
|
70
|
+
waiter_id: typing.Hashable = hasher.get_hash_from_data(id).expect(
|
|
71
|
+
RuntimeError("Couldn't create hash from data")
|
|
72
|
+
)
|
|
73
|
+
short_state = self.storage[hasher].pop(waiter_id, None)
|
|
74
|
+
if short_state is None:
|
|
75
|
+
raise LookupError(
|
|
76
|
+
"Waiter with identificator {} is not found for hasher {!r}.".format(waiter_id, hasher)
|
|
77
|
+
)
|
|
78
|
+
|
|
79
|
+
if on_drop := short_state.actions.get("on_drop"):
|
|
80
|
+
on_drop(short_state, **context)
|
|
81
|
+
|
|
82
|
+
short_state.cancel()
|
|
83
|
+
|
|
84
|
+
async def wait_from_event(
|
|
85
|
+
self,
|
|
86
|
+
view: BaseStateView[EventModel],
|
|
87
|
+
event: EventModel,
|
|
88
|
+
*,
|
|
89
|
+
filter: ABCRule | None = None,
|
|
90
|
+
release: ABCRule | None = None,
|
|
91
|
+
lifetime: datetime.timedelta | float | None = None,
|
|
92
|
+
**actions: typing.Unpack[WaiterActions[EventModel]],
|
|
93
|
+
) -> ShortStateContext[EventModel]:
|
|
94
|
+
hasher = StateViewHasher(view)
|
|
95
|
+
return await self.wait(
|
|
96
|
+
hasher=hasher,
|
|
97
|
+
data=hasher.get_data_from_event(event).expect(
|
|
98
|
+
RuntimeError("Hasher couldn't create data from event."),
|
|
99
|
+
),
|
|
100
|
+
filter=filter,
|
|
101
|
+
release=release,
|
|
102
|
+
lifetime=lifetime,
|
|
103
|
+
**actions,
|
|
104
|
+
)
|
|
105
|
+
|
|
106
|
+
async def wait(
|
|
107
|
+
self,
|
|
108
|
+
hasher: Hasher[EventModel, HasherData],
|
|
109
|
+
data: HasherData,
|
|
110
|
+
*,
|
|
111
|
+
filter: ABCRule | None = None,
|
|
112
|
+
release: ABCRule | None = None,
|
|
113
|
+
lifetime: datetime.timedelta | float | None = None,
|
|
114
|
+
**actions: typing.Unpack[WaiterActions[EventModel]],
|
|
115
|
+
) -> ShortStateContext[EventModel]:
|
|
116
|
+
if isinstance(lifetime, int | float):
|
|
117
|
+
lifetime = datetime.timedelta(seconds=lifetime)
|
|
118
|
+
|
|
119
|
+
event = asyncio.Event()
|
|
120
|
+
short_state = ShortState[EventModel](
|
|
121
|
+
event,
|
|
122
|
+
actions,
|
|
123
|
+
release=release,
|
|
124
|
+
filter=filter,
|
|
125
|
+
lifetime=lifetime or self.base_state_lifetime,
|
|
126
|
+
)
|
|
127
|
+
waiter_hash = hasher.get_hash_from_data(data).expect(RuntimeError("Hasher couldn't create hash."))
|
|
128
|
+
|
|
129
|
+
if hasher not in self.storage:
|
|
130
|
+
if self.dispatch:
|
|
131
|
+
view: BaseView[EventModel] = self.dispatch.get_view(hasher.view_class).expect(
|
|
132
|
+
RuntimeError(f"View {hasher.view_class.__name__!r} is not defined in dispatch.")
|
|
133
|
+
)
|
|
134
|
+
view.middlewares.insert(0, WaiterMiddleware(self, hasher))
|
|
135
|
+
self.storage[hasher] = LimitedDict(maxlimit=self.max_storage_size)
|
|
136
|
+
|
|
137
|
+
if (deleted_short_state := self.storage[hasher].set(waiter_hash, short_state)) is not None:
|
|
138
|
+
deleted_short_state.cancel()
|
|
139
|
+
|
|
140
|
+
await event.wait()
|
|
141
|
+
self.storage[hasher].pop(waiter_hash, None)
|
|
142
|
+
assert short_state.context is not None
|
|
143
|
+
return short_state.context
|
|
144
|
+
|
|
145
|
+
async def clear_storage(self) -> None:
|
|
146
|
+
"""Clears storage."""
|
|
147
|
+
|
|
148
|
+
for hasher in self.storage:
|
|
149
|
+
now = datetime.datetime.now()
|
|
150
|
+
for ident, short_state in self.storage.get(hasher, {}).copy().items():
|
|
151
|
+
if short_state.expiration_date is not None and now > short_state.expiration_date:
|
|
152
|
+
await self.drop(
|
|
153
|
+
hasher,
|
|
154
|
+
ident,
|
|
155
|
+
force=True,
|
|
156
|
+
)
|
|
157
|
+
|
|
158
|
+
|
|
159
|
+
async def clear_wm_storage_worker(
|
|
160
|
+
wm: WaiterMachine,
|
|
161
|
+
interval_seconds: int = 60,
|
|
162
|
+
) -> typing.NoReturn:
|
|
163
|
+
while True:
|
|
164
|
+
await wm.clear_storage()
|
|
165
|
+
await asyncio.sleep(interval_seconds)
|
|
166
|
+
|
|
167
|
+
|
|
168
|
+
__all__ = ("WaiterMachine",)
|
|
@@ -1,89 +1,89 @@
|
|
|
1
|
-
import datetime
|
|
2
|
-
import typing
|
|
3
|
-
|
|
4
|
-
from telegrinder.bot.cute_types.base import BaseCute
|
|
5
|
-
from telegrinder.bot.dispatch.context import Context
|
|
6
|
-
from telegrinder.bot.dispatch.handler.func import FuncHandler
|
|
7
|
-
from telegrinder.bot.dispatch.middleware.abc import ABCMiddleware
|
|
8
|
-
from telegrinder.bot.dispatch.process import check_rule
|
|
9
|
-
from telegrinder.bot.dispatch.waiter_machine.short_state import ShortStateContext
|
|
10
|
-
from telegrinder.modules import logger
|
|
11
|
-
|
|
12
|
-
from .hasher import Hasher
|
|
13
|
-
|
|
14
|
-
if typing.TYPE_CHECKING:
|
|
15
|
-
from .machine import WaiterMachine
|
|
16
|
-
from .short_state import ShortState
|
|
17
|
-
|
|
18
|
-
EventType = typing.TypeVar("EventType", bound=BaseCute)
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
class WaiterMiddleware(ABCMiddleware[EventType]):
|
|
22
|
-
def __init__(
|
|
23
|
-
self,
|
|
24
|
-
machine: "WaiterMachine",
|
|
25
|
-
hasher: Hasher,
|
|
26
|
-
) -> None:
|
|
27
|
-
self.machine = machine
|
|
28
|
-
self.hasher = hasher
|
|
29
|
-
|
|
30
|
-
async def pre(self, event: EventType, ctx: Context) -> bool:
|
|
31
|
-
if self.hasher not in self.machine.storage:
|
|
32
|
-
return True
|
|
33
|
-
|
|
34
|
-
key = self.hasher.get_hash_from_data_from_event(event)
|
|
35
|
-
if key is None:
|
|
36
|
-
logger.info(f"Unable to get hash from event with hasher {self.hasher}")
|
|
37
|
-
return True
|
|
38
|
-
|
|
39
|
-
short_state: "ShortState[EventType] | None" = self.machine.storage[self.hasher].get(key.unwrap())
|
|
40
|
-
if not short_state:
|
|
41
|
-
return True
|
|
42
|
-
|
|
43
|
-
preset_context = Context(short_state=short_state)
|
|
44
|
-
if short_state.context is not None:
|
|
45
|
-
preset_context.update(short_state.context.context)
|
|
46
|
-
|
|
47
|
-
# Run filter rule
|
|
48
|
-
if short_state.filter and not await check_rule(
|
|
49
|
-
event.ctx_api, short_state.filter, ctx.raw_update, preset_context
|
|
50
|
-
):
|
|
51
|
-
logger.debug("Filter rule {!r} failed", short_state.filter)
|
|
52
|
-
return True
|
|
53
|
-
|
|
54
|
-
if short_state.expiration_date is not None and datetime.datetime.now() >= short_state.expiration_date:
|
|
55
|
-
await self.machine.drop(
|
|
56
|
-
self.hasher,
|
|
57
|
-
self.hasher.get_data_from_event(event).unwrap(),
|
|
58
|
-
**preset_context.copy(),
|
|
59
|
-
)
|
|
60
|
-
return True
|
|
61
|
-
|
|
62
|
-
handler = FuncHandler(
|
|
63
|
-
self.pass_runtime,
|
|
64
|
-
[short_state.release] if short_state.release else [],
|
|
65
|
-
dataclass=None,
|
|
66
|
-
preset_context=preset_context,
|
|
67
|
-
)
|
|
68
|
-
result = await handler.check(event.ctx_api, ctx.raw_update, ctx)
|
|
69
|
-
|
|
70
|
-
if result is True:
|
|
71
|
-
await handler.run(event.api, event, ctx)
|
|
72
|
-
|
|
73
|
-
elif on_miss := short_state.actions.get("on_miss"): # noqa: SIM102
|
|
74
|
-
if await on_miss.check(event.ctx_api, ctx.raw_update, ctx):
|
|
75
|
-
await on_miss.run(event.ctx_api, event, ctx)
|
|
76
|
-
|
|
77
|
-
return False
|
|
78
|
-
|
|
79
|
-
async def pass_runtime(
|
|
80
|
-
self,
|
|
81
|
-
event: EventType,
|
|
82
|
-
short_state: "ShortState[EventType]",
|
|
83
|
-
ctx: Context,
|
|
84
|
-
) -> None:
|
|
85
|
-
short_state.context = ShortStateContext(event, ctx)
|
|
86
|
-
short_state.event.set()
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
__all__ = ("WaiterMiddleware",)
|
|
1
|
+
import datetime
|
|
2
|
+
import typing
|
|
3
|
+
|
|
4
|
+
from telegrinder.bot.cute_types.base import BaseCute
|
|
5
|
+
from telegrinder.bot.dispatch.context import Context
|
|
6
|
+
from telegrinder.bot.dispatch.handler.func import FuncHandler
|
|
7
|
+
from telegrinder.bot.dispatch.middleware.abc import ABCMiddleware
|
|
8
|
+
from telegrinder.bot.dispatch.process import check_rule
|
|
9
|
+
from telegrinder.bot.dispatch.waiter_machine.short_state import ShortStateContext
|
|
10
|
+
from telegrinder.modules import logger
|
|
11
|
+
|
|
12
|
+
from .hasher import Hasher
|
|
13
|
+
|
|
14
|
+
if typing.TYPE_CHECKING:
|
|
15
|
+
from .machine import WaiterMachine
|
|
16
|
+
from .short_state import ShortState
|
|
17
|
+
|
|
18
|
+
EventType = typing.TypeVar("EventType", bound=BaseCute)
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
class WaiterMiddleware(ABCMiddleware[EventType]):
|
|
22
|
+
def __init__(
|
|
23
|
+
self,
|
|
24
|
+
machine: "WaiterMachine",
|
|
25
|
+
hasher: Hasher,
|
|
26
|
+
) -> None:
|
|
27
|
+
self.machine = machine
|
|
28
|
+
self.hasher = hasher
|
|
29
|
+
|
|
30
|
+
async def pre(self, event: EventType, ctx: Context) -> bool:
|
|
31
|
+
if self.hasher not in self.machine.storage:
|
|
32
|
+
return True
|
|
33
|
+
|
|
34
|
+
key = self.hasher.get_hash_from_data_from_event(event)
|
|
35
|
+
if key is None:
|
|
36
|
+
logger.info(f"Unable to get hash from event with hasher {self.hasher}")
|
|
37
|
+
return True
|
|
38
|
+
|
|
39
|
+
short_state: "ShortState[EventType] | None" = self.machine.storage[self.hasher].get(key.unwrap())
|
|
40
|
+
if not short_state:
|
|
41
|
+
return True
|
|
42
|
+
|
|
43
|
+
preset_context = Context(short_state=short_state)
|
|
44
|
+
if short_state.context is not None:
|
|
45
|
+
preset_context.update(short_state.context.context)
|
|
46
|
+
|
|
47
|
+
# Run filter rule
|
|
48
|
+
if short_state.filter and not await check_rule(
|
|
49
|
+
event.ctx_api, short_state.filter, ctx.raw_update, preset_context
|
|
50
|
+
):
|
|
51
|
+
logger.debug("Filter rule {!r} failed", short_state.filter)
|
|
52
|
+
return True
|
|
53
|
+
|
|
54
|
+
if short_state.expiration_date is not None and datetime.datetime.now() >= short_state.expiration_date:
|
|
55
|
+
await self.machine.drop(
|
|
56
|
+
self.hasher,
|
|
57
|
+
self.hasher.get_data_from_event(event).unwrap(),
|
|
58
|
+
**preset_context.copy(),
|
|
59
|
+
)
|
|
60
|
+
return True
|
|
61
|
+
|
|
62
|
+
handler = FuncHandler(
|
|
63
|
+
self.pass_runtime,
|
|
64
|
+
[short_state.release] if short_state.release else [],
|
|
65
|
+
dataclass=None,
|
|
66
|
+
preset_context=preset_context,
|
|
67
|
+
)
|
|
68
|
+
result = await handler.check(event.ctx_api, ctx.raw_update, ctx)
|
|
69
|
+
|
|
70
|
+
if result is True:
|
|
71
|
+
await handler.run(event.api, event, ctx)
|
|
72
|
+
|
|
73
|
+
elif on_miss := short_state.actions.get("on_miss"): # noqa: SIM102
|
|
74
|
+
if await on_miss.check(event.ctx_api, ctx.raw_update, ctx):
|
|
75
|
+
await on_miss.run(event.ctx_api, event, ctx)
|
|
76
|
+
|
|
77
|
+
return False
|
|
78
|
+
|
|
79
|
+
async def pass_runtime(
|
|
80
|
+
self,
|
|
81
|
+
event: EventType,
|
|
82
|
+
short_state: "ShortState[EventType]",
|
|
83
|
+
ctx: Context,
|
|
84
|
+
) -> None:
|
|
85
|
+
short_state.context = ShortStateContext(event, ctx)
|
|
86
|
+
short_state.event.set()
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
__all__ = ("WaiterMiddleware",)
|