telegrinder 0.3.0.post2__py3-none-any.whl → 0.3.1__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.

@@ -24,6 +24,7 @@ if typing.TYPE_CHECKING:
24
24
 
25
25
  AdaptTo = typing.TypeVar("AdaptTo", default=typing.Any, contravariant=True)
26
26
 
27
+ CheckResult: typing.TypeAlias = bool | typing.Coroutine[typing.Any, typing.Any, bool]
27
28
  Message: typing.TypeAlias = MessageCute
28
29
  Update: typing.TypeAlias = UpdateCute
29
30
 
@@ -48,38 +49,38 @@ class ABCRule(ABC, typing.Generic[AdaptTo]):
48
49
  if typing.TYPE_CHECKING:
49
50
 
50
51
  @typing.overload
51
- async def check(self) -> bool: ...
52
+ def check(self) -> CheckResult: ...
52
53
 
53
54
  @typing.overload
54
- async def check(self, event: AdaptTo, /) -> bool: ...
55
+ def check(self, event: AdaptTo, /) -> CheckResult: ...
55
56
 
56
57
  @typing.overload
57
- async def check(self, event: AdaptTo, ctx: Context, /) -> bool: ...
58
+ def check(self, event: AdaptTo, ctx: Context, /) -> CheckResult: ...
58
59
 
59
60
  @typing.overload
60
- async def check(
61
+ def check(
61
62
  self,
62
63
  event: AdaptTo,
63
64
  ctx: Context,
64
65
  /,
65
66
  *args: typing.Any,
66
67
  **kwargs: typing.Any,
67
- ) -> bool: ...
68
+ ) -> CheckResult: ...
68
69
 
69
70
  @typing.overload
70
- async def check(self, event: AdaptTo, /, *args: typing.Any, **kwargs: typing.Any) -> bool: ...
71
+ def check(self, event: AdaptTo, /, *args: typing.Any, **kwargs: typing.Any) -> CheckResult: ...
71
72
 
72
73
  @typing.overload
73
- async def check(self, ctx: Context, /, *args: typing.Any, **kwargs: typing.Any) -> bool: ...
74
+ def check(self, ctx: Context, /, *args: typing.Any, **kwargs: typing.Any) -> CheckResult: ...
74
75
 
75
76
  @abstractmethod
76
- async def check(self, *args: typing.Any, **kwargs: typing.Any) -> bool:
77
+ def check(self, *args: typing.Any, **kwargs: typing.Any) -> CheckResult:
77
78
  pass
78
79
  else:
79
80
  adapter = RawUpdateAdapter()
80
81
 
81
82
  @abstractmethod
82
- async def check(self, *args, **kwargs):
83
+ def check(self, *args, **kwargs):
83
84
  pass
84
85
 
85
86
  def __init_subclass__(cls, requires: list["ABCRule"] | None = None) -> None:
@@ -171,7 +172,10 @@ class ABCRule(ABC, typing.Generic[AdaptTo]):
171
172
  "because it cannot be resolved."
172
173
  )
173
174
 
174
- return await bound_check_rule(**kw) # type: ignore
175
+ result = bound_check_rule(**kw) # type: ignore
176
+ if inspect.isawaitable(result):
177
+ result = await result
178
+ return result
175
179
 
176
180
  async def translate(self, translator: ABCTranslator) -> typing.Self:
177
181
  return self
@@ -229,5 +233,6 @@ __all__ = (
229
233
  "Never",
230
234
  "NotRule",
231
235
  "OrRule",
236
+ "CheckResult",
232
237
  "with_caching_translations",
233
238
  )
@@ -12,7 +12,7 @@ from telegrinder.model import decoder
12
12
  from telegrinder.tools.buttons import DataclassInstance
13
13
  from telegrinder.types.enums import UpdateType
14
14
 
15
- from .abc import ABCRule
15
+ from .abc import ABCRule, CheckResult
16
16
  from .markup import Markup, PatternLike, check_string
17
17
 
18
18
  CallbackQuery: typing.TypeAlias = CallbackQueryCute
@@ -26,12 +26,12 @@ class CallbackQueryRule(ABCRule[CallbackQuery], abc.ABC):
26
26
  adapter: EventAdapter[CallbackQuery] = EventAdapter(UpdateType.CALLBACK_QUERY, CallbackQuery)
27
27
 
28
28
  @abc.abstractmethod
29
- async def check(self, event: CallbackQuery, context: Context) -> bool:
29
+ def check(self, event: CallbackQuery, context: Context) -> CheckResult:
30
30
  pass
31
31
 
32
32
 
33
33
  class HasData(CallbackQueryRule):
34
- async def check(self, event: CallbackQuery) -> bool:
34
+ def check(self, event: CallbackQuery) -> bool:
35
35
  return bool(event.data.unwrap_or_none())
36
36
 
37
37
 
@@ -122,7 +122,7 @@ class CallbackDataEq(CallbackQueryDataRule):
122
122
  def __init__(self, value: str, /) -> None:
123
123
  self.value = value
124
124
 
