telegrinder 0.3.4__py3-none-any.whl → 0.4.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of telegrinder might be problematic. Click here for more details.

Files changed (192) hide show
  1. telegrinder/__init__.py +148 -149
  2. telegrinder/api/__init__.py +9 -8
  3. telegrinder/api/api.py +101 -93
  4. telegrinder/api/error.py +20 -16
  5. telegrinder/api/response.py +20 -20
  6. telegrinder/api/token.py +36 -36
  7. telegrinder/bot/__init__.py +72 -66
  8. telegrinder/bot/bot.py +83 -76
  9. telegrinder/bot/cute_types/__init__.py +19 -17
  10. telegrinder/bot/cute_types/base.py +184 -258
  11. telegrinder/bot/cute_types/callback_query.py +400 -385
  12. telegrinder/bot/cute_types/chat_join_request.py +62 -61
  13. telegrinder/bot/cute_types/chat_member_updated.py +157 -160
  14. telegrinder/bot/cute_types/inline_query.py +44 -43
  15. telegrinder/bot/cute_types/message.py +2590 -2637
  16. telegrinder/bot/cute_types/pre_checkout_query.py +42 -0
  17. telegrinder/bot/cute_types/update.py +112 -104
  18. telegrinder/bot/cute_types/utils.py +62 -95
  19. telegrinder/bot/dispatch/__init__.py +59 -55
  20. telegrinder/bot/dispatch/abc.py +76 -77
  21. telegrinder/bot/dispatch/context.py +96 -98
  22. telegrinder/bot/dispatch/dispatch.py +254 -202
  23. telegrinder/bot/dispatch/handler/__init__.py +13 -13
  24. telegrinder/bot/dispatch/handler/abc.py +23 -24
  25. telegrinder/bot/dispatch/handler/audio_reply.py +44 -44
  26. telegrinder/bot/dispatch/handler/base.py +57 -57
  27. telegrinder/bot/dispatch/handler/document_reply.py +44 -44
  28. telegrinder/bot/dispatch/handler/func.py +129 -135
  29. telegrinder/bot/dispatch/handler/media_group_reply.py +44 -43
  30. telegrinder/bot/dispatch/handler/message_reply.py +36 -36
  31. telegrinder/bot/dispatch/handler/photo_reply.py +44 -44
  32. telegrinder/bot/dispatch/handler/sticker_reply.py +37 -37
  33. telegrinder/bot/dispatch/handler/video_reply.py +44 -44
  34. telegrinder/bot/dispatch/middleware/__init__.py +3 -3
  35. telegrinder/bot/dispatch/middleware/abc.py +97 -22
  36. telegrinder/bot/dispatch/middleware/global_middleware.py +70 -0
  37. telegrinder/bot/dispatch/process.py +151 -157
  38. telegrinder/bot/dispatch/return_manager/__init__.py +15 -13
  39. telegrinder/bot/dispatch/return_manager/abc.py +104 -108
  40. telegrinder/bot/dispatch/return_manager/callback_query.py +20 -20
  41. telegrinder/bot/dispatch/return_manager/inline_query.py +15 -15
  42. telegrinder/bot/dispatch/return_manager/message.py +36 -36
  43. telegrinder/bot/dispatch/return_manager/pre_checkout_query.py +20 -0
  44. telegrinder/bot/dispatch/view/__init__.py +15 -13
  45. telegrinder/bot/dispatch/view/abc.py +45 -41
  46. telegrinder/bot/dispatch/view/base.py +231 -200
  47. telegrinder/bot/dispatch/view/box.py +140 -129
  48. telegrinder/bot/dispatch/view/callback_query.py +16 -17
  49. telegrinder/bot/dispatch/view/chat_join_request.py +11 -16
  50. telegrinder/bot/dispatch/view/chat_member.py +37 -39
  51. telegrinder/bot/dispatch/view/inline_query.py +16 -17
  52. telegrinder/bot/dispatch/view/message.py +43 -44
  53. telegrinder/bot/dispatch/view/pre_checkout_query.py +16 -0
  54. telegrinder/bot/dispatch/view/raw.py +116 -114
  55. telegrinder/bot/dispatch/waiter_machine/__init__.py +17 -17
  56. telegrinder/bot/dispatch/waiter_machine/actions.py +14 -13
  57. telegrinder/bot/dispatch/waiter_machine/hasher/__init__.py +8 -8
  58. telegrinder/bot/dispatch/waiter_machine/hasher/callback.py +55 -55
  59. telegrinder/bot/dispatch/waiter_machine/hasher/hasher.py +59 -57
  60. telegrinder/bot/dispatch/waiter_machine/hasher/message.py +51 -51
  61. telegrinder/bot/dispatch/waiter_machine/hasher/state.py +20 -19
  62. telegrinder/bot/dispatch/waiter_machine/machine.py +251 -172
  63. telegrinder/bot/dispatch/waiter_machine/middleware.py +94 -89
  64. telegrinder/bot/dispatch/waiter_machine/short_state.py +57 -68
  65. telegrinder/bot/polling/__init__.py +4 -4
  66. telegrinder/bot/polling/abc.py +25 -25
  67. telegrinder/bot/polling/polling.py +139 -131
  68. telegrinder/bot/rules/__init__.py +85 -62
  69. telegrinder/bot/rules/abc.py +213 -206
  70. telegrinder/bot/rules/callback_data.py +122 -163
  71. telegrinder/bot/rules/chat_join.py +45 -43
  72. telegrinder/bot/rules/command.py +126 -126
  73. telegrinder/bot/rules/enum_text.py +33 -36
  74. telegrinder/bot/rules/func.py +28 -26
  75. telegrinder/bot/rules/fuzzy.py +24 -24
  76. telegrinder/bot/rules/id.py +24 -0
  77. telegrinder/bot/rules/inline.py +58 -56
  78. telegrinder/bot/rules/integer.py +21 -20
  79. telegrinder/bot/rules/is_from.py +127 -127
  80. telegrinder/bot/rules/logic.py +18 -0
  81. telegrinder/bot/rules/markup.py +42 -43
  82. telegrinder/bot/rules/mention.py +14 -14
  83. telegrinder/bot/rules/message.py +15 -17
  84. telegrinder/bot/rules/message_entities.py +33 -35
  85. telegrinder/bot/rules/node.py +33 -27
  86. telegrinder/bot/rules/payload.py +81 -0
  87. telegrinder/bot/rules/payment_invoice.py +29 -0
  88. telegrinder/bot/rules/regex.py +36 -37
  89. telegrinder/bot/rules/rule_enum.py +72 -72
  90. telegrinder/bot/rules/start.py +42 -42
  91. telegrinder/bot/rules/state.py +35 -37
  92. telegrinder/bot/rules/text.py +38 -33
  93. telegrinder/bot/rules/update.py +15 -15
  94. telegrinder/bot/scenario/__init__.py +5 -5
  95. telegrinder/bot/scenario/abc.py +17 -19
  96. telegrinder/bot/scenario/checkbox.py +174 -176
  97. telegrinder/bot/scenario/choice.py +48 -51
  98. telegrinder/client/__init__.py +12 -4
  99. telegrinder/client/abc.py +100 -75
  100. telegrinder/client/aiohttp.py +134 -130
  101. telegrinder/client/form_data.py +31 -0
  102. telegrinder/client/sonic.py +212 -0
  103. telegrinder/model.py +208 -315
  104. telegrinder/modules.py +239 -237
  105. telegrinder/msgspec_json.py +14 -14
  106. telegrinder/msgspec_utils.py +478 -410
  107. telegrinder/node/__init__.py +86 -25
  108. telegrinder/node/attachment.py +163 -87
  109. telegrinder/node/base.py +288 -160
  110. telegrinder/node/callback_query.py +54 -53
  111. telegrinder/node/command.py +34 -33
  112. telegrinder/node/composer.py +163 -198
  113. telegrinder/node/container.py +33 -27
  114. telegrinder/node/either.py +82 -0
  115. telegrinder/node/event.py +54 -65
  116. telegrinder/node/file.py +51 -0
  117. telegrinder/node/me.py +15 -16
  118. telegrinder/node/payload.py +78 -0
  119. telegrinder/node/polymorphic.py +67 -48
  120. telegrinder/node/rule.py +72 -76
  121. telegrinder/node/scope.py +36 -38
  122. telegrinder/node/source.py +87 -71
  123. telegrinder/node/text.py +53 -41
  124. telegrinder/node/tools/__init__.py +3 -3
  125. telegrinder/node/tools/generator.py +36 -40
  126. telegrinder/py.typed +0 -0
  127. telegrinder/rules.py +1 -62
  128. telegrinder/tools/__init__.py +152 -93
  129. telegrinder/tools/adapter/__init__.py +19 -0
  130. telegrinder/tools/adapter/abc.py +49 -0
  131. telegrinder/tools/adapter/dataclass.py +56 -0
  132. telegrinder/{bot/rules → tools}/adapter/errors.py +5 -5
  133. telegrinder/{bot/rules → tools}/adapter/event.py +63 -65
  134. telegrinder/{bot/rules → tools}/adapter/node.py +46 -48
  135. telegrinder/{bot/rules → tools}/adapter/raw_event.py +27 -27
  136. telegrinder/{bot/rules → tools}/adapter/raw_update.py +30 -30
  137. telegrinder/tools/buttons.py +106 -80
  138. telegrinder/tools/callback_data_serilization/__init__.py +5 -0
  139. telegrinder/tools/callback_data_serilization/abc.py +51 -0
  140. telegrinder/tools/callback_data_serilization/json_ser.py +60 -0
  141. telegrinder/tools/callback_data_serilization/msgpack_ser.py +172 -0
  142. telegrinder/tools/error_handler/__init__.py +7 -7
  143. telegrinder/tools/error_handler/abc.py +30 -33
  144. telegrinder/tools/error_handler/error.py +9 -9
  145. telegrinder/tools/error_handler/error_handler.py +179 -193
  146. telegrinder/tools/formatting/__init__.py +83 -63
  147. telegrinder/tools/formatting/deep_links.py +541 -0
  148. telegrinder/tools/formatting/{html.py → html_formatter.py} +266 -294
  149. telegrinder/tools/formatting/spec_html_formats.py +71 -117
  150. telegrinder/tools/functional.py +8 -12
  151. telegrinder/tools/global_context/__init__.py +7 -7
  152. telegrinder/tools/global_context/abc.py +63 -63
  153. telegrinder/tools/global_context/global_context.py +387 -412
  154. telegrinder/tools/global_context/telegrinder_ctx.py +27 -27
  155. telegrinder/tools/i18n/__init__.py +7 -7
  156. telegrinder/tools/i18n/abc.py +30 -30
  157. telegrinder/tools/i18n/middleware/__init__.py +3 -3
  158. telegrinder/tools/i18n/middleware/abc.py +22 -25
  159. telegrinder/tools/i18n/simple.py +43 -43
  160. telegrinder/tools/input_file_directory.py +30 -0
  161. telegrinder/tools/keyboard.py +128 -128
  162. telegrinder/tools/lifespan.py +105 -0
  163. telegrinder/tools/limited_dict.py +32 -37
  164. telegrinder/tools/loop_wrapper/__init__.py +4 -4
  165. telegrinder/tools/loop_wrapper/abc.py +20 -15
  166. telegrinder/tools/loop_wrapper/loop_wrapper.py +169 -224
  167. telegrinder/tools/magic.py +307 -157
  168. telegrinder/tools/parse_mode.py +6 -6
  169. telegrinder/tools/state_storage/__init__.py +4 -4
  170. telegrinder/tools/state_storage/abc.py +31 -35
  171. telegrinder/tools/state_storage/memory.py +25 -25
  172. telegrinder/tools/strings.py +13 -0
  173. telegrinder/types/__init__.py +268 -260
  174. telegrinder/types/enums.py +711 -701
  175. telegrinder/types/input_file.py +51 -0
  176. telegrinder/types/methods.py +5055 -4633
  177. telegrinder/types/objects.py +7058 -6950
  178. telegrinder/verification_utils.py +30 -32
  179. {telegrinder-0.3.4.dist-info → telegrinder-0.4.0.dist-info}/LICENSE +22 -22
  180. telegrinder-0.4.0.dist-info/METADATA +144 -0
  181. telegrinder-0.4.0.dist-info/RECORD +182 -0
  182. {telegrinder-0.3.4.dist-info → telegrinder-0.4.0.dist-info}/WHEEL +1 -1
  183. telegrinder/bot/rules/adapter/__init__.py +0 -17
  184. telegrinder/bot/rules/adapter/abc.py +0 -31
  185. telegrinder/node/message.py +0 -14
  186. telegrinder/node/update.py +0 -15
  187. telegrinder/tools/formatting/links.py +0 -38
  188. telegrinder/tools/kb_set/__init__.py +0 -4
  189. telegrinder/tools/kb_set/base.py +0 -15
  190. telegrinder/tools/kb_set/yaml.py +0 -63
  191. telegrinder-0.3.4.dist-info/METADATA +0 -110
  192. telegrinder-0.3.4.dist-info/RECORD +0 -165
