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/__init__.py CHANGED
@@ -1,145 +1,140 @@
1
- """Telegrinder
2
-
3
- Modern visionary telegram bot framework.
4
-
5
- * Type hinted
6
- * Customizable and extensible
7
- * Ready to use scenarios and rules
8
- * Fast models built on [msgspec](https://github.com/jcrist/msgspec)
9
- * Both low-level and high-level API
10
- * Support [optional dependecies](https://github.com/timoniq/telegrinder/blob/dev/docs/guide/optional_dependencies.md)
11
-
12
- Basic example:
13
-
14
- ```python
15
- from telegrinder import API, Message, Telegrinder, Token
16
- from telegrinder.modules import logger
17
- from telegrinder.rules import Text
18
-
19
- api = API(token=Token("123:token"))
20
- bot = Telegrinder(api)
21
- logger.set_level("INFO")
22
-
23
-
24
- @bot.on.message(Text("/start"))
25
- async def start(message: Message):
26
- me = (await api.get_me()).unwrap()
27
- await message.answer(f"Hello, {message.from_user.full_name}! I'm {me.full_name}.")
28
-
29
-
30
- bot.run_forever()
31
- ```
32
- """
33
-
34
- import typing
35
-
36
- from .api import API, APIError, APIResponse, Token
37
- from .bot import (
38
- CALLBACK_QUERY_FOR_MESSAGE,
39
- CALLBACK_QUERY_FROM_CHAT,
40
- CALLBACK_QUERY_IN_CHAT_FOR_MESSAGE,
41
- MESSAGE_FROM_USER,
42
- MESSAGE_FROM_USER_IN_CHAT,
43
- MESSAGE_IN_CHAT,
44
- ABCDispatch,
45
- ABCHandler,
46
- ABCMiddleware,
47
- ABCPolling,
48
- ABCReturnManager,
49
- ABCRule,
50
- ABCScenario,
51
- ABCStateView,
52
- ABCView,
53
- AudioReplyHandler,
54
- BaseCute,
55
- BaseReturnManager,
56
- BaseStateView,
57
- BaseView,
58
- CallbackQueryCute,
59
- CallbackQueryReturnManager,
60
- CallbackQueryRule,
61
- CallbackQueryView,
62
- ChatJoinRequestCute,
63
- ChatJoinRequestRule,
64
- ChatJoinRequestView,
65
- ChatMemberUpdatedCute,
66
- ChatMemberView,
67
- Checkbox,
68
- Choice,
69
- Context,
70
- Dispatch,
71
- DocumentReplyHandler,
72
- FuncHandler,
73
- Hasher,
74
- InlineQueryCute,
75
- InlineQueryReturnManager,
76
- InlineQueryRule,
77
- MediaGroupReplyHandler,
78
- MessageCute,
79
- MessageReplyHandler,
80
- MessageReturnManager,
81
- MessageRule,
82
- MessageView,
83
- PhotoReplyHandler,
84
- Polling,
85
- RawEventView,
86
- ShortState,
87
- StateViewHasher,
88
- StickerReplyHandler,
89
- Telegrinder,
90
- UpdateCute,
91
- VideoReplyHandler,
92
- ViewBox,
93
- WaiterMachine,
94
- register_manager,
95
- )
96
- from .bot.rules import StateMeta
97
- from .client import ABCClient, AiohttpClient
98
- from .model import Model
99
- from .modules import logger
100
- from .tools import (
101
- ABCErrorHandler,
102
- ABCGlobalContext,
103
- ABCLoopWrapper,
104
- ABCStateStorage,
105
- ABCTranslator,
106
- ABCTranslatorMiddleware,
107
- AnyMarkup,
108
- Button,
109
- CtxVar,
110
- DelayedTask,
111
- ErrorHandler,
112
- FormatString,
113
- GlobalContext,
114
- HTMLFormatter,
115
- I18nEnum,
116
- InlineButton,
117
- InlineKeyboard,
118
- Keyboard,
119
- KeyboardSetBase,
120
- KeyboardSetYAML,
121
- Lifespan,
122
- LoopWrapper,
123
- MemoryStateStorage,
124
- ParseMode,
125
- RowButtons,
126
- SimpleI18n,
127
- SimpleTranslator,
128
- StateData,
129
- ctx_var,
130
- magic_bundle,
131
- )
132
-
133
- Update: typing.TypeAlias = UpdateCute
134
- Message: typing.TypeAlias = MessageCute
135
- ChatJoinRequest: typing.TypeAlias = ChatJoinRequestCute
136
- ChatMemberUpdated: typing.TypeAlias = ChatMemberUpdatedCute
137
- CallbackQuery: typing.TypeAlias = CallbackQueryCute
138
- InlineQuery: typing.TypeAlias = InlineQueryCute
139
- Bot: typing.TypeAlias = Telegrinder
140
-
141
-
142
- __all__ = (
1
+ """Telegrinder
2
+
3
+ Modern visionary telegram bot framework.
4
+
5
+ * Type hinted
6
+ * Customizable and extensible
7
+ * Ready to use scenarios and rules
8
+ * Fast models built on [msgspec](https://github.com/jcrist/msgspec)
9
+ * Both low-level and high-level API
10
+ * Support [optional dependecies](https://github.com/timoniq/telegrinder/blob/dev/docs/guide/optional_dependencies.md)
11
+
12
+ Basic example:
13
+
14
+ ```python
15
+ from telegrinder import API, Message, Telegrinder, Token
16
+ from telegrinder.modules import logger
17
+ from telegrinder.rules import Text
18
+
19
+ api = API(token=Token("123:token"))
20
+ bot = Telegrinder(api)
21
+ logger.set_level("INFO")
22
+
23
+
24
+ @bot.on.message(Text("/start"))
25
+ async def start(message: Message):
26
+ me = (await api.get_me()).unwrap()
27
+ await message.answer(f"Hello, {message.from_user.full_name}! I'm {me.full_name}.")
28
+
29
+
30
+ bot.run_forever()
31
+ ```
32
+ """
33
+
34
+ import typing
35
+
36
+ from .api import API, APIError, APIResponse, APIServerError, Token
37
+ from .bot import (
38
+ CALLBACK_QUERY_FOR_MESSAGE,
39
+ CALLBACK_QUERY_FROM_CHAT,
40
+ CALLBACK_QUERY_IN_CHAT_FOR_MESSAGE,
41
+ MESSAGE_FROM_USER,
42
+ MESSAGE_FROM_USER_IN_CHAT,
43
+ MESSAGE_IN_CHAT,
44
+ ABCDispatch,
45
+ ABCHandler,
46
+ ABCMiddleware,
47
+ ABCPolling,
48
+ ABCReturnManager,
49
+ ABCRule,
50
+ ABCScenario,
51
+ ABCStateView,
52
+ ABCView,
53
+ AudioReplyHandler,
54
+ BaseCute,
55
+ BaseReturnManager,
56
+ BaseStateView,
57
+ BaseView,
58
+ CallbackQueryCute,
59
+ CallbackQueryReturnManager,
60
+ CallbackQueryRule,
61
+ CallbackQueryView,
62
+ ChatJoinRequestCute,
63
+ ChatJoinRequestRule,
64
+ ChatJoinRequestView,
65
+ ChatMemberUpdatedCute,
66
+ ChatMemberView,
67
+ Checkbox,
68
+ Choice,
69
+ Context,
70
+ Dispatch,
71
+ DocumentReplyHandler,
72
+ FuncHandler,
73
+ Hasher,
74
+ InlineQueryCute,
75
+ InlineQueryReturnManager,
76
+ InlineQueryRule,
77
+ MediaGroupReplyHandler,
78
+ MessageCute,
79
+ MessageReplyHandler,
80
+ MessageReturnManager,
81
+ MessageRule,
82
+ MessageView,
83
+ PhotoReplyHandler,
84
+ Polling,
85
+ PreCheckoutQueryCute,
86
+ PreCheckoutQueryManager,
87
+ PreCheckoutQueryView,
88
+ RawEventView,
89
+ ShortState,
90
+ StateViewHasher,
91
+ StickerReplyHandler,
92
+ Telegrinder,
93
+ UpdateCute,
94
+ VideoReplyHandler,
95
+ ViewBox,
96
+ WaiterMachine,
97
+ register_manager,
98
+ )
99
+ from .client import ABCClient, AiohttpClient, AiosonicClient
100
+ from .model import Model
101
+ from .modules import logger
102
+ from .tools.error_handler import ABCErrorHandler, ErrorHandler
103
+ from .tools.formatting import HTMLFormatter
104
+ from .tools.global_context import ABCGlobalContext, CtxVar, GlobalContext, ctx_var
105
+ from .tools.i18n import (
106
+ ABCTranslator,
107
+ ABCTranslatorMiddleware,
108
+ I18nEnum,
109
+ SimpleI18n,
110
+ SimpleTranslator,
111
+ )
112
+ from .tools.input_file_directory import InputFileDirectory
113
+ from .tools.keyboard import (
114
+ AnyMarkup,
115
+ Button,
116
+ InlineButton,
117
+ InlineKeyboard,
118
+ Keyboard,
119
+ RowButtons,
120
+ )
121
+ from .tools.lifespan import Lifespan
122
+ from .tools.loop_wrapper import ABCLoopWrapper, DelayedTask, LoopWrapper
123
+ from .tools.magic import cache_translation, get_cached_translation, magic_bundle
124
+ from .tools.parse_mode import ParseMode
125
+ from .tools.state_storage import ABCStateStorage, MemoryStateStorage, StateData
126
+
127
+ Update: typing.TypeAlias = UpdateCute
128
+ Message: typing.TypeAlias = MessageCute
129
+ PreCheckoutQuery: typing.TypeAlias = PreCheckoutQueryCute
130
+ ChatJoinRequest: typing.TypeAlias = ChatJoinRequestCute
131
+ ChatMemberUpdated: typing.TypeAlias = ChatMemberUpdatedCute
132
+ CallbackQuery: typing.TypeAlias = CallbackQueryCute
133
+ InlineQuery: typing.TypeAlias = InlineQueryCute
134
+ Bot: typing.TypeAlias = Telegrinder
135
+
136
+
137
+ __all__ = (
143
138
  "ABCClient",
144
139
  "ABCDispatch",
145
140
  "ABCErrorHandler",
@@ -160,7 +155,9 @@ __all__ = (
160
155
  "API",
161
156
  "APIError",
162
157
  "APIResponse",
158
+ "APIServerError",
163
159
  "AiohttpClient",
160
+ "AiosonicClient",
164
161
  "AnyMarkup",
165
162
  "AudioReplyHandler",
166
163
  "BaseCute",
@@ -192,7 +189,6 @@ __all__ = (
192
189
  "Dispatch",
193
190
  "DocumentReplyHandler",
194
191
  "ErrorHandler",
195
- "FormatString",
196
192
  "FuncHandler",
197
193
  "GlobalContext",
198
194
  "HTMLFormatter",
@@ -204,9 +200,8 @@ __all__ = (
204
200
  "InlineQueryCute",
205
201
  "InlineQueryReturnManager",
206
202
  "InlineQueryRule",
203
+ "InputFileDirectory",
207
204
  "Keyboard",
208
- "KeyboardSetBase",
209
- "KeyboardSetYAML",
210
205
  "Lifespan",
211
206
  "LoopWrapper",
212
207
  "MESSAGE_FROM_USER",
@@ -226,6 +221,10 @@ __all__ = (
226
221
  "ParseMode",
227
222
  "PhotoReplyHandler",
228
223
  "Polling",
224
+ "PreCheckoutQuery",
225
+ "PreCheckoutQueryCute",
226
+ "PreCheckoutQueryManager",
227
+ "PreCheckoutQueryView",
229
228
  "RawEventView",
230
229
  "RowButtons",
231
230
  "ShortState",
@@ -233,8 +232,6 @@ __all__ = (
233
232
  "SimpleTranslator",
234
233
  "StateData",
235
234
  "StateData",
236
- "StateMeta",
237
- "StateMeta",
238
235
  "StateViewHasher",
239
236
  "StickerReplyHandler",
240
237
  "Telegrinder",
@@ -244,8 +241,10 @@ __all__ = (
244
241
  "VideoReplyHandler",
245
242
  "ViewBox",
246
243
  "WaiterMachine",
244
+ "cache_translation",
247
245
  "ctx_var",
246
+ "get_cached_translation",
248
247
  "logger",
249
248
  "magic_bundle",
250
- "register_manager",
251
- )
249
+ "register_manager",
250
+ )
@@ -1,12 +1,13 @@
1
- from .api import API
2
- from .error import APIError, InvalidTokenError
3
- from .response import APIResponse
4
- from .token import Token
5
-
6
- __all__ = (
1
+ from .api import API
2
+ from .error import APIError, APIServerError, InvalidTokenError
3
+ from .response import APIResponse
4
+ from .token import Token
5
+
6
+ __all__ = (
7
7
  "API",
8
8
  "APIError",
9
9
  "APIResponse",
10
+ "APIServerError",
10
11
  "InvalidTokenError",
11
- "Token",
12
- )
12
+ "Token",
13
+ )
telegrinder/api/api.py CHANGED
@@ -1,93 +1,101 @@
1
- import typing
2
- from functools import cached_property
3
-
4
- import msgspec
5
- from fntypes.result import Error, Ok, Result
6
-
7
- from telegrinder.api.error import APIError
8
- from telegrinder.api.response import APIResponse
9
- from telegrinder.api.token import Token
10
- from telegrinder.client import ABCClient, AiohttpClient
11
- from telegrinder.model import DataConverter, decoder
12
- from telegrinder.types.methods import APIMethods
13
-
14
-
15
- def compose_data(
16
- client: ABCClient,
17
- data: dict[str, typing.Any],
18
- files: dict[str, tuple[str, bytes]],
19
- ) -> typing.Any:
20
- converter = DataConverter(_files=files.copy())
21
- return client.get_form(
22
- data={k: converter(v) for k, v in data.items()},
23
- files=converter.files,
24
- )
25
-
26
-
27
- class API(APIMethods):
28
- """Bot API with available API methods and http client."""
29
-
30
- API_URL = "https://api.telegram.org/"
31
- API_FILE_URL = "https://api.telegram.org/file/"
32
-
33
- def __init__(self, token: Token, *, http: ABCClient | None = None) -> None:
34
- self.token = token
35
- self.http = http or AiohttpClient()
36
- super().__init__(self)
37
-
38
- def __repr__(self) -> str:
39
- return "<{}: token={!r}, http={!r}>".format(
40
- self.__class__.__name__,
41
- self.token,
42
- self.http,
43
- )
44
-
45
- @cached_property
46
- def id(self) -> int:
47
- return self.token.bot_id
48
-
49
- @property
50
- def request_url(self) -> str:
51
- return self.API_URL + f"bot{self.token}/"
52
-
53
- @property
54
- def request_file_url(self) -> str:
55
- return self.API_FILE_URL + f"bot{self.token}/"
56
-
57
- async def download_file(self, file_path: str) -> bytes:
58
- return await self.http.request_content(f"{self.request_file_url}/{file_path}")
59
-
60
- async def request(
61
- self,
62
- method: str,
63
- data: dict[str, typing.Any] | None = None,
64
- files: dict[str, tuple[str, bytes]] | None = None,
65
- ) -> Result[dict[str, typing.Any] | list[typing.Any] | bool, APIError]:
66
- response = await self.http.request_json(
67
- url=self.request_url + method,
68
- data=compose_data(self.http, data or {}, files or {}),
69
- )
70
- if response.get("ok"):
71
- assert "result" in response
72
- return Ok(response["result"])
73
- return Error(
74
- APIError(
75
- code=response.get("error_code", 400),
76
- error=response.get("description"),
77
- )
78
- )
79
-
80
- async def request_raw(
81
- self,
82
- method: str,
83
- data: dict[str, typing.Any] | None = None,
84
- files: dict[str, tuple[str, bytes]] | None = None,
85
- ) -> Result[msgspec.Raw, APIError]:
86
- response_bytes = await self.http.request_bytes(
87
- url=self.request_url + method,
88
- data=compose_data(self.http, data or {}, files or {}),
89
- )
90
- return decoder.decode(response_bytes, type=APIResponse).to_result()
91
-
92
-
93
- __all__ = ("API",)
1
+ from functools import cached_property
2
+
3
+ import msgspec
4
+ import typing_extensions as typing
5
+ from fntypes.result import Error, Ok, Result
6
+
7
+ from telegrinder.api.error import APIError
8
+ from telegrinder.api.response import APIResponse
9
+ from telegrinder.api.token import Token
10
+ from telegrinder.client import ABCClient, AiohttpClient, MultipartFormProto
11
+ from telegrinder.model import decoder
12
+ from telegrinder.types.methods import APIMethods
13
+
14
+ HTTPClient = typing.TypeVar("HTTPClient", bound=ABCClient, default=AiohttpClient)
15
+
16
+ type Json = str | int | float | bool | list[Json] | dict[str, Json] | None
17
+
18
+
19
+ def compose_data[MultipartForm: MultipartFormProto](
20
+ client: ABCClient[MultipartForm],
21
+ data: dict[str, typing.Any],
22
+ files: dict[str, tuple[str, bytes]],
23
+ ) -> MultipartForm:
24
+ if not data and not files:
25
+ return client.multipart_form_factory()
26
+ return client.get_form(data=data, files=files)
27
+
28
+
29
+ class API(APIMethods[HTTPClient], typing.Generic[HTTPClient]):
30
+ """Bot API with available API methods and http client."""
31
+
32
+ API_URL = "https://api.telegram.org/"
33
+ API_FILE_URL = "https://api.telegram.org/file/"
34
+
35
+ token: Token
36
+ http: HTTPClient
37
+
38
+ def __init__(self, token: Token, *, http: HTTPClient | None = None) -> None:
39
+ self.token = token
40
+ self.http = http or AiohttpClient() # type: ignore
41
+ super().__init__(api=self)
42
+
43
+ def __repr__(self) -> str:
44
+ return "<{}: token={!r}, http={!r}>".format(
45
+ self.__class__.__name__,
46
+ self.token,
47
+ self.http,
48
+ )
49
+
50
+ @cached_property
51
+ def id(self) -> int:
52
+ return self.token.bot_id
53
+
54
+ @property
55
+ def request_url(self) -> str:
56
+ return self.API_URL + f"bot{self.token}/"
57
+
58
+ @property
59
+ def request_file_url(self) -> str:
60
+ return self.API_FILE_URL + f"bot{self.token}/"
61
+
62
+ async def download_file(self, file_path: str) -> bytes:
63
+ return await self.http.request_content(f"{self.request_file_url}/{file_path}")
64
+
65
+ async def request(
66
+ self,
67
+ method: str,
68
+ data: dict[str, typing.Any] | None = None,
69
+ files: dict[str, tuple[str, bytes]] | None = None,
70
+ ) -> Result[Json, APIError]:
71
+ """Request a `JSON` response with the `POST` HTTP method and passing data, files as `multipart/form-data`."""
72
+ response = await self.http.request_json(
73
+ url=self.request_url + method,
74
+ method="POST",
75
+ data=compose_data(self.http, data or {}, files or {}),
76
+ )
77
+ if response.get("ok", False) is True:
78
+ return Ok(response["result"])
79
+ return Error(
80
+ APIError(
81
+ code=response.get("error_code", 400),
82
+ error=response.get("description", "Something went wrong"),
83
+ ),
84
+ )
85
+
86
+ async def request_raw(
87
+ self,
88
+ method: str,
89
+ data: dict[str, typing.Any] | None = None,
90
+ files: dict[str, tuple[str, bytes]] | None = None,
91
+ ) -> Result[msgspec.Raw, APIError]:
92
+ """Request a `raw` response with the `POST` HTTP method and passing data, files as `multipart/form-data`."""
93
+ response_bytes = await self.http.request_bytes(
94
+ url=self.request_url + method,
95
+ method="POST",
96
+ data=compose_data(self.http, data or {}, files or {}),
97
+ )
98
+ return decoder.decode(response_bytes, type=APIResponse).to_result()
99
+
100
+
101
+ __all__ = ("API",)
telegrinder/api/error.py CHANGED
@@ -1,16 +1,20 @@
1
- class APIError(BaseException):
2
- def __init__(self, code: int, error: str | None = None) -> None:
3
- self.code, self.error = code, error
4
-
5
- def __str__(self) -> str:
6
- return f"[{self.code}] {self.error or 'Something went wrong'}"
7
-
8
- def __repr__(self) -> str:
9
- return f"<APIError: {self.__str__()}>"
10
-
11
-
12
- class InvalidTokenError(BaseException):
13
- pass
14
-
15
-
16
- __all__ = ("APIError", "InvalidTokenError")
1
+ class APIError(Exception):
2
+ def __init__(self, code: int, error: str) -> None:
3
+ self.code, self.error = code, error
4
+
5
+ def __str__(self) -> str:
6
+ return f"[{self.code}] {self.error}"
7
+
8
+ def __repr__(self) -> str:
9
+ return f"<APIError: {self.__str__()}>"
10
+
11
+
12
+ class APIServerError(Exception):
13
+ pass
14
+
15
+
16
+ class InvalidTokenError(BaseException):
17
+ pass
18
+
19
+
20
+ __all__ = ("APIError", "APIServerError", "InvalidTokenError")
@@ -1,20 +1,20 @@
1
- import msgspec
2
- from fntypes.result import Error, Ok, Result
3
-
4
- from telegrinder.api.error import APIError
5
- from telegrinder.model import Model
6
-
7
-
8
- class APIResponse(Model):
9
- ok: bool = False
10
- result: msgspec.Raw = msgspec.Raw(b"")
11
- error_code: int = 0
12
- description: str = ""
13
-
14
- def to_result(self) -> Result[msgspec.Raw, APIError]:
15
- if self.ok:
16
- return Ok(self.result)
17
- return Error(APIError(self.error_code, self.description))
18
-
19
-
20
- __all__ = ("APIResponse",)
1
+ import msgspec
2
+ from fntypes.result import Error, Ok, Result
3
+
4
+ from telegrinder.api.error import APIError
5
+ from telegrinder.model import Model
6
+
7
+
8
+ class APIResponse(Model):
9
+ ok: bool = False
10
+ result: msgspec.Raw = msgspec.Raw(b"")
11
+ error_code: int = 400
12
+ description: str = "Something went wrong"
13
+
14
+ def to_result(self) -> Result[msgspec.Raw, APIError]:
15
+ if self.ok:
16
+ return Ok(self.result)
17
+ return Error(APIError(self.error_code, self.description))
18
+
19
+
20
+ __all__ = ("APIResponse",)