telegrinder 0.4.2__py3-none-any.whl → 0.5.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.

Files changed (233) hide show
  1. telegrinder/__init__.py +37 -55
  2. telegrinder/__meta__.py +1 -0
  3. telegrinder/api/__init__.py +6 -4
  4. telegrinder/api/api.py +100 -26
  5. telegrinder/api/error.py +42 -8
  6. telegrinder/api/response.py +4 -1
  7. telegrinder/api/token.py +2 -2
  8. telegrinder/bot/__init__.py +9 -25
  9. telegrinder/bot/bot.py +31 -25
  10. telegrinder/bot/cute_types/__init__.py +0 -0
  11. telegrinder/bot/cute_types/base.py +103 -61
  12. telegrinder/bot/cute_types/callback_query.py +447 -400
  13. telegrinder/bot/cute_types/chat_join_request.py +59 -62
  14. telegrinder/bot/cute_types/chat_member_updated.py +154 -157
  15. telegrinder/bot/cute_types/inline_query.py +41 -44
  16. telegrinder/bot/cute_types/message.py +2621 -2590
  17. telegrinder/bot/cute_types/pre_checkout_query.py +38 -42
  18. telegrinder/bot/cute_types/update.py +1 -8
  19. telegrinder/bot/cute_types/utils.py +1 -1
  20. telegrinder/bot/dispatch/__init__.py +10 -15
  21. telegrinder/bot/dispatch/abc.py +12 -11
  22. telegrinder/bot/dispatch/action.py +104 -0
  23. telegrinder/bot/dispatch/context.py +32 -26
  24. telegrinder/bot/dispatch/dispatch.py +61 -134
  25. telegrinder/bot/dispatch/handler/__init__.py +2 -0
  26. telegrinder/bot/dispatch/handler/abc.py +10 -8
  27. telegrinder/bot/dispatch/handler/audio_reply.py +2 -3
  28. telegrinder/bot/dispatch/handler/base.py +10 -33
  29. telegrinder/bot/dispatch/handler/document_reply.py +2 -3
  30. telegrinder/bot/dispatch/handler/func.py +55 -87
  31. telegrinder/bot/dispatch/handler/media_group_reply.py +2 -3
  32. telegrinder/bot/dispatch/handler/message_reply.py +2 -3
  33. telegrinder/bot/dispatch/handler/photo_reply.py +2 -3
  34. telegrinder/bot/dispatch/handler/sticker_reply.py +2 -3
  35. telegrinder/bot/dispatch/handler/video_reply.py +2 -3
  36. telegrinder/bot/dispatch/middleware/__init__.py +0 -0
  37. telegrinder/bot/dispatch/middleware/abc.py +79 -55
  38. telegrinder/bot/dispatch/middleware/global_middleware.py +18 -33
  39. telegrinder/bot/dispatch/process.py +84 -105
  40. telegrinder/bot/dispatch/return_manager/__init__.py +0 -0
  41. telegrinder/bot/dispatch/return_manager/abc.py +102 -65
  42. telegrinder/bot/dispatch/return_manager/callback_query.py +4 -5
  43. telegrinder/bot/dispatch/return_manager/inline_query.py +3 -4
  44. telegrinder/bot/dispatch/return_manager/message.py +8 -10
  45. telegrinder/bot/dispatch/return_manager/pre_checkout_query.py +4 -5
  46. telegrinder/bot/dispatch/view/__init__.py +4 -4
  47. telegrinder/bot/dispatch/view/abc.py +6 -16
  48. telegrinder/bot/dispatch/view/base.py +54 -178
  49. telegrinder/bot/dispatch/view/box.py +19 -18
  50. telegrinder/bot/dispatch/view/callback_query.py +4 -8
  51. telegrinder/bot/dispatch/view/chat_join_request.py +5 -6
  52. telegrinder/bot/dispatch/view/chat_member.py +5 -25
  53. telegrinder/bot/dispatch/view/error.py +9 -0
  54. telegrinder/bot/dispatch/view/inline_query.py +4 -8
  55. telegrinder/bot/dispatch/view/message.py +5 -25
  56. telegrinder/bot/dispatch/view/pre_checkout_query.py +4 -8
  57. telegrinder/bot/dispatch/view/raw.py +3 -109
  58. telegrinder/bot/dispatch/waiter_machine/__init__.py +2 -5
  59. telegrinder/bot/dispatch/waiter_machine/actions.py +6 -4
  60. telegrinder/bot/dispatch/waiter_machine/hasher/__init__.py +1 -3
  61. telegrinder/bot/dispatch/waiter_machine/hasher/callback.py +1 -1
  62. telegrinder/bot/dispatch/waiter_machine/hasher/hasher.py +11 -7
  63. telegrinder/bot/dispatch/waiter_machine/hasher/message.py +0 -0
  64. telegrinder/bot/dispatch/waiter_machine/machine.py +43 -60
  65. telegrinder/bot/dispatch/waiter_machine/middleware.py +19 -23
  66. telegrinder/bot/dispatch/waiter_machine/short_state.py +6 -5
  67. telegrinder/bot/polling/__init__.py +0 -0
  68. telegrinder/bot/polling/abc.py +0 -0
  69. telegrinder/bot/polling/polling.py +209 -88
  70. telegrinder/bot/rules/__init__.py +3 -16
  71. telegrinder/bot/rules/abc.py +42 -122
  72. telegrinder/bot/rules/callback_data.py +29 -49
  73. telegrinder/bot/rules/chat_join.py +5 -23
  74. telegrinder/bot/rules/command.py +8 -4
  75. telegrinder/bot/rules/enum_text.py +3 -4
  76. telegrinder/bot/rules/func.py +7 -14
  77. telegrinder/bot/rules/fuzzy.py +3 -4
  78. telegrinder/bot/rules/inline.py +8 -20
  79. telegrinder/bot/rules/integer.py +2 -3
  80. telegrinder/bot/rules/is_from.py +12 -11
  81. telegrinder/bot/rules/logic.py +11 -5
  82. telegrinder/bot/rules/markup.py +22 -14
  83. telegrinder/bot/rules/mention.py +8 -7
  84. telegrinder/bot/rules/message_entities.py +8 -4
  85. telegrinder/bot/rules/node.py +23 -12
  86. telegrinder/bot/rules/payload.py +5 -4
  87. telegrinder/bot/rules/payment_invoice.py +6 -21
  88. telegrinder/bot/rules/regex.py +2 -4
  89. telegrinder/bot/rules/rule_enum.py +8 -7
  90. telegrinder/bot/rules/start.py +5 -6
  91. telegrinder/bot/rules/state.py +1 -1
  92. telegrinder/bot/rules/text.py +4 -15
  93. telegrinder/bot/rules/update.py +3 -4
  94. telegrinder/bot/scenario/__init__.py +0 -0
  95. telegrinder/bot/scenario/abc.py +6 -5
  96. telegrinder/bot/scenario/checkbox.py +1 -1
  97. telegrinder/bot/scenario/choice.py +30 -39
  98. telegrinder/client/__init__.py +3 -5
  99. telegrinder/client/abc.py +11 -6
  100. telegrinder/client/aiohttp.py +141 -27
  101. telegrinder/client/form_data.py +1 -1
  102. telegrinder/model.py +61 -89
  103. telegrinder/modules.py +325 -102
  104. telegrinder/msgspec_utils/__init__.py +40 -0
  105. telegrinder/msgspec_utils/abc.py +18 -0
  106. telegrinder/msgspec_utils/custom_types/__init__.py +6 -0
  107. telegrinder/msgspec_utils/custom_types/datetime.py +24 -0
  108. telegrinder/msgspec_utils/custom_types/enum_meta.py +43 -0
  109. telegrinder/msgspec_utils/custom_types/literal.py +25 -0
  110. telegrinder/msgspec_utils/custom_types/option.py +17 -0
  111. telegrinder/msgspec_utils/decoder.py +389 -0
  112. telegrinder/msgspec_utils/encoder.py +206 -0
  113. telegrinder/{msgspec_json.py → msgspec_utils/json.py} +6 -5
  114. telegrinder/msgspec_utils/tools.py +75 -0
  115. telegrinder/node/__init__.py +24 -7
  116. telegrinder/node/attachment.py +1 -0
  117. telegrinder/node/base.py +154 -72
  118. telegrinder/node/callback_query.py +5 -5
  119. telegrinder/node/collection.py +39 -0
  120. telegrinder/node/command.py +1 -2
  121. telegrinder/node/composer.py +121 -72
  122. telegrinder/node/container.py +11 -8
  123. telegrinder/node/context.py +48 -0
  124. telegrinder/node/either.py +27 -40
  125. telegrinder/node/error.py +41 -0
  126. telegrinder/node/event.py +37 -11
  127. telegrinder/node/exceptions.py +7 -0
  128. telegrinder/node/file.py +0 -0
  129. telegrinder/node/i18n.py +108 -0
  130. telegrinder/node/me.py +3 -2
  131. telegrinder/node/payload.py +1 -1
  132. telegrinder/node/polymorphic.py +63 -28
  133. telegrinder/node/reply_message.py +12 -0
  134. telegrinder/node/rule.py +6 -13
  135. telegrinder/node/scope.py +14 -5
  136. telegrinder/node/session.py +53 -0
  137. telegrinder/node/source.py +41 -9
  138. telegrinder/node/text.py +1 -2
  139. telegrinder/node/tools/__init__.py +0 -0
  140. telegrinder/node/tools/generator.py +3 -5
  141. telegrinder/node/utility.py +16 -0
  142. telegrinder/py.typed +0 -0
  143. telegrinder/rules.py +0 -0
  144. telegrinder/tools/__init__.py +48 -88
  145. telegrinder/tools/aio.py +103 -0
  146. telegrinder/tools/callback_data_serialization/__init__.py +5 -0
  147. telegrinder/tools/{callback_data_serilization → callback_data_serialization}/abc.py +0 -0
  148. telegrinder/tools/{callback_data_serilization → callback_data_serialization}/json_ser.py +2 -3
  149. telegrinder/tools/{callback_data_serilization → callback_data_serialization}/msgpack_ser.py +45 -27
  150. telegrinder/tools/final.py +21 -0
  151. telegrinder/tools/formatting/__init__.py +2 -18
  152. telegrinder/tools/formatting/deep_links/__init__.py +39 -0
  153. telegrinder/tools/formatting/{deep_links.py → deep_links/links.py} +12 -85
  154. telegrinder/tools/formatting/deep_links/parsing.py +90 -0
  155. telegrinder/tools/formatting/deep_links/validators.py +8 -0
  156. telegrinder/tools/formatting/html_formatter.py +18 -45
  157. telegrinder/tools/fullname.py +83 -0
  158. telegrinder/tools/global_context/__init__.py +4 -3
  159. telegrinder/tools/global_context/abc.py +17 -14
  160. telegrinder/tools/global_context/builtin_context.py +39 -0
  161. telegrinder/tools/global_context/global_context.py +138 -39
  162. telegrinder/tools/input_file_directory.py +0 -0
  163. telegrinder/tools/keyboard/__init__.py +39 -0
  164. telegrinder/tools/keyboard/abc.py +159 -0
  165. telegrinder/tools/keyboard/base.py +77 -0
  166. telegrinder/tools/keyboard/buttons/__init__.py +14 -0
  167. telegrinder/tools/keyboard/buttons/base.py +18 -0
  168. telegrinder/tools/{buttons.py → keyboard/buttons/buttons.py} +71 -23
  169. telegrinder/tools/keyboard/buttons/static_buttons.py +56 -0
  170. telegrinder/tools/keyboard/buttons/tools.py +18 -0
  171. telegrinder/tools/keyboard/data.py +20 -0
  172. telegrinder/tools/keyboard/keyboard.py +131 -0
  173. telegrinder/tools/keyboard/static_keyboard.py +83 -0
  174. telegrinder/tools/lifespan.py +87 -51
  175. telegrinder/tools/limited_dict.py +4 -1
  176. telegrinder/tools/loop_wrapper.py +332 -0
  177. telegrinder/tools/magic/__init__.py +32 -0
  178. telegrinder/tools/magic/annotations.py +165 -0
  179. telegrinder/tools/magic/dictionary.py +20 -0
  180. telegrinder/tools/magic/function.py +246 -0
  181. telegrinder/tools/magic/shortcut.py +111 -0
  182. telegrinder/tools/parse_mode.py +9 -3
  183. telegrinder/tools/singleton/__init__.py +4 -0
  184. telegrinder/tools/singleton/abc.py +14 -0
  185. telegrinder/tools/singleton/singleton.py +18 -0
  186. telegrinder/tools/state_storage/__init__.py +0 -0
  187. telegrinder/tools/state_storage/abc.py +6 -1
  188. telegrinder/tools/state_storage/memory.py +1 -1
  189. telegrinder/tools/strings.py +0 -0
  190. telegrinder/types/__init__.py +307 -268
  191. telegrinder/types/enums.py +64 -37
  192. telegrinder/types/input_file.py +3 -3
  193. telegrinder/types/methods.py +5699 -5055
  194. telegrinder/types/methods_utils.py +62 -0
  195. telegrinder/types/objects.py +7846 -7058
  196. telegrinder/verification_utils.py +3 -1
  197. telegrinder-0.5.0.dist-info/METADATA +162 -0
  198. telegrinder-0.5.0.dist-info/RECORD +200 -0
  199. {telegrinder-0.4.2.dist-info → telegrinder-0.5.0.dist-info}/licenses/LICENSE +2 -2
  200. telegrinder/bot/dispatch/waiter_machine/hasher/state.py +0 -20
  201. telegrinder/bot/rules/id.py +0 -24
  202. telegrinder/bot/rules/message.py +0 -15
  203. telegrinder/client/sonic.py +0 -212
  204. telegrinder/msgspec_utils.py +0 -478
  205. telegrinder/tools/adapter/__init__.py +0 -19
  206. telegrinder/tools/adapter/abc.py +0 -49
  207. telegrinder/tools/adapter/dataclass.py +0 -56
  208. telegrinder/tools/adapter/errors.py +0 -5
  209. telegrinder/tools/adapter/event.py +0 -61
  210. telegrinder/tools/adapter/node.py +0 -46
  211. telegrinder/tools/adapter/raw_event.py +0 -27
  212. telegrinder/tools/adapter/raw_update.py +0 -30
  213. telegrinder/tools/callback_data_serilization/__init__.py +0 -5
  214. telegrinder/tools/error_handler/__init__.py +0 -10
  215. telegrinder/tools/error_handler/abc.py +0 -30
  216. telegrinder/tools/error_handler/error.py +0 -9
  217. telegrinder/tools/error_handler/error_handler.py +0 -179
  218. telegrinder/tools/formatting/spec_html_formats.py +0 -75
  219. telegrinder/tools/functional.py +0 -8
  220. telegrinder/tools/global_context/telegrinder_ctx.py +0 -27
  221. telegrinder/tools/i18n/__init__.py +0 -12
  222. telegrinder/tools/i18n/abc.py +0 -32
  223. telegrinder/tools/i18n/middleware/__init__.py +0 -3
  224. telegrinder/tools/i18n/middleware/abc.py +0 -22
  225. telegrinder/tools/i18n/simple.py +0 -43
  226. telegrinder/tools/keyboard.py +0 -132
  227. telegrinder/tools/loop_wrapper/__init__.py +0 -4
  228. telegrinder/tools/loop_wrapper/abc.py +0 -20
  229. telegrinder/tools/loop_wrapper/loop_wrapper.py +0 -169
  230. telegrinder/tools/magic.py +0 -344
  231. telegrinder-0.4.2.dist-info/METADATA +0 -151
  232. telegrinder-0.4.2.dist-info/RECORD +0 -182
  233. {telegrinder-0.4.2.dist-info → telegrinder-0.5.0.dist-info}/WHEEL +0 -0