telegrinder/node/text.py CHANGED
@@ -1,41 +1,53 @@
1
- import typing
2
-
3
- from telegrinder.node.base import ComposeError, FactoryNode, ScalarNode
4
- from telegrinder.node.message import MessageNode
5
-
6
-
7
- class Text(ScalarNode, str):
8
- @classmethod
9
- def compose(cls, message: MessageNode) -> str:
10
- if not message.text:
11
- raise ComposeError("Message has no text.")
12
- return message.text.unwrap()
13
-
14
-
15
- class TextInteger(ScalarNode, int):
16
- @classmethod
17
- def compose(cls, text: Text) -> int:
18
- if not text.isdigit():
19
- raise ComposeError("Text is not digit.")
20
- return int(text)
21
-
22
-
23
- if typing.TYPE_CHECKING:
24
- from typing import Literal as TextLiteral
25
-
26
- else:
27
-
28
- class TextLiteral(FactoryNode):
29
- texts: tuple[str, ...]
30
-
31
- def __class_getitem__(cls, texts, /):
32
- return cls(texts=(texts,) if not isinstance(texts, tuple) else texts)
33
-
34
- @classmethod
35
- def compose(cls, text: Text) -> str:
36
- if text in cls.texts:
37
- return text
38
- raise ComposeError("Text matching failed.")
39
-
40
-
41
- __all__ = ("Text", "TextInteger", "TextLiteral")
1
+ import typing
2
+
3
+ from telegrinder.bot.cute_types.message import MessageCute
4
+ from telegrinder.node.base import ComposeError, FactoryNode, scalar_node
5
+ from telegrinder.node.either import Either
6
+
7
+
8
+ @scalar_node
9
+ class Caption:
10
+ @classmethod
11
+ def compose(cls, message: MessageCute) -> str:
12
+ if not message.caption:
13
+ raise ComposeError("Message has no caption.")
14
+ return message.caption.unwrap()
15
+
16
+
17
+ @scalar_node
18
+ class Text:
19
+ @classmethod
20
+ def compose(cls, message: MessageCute) -> str:
21
+ if not message.text:
22
+ raise ComposeError("Message has no text.")
23
+ return message.text.unwrap()
24
+
25
+
26
+ @scalar_node
27
+ class TextInteger:
28
+ @classmethod
29
+ def compose(cls, text: Either[Text, Caption]) -> int:
30
+ if not text.isdigit():
31
+ raise ComposeError("Text is not digit.")
32
+ return int(text)
33
+
34
+
35
+ if typing.TYPE_CHECKING:
36
+ from typing import Literal as TextLiteral
37
+
38
+ else:
39
+
40
+ class TextLiteral(FactoryNode):
41
+ texts: tuple[str, ...]
42
+
43
+ def __class_getitem__(cls, texts, /):
44
+ return cls(texts=(texts,) if not isinstance(texts, tuple) else texts)
45
+
46
+ @classmethod
47
+ def compose(cls, text: Text) -> str:
48
+ if text in cls.texts:
49
+ return text
50
+ raise ComposeError("Text mismatched literal.")
51
+
52
+
53
+ __all__ = ("Caption", "Text", "TextInteger", "TextLiteral")
@@ -1,3 +1,3 @@
1
- from .generator import generate_node
2
-
3
- __all__ = ("generate_node",)
1
+ from .generator import generate_node
2
+
3
+ __all__ = ("generate_node",)
@@ -1,40 +1,36 @@
1
- import inspect
2
- import typing
3
-
4
- from telegrinder.node.base import ComposeError, Node
5
- from telegrinder.node.container import ContainerNode
6
-
7
- T = typing.TypeVar("T")
8
-
9
-
10
- def cast_false_to_none(value: T) -> T | None:
11
- if value is False:
12
- return None
13
- return value
14
-
15
-
16
- def error_on_none(value: T | None) -> T:
17
- if value is None:
18
- raise ComposeError
19
- return value
20
-
21
-
22
- def generate_node(
23
- subnodes: tuple[type[Node], ...],
24
- func: typing.Callable[..., typing.Any],
25
- casts: tuple[typing.Callable[[typing.Any], typing.Any], ...] = (cast_false_to_none, error_on_none),
26
- ) -> type[Node]:
27
- async def compose(cls, **kw) -> typing.Any:
28
- result = func(*ContainerNode.compose(**kw)) # type: ignore
29
- if inspect.isawaitable(result):
30
- result = await result
31
- for cast in casts:
32
- result = cast(result)
33
- return result
34
-
35
- container = ContainerNode.link_nodes(list(subnodes))
36
- compose.__annotations__ = container.get_subnodes()
37
- return type("_ContainerNode", (container,), {"compose": classmethod(compose)})
38
-
39
-
40
- __all__ = ("generate_node",)
1
+ import inspect
2
+ import typing
3
+
4
+ from telegrinder.node.base import ComposeError, IsNode, Node
5
+ from telegrinder.node.container import ContainerNode
6
+
7
+
8
+ def cast_false_to_none[Value](value: Value) -> Value | None:
9
+ if value is False:
10
+ return None
11
+ return value
12
+
13
+
14
+ def error_on_none[Value](value: Value | None) -> Value:
15
+ if value is None:
16
+ raise ComposeError
17
+ return value
18
+
19
+
20
+ def generate_node(
21
+ subnodes: tuple[IsNode, ...],
22
+ func: typing.Callable[..., typing.Any],
23
+ casts: tuple[typing.Callable[[typing.Any], typing.Any], ...] = (cast_false_to_none, error_on_none),
24
+ ) -> type[Node]:
25
+ async def compose(cls, *args: typing.Any) -> typing.Any:
26
+ result = func(*args)
27
+ if inspect.isawaitable(result):
28
+ result = await result
29
+ for cast in casts:
30
+ result = cast(result)
31
+ return result
32
+
33
+ return ContainerNode.link_nodes(linked_nodes=list(subnodes), composer=compose)
34
+
35
+
36
+ __all__ = ("generate_node",)
telegrinder/py.typed CHANGED
File without changes
telegrinder/rules.py CHANGED
@@ -1,62 +1 @@
1
- from .bot.rules import * # noqa: F403
2
-
3
- __all__ = (
4
- "ABCRule",
5
- "AndRule",
6
- "Argument",
7
- "CallbackDataEq",
8
- "CallbackDataJsonEq",
9
- "CallbackDataJsonModel",
10
- "CallbackDataMap",
11
- "CallbackDataMarkup",
12
- "CallbackQueryDataRule",
13
- "CallbackQueryRule",
14
- "ChatJoinRequestRule",
15
- "Command",
16
- "EnumTextRule",
17
- "FuncRule",
18
- "FuzzyText",
19
- "HasData",
20
- "HasEntities",
21
- "HasInviteLink",
22
- "HasLocation",
23
- "HasMention",
24
- "HasText",
25
- "InlineQueryChatType",
26
- "InlineQueryMarkup",
27
- "InlineQueryRule",
28
- "InlineQueryText",
29
- "IntegerInRange",
30
- "InviteLinkByCreator",
31
- "InviteLinkName",
32
- "IsBot",
33
- "IsChat",
34
- "IsChatId",
35
- "IsDice",
36
- "IsDiceEmoji",
37
- "IsForum",
38
- "IsForward",
39
- "IsForwardType",
40
- "IsGroup",
41
- "IsInteger",
42
- "IsLanguageCode",
43
- "IsPremium",
44
- "IsPrivate",
45
- "IsReply",
46
- "IsSuperGroup",
47
- "IsUpdateType",
48
- "IsUser",
49
- "IsUserId",
50
- "Markup",
51
- "MessageEntities",
52
- "MessageRule",
53
- "NodeRule",
54
- "NotRule",
55
- "OrRule",
56
- "Regex",
57
- "RuleEnum",
58
- "StartCommand",
59
- "State",
60
- "StateMeta",
61
- "Text",
62
- )
1
+ from .bot.rules import * # noqa: F403
@@ -1,75 +1,111 @@
1
- from .buttons import BaseButton
2
- from .error_handler import ABCErrorHandler, Catcher, CatcherError, ErrorHandler
3
- from .formatting import (
4
- BaseSpecFormat,
5
- ChannelBoostLink,
6
- FormatString,
7
- HTMLFormatter,
8
- InviteChatLink,
9
- Link,
10
- Mention,
11
- PreCode,
12
- ResolveDomain,
13
- SpecialFormat,
14
- StartBotLink,
15
- StartGroupLink,
16
- TgEmoji,
17
- block_quote,
18
- bold,
19
- channel_boost_link,
20
- code_inline,
21
- escape,
22
- get_channel_boost_link,
23
- get_invite_chat_link,
24
- get_mention_link,
25
- get_resolve_domain_link,
26
- get_start_bot_link,
27
- get_start_group_link,
28
- invite_chat_link,
29
- italic,
30
- link,
31
- mention,
32
- pre_code,
33
- resolve_domain,
34
- spoiler,
35
- start_bot_link,
36
- start_group_link,
37
- strike,
38
- tg_emoji,
39
- underline,
40
- )
41
- from .global_context import (
42
- ABCGlobalContext,
43
- CtxVar,
44
- GlobalContext,
45
- GlobalCtxVar,
46
- TelegrinderContext,
47
- ctx_var,
48
- )
49
- from .i18n import (
50
- ABCI18n,
51
- ABCTranslator,
52
- ABCTranslatorMiddleware,
53
- I18nEnum,
54
- SimpleI18n,
55
- SimpleTranslator,
56
- )
57
- from .kb_set import KeyboardSetBase, KeyboardSetYAML
58
- from .keyboard import (
59
- AnyMarkup,
60
- Button,
61
- InlineButton,
62
- InlineKeyboard,
63
- Keyboard,
64
- RowButtons,
65
- )
66
- from .limited_dict import LimitedDict
67
- from .loop_wrapper import ABCLoopWrapper, DelayedTask, Lifespan, LoopWrapper
68
- from .magic import impl, magic_bundle, resolve_arg_names
69
- from .parse_mode import ParseMode
70
- from .state_storage import ABCStateStorage, MemoryStateStorage, StateData
71
-
72
- __all__ = (
1
+ from .adapter import (
2
+ ABCAdapter,
3
+ DataclassAdapter,
4
+ EventAdapter,
5
+ NodeAdapter,
6
+ RawEventAdapter,
7
+ RawUpdateAdapter,
8
+ )
9
+ from .buttons import BaseButton
10
+ from .callback_data_serilization import (
11
+ ABCDataSerializer,
12
+ JSONSerializer,
13
+ MsgPackSerializer,
14
+ )
15
+ from .error_handler import ABCErrorHandler, Catcher, CatcherError, ErrorHandler
16
+ from .formatting import (
17
+ Base,
18
+ BlockQuote,
19
+ FormatString,
20
+ HTMLFormatter,
21
+ Link,
22
+ Mention,
23
+ PreCode,
24
+ SpecialFormat,
25
+ TgEmoji,
26
+ block_quote,
27
+ bold,
28
+ code_inline,
29
+ escape,
30
+ italic,
31
+ link,
32
+ mention,
33
+ pre_code,
34
+ spoiler,
35
+ strike,
36
+ tg_bot_attach_open_any_chat,
37
+ tg_bot_attach_open_current_chat,
38
+ tg_bot_attach_open_specific_chat,
39
+ tg_bot_start_link,
40
+ tg_bot_startchannel_link,
41
+ tg_bot_startgroup_link,
42
+ tg_chat_folder_link,
43
+ tg_chat_invite_link,
44
+ tg_direct_mini_app_link,
45
+ tg_emoji,
46
+ tg_emoji_link,
47
+ tg_emoji_stickerset_link,
48
+ tg_invoice_link,
49
+ tg_language_pack_link,
50
+ tg_main_mini_app_link,
51
+ tg_mention_link,
52
+ tg_open_message_link,
53
+ tg_premium_multigift_link,
54
+ tg_premium_offer_link,
55
+ tg_private_channel_boost_link,
56
+ tg_private_message_link,
57
+ tg_public_channel_boost_link,
58
+ tg_public_message_link,
59
+ tg_public_username_link,
60
+ tg_share_link,
61
+ tg_story_link,
62
+ underline,
63
+ )
64
+ from .functional import from_optional
65
+ from .global_context import (
66
+ ABCGlobalContext,
67
+ CtxVar,
68
+ GlobalContext,
69
+ GlobalCtxVar,
70
+ TelegrinderContext,
71
+ ctx_var,
72
+ )
73
+ from .i18n import (
74
+ ABCI18n,
75
+ ABCTranslator,
76
+ ABCTranslatorMiddleware,
77
+ I18nEnum,
78
+ SimpleI18n,
79
+ SimpleTranslator,
80
+ )
81
+ from .input_file_directory import InputFileDirectory
82
+ from .keyboard import (
83
+ AnyMarkup,
84
+ Button,
85
+ InlineButton,
86
+ InlineKeyboard,
87
+ Keyboard,
88
+ RowButtons,
89
+ )
90
+ from .limited_dict import LimitedDict
91
+ from .loop_wrapper import ABCLoopWrapper, DelayedTask, Lifespan, LoopWrapper
92
+ from .magic import (
93
+ cancel_future,
94
+ get_annotations,
95
+ get_cached_translation,
96
+ get_default_args,
97
+ get_func_parameters,
98
+ get_impls,
99
+ impl,
100
+ magic_bundle,
101
+ resolve_arg_names,
102
+ )
103
+ from .parse_mode import ParseMode
104
+ from .state_storage import ABCStateStorage, MemoryStateStorage, StateData
105
+
106
+ __all__ = (
107
+ "ABCAdapter",
108
+ "ABCDataSerializer",
73
109
  "ABCErrorHandler",
74
110
  "ABCGlobalContext",
75
111
  "ABCI18n",
@@ -78,15 +114,17 @@ __all__ = (
78
114
  "ABCTranslator",
79
115
  "ABCTranslatorMiddleware",
80
116
  "AnyMarkup",
117
+ "Base",
81
118
  "BaseButton",
82
- "BaseSpecFormat",
119
+ "BlockQuote",
83
120
  "Button",
84
121
  "Catcher",
85
122
  "CatcherError",
86
- "ChannelBoostLink",
87
123
  "CtxVar",
124
+ "DataclassAdapter",
88
125
  "DelayedTask",
89
126
  "ErrorHandler",
127
+ "EventAdapter",
90
128
  "FormatString",
91
129
  "GlobalContext",
92
130
  "GlobalCtxVar",
@@ -94,53 +132,74 @@ __all__ = (
94
132
  "I18nEnum",
95
133
  "InlineButton",
96
134
  "InlineKeyboard",
97
- "InviteChatLink",
135
+ "InputFileDirectory",
136
+ "JSONSerializer",
98
137
  "Keyboard",
99
- "KeyboardSetBase",
100
- "KeyboardSetYAML",
101
138
  "Lifespan",
102
139
  "LimitedDict",
103
140
  "Link",
104
141
  "LoopWrapper",
105
142
  "MemoryStateStorage",
106
143
  "Mention",
144
+ "MsgPackSerializer",
145
+ "NodeAdapter",
107
146
  "ParseMode",
108
147
  "PreCode",
109
- "ResolveDomain",
148
+ "RawEventAdapter",
149
+ "RawUpdateAdapter",
110
150
  "RowButtons",
111
151
  "SimpleI18n",
112
152
  "SimpleTranslator",
113
153
  "SpecialFormat",
114
- "StartBotLink",
115
- "StartGroupLink",
116
154
  "StateData",
117
155
  "TelegrinderContext",
118
156
  "TgEmoji",
119
157
  "block_quote",
120
158
  "bold",
121
- "channel_boost_link",
159
+ "cancel_future",
122
160
  "code_inline",
123
161
  "ctx_var",
124
162
  "escape",
125
- "get_channel_boost_link",
126
- "get_invite_chat_link",
127
- "get_mention_link",
128
- "get_resolve_domain_link",
129
- "get_start_bot_link",
130
- "get_start_group_link",
163
+ "from_optional",
164
+ "get_annotations",
165
+ "get_cached_translation",
166
+ "get_default_args",
167
+ "get_func_parameters",
168
+ "get_impls",
131
169
  "impl",
132
- "invite_chat_link",
133
170
  "italic",
134
171
  "link",
135
172
  "magic_bundle",
136
173
  "mention",
137
174
  "pre_code",
138
175
  "resolve_arg_names",
139
- "resolve_domain",
140
176
  "spoiler",
141
- "start_bot_link",
142
- "start_group_link",
143
177
  "strike",
178
+ "tg_bot_attach_open_any_chat",
179
+ "tg_bot_attach_open_current_chat",
180
+ "tg_bot_attach_open_specific_chat",
181
+ "tg_bot_start_link",
182
+ "tg_bot_startchannel_link",
183
+ "tg_bot_startgroup_link",
184
+ "tg_chat_folder_link",
185
+ "tg_chat_invite_link",
186
+ "tg_direct_mini_app_link",
144
187
  "tg_emoji",
145
- "underline",
146
- )
188
+ "tg_emoji_link",
189
+ "tg_emoji_stickerset_link",
190
+ "tg_invoice_link",
191
+ "tg_language_pack_link",
192
+ "tg_main_mini_app_link",
193
+ "tg_mention_link",
194
+ "tg_open_message_link",
195
+ "tg_premium_multigift_link",
196
+ "tg_premium_offer_link",
197
+ "tg_private_channel_boost_link",
198
+ "tg_private_message_link",
199
+ "tg_public_channel_boost_link",
200
+ "tg_public_message_link",
201
+ "tg_public_username_link",
202
+ "tg_share_link",
203
+ "tg_story_link",
204
+ "underline",
205
+ )
@@ -0,0 +1,19 @@
1
+ from telegrinder.tools.adapter.abc import ABCAdapter, AdaptResult, Event
2
+ from telegrinder.tools.adapter.dataclass import DataclassAdapter
3
+ from telegrinder.tools.adapter.errors import AdapterError
4
+ from telegrinder.tools.adapter.event import EventAdapter
5
+ from telegrinder.tools.adapter.node import NodeAdapter
6
+ from telegrinder.tools.adapter.raw_event import RawEventAdapter
7
+ from telegrinder.tools.adapter.raw_update import RawUpdateAdapter
8
+
9
+ __all__ = (
10
+ "ABCAdapter",
11
+ "AdaptResult",
12
+ "AdapterError",
13
+ "DataclassAdapter",
14
+ "Event",
15
+ "EventAdapter",
16
+ "NodeAdapter",
17
+ "RawEventAdapter",
18
+ "RawUpdateAdapter",
19
+ )
@@ -0,0 +1,49 @@
1
+ import abc
2
+ import dataclasses
3
+ import inspect
4
+ import typing
5
+
6
+ from fntypes import Error, Nothing, Ok, Option, Some
7
+ from fntypes.result import Result
8
+
9
+ from telegrinder.modules import logger
10
+ from telegrinder.tools.adapter.errors import AdapterError
11
+
12
+ type AdaptResult[To] = Result[To, AdapterError] | typing.Awaitable[Result[To, AdapterError]]
13
+
14
+
15
+ if typing.TYPE_CHECKING:
16
+ from telegrinder.api.api import API
17
+ from telegrinder.bot.dispatch.context import Context
18
+ from telegrinder.model import Model
19
+
20
+
21
+ class ABCAdapter[From: "Model", To](abc.ABC):
22
+ ADAPTED_VALUE_KEY: str | None = None
23
+
24
+ @abc.abstractmethod
25
+ def adapt(self, api: "API", update: From, context: "Context") -> AdaptResult[To]:
26
+ pass
27
+
28
+
29
+ @dataclasses.dataclass(slots=True)
30
+ class Event[To]:
31
+ obj: To
32
+
33
+
34
+ async def run_adapter[T, U: "Model"](
35
+ adapter: "ABCAdapter[U, T]",
36
+ api: "API",
37
+ update: U,
38
+ context: "Context",
39
+ ) -> Option[T]:
40
+ adapt_result = adapter.adapt(api, update, context)
41
+ match await adapt_result if inspect.isawaitable(adapt_result) else adapt_result:
42
+ case Ok(value):
43
+ return Some(value)
44
+ case Error(err):
45
+ logger.debug("Adapter {!r} failed with error message: {!r}", adapter, str(err))
46
+ return Nothing()
47
+
48
+
49
+ __all__ = ("ABCAdapter", "AdaptResult", "Event", "run_adapter")
@@ -0,0 +1,56 @@
1
+ from fntypes.option import Nothing, Some
2
+ from fntypes.result import Error, Ok, Result
3
+
4
+ from telegrinder.api.api import API
5
+ from telegrinder.bot.cute_types.base import BaseCute
6
+ from telegrinder.bot.cute_types.update import UpdateCute
7
+ from telegrinder.bot.dispatch.context import Context
8
+ from telegrinder.tools.adapter.abc import ABCAdapter
9
+ from telegrinder.tools.adapter.errors import AdapterError
10
+ from telegrinder.types.enums import UpdateType
11
+ from telegrinder.types.objects import Update
12
+
13
+
14
+ class DataclassAdapter[Dataclass](ABCAdapter[Update, Dataclass]):
15
+ ADAPTED_VALUE_KEY: str
16
+
17
+ def __init__(
18
+ self,
19
+ dataclass: type[Dataclass],
20
+ update_type: UpdateType | None = None,
21
+ ) -> None:
22
+ self.ADAPTED_VALUE_KEY = f"_adapted_dataclass_{dataclass.__name__}"
23
+ self.dataclass = dataclass
24
+ self.update_type = update_type
25
+
26
+ def __repr__(self) -> str:
27
+ return f"<Update -> {self.dataclass.__name__}>"
28
+
29
+ def adapt(self, api: API, update: Update, context: Context) -> Result[Dataclass, AdapterError]:
30
+ if self.ADAPTED_VALUE_KEY in context:
31
+ return Ok(context[self.ADAPTED_VALUE_KEY])
32
+
33
+ update_type = (self.update_type or update.update_type).value
34
+ try:
35
+ if self.dataclass is Update:
36
+ return Ok(update) # type: ignore
37
+ elif issubclass(self.dataclass, UpdateCute):
38
+ dataclass = self.dataclass.from_update(update, bound_api=api)
39
+ else:
40
+ match getattr(update, update_type):
41
+ case Some(val):
42
+ dataclass = (
43
+ self.dataclass.from_update(val, bound_api=api)
44
+ if issubclass(self.dataclass, BaseCute)
45
+ else self.dataclass(**val.to_dict())
46
+ )
47
+ case Nothing():
48
+ return Error(AdapterError(f"Update has no event {update_type!r}."))
49
+ except Exception as e:
50
+ return Error(AdapterError(f"Cannot adapt Update to {self.dataclass!r}, error: {e!r}"))
51
+
52
+ context[self.ADAPTED_VALUE_KEY] = dataclass
53
+ return Ok(dataclass) # type: ignore
54
+
55
+
56
+ __all__ = ("DataclassAdapter",)
@@ -1,5 +1,5 @@
1
- class AdapterError(RuntimeError):
2
- pass
3
-
4
-
5
- __all__ = ("AdapterError",)
1
+ class AdapterError(RuntimeError):
2
+ pass
3
+
4
+
5
+ __all__ = ("AdapterError",)