125
- async def check(self, event: CallbackQuery) -> bool:
125
+ def check(self, event: CallbackQuery) -> bool:
126
126
  return event.data.unwrap() == self.value
127
127
 
128
128
 
@@ -130,7 +130,7 @@ class CallbackDataJsonEq(CallbackQueryDataRule):
130
130
  def __init__(self, d: dict[str, typing.Any], /) -> None:
131
131
  self.d = d
132
132
 
133
- async def check(self, event: CallbackQuery) -> bool:
133
+ def check(self, event: CallbackQuery) -> bool:
134
134
  return event.decode_callback_data().unwrap_or_none() == self.d
135
135
 
136
136
 
@@ -144,7 +144,7 @@ class CallbackDataJsonModel(CallbackQueryDataRule):
144
144
  self.model = model
145
145
  self.alias = alias or "data"
146
146
 
147
- async def check(self, event: CallbackQuery, ctx: Context) -> bool:
147
+ def check(self, event: CallbackQuery, ctx: Context) -> bool:
148
148
  with suppress(BaseException):
149
149
  ctx.set(self.alias, decoder.decode(event.data.unwrap().encode(), type=self.model))
150
150
  return True
@@ -155,7 +155,7 @@ class CallbackDataMarkup(CallbackQueryDataRule):
155
155
  def __init__(self, patterns: PatternLike | list[PatternLike], /) -> None:
156
156
  self.patterns = Markup(patterns).patterns
157
157
 
158
- async def check(self, event: CallbackQuery, ctx: Context) -> bool:
158
+ def check(self, event: CallbackQuery, ctx: Context) -> bool:
159
159
  return check_string(self.patterns, event.data.unwrap(), ctx)
160
160
 
161
161
 
@@ -6,7 +6,7 @@ from telegrinder.bot.dispatch.context import Context
6
6
  from telegrinder.bot.rules.adapter import EventAdapter
7
7
  from telegrinder.types.enums import UpdateType
8
8
 
9
- from .abc import ABCRule
9
+ from .abc import ABCRule, CheckResult
10
10
 
11
11
  ChatJoinRequest: typing.TypeAlias = ChatJoinRequestCute
12
12
 
@@ -15,12 +15,12 @@ class ChatJoinRequestRule(ABCRule[ChatJoinRequest], requires=[]):
15
15
  adapter: EventAdapter[ChatJoinRequest] = EventAdapter(UpdateType.CHAT_JOIN_REQUEST, ChatJoinRequest)
16
16
 
17
17
  @abc.abstractmethod
18
- async def check(self, event: ChatJoinRequest, context: Context) -> bool:
18
+ def check(self, event: ChatJoinRequest, context: Context) -> CheckResult:
19
19
  pass
20
20
 
21
21
 
22
22
  class HasInviteLink(ChatJoinRequestRule):
23
- async def check(self, event: ChatJoinRequest) -> bool:
23
+ def check(self, event: ChatJoinRequest) -> bool:
24
24
  return bool(event.invite_link)
25
25
 
26
26
 
@@ -28,7 +28,7 @@ class InviteLinkName(ChatJoinRequestRule, requires=[HasInviteLink()]):
28
28
  def __init__(self, name: str, /) -> None:
29
29
  self.name = name
30
30
 
31
- async def check(self, event: ChatJoinRequest) -> bool:
31
+ def check(self, event: ChatJoinRequest) -> bool:
32
32
  return event.invite_link.unwrap().name.unwrap_or_none() == self.name
33
33
 
34
34
 
@@ -36,7 +36,7 @@ class InviteLinkByCreator(ChatJoinRequestRule, requires=[HasInviteLink()]):
36
36
  def __init__(self, creator_id: int, /) -> None:
37
37
  self.creator_id = creator_id
38
38
 
39
- async def check(self, event: ChatJoinRequest) -> bool:
39
+ def check(self, event: ChatJoinRequest) -> bool:
40
40
  return event.invite_link.unwrap().creator.id == self.creator_id
41
41
 
42
42
 
@@ -97,7 +97,7 @@ class Command(ABCRule):
97
97
 
98
98
  return None
99
99
 
100
- async def check(self, command: CommandInfo, me: Me, src: Source, ctx: Context) -> bool:
100
+ def check(self, command: CommandInfo, me: Me, src: Source, ctx: Context) -> bool:
101
101
  name = self.remove_prefix(command.name)
102
102
  if name is None:
103
103
  return False
@@ -25,9 +25,12 @@ class EnumTextRule(ABCRule, typing.Generic[T]):
25
25
  return enumeration
26
26
  raise KeyError("Enumeration is undefined.")
27
27
 
28
- async def check(self, text: Text, ctx: Context) -> bool:
28
+ def check(self, text: Text, ctx: Context) -> bool:
29
29
  text = text.lower() # type: ignore
30
30
  if text not in self.texts:
31
31
  return False
32
32
  ctx.enum_text = self.find(text)
33
33
  return True
34
+
35
+
36
+ __all__ = ("EnumTextRule",)
@@ -13,7 +13,7 @@ class FuzzyText(ABCRule):
13
13
  self.texts = texts
14
14
  self.min_ratio = min_ratio