@@ -1,10 +1,11 @@
1
1
  import typing
2
2
 
3
+ from telegrinder.bot.cute_types.message import MessageCute
4
+ from telegrinder.bot.rules.abc import ABCRule
3
5
  from telegrinder.node.source import ChatSource, UserSource
4
6
  from telegrinder.types.enums import ChatType, DiceEmoji
5
7
 
6
- from .abc import ABCRule, Message
7
- from .message import MessageRule
8
+ Message: typing.TypeAlias = MessageCute
8
9
 
9
10
 
10
11
  class IsBot(ABCRule):
@@ -71,12 +72,12 @@ class IsChat(ABCRule):
71
72
  return chat.type in (ChatType.GROUP, ChatType.SUPERGROUP)
72
73
 
73
74
 
74
- class IsDice(MessageRule):
75
+ class IsDice(ABCRule):
75
76
  def check(self, message: Message) -> bool:
76
77
  return bool(message.dice)
77
78
 
78
79
 
79
- class IsDiceEmoji(MessageRule, requires=[IsDice()]):
80
+ class IsDiceEmoji(ABCRule, requires=[IsDice()]):
80
81
  def __init__(self, dice_emoji: DiceEmoji, /) -> None:
81
82
  self.dice_emoji = dice_emoji
82
83
 
