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
telegrinder/bot/rules/markup.py
CHANGED
|
@@ -1,43 +1,42 @@
|
|
|
1
|
-
import typing
|
|
2
|
-
|
|
3
|
-
import vbml
|
|
4
|
-
|
|
5
|
-
from telegrinder.bot.dispatch.context import Context
|
|
6
|
-
from telegrinder.node.
|
|
7
|
-
from telegrinder.
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
if isinstance(pattern, str)
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
__all__ = ("Markup", "check_string")
|
|
1
|
+
import typing
|
|
2
|
+
|
|
3
|
+
import vbml
|
|
4
|
+
|
|
5
|
+
from telegrinder.bot.dispatch.context import Context
|
|
6
|
+
from telegrinder.node.either import Either
|
|
7
|
+
from telegrinder.node.text import Caption, Text
|
|
8
|
+
from telegrinder.tools.global_context.telegrinder_ctx import TelegrinderContext
|
|
9
|
+
|
|
10
|
+
from .abc import ABCRule
|
|
11
|
+
|
|
12
|
+
type PatternLike = str | vbml.Pattern
|
|
13
|
+
global_ctx: typing.Final[TelegrinderContext] = TelegrinderContext()
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
def check_string(patterns: list[vbml.Pattern], s: str, ctx: Context) -> bool:
|
|
17
|
+
for pattern in patterns:
|
|
18
|
+
match global_ctx.vbml_patcher.check(pattern, s):
|
|
19
|
+
case None | False:
|
|
20
|
+
continue
|
|
21
|
+
case {**response}:
|
|
22
|
+
ctx |= response
|
|
23
|
+
return True
|
|
24
|
+
return False
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
class Markup(ABCRule):
|
|
28
|
+
"""Markup Language. See the [vbml documentation](https://github.com/tesseradecade/vbml/blob/master/docs/index.md)."""
|
|
29
|
+
|
|
30
|
+
def __init__(self, patterns: PatternLike | list[PatternLike], /) -> None:
|
|
31
|
+
if not isinstance(patterns, list):
|
|
32
|
+
patterns = [patterns]
|
|
33
|
+
self.patterns = [
|
|
34
|
+
vbml.Pattern(pattern, flags=global_ctx.vbml_pattern_flags) if isinstance(pattern, str) else pattern
|
|
35
|
+
for pattern in patterns
|
|
36
|
+
]
|
|
37
|
+
|
|
38
|
+
def check(self, text: Either[Text, Caption], ctx: Context) -> bool:
|
|
39
|
+
return check_string(self.patterns, text, ctx)
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
__all__ = ("Markup", "check_string")
|
telegrinder/bot/rules/mention.py
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
|
-
from telegrinder.types.enums import MessageEntityType
|
|
2
|
-
|
|
3
|
-
from .message import Message, MessageRule
|
|
4
|
-
from .text import HasText
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
class HasMention(MessageRule, requires=[HasText()]):
|
|
8
|
-
def check(self, message: Message) -> bool:
|
|
9
|
-
if not message.entities.unwrap_or_none():
|
|
10
|
-
return False
|
|
11
|
-
return any(entity.type == MessageEntityType.MENTION for entity in message.entities.unwrap())
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
__all__ = ("HasMention",)
|
|
1
|
+
from telegrinder.types.enums import MessageEntityType
|
|
2
|
+
|
|
3
|
+
from .message import Message, MessageRule
|
|
4
|
+
from .text import HasText
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class HasMention(MessageRule, requires=[HasText()]):
|
|
8
|
+
def check(self, message: Message) -> bool:
|
|
9
|
+
if not message.entities.unwrap_or_none():
|
|
10
|
+
return False
|
|
11
|
+
return any(entity.type == MessageEntityType.MENTION for entity in message.entities.unwrap())
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
__all__ = ("HasMention",)
|
telegrinder/bot/rules/message.py
CHANGED
|
@@ -1,17 +1,15 @@
|
|
|
1
|
-
import abc
|
|
2
|
-
import typing
|
|
3
|
-
|
|
4
|
-
from telegrinder.
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
from .
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
class MessageRule(ABCRule[Message], abc.ABC):
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
__all__ = ("MessageRule",)
|
|
1
|
+
import abc
|
|
2
|
+
import typing
|
|
3
|
+
|
|
4
|
+
from telegrinder.tools.adapter.event import EventAdapter
|
|
5
|
+
from telegrinder.types.objects import Message as MessageEvent
|
|
6
|
+
|
|
7
|
+
from .abc import ABCRule, CheckResult, Message
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class MessageRule(ABCRule[Message], abc.ABC, adapter=EventAdapter(MessageEvent, Message)):
|
|
11
|
+
@abc.abstractmethod
|
|
12
|
+
def check(self, *args: typing.Any, **kwargs: typing.Any) -> CheckResult: ...
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
__all__ = ("MessageRule",)
|
|
@@ -1,35 +1,33 @@
|
|
|
1
|
-
import
|
|
2
|
-
|
|
3
|
-
from telegrinder.
|
|
4
|
-
|
|
5
|
-
from
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
__all__ = ("HasEntities", "MessageEntities")
|
|
1
|
+
from telegrinder.bot.dispatch.context import Context
|
|
2
|
+
from telegrinder.types.enums import MessageEntityType
|
|
3
|
+
from telegrinder.types.objects import MessageEntity
|
|
4
|
+
|
|
5
|
+
from .message import Message, MessageRule
|
|
6
|
+
|
|
7
|
+
type Entity = str | MessageEntityType
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class HasEntities(MessageRule):
|
|
11
|
+
def check(self, message: Message) -> bool:
|
|
12
|
+
return bool(message.entities)
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class MessageEntities(MessageRule, requires=[HasEntities()]):
|
|
16
|
+
def __init__(self, entities: Entity | list[Entity], /) -> None:
|
|
17
|
+
self.entities = [entities] if not isinstance(entities, list) else entities
|
|
18
|
+
|
|
19
|
+
def check(self, message: Message, ctx: Context) -> bool:
|
|
20
|
+
message_entities: list[MessageEntity] = []
|
|
21
|
+
for entity in message.entities.unwrap():
|
|
22
|
+
for entity_type in self.entities:
|
|
23
|
+
if entity_type == entity.type:
|
|
24
|
+
message_entities.append(entity)
|
|
25
|
+
|
|
26
|
+
if not message_entities:
|
|
27
|
+
return False
|
|
28
|
+
|
|
29
|
+
ctx.message_entities = message_entities
|
|
30
|
+
return True
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
__all__ = ("HasEntities", "MessageEntities")
|
telegrinder/bot/rules/node.py
CHANGED
|
@@ -1,27 +1,33 @@
|
|
|
1
|
-
import typing
|
|
2
|
-
|
|
3
|
-
from telegrinder.bot.dispatch.context import Context
|
|
4
|
-
from telegrinder.node.base import
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
from .
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
class NodeRule(ABCRule
|
|
11
|
-
def __init__(self, *nodes:
|
|
12
|
-
|
|
13
|
-
self.
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
return
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
1
|
+
import typing
|
|
2
|
+
|
|
3
|
+
from telegrinder.bot.dispatch.context import Context
|
|
4
|
+
from telegrinder.node.base import IsNode, NodeType, is_node
|
|
5
|
+
from telegrinder.tools.adapter.node import NodeAdapter
|
|
6
|
+
|
|
7
|
+
from .abc import ABCRule
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class NodeRule(ABCRule):
|
|
11
|
+
def __init__(self, *nodes: IsNode | tuple[str, IsNode]) -> None:
|
|
12
|
+
self.nodes: list[IsNode] = []
|
|
13
|
+
self.node_keys: list[str | None] = []
|
|
14
|
+
|
|
15
|
+
for binding in nodes:
|
|
16
|
+
node_key, node_t = binding if isinstance(binding, tuple) else (None, binding)
|
|
17
|
+
if not is_node(node_t):
|
|
18
|
+
continue
|
|
19
|
+
self.nodes.append(node_t)
|
|
20
|
+
self.node_keys.append(node_key)
|
|
21
|
+
|
|
22
|
+
@property
|
|
23
|
+
def adapter(self) -> NodeAdapter:
|
|
24
|
+
return NodeAdapter(*self.nodes)
|
|
25
|
+
|
|
26
|
+
def check(self, resolved_nodes: tuple[NodeType, ...], ctx: Context) -> typing.Literal[True]:
|
|
27
|
+
for i, node in enumerate(resolved_nodes):
|
|
28
|
+
if key := self.node_keys[i]:
|
|
29
|
+
ctx[key] = node
|
|
30
|
+
return True
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
__all__ = ("NodeRule",)
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import typing
|
|
2
|
+
from contextlib import suppress
|
|
3
|
+
from functools import cached_property
|
|
4
|
+
|
|
5
|
+
import msgspec
|
|
6
|
+
|
|
7
|
+
from telegrinder.bot.dispatch.context import Context
|
|
8
|
+
from telegrinder.bot.rules.abc import ABCRule
|
|
9
|
+
from telegrinder.bot.rules.markup import Markup, PatternLike, check_string
|
|
10
|
+
from telegrinder.msgspec_json import loads
|
|
11
|
+
from telegrinder.node.base import Node
|
|
12
|
+
from telegrinder.node.payload import Payload, PayloadData
|
|
13
|
+
from telegrinder.tools.callback_data_serilization.abc import ABCDataSerializer, ModelType
|
|
14
|
+
from telegrinder.tools.callback_data_serilization.json_ser import JSONSerializer
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class PayloadRule[Data](ABCRule):
|
|
18
|
+
def __init__(
|
|
19
|
+
self,
|
|
20
|
+
data_type: type[Data],
|
|
21
|
+
serializer: type[ABCDataSerializer[Data]],
|
|
22
|
+
*,
|
|
23
|
+
alias: str | None = None,
|
|
24
|
+
) -> None:
|
|
25
|
+
self.data_type = data_type
|
|
26
|
+
self.serializer = serializer
|
|
27
|
+
self.alias = alias or "data"
|
|
28
|
+
|
|
29
|
+
@cached_property
|
|
30
|
+
def required_nodes(self) -> dict[str, type[Node]]:
|
|
31
|
+
return {"payload": PayloadData[self.data_type, self.serializer]} # type: ignore
|
|
32
|
+
|
|
33
|
+
def check(self, payload: PayloadData[Data], context: Context) -> typing.Literal[True]:
|
|
34
|
+
context.set(self.alias, payload)
|
|
35
|
+
return True
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
class PayloadModelRule[Model: ModelType](PayloadRule[Model]):
|
|
39
|
+
def __init__(
|
|
40
|
+
self,
|
|
41
|
+
model_t: type[Model],
|
|
42
|
+
*,
|
|
43
|
+
serializer: type[ABCDataSerializer[Model]] | None = None,
|
|
44
|
+
alias: str | None = None,
|
|
45
|
+
) -> None:
|
|
46
|
+
super().__init__(model_t, serializer or JSONSerializer, alias=alias or "model")
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
class PayloadEqRule(ABCRule):
|
|
50
|
+
def __init__(self, payloads: str | list[str], /) -> None:
|
|
51
|
+
self.payloads = [payloads] if isinstance(payloads, str) else payloads
|
|
52
|
+
|
|
53
|
+
def check(self, payload: Payload) -> bool:
|
|
54
|
+
return any(p == payload for p in self.payloads)
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
class PayloadMarkupRule(ABCRule):
|
|
58
|
+
def __init__(self, pattern: PatternLike | list[PatternLike], /) -> None:
|
|
59
|
+
self.patterns = Markup(pattern).patterns
|
|
60
|
+
|
|
61
|
+
def check(self, payload: Payload, context: Context) -> bool:
|
|
62
|
+
return check_string(self.patterns, payload, context)
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
class PayloadJsonEqRule(ABCRule):
|
|
66
|
+
def __init__(self, payload: dict[str, typing.Any], /) -> None:
|
|
67
|
+
self.payload = payload
|
|
68
|
+
|
|
69
|
+
def check(self, payload: Payload) -> bool:
|
|
70
|
+
with suppress(msgspec.DecodeError, msgspec.ValidationError):
|
|
71
|
+
return self.payload == loads(payload)
|
|
72
|
+
return False
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
__all__ = (
|
|
76
|
+
"PayloadEqRule",
|
|
77
|
+
"PayloadJsonEqRule",
|
|
78
|
+
"PayloadMarkupRule",
|
|
79
|
+
"PayloadModelRule",
|
|
80
|
+
"PayloadRule",
|
|
81
|
+
)
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import abc
|
|
2
|
+
import typing
|
|
3
|
+
|
|
4
|
+
from telegrinder.bot.cute_types.pre_checkout_query import PreCheckoutQueryCute
|
|
5
|
+
from telegrinder.bot.rules.abc import ABCRule, CheckResult
|
|
6
|
+
from telegrinder.tools.adapter.event import EventAdapter
|
|
7
|
+
from telegrinder.types.enums import Currency, UpdateType
|
|
8
|
+
|
|
9
|
+
PreCheckoutQuery: typing.TypeAlias = PreCheckoutQueryCute
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class PaymentInvoiceRule(
|
|
13
|
+
ABCRule[PreCheckoutQuery],
|
|
14
|
+
abc.ABC,
|
|
15
|
+
adapter=EventAdapter(UpdateType.PRE_CHECKOUT_QUERY, PreCheckoutQuery),
|
|
16
|
+
):
|
|
17
|
+
@abc.abstractmethod
|
|
18
|
+
def check(self, *args: typing.Any, **kwargs: typing.Any) -> CheckResult: ...
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
class PaymentInvoiceCurrency(PaymentInvoiceRule):
|
|
22
|
+
def __init__(self, currency: str | Currency, /) -> None:
|
|
23
|
+
self.currency = currency
|
|
24
|
+
|
|
25
|
+
def check(self, query: PreCheckoutQuery) -> bool:
|
|
26
|
+
return self.currency == query.currency
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
__all__ = ("PaymentInvoiceCurrency", "PaymentInvoiceRule")
|
telegrinder/bot/rules/regex.py
CHANGED
|
@@ -1,37 +1,36 @@
|
|
|
1
|
-
import re
|
|
2
|
-
import typing
|
|
3
|
-
|
|
4
|
-
from telegrinder.bot.dispatch.context import Context
|
|
5
|
-
from telegrinder.node.
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
response
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
__all__ = ("Regex",)
|
|
1
|
+
import re
|
|
2
|
+
import typing
|
|
3
|
+
|
|
4
|
+
from telegrinder.bot.dispatch.context import Context
|
|
5
|
+
from telegrinder.node.either import Either
|
|
6
|
+
from telegrinder.node.text import Caption, Text
|
|
7
|
+
|
|
8
|
+
from .abc import ABCRule
|
|
9
|
+
|
|
10
|
+
type PatternLike = str | typing.Pattern[str]
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class Regex(ABCRule):
|
|
14
|
+
def __init__(self, regexp: PatternLike | list[PatternLike]) -> None:
|
|
15
|
+
self.regexp: list[re.Pattern[str]] = []
|
|
16
|
+
match regexp:
|
|
17
|
+
case re.Pattern() as pattern:
|
|
18
|
+
self.regexp.append(pattern)
|
|
19
|
+
case str(regex):
|
|
20
|
+
self.regexp.append(re.compile(regex))
|
|
21
|
+
case _:
|
|
22
|
+
self.regexp.extend(re.compile(regexp) if isinstance(regexp, str) else regexp for regexp in regexp)
|
|
23
|
+
|
|
24
|
+
def check(self, text: Either[Text, Caption], ctx: Context) -> bool:
|
|
25
|
+
for regexp in self.regexp:
|
|
26
|
+
response = re.match(regexp, text)
|
|
27
|
+
if response is not None:
|
|
28
|
+
if matches := response.groupdict():
|
|
29
|
+
ctx |= matches
|
|
30
|
+
else:
|
|
31
|
+
ctx |= {"matches": response.groups() or (response.group(),)}
|
|
32
|
+
return True
|
|
33
|
+
return False
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
__all__ = ("Regex",)
|
|
@@ -1,72 +1,72 @@
|
|
|
1
|
-
import dataclasses
|
|
2
|
-
import typing
|
|
3
|
-
|
|
4
|
-
from telegrinder.bot.dispatch.context import Context
|
|
5
|
-
|
|
6
|
-
from .abc import ABCRule, Update, check_rule
|
|
7
|
-
from .func import FuncRule
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
@dataclasses.dataclass(slots=True)
|
|
11
|
-
class RuleEnumState:
|
|
12
|
-
name: str
|
|
13
|
-
rule: ABCRule
|
|
14
|
-
cls: type["RuleEnum"]
|
|
15
|
-
|
|
16
|
-
def __eq__(self, other: typing.Self) -> bool:
|
|
17
|
-
return self.cls == other.cls and self.name == other.name
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
class RuleEnum(ABCRule):
|
|
21
|
-
__enum__: list[RuleEnumState]
|
|
22
|
-
|
|
23
|
-
def __init_subclass__(cls, *args: typing.Any, **kwargs: typing.Any) -> None:
|
|
24
|
-
new_attributes = set(cls.__dict__) - set(RuleEnum.__dict__) - {"__enum__", "__init__"}
|
|
25
|
-
enum_lst: list[RuleEnumState] = []
|
|
26
|
-
|
|
27
|
-
self = cls.__new__(cls)
|
|
28
|
-
self.__init__()
|
|
29
|
-
|
|
30
|
-
for attribute_name in new_attributes:
|
|
31
|
-
rules = getattr(cls, attribute_name)
|
|
32
|
-
attribute = RuleEnumState(attribute_name, rules, cls)
|
|
33
|
-
|
|
34
|
-
setattr(
|
|
35
|
-
self,
|
|
36
|
-
attribute.name,
|
|
37
|
-
self & FuncRule(lambda _, ctx: self.must_be_state(ctx, attribute)), # type: ignore
|
|
38
|
-
)
|
|
39
|
-
enum_lst.append(attribute)
|
|
40
|
-
|
|
41
|
-
setattr(cls, "__enum__", enum_lst)
|
|
42
|
-
|
|
43
|
-
@classmethod
|
|
44
|
-
def save_state(cls, ctx: Context, enum: RuleEnumState) -> None:
|
|
45
|
-
ctx.update({cls.__class__.__name__ + "_state": enum})
|
|
46
|
-
|
|
47
|
-
@classmethod
|
|
48
|
-
def check_state(cls, ctx: Context) -> RuleEnumState | None:
|
|
49
|
-
return ctx.get(cls.__class__.__name__ + "_state")
|
|
50
|
-
|
|
51
|
-
@classmethod
|
|
52
|
-
def must_be_state(cls, ctx: Context, state: RuleEnumState) -> bool:
|
|
53
|
-
real_state = cls.check_state(ctx)
|
|
54
|
-
if not real_state:
|
|
55
|
-
return False
|
|
56
|
-
return real_state == state
|
|
57
|
-
|
|
58
|
-
async def check(self, event: Update, ctx: Context) -> bool:
|
|
59
|
-
if self.check_state(ctx):
|
|
60
|
-
return True
|
|
61
|
-
|
|
62
|
-
for enum in self.__enum__:
|
|
63
|
-
ctx_copy = ctx.copy()
|
|
64
|
-
if await check_rule(event.ctx_api, enum.rule, event, ctx_copy):
|
|
65
|
-
ctx.update(ctx_copy)
|
|
66
|
-
self.save_state(ctx, enum)
|
|
67
|
-
return True
|
|
68
|
-
|
|
69
|
-
return False
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
__all__ = ("RuleEnum", "RuleEnumState")
|
|
1
|
+
import dataclasses
|
|
2
|
+
import typing
|
|
3
|
+
|
|
4
|
+
from telegrinder.bot.dispatch.context import Context
|
|
5
|
+
|
|
6
|
+
from .abc import ABCRule, Update, check_rule
|
|
7
|
+
from .func import FuncRule
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
@dataclasses.dataclass(slots=True)
|
|
11
|
+
class RuleEnumState:
|
|
12
|
+
name: str
|
|
13
|
+
rule: ABCRule
|
|
14
|
+
cls: type["RuleEnum"]
|
|
15
|
+
|
|
16
|
+
def __eq__(self, other: typing.Self) -> bool:
|
|
17
|
+
return self.cls == other.cls and self.name == other.name
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
class RuleEnum(ABCRule):
|
|
21
|
+
__enum__: list[RuleEnumState]
|
|
22
|
+
|
|
23
|
+
def __init_subclass__(cls, *args: typing.Any, **kwargs: typing.Any) -> None:
|
|
24
|
+
new_attributes = set(cls.__dict__) - set(RuleEnum.__dict__) - {"__enum__", "__init__"}
|
|
25
|
+
enum_lst: list[RuleEnumState] = []
|
|
26
|
+
|
|
27
|
+
self = cls.__new__(cls)
|
|
28
|
+
self.__init__()
|
|
29
|
+
|
|
30
|
+
for attribute_name in new_attributes:
|
|
31
|
+
rules = getattr(cls, attribute_name)
|
|
32
|
+
attribute = RuleEnumState(attribute_name, rules, cls)
|
|
33
|
+
|
|
34
|
+
setattr(
|
|
35
|
+
self,
|
|
36
|
+
attribute.name,
|
|
37
|
+
self & FuncRule(lambda _, ctx: self.must_be_state(ctx, attribute)), # type: ignore
|
|
38
|
+
)
|
|
39
|
+
enum_lst.append(attribute)
|
|
40
|
+
|
|
41
|
+
setattr(cls, "__enum__", enum_lst)
|
|
42
|
+
|
|
43
|
+
@classmethod
|
|
44
|
+
def save_state(cls, ctx: Context, enum: RuleEnumState) -> None:
|
|
45
|
+
ctx.update({cls.__class__.__name__ + "_state": enum})
|
|
46
|
+
|
|
47
|
+
@classmethod
|
|
48
|
+
def check_state(cls, ctx: Context) -> RuleEnumState | None:
|
|
49
|
+
return ctx.get(cls.__class__.__name__ + "_state")
|
|
50
|
+
|
|
51
|
+
@classmethod
|
|
52
|
+
def must_be_state(cls, ctx: Context, state: RuleEnumState) -> bool:
|
|
53
|
+
real_state = cls.check_state(ctx)
|
|
54
|
+
if not real_state:
|
|
55
|
+
return False
|
|
56
|
+
return real_state == state
|
|
57
|
+
|
|
58
|
+
async def check(self, event: Update, ctx: Context) -> bool:
|
|
59
|
+
if self.check_state(ctx):
|
|
60
|
+
return True
|
|
61
|
+
|
|
62
|
+
for enum in self.__enum__:
|
|
63
|
+
ctx_copy = ctx.copy()
|
|
64
|
+
if await check_rule(event.ctx_api, enum.rule, event, ctx_copy):
|
|
65
|
+
ctx.update(ctx_copy)
|
|
66
|
+
self.save_state(ctx, enum)
|
|
67
|
+
return True
|
|
68
|
+
|
|
69
|
+
return False
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
__all__ = ("RuleEnum", "RuleEnumState")
|