15
15
 
16
- async def check(self, message_text: Text, ctx: Context) -> bool:
16
+ def check(self, message_text: Text, ctx: Context) -> bool:
17
17
  match = max(difflib.SequenceMatcher(a=message_text, b=text).ratio() for text in self.texts)
18
18
  if match < self.min_ratio:
19
19
  return False
@@ -3,7 +3,7 @@ import typing
3
3
 
4
4
  from telegrinder.bot.cute_types import InlineQueryCute
5
5
  from telegrinder.bot.dispatch.context import Context
6
- from telegrinder.bot.rules.abc import ABCRule
6
+ from telegrinder.bot.rules.abc import ABCRule, CheckResult
7
7
  from telegrinder.bot.rules.adapter import EventAdapter
8
8
  from telegrinder.types.enums import ChatType, UpdateType
9
9
 
@@ -16,11 +16,11 @@ class InlineQueryRule(ABCRule[InlineQuery], abc.ABC):
16
16
  adapter: EventAdapter[InlineQuery] = EventAdapter(UpdateType.INLINE_QUERY, InlineQuery)
17
17
 
18
18
  @abc.abstractmethod
19
- async def check(self, query: InlineQuery, ctx: Context) -> bool: ...
19
+ def check(self, query: InlineQuery, ctx: Context) -> CheckResult: ...
20
20
 
21
21
 
22
22
  class HasLocation(InlineQueryRule):
23
- async def check(self, query: InlineQuery) -> bool:
23
+ def check(self, query: InlineQuery) -> bool:
24
24
  return bool(query.location)
25
25
 
26
26
 
@@ -28,7 +28,7 @@ class InlineQueryChatType(InlineQueryRule):
28
28
  def __init__(self, chat_type: ChatType, /) -> None:
29
29
  self.chat_type = chat_type
30
30
 
31
- async def check(self, query: InlineQuery) -> bool:
31
+ def check(self, query: InlineQuery) -> bool:
32
32
  return query.chat_type.map(lambda x: x == self.chat_type).unwrap_or(False)
33
33
 
34
34
 
@@ -39,7 +39,7 @@ class InlineQueryText(InlineQueryRule):
39
39
  ]
40
40
  self.lower_case = lower_case
41
41
 
42
- async def check(self, query: InlineQuery) -> bool:
42
+ def check(self, query: InlineQuery) -> bool:
43
43
  return (query.query.lower() if self.lower_case else query.query) in self.texts
44
44
 
45
45
 
@@ -47,7 +47,7 @@ class InlineQueryMarkup(InlineQueryRule):
47
47
  def __init__(self, patterns: PatternLike | list[PatternLike], /) -> None:
48
48
  self.patterns = Markup(patterns).patterns
49
49
 
50
- async def check(self, query: InlineQuery, ctx: Context) -> bool:
50
+ def check(self, query: InlineQuery, ctx: Context) -> bool:
51
51
  return check_string(self.patterns, query.query, ctx)
52
52
 
53
53
 
@@ -13,7 +13,7 @@ class IntegerInRange(ABCRule):
13
13
  def __init__(self, rng: range) -> None:
14
14
  self.rng = rng
15
15
 
16
- async def check(self, integer: TextInteger) -> bool:
16
+ def check(self, integer: TextInteger) -> bool:
17
17
  return integer in self.rng
18
18
 
19
19
 
@@ -8,17 +8,17 @@ from .message import MessageRule
8
8
 
9
9
 
10
10
  class IsBot(ABCRule):
11
- async def check(self, user: UserSource) -> bool:
11
+ def check(self, user: UserSource) -> bool:
12
12
  return user.is_bot
13
13
 
14
14
 
15
15
  class IsUser(ABCRule):
16
- async def check(self, user: UserSource) -> bool:
16
+ def check(self, user: UserSource) -> bool:
17
17
  return not user.is_bot
18
18
 
19
19
 
20
20
  class IsPremium(ABCRule):
21
- async def check(self, user: UserSource) -> bool:
21
+ def check(self, user: UserSource) -> bool:
22
22
  return user.is_premium.unwrap_or(False)
23
23
 
24
24
 
@@ -26,7 +26,7 @@ class IsLanguageCode(ABCRule):
26
26
  def __init__(self, lang_codes: str | list[str], /) -> None:
27
27
  self.lang_codes = [lang_codes] if isinstance(lang_codes, str) else lang_codes
28
28
 
29
- async def check(self, user: UserSource) -> bool:
29
+ def check(self, user: UserSource) -> bool:
30
30
  return user.language_code.unwrap_or_none() in self.lang_codes
31
31
 
32
32
 
@@ -34,12 +34,12 @@ class IsUserId(ABCRule):
34
34
  def __init__(self, user_ids: int | list[int], /) -> None:
35
35
  self.user_ids = [user_ids] if isinstance(user_ids, int) else user_ids
36
36
 
37
- async def check(self, user: UserSource) -> bool:
37
+ def check(self, user: UserSource) -> bool:
38
38
  return user.id in self.user_ids
39
39
 
40
40
 
41
41
  class IsForum(ABCRule):