@@ -84,12 +85,12 @@ class IsDiceEmoji(MessageRule, requires=[IsDice()]):
84
85
  return message.dice.unwrap().emoji == self.dice_emoji
85
86
 
86
87
 
87
- class IsForward(MessageRule):
88
+ class IsForward(ABCRule):
88
89
  def check(self, message: Message) -> bool:
89
90
  return bool(message.forward_origin)
90
91
 
91
92
 
92
- class IsForwardType(MessageRule, requires=[IsForward()]):
93
+ class IsForwardType(ABCRule, requires=[IsForward()]):
93
94
  def __init__(self, fwd_type: typing.Literal["user", "hidden_user", "chat", "channel"], /) -> None:
94
95
  self.fwd_type = fwd_type
95
96
 
@@ -97,27 +98,27 @@ class IsForwardType(MessageRule, requires=[IsForward()]):
97
98
  return message.forward_origin.unwrap().v.type == self.fwd_type
98
99
 
99
100
 
100
- class IsReply(MessageRule):
101
+ class IsReply(ABCRule):
101
102
  def check(self, message: Message) -> bool:
102
103
  return bool(message.reply_to_message)
103
104
 
104
105
 
105
- class IsSticker(MessageRule):
106
+ class IsSticker(ABCRule):
106
107
  def check(self, message: Message) -> bool:
