telegrinder 0.3.4__py3-none-any.whl → 0.4.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.
Potentially problematic release.
This version of telegrinder might be problematic. Click here for more details.
- telegrinder/__init__.py +148 -149
- telegrinder/api/__init__.py +9 -8
- telegrinder/api/api.py +101 -93
- telegrinder/api/error.py +20 -16
- telegrinder/api/response.py +20 -20
- telegrinder/api/token.py +36 -36
- telegrinder/bot/__init__.py +72 -66
- telegrinder/bot/bot.py +83 -76
- telegrinder/bot/cute_types/__init__.py +19 -17
- telegrinder/bot/cute_types/base.py +184 -258
- telegrinder/bot/cute_types/callback_query.py +400 -385
- telegrinder/bot/cute_types/chat_join_request.py +62 -61
- telegrinder/bot/cute_types/chat_member_updated.py +157 -160
- telegrinder/bot/cute_types/inline_query.py +44 -43
- telegrinder/bot/cute_types/message.py +2590 -2637
- telegrinder/bot/cute_types/pre_checkout_query.py +42 -0
- telegrinder/bot/cute_types/update.py +112 -104
- telegrinder/bot/cute_types/utils.py +62 -95
- telegrinder/bot/dispatch/__init__.py +59 -55
- telegrinder/bot/dispatch/abc.py +76 -77
- telegrinder/bot/dispatch/context.py +96 -98
- telegrinder/bot/dispatch/dispatch.py +254 -202
- telegrinder/bot/dispatch/handler/__init__.py +13 -13
- telegrinder/bot/dispatch/handler/abc.py +23 -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 +129 -135
- telegrinder/bot/dispatch/handler/media_group_reply.py +44 -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 +97 -22
- telegrinder/bot/dispatch/middleware/global_middleware.py +70 -0
- telegrinder/bot/dispatch/process.py +151 -157
- telegrinder/bot/dispatch/return_manager/__init__.py +15 -13
- telegrinder/bot/dispatch/return_manager/abc.py +104 -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/return_manager/pre_checkout_query.py +20 -0
- telegrinder/bot/dispatch/view/__init__.py +15 -13
- telegrinder/bot/dispatch/view/abc.py +45 -41
- telegrinder/bot/dispatch/view/base.py +231 -200
- telegrinder/bot/dispatch/view/box.py +140 -129
- telegrinder/bot/dispatch/view/callback_query.py +16 -17
- telegrinder/bot/dispatch/view/chat_join_request.py +11 -16
- telegrinder/bot/dispatch/view/chat_member.py +37 -39
- telegrinder/bot/dispatch/view/inline_query.py +16 -17
- telegrinder/bot/dispatch/view/message.py +43 -44
- telegrinder/bot/dispatch/view/pre_checkout_query.py +16 -0
- telegrinder/bot/dispatch/view/raw.py +116 -114
- telegrinder/bot/dispatch/waiter_machine/__init__.py +17 -17
- telegrinder/bot/dispatch/waiter_machine/actions.py +14 -13
- telegrinder/bot/dispatch/waiter_machine/hasher/__init__.py +8 -8
- telegrinder/bot/dispatch/waiter_machine/hasher/callback.py +55 -55
- telegrinder/bot/dispatch/waiter_machine/hasher/hasher.py +59 -57
- telegrinder/bot/dispatch/waiter_machine/hasher/message.py +51 -51
- telegrinder/bot/dispatch/waiter_machine/hasher/state.py +20 -19
- telegrinder/bot/dispatch/waiter_machine/machine.py +251 -172
- telegrinder/bot/dispatch/waiter_machine/middleware.py +94 -89
- telegrinder/bot/dispatch/waiter_machine/short_state.py +57 -68
- telegrinder/bot/polling/__init__.py +4 -4
- telegrinder/bot/polling/abc.py +25 -25
- telegrinder/bot/polling/polling.py +139 -131
- telegrinder/bot/rules/__init__.py +85 -62
- telegrinder/bot/rules/abc.py +213 -206
- telegrinder/bot/rules/callback_data.py +122 -163
- telegrinder/bot/rules/chat_join.py +45 -43
- telegrinder/bot/rules/command.py +126 -126
- telegrinder/bot/rules/enum_text.py +33 -36
- telegrinder/bot/rules/func.py +28 -26
- telegrinder/bot/rules/fuzzy.py +24 -24
- telegrinder/bot/rules/id.py +24 -0
- telegrinder/bot/rules/inline.py +58 -56
- telegrinder/bot/rules/integer.py +21 -20
- telegrinder/bot/rules/is_from.py +127 -127
- telegrinder/bot/rules/logic.py +18 -0
- telegrinder/bot/rules/markup.py +42 -43
- telegrinder/bot/rules/mention.py +14 -14
- telegrinder/bot/rules/message.py +15 -17
- telegrinder/bot/rules/message_entities.py +33 -35
- telegrinder/bot/rules/node.py +33 -27
- telegrinder/bot/rules/payload.py +81 -0
- telegrinder/bot/rules/payment_invoice.py +29 -0
- telegrinder/bot/rules/regex.py +36 -37
- telegrinder/bot/rules/rule_enum.py +72 -72
- telegrinder/bot/rules/start.py +42 -42
- telegrinder/bot/rules/state.py +35 -37
- telegrinder/bot/rules/text.py +38 -33
- telegrinder/bot/rules/update.py +15 -15
- telegrinder/bot/scenario/__init__.py +5 -5
- telegrinder/bot/scenario/abc.py +17 -19
- telegrinder/bot/scenario/checkbox.py +174 -176
- telegrinder/bot/scenario/choice.py +48 -51
- telegrinder/client/__init__.py +12 -4
- telegrinder/client/abc.py +100 -75
- telegrinder/client/aiohttp.py +134 -130
- telegrinder/client/form_data.py +31 -0
- telegrinder/client/sonic.py +212 -0
- telegrinder/model.py +208 -315
- telegrinder/modules.py +239 -237
- telegrinder/msgspec_json.py +14 -14
- telegrinder/msgspec_utils.py +478 -410
- telegrinder/node/__init__.py +86 -25
- telegrinder/node/attachment.py +163 -87
- telegrinder/node/base.py +288 -160
- telegrinder/node/callback_query.py +54 -53
- telegrinder/node/command.py +34 -33
- telegrinder/node/composer.py +163 -198
- telegrinder/node/container.py +33 -27
- telegrinder/node/either.py +82 -0
- telegrinder/node/event.py +54 -65
- telegrinder/node/file.py +51 -0
- telegrinder/node/me.py +15 -16
- telegrinder/node/payload.py +78 -0
- telegrinder/node/polymorphic.py +67 -48
- telegrinder/node/rule.py +72 -76
- telegrinder/node/scope.py +36 -38
- telegrinder/node/source.py +87 -71
- telegrinder/node/text.py +53 -41
- telegrinder/node/tools/__init__.py +3 -3
- telegrinder/node/tools/generator.py +36 -40
- telegrinder/py.typed +0 -0
- telegrinder/rules.py +1 -62
- telegrinder/tools/__init__.py +152 -93
- telegrinder/tools/adapter/__init__.py +19 -0
- telegrinder/tools/adapter/abc.py +49 -0
- telegrinder/tools/adapter/dataclass.py +56 -0
- telegrinder/{bot/rules → tools}/adapter/errors.py +5 -5
- telegrinder/{bot/rules → tools}/adapter/event.py +63 -65
- telegrinder/{bot/rules → tools}/adapter/node.py +46 -48
- telegrinder/{bot/rules → tools}/adapter/raw_event.py +27 -27
- telegrinder/{bot/rules → tools}/adapter/raw_update.py +30 -30
- telegrinder/tools/buttons.py +106 -80
- telegrinder/tools/callback_data_serilization/__init__.py +5 -0
- telegrinder/tools/callback_data_serilization/abc.py +51 -0
- telegrinder/tools/callback_data_serilization/json_ser.py +60 -0
- telegrinder/tools/callback_data_serilization/msgpack_ser.py +172 -0
- telegrinder/tools/error_handler/__init__.py +7 -7
- telegrinder/tools/error_handler/abc.py +30 -33
- telegrinder/tools/error_handler/error.py +9 -9
- telegrinder/tools/error_handler/error_handler.py +179 -193
- telegrinder/tools/formatting/__init__.py +83 -63
- telegrinder/tools/formatting/deep_links.py +541 -0
- telegrinder/tools/formatting/{html.py → html_formatter.py} +266 -294
- telegrinder/tools/formatting/spec_html_formats.py +71 -117
- telegrinder/tools/functional.py +8 -12
- telegrinder/tools/global_context/__init__.py +7 -7
- telegrinder/tools/global_context/abc.py +63 -63
- telegrinder/tools/global_context/global_context.py +387 -412
- telegrinder/tools/global_context/telegrinder_ctx.py +27 -27
- telegrinder/tools/i18n/__init__.py +7 -7
- telegrinder/tools/i18n/abc.py +30 -30
- telegrinder/tools/i18n/middleware/__init__.py +3 -3
- telegrinder/tools/i18n/middleware/abc.py +22 -25
- telegrinder/tools/i18n/simple.py +43 -43
- telegrinder/tools/input_file_directory.py +30 -0
- telegrinder/tools/keyboard.py +128 -128
- telegrinder/tools/lifespan.py +105 -0
- telegrinder/tools/limited_dict.py +32 -37
- telegrinder/tools/loop_wrapper/__init__.py +4 -4
- telegrinder/tools/loop_wrapper/abc.py +20 -15
- telegrinder/tools/loop_wrapper/loop_wrapper.py +169 -224
- telegrinder/tools/magic.py +307 -157
- telegrinder/tools/parse_mode.py +6 -6
- telegrinder/tools/state_storage/__init__.py +4 -4
- telegrinder/tools/state_storage/abc.py +31 -35
- telegrinder/tools/state_storage/memory.py +25 -25
- telegrinder/tools/strings.py +13 -0
- telegrinder/types/__init__.py +268 -260
- telegrinder/types/enums.py +711 -701
- telegrinder/types/input_file.py +51 -0
- telegrinder/types/methods.py +5055 -4633
- telegrinder/types/objects.py +7058 -6950
- telegrinder/verification_utils.py +30 -32
- {telegrinder-0.3.4.dist-info → telegrinder-0.4.0.dist-info}/LICENSE +22 -22
- telegrinder-0.4.0.dist-info/METADATA +144 -0
- telegrinder-0.4.0.dist-info/RECORD +182 -0
- {telegrinder-0.3.4.dist-info → telegrinder-0.4.0.dist-info}/WHEEL +1 -1
- telegrinder/bot/rules/adapter/__init__.py +0 -17
- telegrinder/bot/rules/adapter/abc.py +0 -31
- telegrinder/node/message.py +0 -14
- telegrinder/node/update.py +0 -15
- telegrinder/tools/formatting/links.py +0 -38
- telegrinder/tools/kb_set/__init__.py +0 -4
- telegrinder/tools/kb_set/base.py +0 -15
- telegrinder/tools/kb_set/yaml.py +0 -63
- telegrinder-0.3.4.dist-info/METADATA +0 -110
- telegrinder-0.3.4.dist-info/RECORD +0 -165
|
@@ -1,44 +1,44 @@
|
|
|
1
|
-
import typing
|
|
2
|
-
|
|
3
|
-
from telegrinder.api.api import API
|
|
4
|
-
from telegrinder.bot.cute_types.message import MessageCute
|
|
5
|
-
from telegrinder.bot.dispatch.context import Context
|
|
6
|
-
from telegrinder.bot.dispatch.handler.base import BaseReplyHandler
|
|
7
|
-
from telegrinder.bot.rules.abc import ABCRule
|
|
8
|
-
from telegrinder.types.objects import InputFile
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
class PhotoReplyHandler(BaseReplyHandler):
|
|
12
|
-
def __init__(
|
|
13
|
-
self,
|
|
14
|
-
photo: InputFile | str,
|
|
15
|
-
*rules: ABCRule,
|
|
16
|
-
caption: str | None = None,
|
|
17
|
-
parse_mode: str | None = None,
|
|
18
|
-
|
|
19
|
-
as_reply: bool = False,
|
|
20
|
-
preset_context: Context | None = None,
|
|
21
|
-
**default_params: typing.Any,
|
|
22
|
-
) -> None:
|
|
23
|
-
self.photo = photo
|
|
24
|
-
self.parse_mode = parse_mode
|
|
25
|
-
self.caption = caption
|
|
26
|
-
super().__init__(
|
|
27
|
-
*rules,
|
|
28
|
-
|
|
29
|
-
as_reply=as_reply,
|
|
30
|
-
preset_context=preset_context,
|
|
31
|
-
**default_params,
|
|
32
|
-
)
|
|
33
|
-
|
|
34
|
-
async def run(self, _: API, event: MessageCute, __: Context) -> typing.Any:
|
|
35
|
-
method = event.answer_photo if not self.as_reply else event.reply_photo
|
|
36
|
-
await method(
|
|
37
|
-
photo=self.photo,
|
|
38
|
-
parse_mode=self.parse_mode,
|
|
39
|
-
caption=self.caption,
|
|
40
|
-
**self.default_params,
|
|
41
|
-
)
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
__all__ = ("PhotoReplyHandler",)
|
|
1
|
+
import typing
|
|
2
|
+
|
|
3
|
+
from telegrinder.api.api import API
|
|
4
|
+
from telegrinder.bot.cute_types.message import MessageCute
|
|
5
|
+
from telegrinder.bot.dispatch.context import Context
|
|
6
|
+
from telegrinder.bot.dispatch.handler.base import BaseReplyHandler
|
|
7
|
+
from telegrinder.bot.rules.abc import ABCRule
|
|
8
|
+
from telegrinder.types.objects import InputFile
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class PhotoReplyHandler(BaseReplyHandler):
|
|
12
|
+
def __init__(
|
|
13
|
+
self,
|
|
14
|
+
photo: InputFile | str,
|
|
15
|
+
*rules: ABCRule,
|
|
16
|
+
caption: str | None = None,
|
|
17
|
+
parse_mode: str | None = None,
|
|
18
|
+
final: bool = True,
|
|
19
|
+
as_reply: bool = False,
|
|
20
|
+
preset_context: Context | None = None,
|
|
21
|
+
**default_params: typing.Any,
|
|
22
|
+
) -> None:
|
|
23
|
+
self.photo = photo
|
|
24
|
+
self.parse_mode = parse_mode
|
|
25
|
+
self.caption = caption
|
|
26
|
+
super().__init__(
|
|
27
|
+
*rules,
|
|
28
|
+
final=final,
|
|
29
|
+
as_reply=as_reply,
|
|
30
|
+
preset_context=preset_context,
|
|
31
|
+
**default_params,
|
|
32
|
+
)
|
|
33
|
+
|
|
34
|
+
async def run(self, _: API, event: MessageCute, __: Context) -> typing.Any:
|
|
35
|
+
method = event.answer_photo if not self.as_reply else event.reply_photo
|
|
36
|
+
await method(
|
|
37
|
+
photo=self.photo,
|
|
38
|
+
parse_mode=self.parse_mode,
|
|
39
|
+
caption=self.caption,
|
|
40
|
+
**self.default_params,
|
|
41
|
+
)
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
__all__ = ("PhotoReplyHandler",)
|
|
@@ -1,37 +1,37 @@
|
|
|
1
|
-
import typing
|
|
2
|
-
|
|
3
|
-
from telegrinder.api.api import API
|
|
4
|
-
from telegrinder.bot.cute_types.message import MessageCute
|
|
5
|
-
from telegrinder.bot.dispatch.context import Context
|
|
6
|
-
from telegrinder.bot.dispatch.handler.base import BaseReplyHandler
|
|
7
|
-
from telegrinder.bot.rules.abc import ABCRule
|
|
8
|
-
from telegrinder.types.objects import InputFile
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
class StickerReplyHandler(BaseReplyHandler):
|
|
12
|
-
def __init__(
|
|
13
|
-
self,
|
|
14
|
-
sticker: InputFile | str,
|
|
15
|
-
*rules: ABCRule,
|
|
16
|
-
emoji: str | None = None,
|
|
17
|
-
|
|
18
|
-
as_reply: bool = False,
|
|
19
|
-
preset_context: Context | None = None,
|
|
20
|
-
**default_params: typing.Any,
|
|
21
|
-
) -> None:
|
|
22
|
-
self.sticker = sticker
|
|
23
|
-
self.emoji = emoji
|
|
24
|
-
super().__init__(
|
|
25
|
-
*rules,
|
|
26
|
-
|
|
27
|
-
as_reply=as_reply,
|
|
28
|
-
preset_context=preset_context,
|
|
29
|
-
**default_params,
|
|
30
|
-
)
|
|
31
|
-
|
|
32
|
-
async def run(self, _: API, event: MessageCute, __: Context) -> typing.Any:
|
|
33
|
-
method = event.answer_sticker if not self.as_reply else event.reply_sticker
|
|
34
|
-
await method(sticker=self.sticker, emoji=self.emoji, **self.default_params)
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
__all__ = ("StickerReplyHandler",)
|
|
1
|
+
import typing
|
|
2
|
+
|
|
3
|
+
from telegrinder.api.api import API
|
|
4
|
+
from telegrinder.bot.cute_types.message import MessageCute
|
|
5
|
+
from telegrinder.bot.dispatch.context import Context
|
|
6
|
+
from telegrinder.bot.dispatch.handler.base import BaseReplyHandler
|
|
7
|
+
from telegrinder.bot.rules.abc import ABCRule
|
|
8
|
+
from telegrinder.types.objects import InputFile
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class StickerReplyHandler(BaseReplyHandler):
|
|
12
|
+
def __init__(
|
|
13
|
+
self,
|
|
14
|
+
sticker: InputFile | str,
|
|
15
|
+
*rules: ABCRule,
|
|
16
|
+
emoji: str | None = None,
|
|
17
|
+
final: bool = True,
|
|
18
|
+
as_reply: bool = False,
|
|
19
|
+
preset_context: Context | None = None,
|
|
20
|
+
**default_params: typing.Any,
|
|
21
|
+
) -> None:
|
|
22
|
+
self.sticker = sticker
|
|
23
|
+
self.emoji = emoji
|
|
24
|
+
super().__init__(
|
|
25
|
+
*rules,
|
|
26
|
+
final=final,
|
|
27
|
+
as_reply=as_reply,
|
|
28
|
+
preset_context=preset_context,
|
|
29
|
+
**default_params,
|
|
30
|
+
)
|
|
31
|
+
|
|
32
|
+
async def run(self, _: API, event: MessageCute, __: Context) -> typing.Any:
|
|
33
|
+
method = event.answer_sticker if not self.as_reply else event.reply_sticker
|
|
34
|
+
await method(sticker=self.sticker, emoji=self.emoji, **self.default_params)
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
__all__ = ("StickerReplyHandler",)
|
|
@@ -1,44 +1,44 @@
|
|
|
1
|
-
import typing
|
|
2
|
-
|
|
3
|
-
from telegrinder.api.api import API
|
|
4
|
-
from telegrinder.bot.cute_types.message import MessageCute
|
|
5
|
-
from telegrinder.bot.dispatch.context import Context
|
|
6
|
-
from telegrinder.bot.dispatch.handler.base import BaseReplyHandler
|
|
7
|
-
from telegrinder.bot.rules.abc import ABCRule
|
|
8
|
-
from telegrinder.types.objects import InputFile
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
class VideoReplyHandler(BaseReplyHandler):
|
|
12
|
-
def __init__(
|
|
13
|
-
self,
|
|
14
|
-
video: InputFile | str,
|
|
15
|
-
*rules: ABCRule,
|
|
16
|
-
caption: str | None = None,
|
|
17
|
-
parse_mode: str | None = None,
|
|
18
|
-
|
|
19
|
-
as_reply: bool = False,
|
|
20
|
-
preset_context: Context | None = None,
|
|
21
|
-
**default_params: typing.Any,
|
|
22
|
-
) -> None:
|
|
23
|
-
self.video = video
|
|
24
|
-
self.parse_mode = parse_mode
|
|
25
|
-
self.caption = caption
|
|
26
|
-
super().__init__(
|
|
27
|
-
*rules,
|
|
28
|
-
|
|
29
|
-
as_reply=as_reply,
|
|
30
|
-
preset_context=preset_context,
|
|
31
|
-
**default_params,
|
|
32
|
-
)
|
|
33
|
-
|
|
34
|
-
async def run(self, _: API, event: MessageCute, __: Context) -> typing.Any:
|
|
35
|
-
method = event.answer_video if not self.as_reply else event.reply_video
|
|
36
|
-
await method(
|
|
37
|
-
video=self.video,
|
|
38
|
-
parse_mode=self.parse_mode,
|
|
39
|
-
caption=self.caption,
|
|
40
|
-
**self.default_params,
|
|
41
|
-
)
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
__all__ = ("VideoReplyHandler",)
|
|
1
|
+
import typing
|
|
2
|
+
|
|
3
|
+
from telegrinder.api.api import API
|
|
4
|
+
from telegrinder.bot.cute_types.message import MessageCute
|
|
5
|
+
from telegrinder.bot.dispatch.context import Context
|
|
6
|
+
from telegrinder.bot.dispatch.handler.base import BaseReplyHandler
|
|
7
|
+
from telegrinder.bot.rules.abc import ABCRule
|
|
8
|
+
from telegrinder.types.objects import InputFile
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class VideoReplyHandler(BaseReplyHandler):
|
|
12
|
+
def __init__(
|
|
13
|
+
self,
|
|
14
|
+
video: InputFile | str,
|
|
15
|
+
*rules: ABCRule,
|
|
16
|
+
caption: str | None = None,
|
|
17
|
+
parse_mode: str | None = None,
|
|
18
|
+
final: bool = True,
|
|
19
|
+
as_reply: bool = False,
|
|
20
|
+
preset_context: Context | None = None,
|
|
21
|
+
**default_params: typing.Any,
|
|
22
|
+
) -> None:
|
|
23
|
+
self.video = video
|
|
24
|
+
self.parse_mode = parse_mode
|
|
25
|
+
self.caption = caption
|
|
26
|
+
super().__init__(
|
|
27
|
+
*rules,
|
|
28
|
+
final=final,
|
|
29
|
+
as_reply=as_reply,
|
|
30
|
+
preset_context=preset_context,
|
|
31
|
+
**default_params,
|
|
32
|
+
)
|
|
33
|
+
|
|
34
|
+
async def run(self, _: API, event: MessageCute, __: Context) -> typing.Any:
|
|
35
|
+
method = event.answer_video if not self.as_reply else event.reply_video
|
|
36
|
+
await method(
|
|
37
|
+
video=self.video,
|
|
38
|
+
parse_mode=self.parse_mode,
|
|
39
|
+
caption=self.caption,
|
|
40
|
+
**self.default_params,
|
|
41
|
+
)
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
__all__ = ("VideoReplyHandler",)
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
from telegrinder.bot.dispatch.middleware.abc import ABCMiddleware
|
|
2
|
-
|
|
3
|
-
__all__ = ("ABCMiddleware",)
|
|
1
|
+
from telegrinder.bot.dispatch.middleware.abc import ABCMiddleware
|
|
2
|
+
|
|
3
|
+
__all__ = ("ABCMiddleware",)
|
|
@@ -1,22 +1,97 @@
|
|
|
1
|
-
import
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
from
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from abc import ABC
|
|
4
|
+
|
|
5
|
+
import typing_extensions as typing
|
|
6
|
+
from fntypes import Some
|
|
7
|
+
|
|
8
|
+
from telegrinder.api import API
|
|
9
|
+
from telegrinder.bot.cute_types.base import BaseCute
|
|
10
|
+
from telegrinder.bot.dispatch.context import Context
|
|
11
|
+
from telegrinder.model import Model
|
|
12
|
+
from telegrinder.modules import logger
|
|
13
|
+
from telegrinder.tools.adapter.abc import ABCAdapter, run_adapter
|
|
14
|
+
from telegrinder.tools.lifespan import Lifespan
|
|
15
|
+
from telegrinder.types.objects import Update
|
|
16
|
+
|
|
17
|
+
ToEvent = typing.TypeVar("ToEvent", bound=Model, default=typing.Any)
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
async def run_middleware[Event: Model, R: bool | None](
|
|
21
|
+
method: typing.Callable[typing.Concatenate[Event, Context, ...], typing.Awaitable[R]],
|
|
22
|
+
api: API[typing.Any],
|
|
23
|
+
event: Event,
|
|
24
|
+
ctx: Context,
|
|
25
|
+
raw_event: Update | None = None,
|
|
26
|
+
adapter: "ABCAdapter[Update, Event] | None" = None,
|
|
27
|
+
*args: typing.Any,
|
|
28
|
+
**kwargs: typing.Any,
|
|
29
|
+
) -> R:
|
|
30
|
+
if adapter is not None:
|
|
31
|
+
if raw_event is None:
|
|
32
|
+
raise RuntimeError("raw_event must be specified to apply adapter")
|
|
33
|
+
match await run_adapter(adapter, api, raw_event, ctx):
|
|
34
|
+
case Some(val):
|
|
35
|
+
event = val
|
|
36
|
+
case _:
|
|
37
|
+
return False # type: ignore
|
|
38
|
+
|
|
39
|
+
logger.debug("Running {}-middleware {!r}...", method.__name__, method.__qualname__.split(".")[0])
|
|
40
|
+
return await method(event, ctx, *args, **kwargs) # type: ignore
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
class ABCMiddleware[Event: Model | BaseCute](ABC):
|
|
44
|
+
adapter: ABCAdapter[Update, Event] | None = None
|
|
45
|
+
|
|
46
|
+
def __repr__(self) -> str:
|
|
47
|
+
name = f"middleware {self.__class__.__name__!r}:"
|
|
48
|
+
has_pre = self.pre.__qualname__.split(".")[0] != "ABCMiddleware"
|
|
49
|
+
has_post = self.post.__qualname__.split(".")[0] != "ABCMiddleware"
|
|
50
|
+
|
|
51
|
+
if has_post:
|
|
52
|
+
name = "post-" + name
|
|
53
|
+
if has_pre:
|
|
54
|
+
name = "pre-" + name
|
|
55
|
+
|
|
56
|
+
return "<{} with adapter={!r}>".format(name, self.adapter)
|
|
57
|
+
|
|
58
|
+
async def pre(self, event: Event, ctx: Context) -> bool: ...
|
|
59
|
+
|
|
60
|
+
async def post(self, event: Event, ctx: Context) -> None: ...
|
|
61
|
+
|
|
62
|
+
@typing.overload
|
|
63
|
+
def to_lifespan(self, event: Event, ctx: Context | None = None, *, api: API) -> Lifespan: ...
|
|
64
|
+
|
|
65
|
+
@typing.overload
|
|
66
|
+
def to_lifespan(self, event: Event, ctx: Context | None = None) -> Lifespan: ...
|
|
67
|
+
|
|
68
|
+
def to_lifespan(
|
|
69
|
+
self,
|
|
70
|
+
event: Event,
|
|
71
|
+
ctx: Context | None = None,
|
|
72
|
+
api: API | None = None,
|
|
73
|
+
**add_context: typing.Any,
|
|
74
|
+
) -> Lifespan:
|
|
75
|
+
if api is None:
|
|
76
|
+
if not isinstance(event, BaseCute):
|
|
77
|
+
raise LookupError("Cannot get api, please pass as kwarg or provide BaseCute api-bound event")
|
|
78
|
+
api = event.api
|
|
79
|
+
|
|
80
|
+
ctx = ctx or Context()
|
|
81
|
+
ctx |= add_context
|
|
82
|
+
return Lifespan(
|
|
83
|
+
startup_tasks=[run_middleware(self.pre, api, event, raw_event=None, ctx=ctx, adapter=None)],
|
|
84
|
+
shutdown_tasks=[
|
|
85
|
+
run_middleware(
|
|
86
|
+
self.post,
|
|
87
|
+
api,
|
|
88
|
+
event,
|
|
89
|
+
raw_event=None,
|
|
90
|
+
ctx=ctx,
|
|
91
|
+
adapter=None,
|
|
92
|
+
)
|
|
93
|
+
],
|
|
94
|
+
)
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
__all__ = ("ABCMiddleware", "run_middleware")
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import inspect
|
|
2
|
+
import typing
|
|
3
|
+
from contextlib import contextmanager
|
|
4
|
+
|
|
5
|
+
from telegrinder.api import API
|
|
6
|
+
from telegrinder.bot.cute_types.update import UpdateCute
|
|
7
|
+
from telegrinder.bot.dispatch.context import Context
|
|
8
|
+
from telegrinder.bot.dispatch.middleware.abc import ABCMiddleware
|
|
9
|
+
from telegrinder.bot.rules.abc import ABCRule, check_rule
|
|
10
|
+
from telegrinder.node import IsNode, compose_nodes
|
|
11
|
+
from telegrinder.tools.adapter.abc import ABCAdapter
|
|
12
|
+
from telegrinder.tools.adapter.raw_update import RawUpdateAdapter
|
|
13
|
+
from telegrinder.types import Update
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class GlobalMiddleware(ABCMiddleware):
|
|
17
|
+
adapter = RawUpdateAdapter()
|
|
18
|
+
|
|
19
|
+
def __init__(self):
|
|
20
|
+
self.filters: set[ABCRule] = set()
|
|
21
|
+
self.source_filters: dict[ABCAdapter | IsNode, dict[typing.Any, ABCRule]] = {}
|
|
22
|
+
|
|
23
|
+
async def pre(self, event: UpdateCute, ctx: Context) -> bool:
|
|
24
|
+
for filter in self.filters:
|
|
25
|
+
if not await check_rule(event.api, filter, event, ctx):
|
|
26
|
+
return False
|
|
27
|
+
|
|
28
|
+
# Simple implication.... Grouped by source categories
|
|
29
|
+
for source, identifiers in self.source_filters.items():
|
|
30
|
+
if isinstance(source, ABCAdapter):
|
|
31
|
+
result = source.adapt(event.api, event, ctx)
|
|
32
|
+
if inspect.isawaitable(result):
|
|
33
|
+
result = await result
|
|
34
|
+
|
|
35
|
+
result = result.unwrap_or_none()
|
|
36
|
+
if result is None:
|
|
37
|
+
return True
|
|
38
|
+
|
|
39
|
+
else:
|
|
40
|
+
result = await compose_nodes({"value": source}, ctx, {Update: event, API: event.api})
|
|
41
|
+
if result := result.unwrap():
|
|
42
|
+
result = result.values["value"]
|
|
43
|
+
else:
|
|
44
|
+
return True
|
|
45
|
+
|
|
46
|
+
if result in identifiers:
|
|
47
|
+
return await check_rule(event.api, identifiers[result], event, ctx)
|
|
48
|
+
|
|
49
|
+
return True
|
|
50
|
+
|
|
51
|
+
@contextmanager
|
|
52
|
+
def apply_filters(
|
|
53
|
+
self,
|
|
54
|
+
*filters: ABCRule,
|
|
55
|
+
source_filter: tuple[ABCAdapter | IsNode, typing.Any, ABCRule] | None = None,
|
|
56
|
+
):
|
|
57
|
+
if source_filter is not None:
|
|
58
|
+
self.source_filters.setdefault(source_filter[0], {})
|
|
59
|
+
self.source_filters[source_filter[0]].update({source_filter[1]: source_filter[2]})
|
|
60
|
+
|
|
61
|
+
self.filters |= set(filters)
|
|
62
|
+
yield
|
|
63
|
+
self.filters.difference_update(filters)
|
|
64
|
+
|
|
65
|
+
if source_filter is not None: # noqa: SIM102
|
|
66
|
+
if identifiers := self.source_filters.get(source_filter[0]):
|
|
67
|
+
identifiers.pop(source_filter[1], None)
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
__all__ = ("GlobalMiddleware",)
|