42
- async def check(self, chat: ChatSource) -> bool:
42
+ def check(self, chat: ChatSource) -> bool:
43
43
  return chat.is_forum.unwrap_or(False)
44
44
 
45
45
 
@@ -47,32 +47,32 @@ class IsChatId(ABCRule):
47
47
  def __init__(self, chat_ids: int | list[int], /) -> None:
48
48
  self.chat_ids = [chat_ids] if isinstance(chat_ids, int) else chat_ids
49
49
 
50
- async def check(self, chat: ChatSource) -> bool:
50
+ def check(self, chat: ChatSource) -> bool:
51
51
  return chat.id in self.chat_ids
52
52
 
53
53
 
54
54
  class IsPrivate(ABCRule):
55
- async def check(self, chat: ChatSource) -> bool:
55
+ def check(self, chat: ChatSource) -> bool:
56
56
  return chat.type == ChatType.PRIVATE
57
57
 
58
58
 
59
59
  class IsGroup(ABCRule):
60
- async def check(self, chat: ChatSource) -> bool:
60
+ def check(self, chat: ChatSource) -> bool:
61
61
  return chat.type == ChatType.GROUP
62
62
 
63
63
 
64
64
  class IsSuperGroup(ABCRule):
65
- async def check(self, chat: ChatSource) -> bool:
65
+ def check(self, chat: ChatSource) -> bool:
66
66
  return chat.type == ChatType.SUPERGROUP
67
67
 
68
68
 
69
69
  class IsChat(ABCRule):
70
- async def check(self, chat: ChatSource) -> bool:
70
+ def check(self, chat: ChatSource) -> bool:
71
71
  return chat.type in (ChatType.GROUP, ChatType.SUPERGROUP)
72
72
 
73
73
 
74
74
  class IsDice(MessageRule):
75
- async def check(self, message: Message) -> bool:
75
+ def check(self, message: Message) -> bool:
76
76
  return bool(message.dice)
77
77
 
78
78
 
@@ -80,12 +80,12 @@ class IsDiceEmoji(MessageRule, requires=[IsDice()]):
80
80
  def __init__(self, dice_emoji: DiceEmoji, /) -> None:
81
81
  self.dice_emoji = dice_emoji
82
82
 
83
- async def check(self, message: Message) -> bool:
83
+ def check(self, message: Message) -> bool:
84
84
  return message.dice.unwrap().emoji == self.dice_emoji
85
85
 
86
86
 
87
87
  class IsForward(MessageRule):
88
- async def check(self, message: Message) -> bool:
88
+ def check(self, message: Message) -> bool:
89
89
  return bool(message.forward_origin)
90
90
 
91
91
 
@@ -93,32 +93,32 @@ class IsForwardType(MessageRule, requires=[IsForward()]):
93
93
  def __init__(self, fwd_type: typing.Literal["user", "hidden_user", "chat", "channel"], /) -> None:
94
94
  self.fwd_type = fwd_type
95
95
 
96
- async def check(self, message: Message) -> bool:
96
+ def check(self, message: Message) -> bool:
97
97
  return message.forward_origin.unwrap().v.type == self.fwd_type
98
98
 
99
99
 
100
100
  class IsReply(MessageRule):
101
- async def check(self, message: Message) -> bool:
101
+ def check(self, message: Message) -> bool:
102
102
  return bool(message.reply_to_message)
103
103
 
104
104
 
105
105
  class IsSticker(MessageRule):
106
- async def check(self, message: Message) -> bool:
106
+ def check(self, message: Message) -> bool:
107
107
  return bool(message.sticker)
108
108
 
109
109
 
110
110
  class IsVideoNote(MessageRule):
111
- async def check(self, message: Message) -> bool:
111
+ def check(self, message: Message) -> bool:
112
112
  return bool(message.video_note)
113
113
 
114
114
 
115
115
  class IsDocument(MessageRule):
116
- async def check(self, message: Message) -> bool:
116
+ def check(self, message: Message) -> bool:
117
117
  return bool(message.document)
118
118
 
119
119
 
120
120
  class IsPhoto(MessageRule):
121
- async def check(self, message: Message) -> bool:
121
+ def check(self, message: Message) -> bool:
122
122
  return bool(message.photo)
123
123
 
124
124
 
@@ -36,7 +36,7 @@ class Markup(ABCRule):
36
36
  for pattern in patterns
37
37
  ]
38
38
 
39
- async def check(self, text: Text, ctx: Context) -> bool:
39
+ def check(self, text: Text, ctx: Context) -> bool:
40
40
  return check_string(self.patterns, text, ctx)
41
41
 
42
42
 
@@ -5,7 +5,7 @@ from .text import HasText
5
5
 
6
6
 
7
7
  class HasMention(MessageRule, requires=[HasText()]):
8
- async def check(self, message: Message) -> bool:
8
+ def check(self, message: Message) -> bool:
9
9
  if not message.entities.unwrap_or_none():
10
10
  return False
11
11
  return any(entity.type == MessageEntityType.MENTION for entity in message.entities.unwrap())