107
108
  return bool(message.sticker)
108
109
 
109
110
 
110
- class IsVideoNote(MessageRule):
111
+ class IsVideoNote(ABCRule):
111
112
  def check(self, message: Message) -> bool:
112
113
  return bool(message.video_note)
113
114
 
114
115
 
115
- class IsDocument(MessageRule):
116
+ class IsDocument(ABCRule):
116
117
  def check(self, message: Message) -> bool:
117
118
  return bool(message.document)
118
119
 
119
120
 
120
- class IsPhoto(MessageRule):
121
+ class IsPhoto(ABCRule):
121
122
  def check(self, message: Message) -> bool:
122
123
  return bool(message.photo)
123
124
 
@@ -1,18 +1,24 @@
1
1
  import typing
2
2
 
3
- from .abc import ABCRule, Context, UpdateCute, check_rule
3
+ from telegrinder.api.api import API
4
+ from telegrinder.bot.rules.abc import ABCRule, Context, check_rule
5
+ from telegrinder.types.objects import Update
4
6
 
5
7
 
6
8
  class If(ABCRule):
7
9
  def __init__(self, condition: ABCRule) -> None:
8
10
  self.conditions = [condition]
9
11
 
10
- async def check(self, update: UpdateCute, ctx: Context) -> bool:
12
+ async def check(self, update: Update, api: API, ctx: Context) -> bool:
11
13
  for condition in self.conditions[:-1]:
12
- if not await check_rule(update.api, condition, update, ctx):
14
+ if not await check_rule(api, condition, update, ctx):
13
15
  return True
14
- return await check_rule(update.api, self.conditions[-1], update, ctx)
15
16
 
16
- def then(self, condition: ABCRule) -> typing.Self:
17
+ return await check_rule(api, self.conditions[-1], update, ctx)
18
+
19
+ def then(self, condition: ABCRule, /) -> typing.Self:
17
20
  self.conditions.append(condition)
