telegrinder 0.3.1__py3-none-any.whl → 0.3.3__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 +17 -17
- telegrinder/bot/cute_types/base.py +258 -234
- telegrinder/bot/cute_types/callback_query.py +385 -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 +43 -53
- telegrinder/bot/cute_types/message.py +2637 -2631
- telegrinder/bot/cute_types/update.py +109 -75
- telegrinder/bot/cute_types/utils.py +95 -95
- telegrinder/bot/dispatch/__init__.py +55 -55
- telegrinder/bot/dispatch/abc.py +77 -77
- telegrinder/bot/dispatch/context.py +98 -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 +135 -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 +55 -55
- telegrinder/bot/dispatch/waiter_machine/hasher/hasher.py +57 -57
- telegrinder/bot/dispatch/waiter_machine/hasher/message.py +51 -51
- telegrinder/bot/dispatch/waiter_machine/hasher/state.py +19 -19
- telegrinder/bot/dispatch/waiter_machine/machine.py +167 -170
- telegrinder/bot/dispatch/waiter_machine/middleware.py +89 -89
- telegrinder/bot/dispatch/waiter_machine/short_state.py +68 -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 +213 -238
- 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 +67 -76
- telegrinder/bot/rules/adapter/node.py +48 -48
- telegrinder/bot/rules/adapter/raw_update.py +30 -30
- telegrinder/bot/rules/callback_data.py +170 -171
- telegrinder/bot/rules/chat_join.py +46 -48
- telegrinder/bot/rules/command.py +126 -126
- telegrinder/bot/rules/enum_text.py +36 -36
- 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 +127 -127
- 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 -147
- 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 +295 -244
- telegrinder/modules.py +237 -237
- telegrinder/msgspec_json.py +14 -14
- telegrinder/msgspec_utils.py +410 -410
- telegrinder/node/__init__.py +7 -3
- telegrinder/node/attachment.py +87 -87
- telegrinder/node/base.py +166 -144
- telegrinder/node/callback_query.py +53 -14
- telegrinder/node/command.py +33 -33
- telegrinder/node/composer.py +198 -184
- telegrinder/node/container.py +27 -27
- telegrinder/node/event.py +65 -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 +41 -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 +283 -283
- 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 +7 -7
- telegrinder/tools/i18n/abc.py +30 -30
- 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 +132 -132
- 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 +224 -216
- telegrinder/tools/magic.py +157 -157
- 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 +260 -260
- telegrinder/types/enums.py +701 -701
- telegrinder/types/methods.py +4633 -4633
- telegrinder/types/objects.py +8561 -6541
- telegrinder/verification_utils.py +32 -32
- {telegrinder-0.3.1.dist-info → telegrinder-0.3.3.dist-info}/LICENSE +22 -22
- {telegrinder-0.3.1.dist-info → telegrinder-0.3.3.dist-info}/METADATA +1 -1
- telegrinder-0.3.3.dist-info/RECORD +164 -0
- telegrinder-0.3.1.dist-info/RECORD +0 -164
- {telegrinder-0.3.1.dist-info → telegrinder-0.3.3.dist-info}/WHEEL +0 -0
|
@@ -1,48 +1,46 @@
|
|
|
1
|
-
import abc
|
|
2
|
-
import typing
|
|
3
|
-
|
|
4
|
-
from telegrinder.bot.cute_types import ChatJoinRequestCute
|
|
5
|
-
from telegrinder.bot.
|
|
6
|
-
from telegrinder.
|
|
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
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
"
|
|
45
|
-
"
|
|
46
|
-
|
|
47
|
-
"InviteLinkName",
|
|
48
|
-
)
|
|
1
|
+
import abc
|
|
2
|
+
import typing
|
|
3
|
+
|
|
4
|
+
from telegrinder.bot.cute_types import ChatJoinRequestCute
|
|
5
|
+
from telegrinder.bot.rules.adapter import EventAdapter
|
|
6
|
+
from telegrinder.types.enums import UpdateType
|
|
7
|
+
|
|
8
|
+
from .abc import ABCRule, CheckResult
|
|
9
|
+
|
|
10
|
+
ChatJoinRequest: typing.TypeAlias = ChatJoinRequestCute
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class ChatJoinRequestRule(ABCRule[ChatJoinRequest], requires=[]):
|
|
14
|
+
adapter: EventAdapter[ChatJoinRequest] = EventAdapter(UpdateType.CHAT_JOIN_REQUEST, ChatJoinRequest)
|
|
15
|
+
|
|
16
|
+
@abc.abstractmethod
|
|
17
|
+
def check(self, *args: typing.Any, **kwargs: typing.Any) -> CheckResult: ...
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
class HasInviteLink(ChatJoinRequestRule):
|
|
21
|
+
def check(self, event: ChatJoinRequest) -> bool:
|
|
22
|
+
return bool(event.invite_link)
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
class InviteLinkName(ChatJoinRequestRule, requires=[HasInviteLink()]):
|
|
26
|
+
def __init__(self, name: str, /) -> None:
|
|
27
|
+
self.name = name
|
|
28
|
+
|
|
29
|
+
def check(self, event: ChatJoinRequest) -> bool:
|
|
30
|
+
return event.invite_link.unwrap().name.unwrap_or_none() == self.name
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
class InviteLinkByCreator(ChatJoinRequestRule, requires=[HasInviteLink()]):
|
|
34
|
+
def __init__(self, creator_id: int, /) -> None:
|
|
35
|
+
self.creator_id = creator_id
|
|
36
|
+
|
|
37
|
+
def check(self, event: ChatJoinRequest) -> bool:
|
|
38
|
+
return event.invite_link.unwrap().creator.id == self.creator_id
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
__all__ = (
|
|
42
|
+
"ChatJoinRequestRule",
|
|
43
|
+
"HasInviteLink",
|
|
44
|
+
"InviteLinkByCreator",
|
|
45
|
+
"InviteLinkName",
|
|
46
|
+
)
|
telegrinder/bot/rules/command.py
CHANGED
|
@@ -1,126 +1,126 @@
|
|
|
1
|
-
import dataclasses
|
|
2
|
-
import typing
|
|
3
|
-
|
|
4
|
-
from telegrinder.bot.dispatch.context import Context
|
|
5
|
-
from telegrinder.node.command import CommandInfo, single_split
|
|
6
|
-
from telegrinder.node.me import Me
|
|
7
|
-
from telegrinder.node.source import Source
|
|
8
|
-
from telegrinder.types.enums import ChatType
|
|
9
|
-
|
|
10
|
-
from .abc import ABCRule
|
|
11
|
-
|
|
12
|
-
Validator: typing.TypeAlias = typing.Callable[[str], typing.Any | None]
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
@dataclasses.dataclass(frozen=True, slots=True)
|
|
16
|
-
class Argument:
|
|
17
|
-
name: str
|
|
18
|
-
validators: list[Validator] = dataclasses.field(default_factory=lambda: [])
|
|
19
|
-
optional: bool = dataclasses.field(default=False, kw_only=True)
|
|
20
|
-
|
|
21
|
-
def check(self, data: str) -> typing.Any | None:
|
|
22
|
-
for validator in self.validators:
|
|
23
|
-
data = validator(data) # type: ignore
|
|
24
|
-
if data is None:
|
|
25
|
-
return None
|
|
26
|
-
return data
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
class Command(ABCRule):
|
|
30
|
-
def __init__(
|
|
31
|
-
self,
|
|
32
|
-
names: str | typing.Iterable[str],
|
|
33
|
-
*arguments: Argument,
|
|
34
|
-
prefixes: tuple[str, ...] = ("/",),
|
|
35
|
-
separator: str = " ",
|
|
36
|
-
lazy: bool = False,
|
|
37
|
-
validate_mention: bool = True,
|
|
38
|
-
mention_needed_in_chat: bool = False,
|
|
39
|
-
) -> None:
|
|
40
|
-
self.names = [names] if isinstance(names, str) else names
|
|
41
|
-
self.arguments = arguments
|
|
42
|
-
self.prefixes = prefixes
|
|
43
|
-
self.separator = separator
|
|
44
|
-
self.lazy = lazy
|
|
45
|
-
self.validate_mention = validate_mention
|
|
46
|
-
|
|
47
|
-
# if true then we'll check for mention when message is from a group
|
|
48
|
-
self.mention_needed_in_chat = mention_needed_in_chat
|
|
49
|
-
|
|
50
|
-
def remove_prefix(self, text: str) -> str | None:
|
|
51
|
-
for prefix in self.prefixes:
|
|
52
|
-
if text.startswith(prefix):
|
|
53
|
-
return text.removeprefix(prefix)
|
|
54
|
-
return None
|
|
55
|
-
|
|
56
|
-
def parse_argument(
|
|
57
|
-
self,
|
|
58
|
-
arguments: list[Argument],
|
|
59
|
-
data_s: str,
|
|
60
|
-
new_s: str,
|
|
61
|
-
s: str,
|
|
62
|
-
) -> dict | None:
|
|
63
|
-
argument = arguments[0]
|
|
64
|
-
data = argument.check(data_s)
|
|
65
|
-
if data is None and not argument.optional:
|
|
66
|
-
return None
|
|
67
|
-
|
|
68
|
-
if data is None:
|
|
69
|
-
return self.parse_arguments(arguments[1:], s)
|
|
70
|
-
|
|
71
|
-
with_argument = self.parse_arguments(arguments[1:], new_s)
|
|
72
|
-
if with_argument is not None:
|
|
73
|
-
return {argument.name: data, **with_argument}
|
|
74
|
-
|
|
75
|
-
if not argument.optional:
|
|
76
|
-
return None
|
|
77
|
-
|
|
78
|
-
return self.parse_arguments(arguments[1:], s)
|
|
79
|
-
|
|
80
|
-
def parse_arguments(self, arguments: list[Argument], s: str) -> dict[str, typing.Any] | None:
|
|
81
|
-
if not arguments:
|
|
82
|
-
return {} if not s else None
|
|
83
|
-
|
|
84
|
-
if self.lazy:
|
|
85
|
-
return self.parse_argument(arguments, *single_split(s, self.separator), s)
|
|
86
|
-
|
|
87
|
-
all_split = s.split(self.separator)
|
|
88
|
-
for i in range(1, len(all_split) + 1):
|
|
89
|
-
ctx = self.parse_argument(
|
|
90
|
-
arguments,
|
|
91
|
-
self.separator.join(all_split[:i]),
|
|
92
|
-
self.separator.join(all_split[i:]),
|
|
93
|
-
s,
|
|
94
|
-
)
|
|
95
|
-
if ctx is not None:
|
|
96
|
-
return ctx
|
|
97
|
-
|
|
98
|
-
return None
|
|
99
|
-
|
|
100
|
-
def check(self, command: CommandInfo, me: Me, src: Source, ctx: Context) -> bool:
|
|
101
|
-
name = self.remove_prefix(command.name)
|
|
102
|
-
if name is None:
|
|
103
|
-
return False
|
|
104
|
-
|
|
105
|
-
if name not in self.names:
|
|
106
|
-
return False
|
|
107
|
-
|
|
108
|
-
if not command.mention and self.mention_needed_in_chat and src.chat.type is not ChatType.PRIVATE:
|
|
109
|
-
return False
|
|
110
|
-
|
|
111
|
-
if command.mention and self.validate_mention: # noqa
|
|
112
|
-
if command.mention.unwrap().lower() != me.username.unwrap().lower():
|
|
113
|
-
return False
|
|
114
|
-
|
|
115
|
-
if not self.arguments:
|
|
116
|
-
return not command.arguments
|
|
117
|
-
|
|
118
|
-
result = self.parse_arguments(list(self.arguments), command.arguments)
|
|
119
|
-
if result is None:
|
|
120
|
-
return False
|
|
121
|
-
|
|
122
|
-
ctx.update(result)
|
|
123
|
-
return True
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
__all__ = ("Argument", "Command", "single_split")
|
|
1
|
+
import dataclasses
|
|
2
|
+
import typing
|
|
3
|
+
|
|
4
|
+
from telegrinder.bot.dispatch.context import Context
|
|
5
|
+
from telegrinder.node.command import CommandInfo, single_split
|
|
6
|
+
from telegrinder.node.me import Me
|
|
7
|
+
from telegrinder.node.source import Source
|
|
8
|
+
from telegrinder.types.enums import ChatType
|
|
9
|
+
|
|
10
|
+
from .abc import ABCRule
|
|
11
|
+
|
|
12
|
+
Validator: typing.TypeAlias = typing.Callable[[str], typing.Any | None]
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
@dataclasses.dataclass(frozen=True, slots=True)
|
|
16
|
+
class Argument:
|
|
17
|
+
name: str
|
|
18
|
+
validators: list[Validator] = dataclasses.field(default_factory=lambda: [])
|
|
19
|
+
optional: bool = dataclasses.field(default=False, kw_only=True)
|
|
20
|
+
|
|
21
|
+
def check(self, data: str) -> typing.Any | None:
|
|
22
|
+
for validator in self.validators:
|
|
23
|
+
data = validator(data) # type: ignore
|
|
24
|
+
if data is None:
|
|
25
|
+
return None
|
|
26
|
+
return data
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
class Command(ABCRule):
|
|
30
|
+
def __init__(
|
|
31
|
+
self,
|
|
32
|
+
names: str | typing.Iterable[str],
|
|
33
|
+
*arguments: Argument,
|
|
34
|
+
prefixes: tuple[str, ...] = ("/",),
|
|
35
|
+
separator: str = " ",
|
|
36
|
+
lazy: bool = False,
|
|
37
|
+
validate_mention: bool = True,
|
|
38
|
+
mention_needed_in_chat: bool = False,
|
|
39
|
+
) -> None:
|
|
40
|
+
self.names = [names] if isinstance(names, str) else names
|
|
41
|
+
self.arguments = arguments
|
|
42
|
+
self.prefixes = prefixes
|
|
43
|
+
self.separator = separator
|
|
44
|
+
self.lazy = lazy
|
|
45
|
+
self.validate_mention = validate_mention
|
|
46
|
+
|
|
47
|
+
# if true then we'll check for mention when message is from a group
|
|
48
|
+
self.mention_needed_in_chat = mention_needed_in_chat
|
|
49
|
+
|
|
50
|
+
def remove_prefix(self, text: str) -> str | None:
|
|
51
|
+
for prefix in self.prefixes:
|
|
52
|
+
if text.startswith(prefix):
|
|
53
|
+
return text.removeprefix(prefix)
|
|
54
|
+
return None
|
|
55
|
+
|
|
56
|
+
def parse_argument(
|
|
57
|
+
self,
|
|
58
|
+
arguments: list[Argument],
|
|
59
|
+
data_s: str,
|
|
60
|
+
new_s: str,
|
|
61
|
+
s: str,
|
|
62
|
+
) -> dict | None:
|
|
63
|
+
argument = arguments[0]
|
|
64
|
+
data = argument.check(data_s)
|
|
65
|
+
if data is None and not argument.optional:
|
|
66
|
+
return None
|
|
67
|
+
|
|
68
|
+
if data is None:
|
|
69
|
+
return self.parse_arguments(arguments[1:], s)
|
|
70
|
+
|
|
71
|
+
with_argument = self.parse_arguments(arguments[1:], new_s)
|
|
72
|
+
if with_argument is not None:
|
|
73
|
+
return {argument.name: data, **with_argument}
|
|
74
|
+
|
|
75
|
+
if not argument.optional:
|
|
76
|
+
return None
|
|
77
|
+
|
|
78
|
+
return self.parse_arguments(arguments[1:], s)
|
|
79
|
+
|
|
80
|
+
def parse_arguments(self, arguments: list[Argument], s: str) -> dict[str, typing.Any] | None:
|
|
81
|
+
if not arguments:
|
|
82
|
+
return {} if not s else None
|
|
83
|
+
|
|
84
|
+
if self.lazy:
|
|
85
|
+
return self.parse_argument(arguments, *single_split(s, self.separator), s)
|
|
86
|
+
|
|
87
|
+
all_split = s.split(self.separator)
|
|
88
|
+
for i in range(1, len(all_split) + 1):
|
|
89
|
+
ctx = self.parse_argument(
|
|
90
|
+
arguments,
|
|
91
|
+
self.separator.join(all_split[:i]),
|
|
92
|
+
self.separator.join(all_split[i:]),
|
|
93
|
+
s,
|
|
94
|
+
)
|
|
95
|
+
if ctx is not None:
|
|
96
|
+
return ctx
|
|
97
|
+
|
|
98
|
+
return None
|
|
99
|
+
|
|
100
|
+
def check(self, command: CommandInfo, me: Me, src: Source, ctx: Context) -> bool:
|
|
101
|
+
name = self.remove_prefix(command.name)
|
|
102
|
+
if name is None:
|
|
103
|
+
return False
|
|
104
|
+
|
|
105
|
+
if name not in self.names:
|
|
106
|
+
return False
|
|
107
|
+
|
|
108
|
+
if not command.mention and self.mention_needed_in_chat and src.chat.type is not ChatType.PRIVATE:
|
|
109
|
+
return False
|
|
110
|
+
|
|
111
|
+
if command.mention and self.validate_mention: # noqa
|
|
112
|
+
if command.mention.unwrap().lower() != me.username.unwrap().lower():
|
|
113
|
+
return False
|
|
114
|
+
|
|
115
|
+
if not self.arguments:
|
|
116
|
+
return not command.arguments
|
|
117
|
+
|
|
118
|
+
result = self.parse_arguments(list(self.arguments), command.arguments)
|
|
119
|
+
if result is None:
|
|
120
|
+
return False
|
|
121
|
+
|
|
122
|
+
ctx.update(result)
|
|
123
|
+
return True
|
|
124
|
+
|
|
125
|
+
|
|
126
|
+
__all__ = ("Argument", "Command", "single_split")
|
|
@@ -1,36 +1,36 @@
|
|
|
1
|
-
import enum
|
|
2
|
-
import typing
|
|
3
|
-
|
|
4
|
-
from telegrinder.bot.dispatch.context import Context
|
|
5
|
-
from telegrinder.node.text import Text
|
|
6
|
-
|
|
7
|
-
from .abc import ABCRule
|
|
8
|
-
|
|
9
|
-
T = typing.TypeVar("T", bound=enum.Enum)
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
class EnumTextRule(ABCRule, typing.Generic[T]):
|
|
13
|
-
def __init__(self, enum_t: type[T], *, lower_case: bool = True) -> None:
|
|
14
|
-
self.enum_t = enum_t
|
|
15
|
-
self.texts = list(
|
|
16
|
-
map(
|
|
17
|
-
lambda x: x.value.lower() if lower_case else x.value,
|
|
18
|
-
self.enum_t,
|
|
19
|
-
)
|
|
20
|
-
)
|
|
21
|
-
|
|
22
|
-
def find(self, s: str) -> T:
|
|
23
|
-
for enumeration in self.enum_t:
|
|
24
|
-
if enumeration.value.lower() == s:
|
|
25
|
-
return enumeration
|
|
26
|
-
raise KeyError("Enumeration is undefined.")
|
|
27
|
-
|
|
28
|
-
def check(self, text: Text, ctx: Context) -> bool:
|
|
29
|
-
text = text.lower() # type: ignore
|
|
30
|
-
if text not in self.texts:
|
|
31
|
-
return False
|
|
32
|
-
ctx.enum_text = self.find(text)
|
|
33
|
-
return True
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
__all__ = ("EnumTextRule",)
|
|
1
|
+
import enum
|
|
2
|
+
import typing
|
|
3
|
+
|
|
4
|
+
from telegrinder.bot.dispatch.context import Context
|
|
5
|
+
from telegrinder.node.text import Text
|
|
6
|
+
|
|
7
|
+
from .abc import ABCRule
|
|
8
|
+
|
|
9
|
+
T = typing.TypeVar("T", bound=enum.Enum)
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class EnumTextRule(ABCRule, typing.Generic[T]):
|
|
13
|
+
def __init__(self, enum_t: type[T], *, lower_case: bool = True) -> None:
|
|
14
|
+
self.enum_t = enum_t
|
|
15
|
+
self.texts = list(
|
|
16
|
+
map(
|
|
17
|
+
lambda x: x.value.lower() if lower_case else x.value,
|
|
18
|
+
self.enum_t,
|
|
19
|
+
)
|
|
20
|
+
)
|
|
21
|
+
|
|
22
|
+
def find(self, s: str) -> T:
|
|
23
|
+
for enumeration in self.enum_t:
|
|
24
|
+
if enumeration.value.lower() == s:
|
|
25
|
+
return enumeration
|
|
26
|
+
raise KeyError("Enumeration is undefined.")
|
|
27
|
+
|
|
28
|
+
def check(self, text: Text, ctx: Context) -> bool:
|
|
29
|
+
text = text.lower() # type: ignore
|
|
30
|
+
if text not in self.texts:
|
|
31
|
+
return False
|
|
32
|
+
ctx.enum_text = self.find(text)
|
|
33
|
+
return True
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
__all__ = ("EnumTextRule",)
|
telegrinder/bot/rules/func.py
CHANGED
|
@@ -1,26 +1,26 @@
|
|
|
1
|
-
import inspect
|
|
2
|
-
import typing
|
|
3
|
-
|
|
4
|
-
from telegrinder.bot.dispatch.context import Context
|
|
5
|
-
from telegrinder.types.objects import Update
|
|
6
|
-
|
|
7
|
-
from .abc import ABCAdapter, ABCRule, AdaptTo, RawUpdateAdapter
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
class FuncRule(ABCRule, typing.Generic[AdaptTo]):
|
|
11
|
-
def __init__(
|
|
12
|
-
self,
|
|
13
|
-
func: typing.Callable[[AdaptTo, Context], typing.Awaitable[bool] | bool],
|
|
14
|
-
adapter: ABCAdapter[Update, AdaptTo] | None = None,
|
|
15
|
-
) -> None:
|
|
16
|
-
self.func = func
|
|
17
|
-
self.adapter = adapter or RawUpdateAdapter() # type: ignore
|
|
18
|
-
|
|
19
|
-
async def check(self, event: AdaptTo, ctx: Context) -> bool:
|
|
20
|
-
result = self.func(event, ctx)
|
|
21
|
-
if inspect.isawaitable(result):
|
|
22
|
-
return await result
|
|
23
|
-
return result # type: ignore
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
__all__ = ("FuncRule",)
|
|
1
|
+
import inspect
|
|
2
|
+
import typing
|
|
3
|
+
|
|
4
|
+
from telegrinder.bot.dispatch.context import Context
|
|
5
|
+
from telegrinder.types.objects import Update
|
|
6
|
+
|
|
7
|
+
from .abc import ABCAdapter, ABCRule, AdaptTo, RawUpdateAdapter
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class FuncRule(ABCRule, typing.Generic[AdaptTo]):
|
|
11
|
+
def __init__(
|
|
12
|
+
self,
|
|
13
|
+
func: typing.Callable[[AdaptTo, Context], typing.Awaitable[bool] | bool],
|
|
14
|
+
adapter: ABCAdapter[Update, AdaptTo] | None = None,
|
|
15
|
+
) -> None:
|
|
16
|
+
self.func = func
|
|
17
|
+
self.adapter = adapter or RawUpdateAdapter() # type: ignore
|
|
18
|
+
|
|
19
|
+
async def check(self, event: AdaptTo, ctx: Context) -> bool:
|
|
20
|
+
result = self.func(event, ctx)
|
|
21
|
+
if inspect.isawaitable(result):
|
|
22
|
+
return await result
|
|
23
|
+
return result # type: ignore
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
__all__ = ("FuncRule",)
|
telegrinder/bot/rules/fuzzy.py
CHANGED
|
@@ -1,24 +1,24 @@
|
|
|
1
|
-
import difflib
|
|
2
|
-
|
|
3
|
-
from telegrinder.bot.dispatch.context import Context
|
|
4
|
-
from telegrinder.node.text import Text
|
|
5
|
-
|
|
6
|
-
from .abc import ABCRule
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
class FuzzyText(ABCRule):
|
|
10
|
-
def __init__(self, texts: str | list[str], min_ratio: float = 0.7) -> None:
|
|
11
|
-
if isinstance(texts, str):
|
|
12
|
-
texts = [texts]
|
|
13
|
-
self.texts = texts
|
|
14
|
-
self.min_ratio = min_ratio
|
|
15
|
-
|
|
16
|
-
def check(self, message_text: Text, ctx: Context) -> bool:
|
|
17
|
-
match = max(difflib.SequenceMatcher(a=message_text, b=text).ratio() for text in self.texts)
|
|
18
|
-
if match < self.min_ratio:
|
|
19
|
-
return False
|
|
20
|
-
ctx.fuzzy_ratio = match
|
|
21
|
-
return True
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
__all__ = ("FuzzyText",)
|
|
1
|
+
import difflib
|
|
2
|
+
|
|
3
|
+
from telegrinder.bot.dispatch.context import Context
|
|
4
|
+
from telegrinder.node.text import Text
|
|
5
|
+
|
|
6
|
+
from .abc import ABCRule
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class FuzzyText(ABCRule):
|
|
10
|
+
def __init__(self, texts: str | list[str], min_ratio: float = 0.7) -> None:
|
|
11
|
+
if isinstance(texts, str):
|
|
12
|
+
texts = [texts]
|
|
13
|
+
self.texts = texts
|
|
14
|
+
self.min_ratio = min_ratio
|
|
15
|
+
|
|
16
|
+
def check(self, message_text: Text, ctx: Context) -> bool:
|
|
17
|
+
match = max(difflib.SequenceMatcher(a=message_text, b=text).ratio() for text in self.texts)
|
|
18
|
+
if match < self.min_ratio:
|
|
19
|
+
return False
|
|
20
|
+
ctx.fuzzy_ratio = match
|
|
21
|
+
return True
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
__all__ = ("FuzzyText",)
|
telegrinder/bot/rules/inline.py
CHANGED
|
@@ -1,60 +1,60 @@
|
|
|
1
|
-
import abc
|
|
2
|
-
import typing
|
|
3
|
-
|
|
4
|
-
from telegrinder.bot.cute_types import InlineQueryCute
|
|
5
|
-
from telegrinder.bot.dispatch.context import Context
|
|
6
|
-
from telegrinder.bot.rules.abc import ABCRule, CheckResult
|
|
7
|
-
from telegrinder.bot.rules.adapter import EventAdapter
|
|
8
|
-
from telegrinder.types.enums import ChatType, UpdateType
|
|
9
|
-
|
|
10
|
-
from .markup import Markup, PatternLike, check_string
|
|
11
|
-
|
|
12
|
-
InlineQuery: typing.TypeAlias = InlineQueryCute
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
class InlineQueryRule(ABCRule[InlineQuery], abc.ABC):
|
|
16
|
-
adapter: EventAdapter[InlineQuery] = EventAdapter(UpdateType.INLINE_QUERY, InlineQuery)
|
|
17
|
-
|
|
18
|
-
@abc.abstractmethod
|
|
19
|
-
def check(self,
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
class HasLocation(InlineQueryRule):
|
|
23
|
-
def check(self, query: InlineQuery) -> bool:
|
|
24
|
-
return bool(query.location)
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
class InlineQueryChatType(InlineQueryRule):
|
|
28
|
-
def __init__(self, chat_type: ChatType, /) -> None:
|
|
29
|
-
self.chat_type = chat_type
|
|
30
|
-
|
|
31
|
-
def check(self, query: InlineQuery) -> bool:
|
|
32
|
-
return query.chat_type.map(lambda x: x == self.chat_type).unwrap_or(False)
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
class InlineQueryText(InlineQueryRule):
|
|
36
|
-
def __init__(self, texts: str | list[str], *, lower_case: bool = False) -> None:
|
|
37
|
-
self.texts = [
|
|
38
|
-
text.lower() if lower_case else text for text in ([texts] if isinstance(texts, str) else texts)
|
|
39
|
-
]
|
|
40
|
-
self.lower_case = lower_case
|
|
41
|
-
|
|
42
|
-
def check(self, query: InlineQuery) -> bool:
|
|
43
|
-
return (query.query.lower() if self.lower_case else query.query) in self.texts
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
class InlineQueryMarkup(InlineQueryRule):
|
|
47
|
-
def __init__(self, patterns: PatternLike | list[PatternLike], /) -> None:
|
|
48
|
-
self.patterns = Markup(patterns).patterns
|
|
49
|
-
|
|
50
|
-
def check(self, query: InlineQuery, ctx: Context) -> bool:
|
|
51
|
-
return check_string(self.patterns, query.query, ctx)
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
__all__ = (
|
|
55
|
-
"HasLocation",
|
|
56
|
-
"InlineQueryChatType",
|
|
57
|
-
"InlineQueryMarkup",
|
|
58
|
-
"InlineQueryRule",
|
|
59
|
-
"InlineQueryText",
|
|
60
|
-
)
|
|
1
|
+
import abc
|
|
2
|
+
import typing
|
|
3
|
+
|
|
4
|
+
from telegrinder.bot.cute_types import InlineQueryCute
|
|
5
|
+
from telegrinder.bot.dispatch.context import Context
|
|
6
|
+
from telegrinder.bot.rules.abc import ABCRule, CheckResult
|
|
7
|
+
from telegrinder.bot.rules.adapter import EventAdapter
|
|
8
|
+
from telegrinder.types.enums import ChatType, UpdateType
|
|
9
|
+
|
|
10
|
+
from .markup import Markup, PatternLike, check_string
|
|
11
|
+
|
|
12
|
+
InlineQuery: typing.TypeAlias = InlineQueryCute
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class InlineQueryRule(ABCRule[InlineQuery], abc.ABC):
|
|
16
|
+
adapter: EventAdapter[InlineQuery] = EventAdapter(UpdateType.INLINE_QUERY, InlineQuery)
|
|
17
|
+
|
|
18
|
+
@abc.abstractmethod
|
|
19
|
+
def check(self, *args: typing.Any, **kwargs: typing.Any) -> CheckResult: ...
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
class HasLocation(InlineQueryRule):
|
|
23
|
+
def check(self, query: InlineQuery) -> bool:
|
|
24
|
+
return bool(query.location)
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
class InlineQueryChatType(InlineQueryRule):
|
|
28
|
+
def __init__(self, chat_type: ChatType, /) -> None:
|
|
29
|
+
self.chat_type = chat_type
|
|
30
|
+
|
|
31
|
+
def check(self, query: InlineQuery) -> bool:
|
|
32
|
+
return query.chat_type.map(lambda x: x == self.chat_type).unwrap_or(False)
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
class InlineQueryText(InlineQueryRule):
|
|
36
|
+
def __init__(self, texts: str | list[str], *, lower_case: bool = False) -> None:
|
|
37
|
+
self.texts = [
|
|
38
|
+
text.lower() if lower_case else text for text in ([texts] if isinstance(texts, str) else texts)
|
|
39
|
+
]
|
|
40
|
+
self.lower_case = lower_case
|
|
41
|
+
|
|
42
|
+
def check(self, query: InlineQuery) -> bool:
|
|
43
|
+
return (query.query.lower() if self.lower_case else query.query) in self.texts
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
class InlineQueryMarkup(InlineQueryRule):
|
|
47
|
+
def __init__(self, patterns: PatternLike | list[PatternLike], /) -> None:
|
|
48
|
+
self.patterns = Markup(patterns).patterns
|
|
49
|
+
|
|
50
|
+
def check(self, query: InlineQuery, ctx: Context) -> bool:
|
|
51
|
+
return check_string(self.patterns, query.query, ctx)
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
__all__ = (
|
|
55
|
+
"HasLocation",
|
|
56
|
+
"InlineQueryChatType",
|
|
57
|
+
"InlineQueryMarkup",
|
|
58
|
+
"InlineQueryRule",
|
|
59
|
+
"InlineQueryText",
|
|
60
|
+
)
|