@@ -3,7 +3,7 @@ import abc
3
3
  from telegrinder.bot.dispatch.context import Context
4
4
  from telegrinder.types.objects import Message as MessageEvent
5
5
 
6
- from .abc import ABCRule, Message
6
+ from .abc import ABCRule, CheckResult, Message
7
7
  from .adapter import EventAdapter
8
8
 
9
9
 
@@ -11,7 +11,7 @@ class MessageRule(ABCRule[Message], abc.ABC):
11
11
  adapter: EventAdapter[Message] = EventAdapter(MessageEvent, Message)
12
12
 
13
13
  @abc.abstractmethod
14
- async def check(self, message: Message, ctx: Context) -> bool: ...
14
+ def check(self, message: Message, ctx: Context) -> CheckResult: ...
15
15
 
16
16
 
17
17
  __all__ = ("MessageRule",)
@@ -10,7 +10,7 @@ Entity: typing.TypeAlias = str | MessageEntityType
10
10
 
11
11
 
12
12
  class HasEntities(MessageRule):
13
- async def check(self, message: Message) -> bool:
13
+ def check(self, message: Message) -> bool:
14
14
  return bool(message.entities)
15
15
 
16
16
 
@@ -18,7 +18,7 @@ class MessageEntities(MessageRule, requires=[HasEntities()]):
18
18
  def __init__(self, entities: Entity | list[Entity], /) -> None:
19
19
  self.entities = [entities] if not isinstance(entities, list) else entities
20
20
 
21
- async def check(self, message: Message, ctx: Context) -> bool:
21
+ def check(self, message: Message, ctx: Context) -> bool:
22
22
  message_entities: list[MessageEntity] = []
23
23
  for entity in message.entities.unwrap():
24
24
  for entity_type in self.entities:
@@ -17,7 +17,7 @@ class NodeRule(ABCRule[tuple[Node, ...]]):
17
17
  def adapter(self) -> NodeAdapter:
18
18
  return NodeAdapter(*self.nodes) # type: ignore
19
19
 
20
- async def check(self, resolved_nodes: tuple[Node, ...], ctx: Context) -> typing.Literal[True]:
20
+ def check(self, resolved_nodes: tuple[Node, ...], ctx: Context) -> typing.Literal[True]:
21
21
  for i, node in enumerate(resolved_nodes):
22
22
  if key := self.node_keys[i]:
23
23
  ctx[key] = node
@@ -22,7 +22,7 @@ class Regex(ABCRule):
22
22
  re.compile(regexp) if isinstance(regexp, str) else regexp for regexp in regexp
23
23
  )
24
24
 
25
- async def check(self, text: Text, ctx: Context) -> bool:
25
+ def check(self, text: Text, ctx: Context) -> bool:
26
26
  for regexp in self.regexp:
27
27
  response = re.match(regexp, text)
28
28
  if response is not None:
@@ -28,7 +28,7 @@ class StartCommand(
28
28
  self.validator = validator
29
29
  self.alias = alias
30
30
 
31
- async def check(self, ctx: Context) -> bool:
31
+ def check(self, ctx: Context) -> bool:
32
32
  param: str | None = ctx.pop("param", None)
33
33
  validated_param = self.validator(param) if self.validator and param is not None else param
34
34
 
@@ -19,7 +19,7 @@ class Text(ABCRule):
19
19
  self.texts = texts if not ignore_case else list(map(str.lower, texts))
20
20
  self.ignore_case = ignore_case
21
21
 
22
- async def check(self, text: node.text.Text) -> bool:
22
+ def check(self, text: node.text.Text) -> bool:
23
23
  return (text if not self.ignore_case else text.lower()) in self.texts
24
24
 
25
25
  @with_caching_translations
@@ -8,7 +8,7 @@ class IsUpdateType(ABCRule):
8
8
  def __init__(self, update_type: UpdateType, /) -> None:
9
9
  self.update_type = update_type
10
10
 
11
- async def check(self, event: UpdateCute) -> bool:
11
+ def check(self, event: UpdateCute) -> bool:
12
12
  return event.update_type == self.update_type
13
13
 
14
14
 
@@ -35,6 +35,7 @@ class Checkbox(ABCScenario[CallbackQueryCute]):
35
35
  message: str,
36
36
  *,
37
37
  ready_text: str = "Ready",
38
+ cancel_text: str | None = None,
38
39
  max_in_row: int = 3,
39
40
  ) -> None:
40
41
  self.chat_id = chat_id
@@ -44,6 +45,7 @@ class Checkbox(ABCScenario[CallbackQueryCute]):
44
45
  self.max_in_row = max_in_row
45
46
  self.random_code = secrets.token_hex(8)
46
47
  self.waiter_machine = waiter_machine
48
+ self.cancel_text = cancel_text
47
49
 
48
50
  def __repr__(self) -> str:
49
51
  return (
@@ -75,6 +77,9 @@ class Checkbox(ABCScenario[CallbackQueryCute]):
75
77
  kb.row()
76
78
 
77
79
  kb.add(InlineButton(self.ready, callback_data=self.random_code + "/ready"))
80
+ if self.cancel_text is not None:
81
+ kb.row()
82
+ kb.add(InlineButton(self.cancel_text, callback_data=self.random_code + "/cancel"))
78
83
  return kb.get_markup()
79
84
 
80
85
  def add_option(
@@ -94,6 +99,9 @@ class Checkbox(ABCScenario[CallbackQueryCute]):
94
99
  code = cb.data.unwrap().replace(self.random_code + "/", "", 1)
95
100
  if code == "ready":
96
101
  return False
102
+ elif code == "cancel":
103
+ self.choices = []
104
+ return False
97
105
 
98
106
  for i, choice in enumerate(self.choices):
99
107
  if choice.code == code:
@@ -1,5 +1,4 @@
1
1
  import enum
2
- import inspect
3
2
  import types
4
3
  import typing
5
4
  from functools import wraps
@@ -40,10 +39,15 @@ def resolve_arg_names(func: FuncType, start_idx: int = 1) -> tuple[str, ...]:
40
39
 
41
40
  @cache_magic_value("__default_args__")
42
41
  def get_default_args(func: FuncType) -> dict[str, typing.Any]:
43
- fspec = inspect.getfullargspec(func)
44
- if not fspec.defaults:
42
+ kwdefaults = func.__kwdefaults__
43
+ if kwdefaults:
44
+ return kwdefaults
45
+
46
+ defaults = func.__defaults__
47
+ if not defaults:
45
48
  return {}
46
- return dict(zip(fspec.args[-len(fspec.defaults) :], fspec.defaults))
49
+
50
+ return {k: defaults[i] for i, k in enumerate(resolve_arg_names(func, start_idx=0)[-len(defaults) :])}
47
51
 
48
52
 
49
53
  def get_annotations(func: FuncType, *, return_type: bool = False) -> dict[str, typing.Any]:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: telegrinder
3
- Version: 0.3.0.post2
3
+ Version: 0.3.1
4
4
  Summary: Modern visionary telegram bot framework.
5
5
  Home-page: https://github.com/timoniq/telegrinder
6
6
  License: MIT
@@ -62,36 +62,36 @@ telegrinder/bot/polling/__init__.py,sha256=OqfIFPS_V6UrCg-vCv9pkMFzTKdNbDP2faBfA
62
62
  telegrinder/bot/polling/abc.py,sha256=qFiKzWTWENK-sSuShC5cPlM-JS4In2c8-1_ARdwdTms,442
63
63
  telegrinder/bot/polling/polling.py,sha256=SOcVfmMS20M2O6ilXxvu507H7S8iNawebclfmwWJe3U,4765
64
64
  telegrinder/bot/rules/__init__.py,sha256=nl2erwXAnICnZwAuqZr5wPm3tLjHGxMU7Qyi03Jym44,2859
65
- telegrinder/bot/rules/abc.py,sha256=EdL6Q81LtGKFm1L3xUUQSUeNnJs3HGUDsU1DE2v1jqk,7084
65
+ telegrinder/bot/rules/abc.py,sha256=9E80uDt9hReMojD94RV9ZPwMRDqyn44ShhBIP6NnE-s,7282
66
66
  telegrinder/bot/rules/adapter/__init__.py,sha256=rZNX-Squn4hsE19tW2q3x-f33ZB6yzgU5eoI1VB0TgI,445
67
67
  telegrinder/bot/rules/adapter/abc.py,sha256=lPyieSDDr1z98rZ4W6Ic8QzHDzCEU9xIYrPKU9qDCas,682
68
68
  telegrinder/bot/rules/adapter/errors.py,sha256=2r_UBTWm5-heU-NchBfobC1f848EWeC64nKvprGnAAY,73
69
69
  telegrinder/bot/rules/adapter/event.py,sha256=XDeHYGwOS7bYsI5bP-iPg5Ut_dzGbTBC089OkJhSfpY,2772
70
70
  telegrinder/bot/rules/adapter/node.py,sha256=VuC_LGGkZh6GKW3dCvfDZhbiA8WJyddY8xxzerUZ7us,1663
71
71
  telegrinder/bot/rules/adapter/raw_update.py,sha256=Pz_xs5dvfsf_FXi9iO0SJFq4JRnDNolYGXqCSP_0tPs,1007
72
- telegrinder/bot/rules/callback_data.py,sha256=WxRUQRITQCH54p-gkdHHovJImYCrHOAfV7zgasc9IJI,5585
73
- telegrinder/bot/rules/chat_join.py,sha256=mFmSOXkiU_wSuIjKgMxh8mIusqeH_-DKVvouxdgZe-4,1446
74
- telegrinder/bot/rules/command.py,sha256=ESJA21HZHWT0RlYzHqOKBa223CTFbqwx_cgvNsWao44,3912
75
- telegrinder/bot/rules/enum_text.py,sha256=YJ6S2fAQts8zCjCgoL7uUGWlnPOH59rjvA7Si2hKyR4,944
72
+ telegrinder/bot/rules/callback_data.py,sha256=ZU9Qi5LyP_CNvpO8XTfNa0HKgX7H27N6oxz3znHNTTU,5569
73
+ telegrinder/bot/rules/chat_join.py,sha256=pHXQv9VMKmBO7OGcHJLk-a9rB5l6sOybFmOWvgh1PXU,1442
74
+ telegrinder/bot/rules/command.py,sha256=gYEWkrOr_xBWXbCnEXBrDs8EHRyW-pwrlascVRmS854,3906
75
+ telegrinder/bot/rules/enum_text.py,sha256=c-B3_iF6nZOnOY1A8s500W37XYeEyQaJIl1OU5aZ3V0,968
76
76
  telegrinder/bot/rules/func.py,sha256=dqcxhC7dIP67Zi20iFz2jCWwwioM2NuemCM5dwpQDXg,769
77
- telegrinder/bot/rules/fuzzy.py,sha256=Kx4S1y6iFqWM3uIUmor47mCmD08NRRJbcciH-dFs19M,676
78
- telegrinder/bot/rules/inline.py,sha256=PNT--QuF3QLUrc7SzW9laz66ZmuDXxKt-ufaeX01c4Q,1931
79
- telegrinder/bot/rules/integer.py,sha256=hJ8aENGl1q_Caw1sbG-MHXsnWZCt9r57IZWY9zLC-TE,435
80
- telegrinder/bot/rules/is_from.py,sha256=aFl4_-r2welnTw7TRzyfQODk0HX5E0aYcEytiY_s3pk,3820
81
- telegrinder/bot/rules/markup.py,sha256=oV_fc8F2cr9DT2RTaGppGZ7XmOSIVpb1hG_QNuUEmBI,1334
82
- telegrinder/bot/rules/mention.py,sha256=xteWbtSjQN3KOXpB8RjuVYu18bGrLxNtVFg6oR-UkxU,435
83
- telegrinder/bot/rules/message.py,sha256=VFfcEmNrw5sW4EYpk2XgLkSE5-rRr7sWC2dFE26Q3cI,442
84
- telegrinder/bot/rules/message_entities.py,sha256=imYBaajJbtRZy4oYsCYnIAUlr6-OiDURuza647VQ_ZU,1097
85
- telegrinder/bot/rules/node.py,sha256=IP7Ke-4hILb12XHNIresMf_87kXhlLfKOloShoQvWN0,892
86
- telegrinder/bot/rules/regex.py,sha256=mjXXPX-NB2e3gFU6LFihLnKANcgUoAL5lOnfmhC3Qnc,1153
77
+ telegrinder/bot/rules/fuzzy.py,sha256=GhI0Eqf5Y69bvIlYDvGbGH6RNQqW81aXK3YV5OVlZ04,670
78
+ telegrinder/bot/rules/inline.py,sha256=SKc9AAL5igUd2LX83Xoe2WCZUWPONcNqvdFcNge8fEQ,1921
79
+ telegrinder/bot/rules/integer.py,sha256=nDabEsuGfzC8cBuOtUCAkeWyFHW6u_BKvvcya2HJr-c,429
80
+ telegrinder/bot/rules/is_from.py,sha256=_ZFdPg6zAsXJ8Cb-sjcRc9fsonzmvGJvh-5Fca2JPTI,3700
81
+ telegrinder/bot/rules/markup.py,sha256=Y7PXvE0nlh5GHT2NJqtWzXMiWmGSkfPABF1WFo0xvrw,1328
82
+ telegrinder/bot/rules/mention.py,sha256=u5VQbEwb1BuYmXMLE0bxLde4fDcvEGCq3JAg0dhuaN8,429
83
+ telegrinder/bot/rules/message.py,sha256=1zwZW4JqQPGPmuy4j3hMxQTQPrp2l29MR9HYXJQHRMM,456
84
+ telegrinder/bot/rules/message_entities.py,sha256=S0vxpXPld7gGESMpk7lb37OnPXGcLYCWWXqcMMwQHHM,1085
85
+ telegrinder/bot/rules/node.py,sha256=CQGzT-pOmuh2Wkbq-1WvOzzWrM3vVsRlGEzBUCZ1v6w,886
86
+ telegrinder/bot/rules/regex.py,sha256=PKryH44NGqeKiW53OggwCsGSFh_rQTddMojQ3AQme5A,1147
87
87
  telegrinder/bot/rules/rule_enum.py,sha256=35GwPKLBTG_ESn4TZLcFJTLNjYXAi_d9wrfIDexoEH8,2113
88
- telegrinder/bot/rules/start.py,sha256=vZMjCSVsRMPKZYWjRK8a6dcEIH3ewkzzaLop0DyN_WM,1153
88
+ telegrinder/bot/rules/start.py,sha256=AipwfOQ2LGCofvgouRmkIiY9mGFLlEUJ-7a3CLIiy4Q,1147
89
89
  telegrinder/bot/rules/state.py,sha256=3hJTT2yVTqGbsdC52qCXqXyctnCZeZuNC7TkpfDjXic,975
90
- telegrinder/bot/rules/text.py,sha256=FumUmmie6x7SqjRrax8lbguvbEKLhHN6_XbGnsRphO4,993
91
- telegrinder/bot/rules/update.py,sha256=k73pZzlzhw77gHAmeIsqehy0-EI2ec8wVGxGRIF_8ao,398
90
+ telegrinder/bot/rules/text.py,sha256=JyypoDCoR6LM2lmK0Ej5sfcXwtGwbLibY7-96w3a80s,987
91
+ telegrinder/bot/rules/update.py,sha256=-mE12-xy0AjOz9RVRVZ8vS7ohGCuf_bNmG26rDbrjfg,392
92
92
  telegrinder/bot/scenario/__init__.py,sha256=nnPjdxdvjoEYYMRUEfWvIhZStiY1C984x1azdRRP9II,136
93
93
  telegrinder/bot/scenario/abc.py,sha256=3UwnA9Nt6CETKm2YclD0gVbn-483fTSBriZADd3p-bM,468
94
- telegrinder/bot/scenario/checkbox.py,sha256=Z4he_M-XuaV5R_SK7yA8ibRnQlCVLeB4_j_A7bJ63vo,4239
94
+ telegrinder/bot/scenario/checkbox.py,sha256=hF8YXPtTceijoJpCe-la2Hu0uStmUvn3g9bCHE3cOCQ,4561
95
95
  telegrinder/bot/scenario/choice.py,sha256=9BiLViO7MEblBcYqlAkW_L3Nfa6NWcF3sj3X1GyIyBc,1480
96
96
  telegrinder/client/__init__.py,sha256=ZiS1Wb_l_kv3FHzEEi1oXtFLwlA_HXmWOzeN0xA3E7Y,104
97
97
  telegrinder/client/abc.py,sha256=OxsTX_PLYBEeFT9zpidFUzAbQL9BM7rQqru7zdn5DiQ,1611
@@ -148,7 +148,7 @@ telegrinder/tools/limited_dict.py,sha256=tb1WT4P3Oia5CsCBXTHzlFjrPnIgf9eHCkQ0zhA
148
148
  telegrinder/tools/loop_wrapper/__init__.py,sha256=ZQ5jmE1lOKnqJlMZ9k2OYmjvOEhOlHPijUWqZ4nHIgk,165
149
149
  telegrinder/tools/loop_wrapper/abc.py,sha256=ET_Dp-kRz75Jo1fZB3qofUgEXN4FqlU0xH2diESKGCM,266
150
150
  telegrinder/tools/loop_wrapper/loop_wrapper.py,sha256=h8Oii3FtLODRafxTez0ZEMNIZ8lhuNRwixO1u0jPhok,6763
151
- telegrinder/tools/magic.py,sha256=BltMDQ_CEEu_b63dvxdKmzMUJRAFdaboGZjAPqITrSk,4509
151
+ telegrinder/tools/magic.py,sha256=jPfjWoNF1cjOewMDpjAajUieSMKNeCSQzyS2fqNwD4M,4597
152
152
  telegrinder/tools/parse_mode.py,sha256=JyQ-x9YAMPLhIIiUX01acyKkpWgs5TBA07W-iUyPHpE,92
153
153
  telegrinder/tools/state_storage/__init__.py,sha256=G2EK2HwS0NbRQIu0OotVlgEYtO_GuzN1aJOIxmDEtz4,211
154
154
  telegrinder/tools/state_storage/abc.py,sha256=9-UOmov9b7bQpeD0JukVsayU2FHmW45FeCnlPdayLhM,958
@@ -158,7 +158,7 @@ telegrinder/types/enums.py,sha256=q9URlXZvrjOUQKpLfV6v9uspBcLrdW0gtU-m8YDnj7w,19
158
158
  telegrinder/types/methods.py,sha256=gIqcFHVogw8bbYO7C7tf1xdzE-m5EiKe998NW-IS2fI,201311
159
159
  telegrinder/types/objects.py,sha256=tfQuJKWYH8l3vmvx65gg2yGh7kpfueU9wPMFsPZIu9k,246627
160
160
  telegrinder/verification_utils.py,sha256=X7N0mHoOzbcYeKa5XxI_EFhmEGX5XNU3qqgbV8YRRa4,987
161
- telegrinder-0.3.0.post2.dist-info/LICENSE,sha256=Q0tKgU8mPOCQAkc6m__BrNIpRge8mPBQJDd59s21NZo,1095
162
- telegrinder-0.3.0.post2.dist-info/METADATA,sha256=tpqQu1DDSr9b9Qq43FmYmnY7OkPFGKU5NDWT3lbEY78,3149
163
- telegrinder-0.3.0.post2.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
164
- telegrinder-0.3.0.post2.dist-info/RECORD,,
161
+ telegrinder-0.3.1.dist-info/LICENSE,sha256=Q0tKgU8mPOCQAkc6m__BrNIpRge8mPBQJDd59s21NZo,1095
162
+ telegrinder-0.3.1.dist-info/METADATA,sha256=zpaW8SHYEC-IUf0Sf23IuXK4xun8gRx_zOXoBbW4VDQ,3143
163
+ telegrinder-0.3.1.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
164
+ telegrinder-0.3.1.dist-info/RECORD,,