18
21
  return self
22
+
23
+
24
+ __all__ = ("If",)
@@ -1,41 +1,49 @@
1
+ import re
1
2
  import typing
2
3
 
3
4
  import vbml
4
5
 
5
6
  from telegrinder.bot.dispatch.context import Context
6
- from telegrinder.node.either import Either
7
+ from telegrinder.bot.rules.abc import ABCRule
7
8
  from telegrinder.node.text import Caption, Text
8
- from telegrinder.tools.global_context.telegrinder_ctx import TelegrinderContext
9
-
10
- from .abc import ABCRule
9
+ from telegrinder.tools.global_context.builtin_context import TelegrinderContext
11
10
 
12
11
  type PatternLike = str | vbml.Pattern
13
- global_ctx: typing.Final[TelegrinderContext] = TelegrinderContext()
12
+
13
+ TELEGRINDER_CONTEXT: typing.Final[TelegrinderContext] = TelegrinderContext()
14
14
 
15
15
 
16
16
  def check_string(patterns: list[vbml.Pattern], s: str, ctx: Context) -> bool:
17
17
  for pattern in patterns:
18
- match global_ctx.vbml_patcher.check(pattern, s):
19
- case None | False:
20
- continue
18
+ match TELEGRINDER_CONTEXT.vbml_patcher.check(pattern, s):
21
19
  case {**response}:
22
20
  ctx |= response
21
+ case None | False:
22
+ continue
23
+
23
24
  return True
25
+
24
26
  return False
25
27
 
26
28
 
27
29
  class Markup(ABCRule):
28
30
  """Markup Language. See the [vbml documentation](https://github.com/tesseradecade/vbml/blob/master/docs/index.md)."""
29
31
 
30
- def __init__(self, patterns: PatternLike | list[PatternLike], /) -> None:
31
- if not isinstance(patterns, list):
32
- patterns = [patterns]
32
+ def __init__(
33
+ self,
34
+ patterns: PatternLike | list[PatternLike],
35
+ /,
36
+ *,
37
+ flags: re.RegexFlag | None = None,
38
+ ) -> None:
33
39
  self.patterns = [
34
- vbml.Pattern(pattern, flags=global_ctx.vbml_pattern_flags) if isinstance(pattern, str) else pattern
35
- for pattern in patterns
40
+ vbml.Pattern(text=pattern, flags=flags or TELEGRINDER_CONTEXT.vbml_pattern_flags)
41
+ if isinstance(pattern, str)
42
+ else pattern
43
+ for pattern in ([patterns] if not isinstance(patterns, list) else patterns)
36
44
  ]
37
45
 
38
- def check(self, text: Either[Text, Caption], ctx: Context) -> bool:
46
+ def check(self, text: Text | Caption, ctx: Context) -> bool:
39
47
  return check_string(self.patterns, text, ctx)
40
48
 
41
49
 
@@ -1,14 +1,15 @@
1
+ from telegrinder.bot.cute_types.message import MessageCute
2
+ from telegrinder.bot.rules.abc import ABCRule
3
+ from telegrinder.bot.rules.text import HasText
1
4
  from telegrinder.types.enums import MessageEntityType
2
5
 
3
- from .message import Message, MessageRule
4
- from .text import HasText
5
6
 
6
-
7
- class HasMention(MessageRule, requires=[HasText()]):
8
- def check(self, message: Message) -> bool:
9
- if not message.entities.unwrap_or_none():
7
+ class HasMention(ABCRule, requires=[HasText()]):
8
+ def check(self, message: MessageCute) -> bool:
9
+ entities = message.entities.unwrap_or_none()
10
+ if not entities:
10
11
  return False
11
- return any(entity.type == MessageEntityType.MENTION for entity in message.entities.unwrap())
12
+ return any(entity.type == MessageEntityType.MENTION for entity in entities)
12
13
 
13
14
 
14
15
  __all__ = ("HasMention",)
@@ -1,18 +1,22 @@
1
+ import typing
2
+
3
+ from telegrinder.bot.cute_types.message import MessageCute
1
4
  from telegrinder.bot.dispatch.context import Context
5
+ from telegrinder.bot.rules.abc import ABCRule
2
6
  from telegrinder.types.enums import MessageEntityType
3
7
  from telegrinder.types.objects import MessageEntity
4
8
 
5
- from .message import Message, MessageRule
6
-
7
9
  type Entity = str | MessageEntityType
8
10
 
11
+ Message: typing.TypeAlias = MessageCute
12
+
9
13
 
10
- class HasEntities(MessageRule):
14
+ class HasEntities(ABCRule):
11
15
  def check(self, message: Message) -> bool:
12
16
  return bool(message.entities)
13
17
 
14
18
 
15
- class MessageEntities(MessageRule, requires=[HasEntities()]):
19
+ class MessageEntities(ABCRule, requires=[HasEntities()]):
16
20
  def __init__(self, entities: Entity | list[Entity], /) -> None:
17
21
  self.entities = [entities] if not isinstance(entities, list) else entities
18
22
 
@@ -1,10 +1,11 @@
1
- import typing
1
+ from fntypes.result import Ok
2
2
 
3
+ from telegrinder.api.api import API
3
4
  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
5
+ from telegrinder.bot.rules.abc import ABCRule
6
+ from telegrinder.node.base import IsNode, is_node
7
+ from telegrinder.node.composer import compose_nodes
8
+ from telegrinder.types.objects import Update
8
9
 
9
10
 
10
11
  class NodeRule(ABCRule):
@@ -19,14 +20,24 @@ class NodeRule(ABCRule):
19
20
  self.nodes.append(node_t)
20
21
  self.node_keys.append(node_key)
21
22
 
22
- @property
23
- def adapter(self) -> NodeAdapter:
24
- return NodeAdapter(*self.nodes)
23
+ async def check(self, update: Update, api: API, context: Context) -> bool:
24
+ result = await compose_nodes(
25
+ nodes={f"node_{i}": node for i, node in enumerate(self.nodes)},
26
+ ctx=context,
27
+ data={Update: update, API: api},
28
+ )
29
+
30
+ match result:
31
+ case Ok(collection):
32
+ resolved_nodes = collection.sessions
33
+ case _:
34
+ return False
35
+
36
+ for i, (node_key, node_value) in enumerate(resolved_nodes.items()):
37
+ if (key := self.node_keys[i]) and node_key == key:
38
+ context[key] = node_value
25
39
 
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
40
+ await collection.close_all()
30
41
  return True
31
42
 
32
43
 
@@ -7,11 +7,11 @@ import msgspec
7
7
  from telegrinder.bot.dispatch.context import Context
8
8
  from telegrinder.bot.rules.abc import ABCRule
9
9
  from telegrinder.bot.rules.markup import Markup, PatternLike, check_string
10
- from telegrinder.msgspec_json import loads
10
+ from telegrinder.msgspec_utils.json import loads
11
11
  from telegrinder.node.base import Node
12
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
13
+ from telegrinder.tools.callback_data_serialization.abc import ABCDataSerializer, ModelType
14
+ from telegrinder.tools.callback_data_serialization.json_ser import JSONSerializer
15
15
 
16
16
 
17
17
  class PayloadRule[Data](ABCRule):
@@ -35,10 +35,11 @@ class PayloadRule[Data](ABCRule):
35
35
  return True
36
36
 
37
37
 
38
- class PayloadModelRule[Model: ModelType](PayloadRule[Model]):
38
+ class PayloadModelRule[Model: ModelType](PayloadRule):
39
39
  def __init__(
40
40
  self,
41
41
  model_t: type[Model],
42
+ /,
42
43
  *,
43
44
  serializer: type[ABCDataSerializer[Model]] | None = None,
44
45
  alias: str | None = None,
@@ -1,29 +1,14 @@
1
- import abc
2
- import typing
3
-
4
1
  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: ...
2
+ from telegrinder.bot.rules.abc import ABCRule
3
+ from telegrinder.types.enums import Currency
19
4
 
20
5
 
21
- class PaymentInvoiceCurrency(PaymentInvoiceRule):
22
- def __init__(self, currency: str | Currency, /) -> None:
6
+ class PaymentInvoiceCurrency(ABCRule):
7
+ def __init__(self, currency: Currency, /) -> None:
23
8
  self.currency = currency
24
9
 
25
- def check(self, query: PreCheckoutQuery) -> bool:
10
+ def check(self, query: PreCheckoutQueryCute) -> bool:
26
11
  return self.currency == query.currency
27
12
 
28
13
 
29
- __all__ = ("PaymentInvoiceCurrency", "PaymentInvoiceRule")
14
+ __all__ = ("PaymentInvoiceCurrency",)
@@ -2,11 +2,9 @@ import re
2
2
  import typing
3
3
 
4
4
  from telegrinder.bot.dispatch.context import Context
5
- from telegrinder.node.either import Either
5
+ from telegrinder.bot.rules.abc import ABCRule
6
6
  from telegrinder.node.text import Caption, Text
7
7
 
8
- from .abc import ABCRule
9
-
10
8
  type PatternLike = str | typing.Pattern[str]
11
9
 
12
10
 
@@ -21,7 +19,7 @@ class Regex(ABCRule):
21
19
  case _:
22
20
  self.regexp.extend(re.compile(regexp) if isinstance(regexp, str) else regexp for regexp in regexp)
23
21
 
24
- def check(self, text: Either[Text, Caption], ctx: Context) -> bool:
22
+ def check(self, text: Text | Caption, ctx: Context) -> bool:
25
23
  for regexp in self.regexp:
26
24
  response = re.match(regexp, text)
27
25
  if response is not None:
@@ -1,10 +1,11 @@
1
1
  import dataclasses
2
2
  import typing
3
3
 
4
+ from telegrinder.api.api import API
4
5
  from telegrinder.bot.dispatch.context import Context
5
-
6
- from .abc import ABCRule, Update, check_rule
7
- from .func import FuncRule
6
+ from telegrinder.bot.rules.abc import ABCRule, check_rule
7
+ from telegrinder.bot.rules.func import FuncRule
8
+ from telegrinder.types.objects import Update
8
9
 
9
10
 
10
11
  @dataclasses.dataclass(slots=True)
@@ -42,11 +43,11 @@ class RuleEnum(ABCRule):
42
43
 
43
44
  @classmethod
44
45
  def save_state(cls, ctx: Context, enum: RuleEnumState) -> None:
45
- ctx.update({cls.__class__.__name__ + "_state": enum})
46
+ ctx.update({cls.__name__ + "_state": enum})
46
47
 
47
48
  @classmethod
48
49
  def check_state(cls, ctx: Context) -> RuleEnumState | None:
49
- return ctx.get(cls.__class__.__name__ + "_state")
50
+ return ctx.get(cls.__name__ + "_state")
50
51
 
51
52
  @classmethod
52
53
  def must_be_state(cls, ctx: Context, state: RuleEnumState) -> bool:
@@ -55,13 +56,13 @@ class RuleEnum(ABCRule):
55
56
  return False
56
57
  return real_state == state
57
58
 
58
- async def check(self, event: Update, ctx: Context) -> bool:
59
+ async def check(self, event: Update, api: API, ctx: Context) -> bool:
59
60
  if self.check_state(ctx):
60
61
  return True
61
62
 
62
63
  for enum in self.__enum__:
63
64
  ctx_copy = ctx.copy()
64
- if await check_rule(event.ctx_api, enum.rule, event, ctx_copy):
65
+ if await check_rule(api, enum.rule, event, ctx_copy):
65
66
  ctx.update(ctx_copy)
66
67
  self.save_state(ctx, enum)
67
68
  return True
@@ -1,16 +1,15 @@
1
1
  import typing
2
2
 
3
3
  from telegrinder.bot.dispatch.context import Context
4
+ from telegrinder.bot.rules.abc import ABCRule
5
+ from telegrinder.bot.rules.is_from import IsPrivate
6
+ from telegrinder.bot.rules.markup import Markup
7
+ from telegrinder.bot.rules.message_entities import MessageEntities
4
8
  from telegrinder.types.enums import MessageEntityType
5
9
 
6
- from .is_from import IsPrivate
7
- from .markup import Markup
8
- from .message import MessageRule
9
- from .message_entities import MessageEntities
10
-
11
10
 
12
11
  class StartCommand(
13
- MessageRule,
12
+ ABCRule,
14
13
  requires=[
15
14
  IsPrivate(),
16
15
  MessageEntities(MessageEntityType.BOT_COMMAND),
@@ -28,7 +28,7 @@ class State[Payload](ABCRule):
28
28
  if self.key != StateMeta.ANY and self.key != state.unwrap().key:
29
29
  return False
30
30
 
31
- ctx["state"] = state.unwrap()
31
+ ctx.state = state.unwrap()
32
32
  return True
33
33
 
34
34
 
@@ -1,10 +1,6 @@
1
- import typing
2
-
3
1
  from telegrinder import node
4
- from telegrinder.tools.i18n.abc import ABCTranslator
5
-
6
- from .abc import ABCRule, with_caching_translations
7
- from .node import NodeRule
2
+ from telegrinder.bot.rules.abc import ABCRule
3
+ from telegrinder.bot.rules.node import NodeRule
8
4
 
9
5
 
10
6
  class HasText(NodeRule):
@@ -21,18 +17,11 @@ class Text(ABCRule):
21
17
  def __init__(self, texts: str | list[str], /, *, ignore_case: bool = False) -> None:
22
18
  if not isinstance(texts, list):
23
19
  texts = [texts]
24
- self.texts = texts if not ignore_case else list(map(str.lower, texts))
20
+ self.texts = set(texts) if not ignore_case else set(map(str.lower, texts))
25
21
  self.ignore_case = ignore_case
26
22
 
27
- def check(self, text: node.either.Either[node.text.Text, node.text.Caption]) -> bool:
23
+ def check(self, text: node.text.Text | node.text.Caption) -> bool:
28
24
  return (text if not self.ignore_case else text.lower()) in self.texts
29
25
 
30
- @with_caching_translations
31
- async def translate(self, translator: ABCTranslator) -> typing.Self:
32
- return self.__class__(
33
- [translator.get(text) for text in self.texts],
34
- ignore_case=self.ignore_case,
35
- )
36
-
37
26
 
38
27
  __all__ = ("HasCaption", "HasText", "Text")
@@ -1,14 +1,13 @@
1
- from telegrinder.bot.cute_types.update import UpdateCute
1
+ from telegrinder.bot.rules.abc import ABCRule
2
2
  from telegrinder.types.enums import UpdateType
3
-
4
- from .abc import ABCRule
3
+ from telegrinder.types.objects import Update
5
4
 
6
5
 
7
6
  class IsUpdateType(ABCRule):
8
7
  def __init__(self, update_type: UpdateType, /) -> None:
9
8
  self.update_type = update_type
10
9
 
11
- def check(self, event: UpdateCute) -> bool:
10
+ def check(self, event: Update) -> bool:
12
11
  return event.update_type == self.update_type
13
12
 
14
13
 
File without changes
@@ -1,16 +1,17 @@
1
+ from __future__ import annotations
2
+
1
3
  import typing
2
4
  from abc import ABC, abstractmethod
3
5
 
4
- from telegrinder.bot.cute_types.base import BaseCute
5
-
6
6
  if typing.TYPE_CHECKING:
7
- from telegrinder.api import API
8
- from telegrinder.bot.dispatch.view.abc import ABCStateView
7
+ from telegrinder.api.api import API
8
+ from telegrinder.bot.cute_types.base import BaseCute
9
+ from telegrinder.bot.dispatch.waiter_machine.hasher.hasher import Hasher
9
10
 
10
11
 
11
12
  class ABCScenario[Event: BaseCute](ABC):
12
13
  @abstractmethod
13
- def wait(self, api: "API", view: "ABCStateView[Event]") -> typing.Any:
14
+ def wait(self, hasher: Hasher, api: API) -> typing.Any:
14
15
  pass
15
16
 
16
17
 
@@ -29,7 +29,7 @@ class Choice[Key: typing.Hashable]:
29
29
  code: str
30
30
 
31
31
 
32
- class _Checkbox(ABCScenario[CallbackQueryCute]):
32
+ class _Checkbox[T](ABCScenario[CallbackQueryCute]):
33
33
  INVALID_CODE = "Invalid code"
34
34
  CALLBACK_ANSWER = "Done"
35
35
  PARSE_MODE = ParseMode.HTML
@@ -1,48 +1,39 @@
1
1
  import typing
2
2
 
3
+ from telegrinder.api.api import API
3
4
  from telegrinder.bot.cute_types.callback_query import CallbackQueryCute
4
5
  from telegrinder.bot.dispatch.waiter_machine.hasher.hasher import Hasher
5
6
  from telegrinder.bot.scenario.checkbox import Checkbox, ChoiceAction
6
7
 
7
- if typing.TYPE_CHECKING:
8
- from telegrinder.api.api import API
9
-
10
- class Choice[Key: typing.Hashable](Checkbox[Key]):
11
- async def wait(
12
- self,
13
- hasher: Hasher[CallbackQueryCute, int],
14
- api: API,
15
- ) -> tuple[Key, int]: ...
16
-
17
- else:
18
-
19
- class Choice(Checkbox):
20
- async def handle(self, cb):
21
- code = cb.data.unwrap().replace(self.random_code + "/", "", 1)
22
- if code == ChoiceAction.READY:
23
- return False
24
-
25
- for choice in self.choices:
26
- choice.is_picked = False
27
-
28
- for i, choice in enumerate(self.choices):
29
- if choice.code == code:
30
- self.choices[i].is_picked = True
31
- await cb.ctx_api.edit_message_text(
32
- text=self.message,
33
- chat_id=cb.message.unwrap().v.chat.id,
34
- message_id=cb.message.unwrap().v.message_id,
35
- parse_mode=self.PARSE_MODE,
36
- reply_markup=self.get_markup(),
37
- )
38
-
39
- return True
40
-
41
- async def wait(self, hasher, api):
42
- if len(tuple(choice for choice in self.choices if choice.is_picked)) != 1:
43
- raise ValueError("Exactly one choice must be picked.")
44
- choices, m_id = await super().wait(hasher, api)
45
- return tuple(choices.keys())[tuple(choices.values()).index(True)], m_id
8
+
9
+ class Choice[Key: typing.Hashable](Checkbox[Key]):
10
+ async def handle(self, cb: CallbackQueryCute) -> bool:
11
+ code = cb.data.unwrap().replace(self.random_code + "/", "", 1)
12
+ if code == ChoiceAction.READY:
13
+ return False
14
+
15
+ for choice in self.choices:
16
+ choice.is_picked = False
17
+
18
+ for i, choice in enumerate(self.choices):
19
+ if choice.code == code:
20
+ self.choices[i].is_picked = True
21
+ await cb.ctx_api.edit_message_text(
22
+ text=self.message,
23
+ chat_id=cb.message.unwrap().v.chat.id,
24
+ message_id=cb.message.unwrap().v.message_id,
25
+ parse_mode=self.PARSE_MODE,
26
+ reply_markup=self.get_markup(),
27
+ )
28
+
29
+ return True
30
+
31
+ async def wait(self, hasher: Hasher[CallbackQueryCute, int], api: API) -> tuple[Key, int]:
32
+ if len(tuple(choice for choice in self.choices if choice.is_picked)) != 1:
33
+ raise ValueError("Exactly one choice must be picked.")
34
+
35
+ choices, m_id = await super().wait(hasher, api)
36
+ return tuple(choices.keys())[tuple(choices.values()).index(True)], m_id
46
37
 
47
38
 
48
39
  __all__ = ("Choice",)
@@ -1,12 +1,10 @@
1
- from .abc import ABCClient
2
- from .aiohttp import AiohttpClient
3
- from .form_data import MultipartFormProto, encode_form_data
4
- from .sonic import AiosonicClient
1
+ from telegrinder.client.abc import ABCClient
2
+ from telegrinder.client.aiohttp import AiohttpClient
3
+ from telegrinder.client.form_data import MultipartFormProto, encode_form_data
5
4
 
6
5
  __all__ = (
7
6
  "ABCClient",
8
7
  "AiohttpClient",
9
- "AiosonicClient",
10
8
  "MultipartFormProto",
11
9
  "encode_form_data",
12
10
  )