telegrinder 0.3.4.post1__py3-none-any.whl → 0.4.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.

Files changed (169) hide show
  1. telegrinder/__init__.py +30 -31
  2. telegrinder/api/__init__.py +2 -1
  3. telegrinder/api/api.py +28 -20
  4. telegrinder/api/error.py +8 -4
  5. telegrinder/api/response.py +2 -2
  6. telegrinder/api/token.py +2 -2
  7. telegrinder/bot/__init__.py +6 -0
  8. telegrinder/bot/bot.py +38 -31
  9. telegrinder/bot/cute_types/__init__.py +2 -0
  10. telegrinder/bot/cute_types/base.py +55 -129
  11. telegrinder/bot/cute_types/callback_query.py +76 -61
  12. telegrinder/bot/cute_types/chat_join_request.py +4 -3
  13. telegrinder/bot/cute_types/chat_member_updated.py +28 -31
  14. telegrinder/bot/cute_types/inline_query.py +5 -4
  15. telegrinder/bot/cute_types/message.py +555 -602
  16. telegrinder/bot/cute_types/pre_checkout_query.py +42 -0
  17. telegrinder/bot/cute_types/update.py +20 -12
  18. telegrinder/bot/cute_types/utils.py +3 -36
  19. telegrinder/bot/dispatch/__init__.py +4 -0
  20. telegrinder/bot/dispatch/abc.py +8 -9
  21. telegrinder/bot/dispatch/context.py +5 -7
  22. telegrinder/bot/dispatch/dispatch.py +85 -33
  23. telegrinder/bot/dispatch/handler/abc.py +5 -6
  24. telegrinder/bot/dispatch/handler/audio_reply.py +2 -2
  25. telegrinder/bot/dispatch/handler/base.py +3 -3
  26. telegrinder/bot/dispatch/handler/document_reply.py +2 -2
  27. telegrinder/bot/dispatch/handler/func.py +36 -42
  28. telegrinder/bot/dispatch/handler/media_group_reply.py +5 -4
  29. telegrinder/bot/dispatch/handler/message_reply.py +2 -2
  30. telegrinder/bot/dispatch/handler/photo_reply.py +2 -2
  31. telegrinder/bot/dispatch/handler/sticker_reply.py +2 -2
  32. telegrinder/bot/dispatch/handler/video_reply.py +2 -2
  33. telegrinder/bot/dispatch/middleware/abc.py +83 -8
  34. telegrinder/bot/dispatch/middleware/global_middleware.py +70 -0
  35. telegrinder/bot/dispatch/process.py +44 -50
  36. telegrinder/bot/dispatch/return_manager/__init__.py +2 -0
  37. telegrinder/bot/dispatch/return_manager/abc.py +6 -10
  38. telegrinder/bot/dispatch/return_manager/pre_checkout_query.py +20 -0
  39. telegrinder/bot/dispatch/view/__init__.py +2 -0
  40. telegrinder/bot/dispatch/view/abc.py +10 -6
  41. telegrinder/bot/dispatch/view/base.py +81 -50
  42. telegrinder/bot/dispatch/view/box.py +20 -9
  43. telegrinder/bot/dispatch/view/callback_query.py +3 -4
  44. telegrinder/bot/dispatch/view/chat_join_request.py +2 -7
  45. telegrinder/bot/dispatch/view/chat_member.py +3 -5
  46. telegrinder/bot/dispatch/view/inline_query.py +3 -4
  47. telegrinder/bot/dispatch/view/message.py +3 -4
  48. telegrinder/bot/dispatch/view/pre_checkout_query.py +16 -0
  49. telegrinder/bot/dispatch/view/raw.py +42 -40
  50. telegrinder/bot/dispatch/waiter_machine/actions.py +5 -4
  51. telegrinder/bot/dispatch/waiter_machine/hasher/__init__.py +0 -0
  52. telegrinder/bot/dispatch/waiter_machine/hasher/callback.py +0 -0
  53. telegrinder/bot/dispatch/waiter_machine/hasher/hasher.py +9 -7
  54. telegrinder/bot/dispatch/waiter_machine/hasher/message.py +0 -0
  55. telegrinder/bot/dispatch/waiter_machine/hasher/state.py +3 -2
  56. telegrinder/bot/dispatch/waiter_machine/machine.py +113 -34
  57. telegrinder/bot/dispatch/waiter_machine/middleware.py +15 -10
  58. telegrinder/bot/dispatch/waiter_machine/short_state.py +7 -18
  59. telegrinder/bot/polling/polling.py +62 -54
  60. telegrinder/bot/rules/__init__.py +24 -1
  61. telegrinder/bot/rules/abc.py +17 -10
  62. telegrinder/bot/rules/callback_data.py +20 -61
  63. telegrinder/bot/rules/chat_join.py +6 -4
  64. telegrinder/bot/rules/command.py +4 -4
  65. telegrinder/bot/rules/enum_text.py +1 -4
  66. telegrinder/bot/rules/func.py +5 -3
  67. telegrinder/bot/rules/fuzzy.py +1 -1
  68. telegrinder/bot/rules/id.py +24 -0
  69. telegrinder/bot/rules/inline.py +6 -4
  70. telegrinder/bot/rules/integer.py +2 -1
  71. telegrinder/bot/rules/logic.py +18 -0
  72. telegrinder/bot/rules/markup.py +5 -6
  73. telegrinder/bot/rules/message.py +2 -4
  74. telegrinder/bot/rules/message_entities.py +1 -3
  75. telegrinder/bot/rules/node.py +15 -9
  76. telegrinder/bot/rules/payload.py +81 -0
  77. telegrinder/bot/rules/payment_invoice.py +29 -0
  78. telegrinder/bot/rules/regex.py +5 -6
  79. telegrinder/bot/rules/state.py +1 -3
  80. telegrinder/bot/rules/text.py +10 -5
  81. telegrinder/bot/rules/update.py +0 -0
  82. telegrinder/bot/scenario/abc.py +2 -4
  83. telegrinder/bot/scenario/checkbox.py +12 -14
  84. telegrinder/bot/scenario/choice.py +6 -9
  85. telegrinder/client/__init__.py +9 -1
  86. telegrinder/client/abc.py +35 -10
  87. telegrinder/client/aiohttp.py +28 -24
  88. telegrinder/client/form_data.py +31 -0
  89. telegrinder/client/sonic.py +212 -0
  90. telegrinder/model.py +38 -145
  91. telegrinder/modules.py +3 -1
  92. telegrinder/msgspec_utils.py +136 -68
  93. telegrinder/node/__init__.py +74 -13
  94. telegrinder/node/attachment.py +92 -16
  95. telegrinder/node/base.py +196 -68
  96. telegrinder/node/callback_query.py +17 -16
  97. telegrinder/node/command.py +3 -2
  98. telegrinder/node/composer.py +40 -75
  99. telegrinder/node/container.py +13 -7
  100. telegrinder/node/either.py +82 -0
  101. telegrinder/node/event.py +20 -31
  102. telegrinder/node/file.py +51 -0
  103. telegrinder/node/me.py +4 -5
  104. telegrinder/node/payload.py +78 -0
  105. telegrinder/node/polymorphic.py +28 -9
  106. telegrinder/node/rule.py +2 -6
  107. telegrinder/node/scope.py +4 -6
  108. telegrinder/node/source.py +37 -21
  109. telegrinder/node/text.py +20 -8
  110. telegrinder/node/tools/generator.py +7 -11
  111. telegrinder/py.typed +0 -0
  112. telegrinder/rules.py +0 -61
  113. telegrinder/tools/__init__.py +97 -38
  114. telegrinder/tools/adapter/__init__.py +19 -0
  115. telegrinder/tools/adapter/abc.py +49 -0
  116. telegrinder/tools/adapter/dataclass.py +56 -0
  117. telegrinder/{bot/rules → tools}/adapter/event.py +8 -10
  118. telegrinder/{bot/rules → tools}/adapter/node.py +8 -10
  119. telegrinder/{bot/rules → tools}/adapter/raw_event.py +2 -2
  120. telegrinder/{bot/rules → tools}/adapter/raw_update.py +2 -2
  121. telegrinder/tools/buttons.py +52 -26
  122. telegrinder/tools/callback_data_serilization/__init__.py +5 -0
  123. telegrinder/tools/callback_data_serilization/abc.py +51 -0
  124. telegrinder/tools/callback_data_serilization/json_ser.py +60 -0
  125. telegrinder/tools/callback_data_serilization/msgpack_ser.py +172 -0
  126. telegrinder/tools/error_handler/abc.py +4 -7
  127. telegrinder/tools/error_handler/error.py +0 -0
  128. telegrinder/tools/error_handler/error_handler.py +34 -48
  129. telegrinder/tools/formatting/__init__.py +57 -37
  130. telegrinder/tools/formatting/deep_links.py +541 -0
  131. telegrinder/tools/formatting/{html.py → html_formatter.py} +51 -79
  132. telegrinder/tools/formatting/spec_html_formats.py +14 -60
  133. telegrinder/tools/functional.py +1 -5
  134. telegrinder/tools/global_context/global_context.py +26 -51
  135. telegrinder/tools/global_context/telegrinder_ctx.py +3 -3
  136. telegrinder/tools/i18n/abc.py +0 -0
  137. telegrinder/tools/i18n/middleware/abc.py +3 -6
  138. telegrinder/tools/input_file_directory.py +30 -0
  139. telegrinder/tools/keyboard.py +9 -9
  140. telegrinder/tools/lifespan.py +105 -0
  141. telegrinder/tools/limited_dict.py +5 -10
  142. telegrinder/tools/loop_wrapper/abc.py +7 -2
  143. telegrinder/tools/loop_wrapper/loop_wrapper.py +40 -95
  144. telegrinder/tools/magic.py +236 -60
  145. telegrinder/tools/state_storage/__init__.py +0 -0
  146. telegrinder/tools/state_storage/abc.py +5 -9
  147. telegrinder/tools/state_storage/memory.py +1 -1
  148. telegrinder/tools/strings.py +13 -0
  149. telegrinder/types/__init__.py +8 -0
  150. telegrinder/types/enums.py +31 -21
  151. telegrinder/types/input_file.py +51 -0
  152. telegrinder/types/methods.py +531 -109
  153. telegrinder/types/objects.py +934 -826
  154. telegrinder/verification_utils.py +0 -2
  155. {telegrinder-0.3.4.post1.dist-info → telegrinder-0.4.1.dist-info}/LICENSE +2 -2
  156. telegrinder-0.4.1.dist-info/METADATA +143 -0
  157. telegrinder-0.4.1.dist-info/RECORD +182 -0
  158. {telegrinder-0.3.4.post1.dist-info → telegrinder-0.4.1.dist-info}/WHEEL +1 -1
  159. telegrinder/bot/rules/adapter/__init__.py +0 -17
  160. telegrinder/bot/rules/adapter/abc.py +0 -31
  161. telegrinder/node/message.py +0 -14
  162. telegrinder/node/update.py +0 -15
  163. telegrinder/tools/formatting/links.py +0 -38
  164. telegrinder/tools/kb_set/__init__.py +0 -4
  165. telegrinder/tools/kb_set/base.py +0 -15
  166. telegrinder/tools/kb_set/yaml.py +0 -63
  167. telegrinder-0.3.4.post1.dist-info/METADATA +0 -110
  168. telegrinder-0.3.4.post1.dist-info/RECORD +0 -165
  169. /telegrinder/{bot/rules → tools}/adapter/errors.py +0 -0
telegrinder/__init__.py CHANGED
@@ -33,7 +33,7 @@ bot.run_forever()
33
33
 
34
34
  import typing
35
35
 
36
- from .api import API, APIError, APIResponse, Token
36
+ from .api import API, APIError, APIResponse, APIServerError, Token
37
37
  from .bot import (
38
38
  CALLBACK_QUERY_FOR_MESSAGE,
39
39
  CALLBACK_QUERY_FROM_CHAT,
@@ -82,6 +82,9 @@ from .bot import (
82
82
  MessageView,
83
83
  PhotoReplyHandler,
84
84
  Polling,
85
+ PreCheckoutQueryCute,
86
+ PreCheckoutQueryManager,
87
+ PreCheckoutQueryView,
85
88
  RawEventView,
86
89
  ShortState,
87
90
  StateViewHasher,
@@ -93,45 +96,37 @@ from .bot import (
93
96
  WaiterMachine,
94
97
  register_manager,
95
98
  )
96
- from .bot.rules import StateMeta
97
- from .client import ABCClient, AiohttpClient
99
+ from .client import ABCClient, AiohttpClient, AiosonicClient
98
100
  from .model import Model
99
101
  from .modules import logger
100
- from .tools import (
101
- ABCErrorHandler,
102
- ABCGlobalContext,
103
- ABCLoopWrapper,
104
- ABCStateStorage,
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 (
105
106
  ABCTranslator,
106
107
  ABCTranslatorMiddleware,
108
+ I18nEnum,
109
+ SimpleI18n,
110
+ SimpleTranslator,
111
+ )
112
+ from .tools.input_file_directory import InputFileDirectory
113
+ from .tools.keyboard import (
107
114
  AnyMarkup,
108
115
  Button,
109
- CtxVar,
110
- DelayedTask,
111
- ErrorHandler,
112
- FormatString,
113
- GlobalContext,
114
- HTMLFormatter,
115
- I18nEnum,
116
116
  InlineButton,
117
117
  InlineKeyboard,
118
118
  Keyboard,
119
- KeyboardSetBase,
120
- KeyboardSetYAML,
121
- Lifespan,
122
- LoopWrapper,
123
- MemoryStateStorage,
124
- ParseMode,
125
119
  RowButtons,
126
- SimpleI18n,
127
- SimpleTranslator,
128
- StateData,
129
- ctx_var,
130
- magic_bundle,
131
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
132
126
 
133
127
  Update: typing.TypeAlias = UpdateCute
134
128
  Message: typing.TypeAlias = MessageCute
129
+ PreCheckoutQuery: typing.TypeAlias = PreCheckoutQueryCute
135
130
  ChatJoinRequest: typing.TypeAlias = ChatJoinRequestCute
136
131
  ChatMemberUpdated: typing.TypeAlias = ChatMemberUpdatedCute
137
132
  CallbackQuery: typing.TypeAlias = CallbackQueryCute
@@ -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,7 +241,9 @@ __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
249
  "register_manager",
@@ -1,5 +1,5 @@
1
1
  from .api import API
2
- from .error import APIError, InvalidTokenError
2
+ from .error import APIError, APIServerError, InvalidTokenError
3
3
  from .response import APIResponse
4
4
  from .token import Token
5
5
 
@@ -7,6 +7,7 @@ __all__ = (
7
7
  "API",
8
8
  "APIError",
9
9
  "APIResponse",
10
+ "APIServerError",
10
11
  "InvalidTokenError",
11
12
  "Token",
12
13
  )
telegrinder/api/api.py CHANGED
@@ -1,39 +1,44 @@
1
- import typing
2
1
  from functools import cached_property
3
2
 
4
3
  import msgspec
4
+ import typing_extensions as typing
5
5
  from fntypes.result import Error, Ok, Result
6
6
 
7
7
  from telegrinder.api.error import APIError
8
8
  from telegrinder.api.response import APIResponse
9
9
  from telegrinder.api.token import Token
10
- from telegrinder.client import ABCClient, AiohttpClient
11
- from telegrinder.model import DataConverter, decoder
10
+ from telegrinder.client import ABCClient, AiohttpClient, MultipartFormProto
11
+ from telegrinder.model import decoder
12
12
  from telegrinder.types.methods import APIMethods
13
13
 
14
+ HTTPClient = typing.TypeVar("HTTPClient", bound=ABCClient, default=AiohttpClient)
14
15
 
15
- def compose_data(
16
- client: ABCClient,
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],
17
21
  data: dict[str, typing.Any],
18
22
  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
- )
23
+ ) -> MultipartForm:
24
+ if not data and not files:
25
+ return client.multipart_form_factory()
26
+ return client.get_form(data=data, files=files)
25
27
 
26
28
 
27
- class API(APIMethods):
29
+ class API(APIMethods[HTTPClient], typing.Generic[HTTPClient]):
28
30
  """Bot API with available API methods and http client."""
29
31
 
30
32
  API_URL = "https://api.telegram.org/"
31
33
  API_FILE_URL = "https://api.telegram.org/file/"
32
34
 
33
- def __init__(self, token: Token, *, http: ABCClient | None = None) -> None:
35
+ token: Token
36
+ http: HTTPClient
37
+
38
+ def __init__(self, token: Token, *, http: HTTPClient | None = None) -> None:
34
39
  self.token = token
35
- self.http = http or AiohttpClient()
36
- super().__init__(self)
40
+ self.http = http or AiohttpClient() # type: ignore
41
+ super().__init__(api=self)
37
42
 
38
43
  def __repr__(self) -> str:
39
44
  return "<{}: token={!r}, http={!r}>".format(
@@ -62,19 +67,20 @@ class API(APIMethods):
62
67
  method: str,
63
68
  data: dict[str, typing.Any] | None = None,
64
69
  files: dict[str, tuple[str, bytes]] | None = None,
65
- ) -> Result[dict[str, typing.Any] | list[typing.Any] | bool, APIError]:
70
+ ) -> Result[Json, APIError]:
71
+ """Request a `JSON` response with the `POST` HTTP method and passing data, files as `multipart/form-data`."""
66
72
  response = await self.http.request_json(
67
73
  url=self.request_url + method,
74
+ method="POST",
68
75
  data=compose_data(self.http, data or {}, files or {}),
69
76
  )
70
- if response.get("ok"):
71
- assert "result" in response
77
+ if response.get("ok", False) is True:
72
78
  return Ok(response["result"])
73
79
  return Error(
74
80
  APIError(
75
81
  code=response.get("error_code", 400),
76
- error=response.get("description"),
77
- )
82
+ error=response.get("description", "Something went wrong"),
83
+ ),
78
84
  )
79
85
 
80
86
  async def request_raw(
@@ -83,8 +89,10 @@ class API(APIMethods):
83
89
  data: dict[str, typing.Any] | None = None,
84
90
  files: dict[str, tuple[str, bytes]] | None = None,
85
91
  ) -> Result[msgspec.Raw, APIError]:
92
+ """Request a `raw` response with the `POST` HTTP method and passing data, files as `multipart/form-data`."""
86
93
  response_bytes = await self.http.request_bytes(
87
94
  url=self.request_url + method,
95
+ method="POST",
88
96
  data=compose_data(self.http, data or {}, files or {}),
89
97
  )
90
98
  return decoder.decode(response_bytes, type=APIResponse).to_result()
telegrinder/api/error.py CHANGED
@@ -1,16 +1,20 @@
1
- class APIError(BaseException):
2
- def __init__(self, code: int, error: str | None = None) -> None:
1
+ class APIError(Exception):
2
+ def __init__(self, code: int, error: str) -> None:
3
3
  self.code, self.error = code, error
4
4
 
5
5
  def __str__(self) -> str:
6
- return f"[{self.code}] {self.error or 'Something went wrong'}"
6
+ return f"[{self.code}] {self.error}"
7
7
 
8
8
  def __repr__(self) -> str:
9
9
  return f"<APIError: {self.__str__()}>"
10
10
 
11
11
 
12
+ class APIServerError(Exception):
13
+ pass
14
+
15
+
12
16
  class InvalidTokenError(BaseException):
13
17
  pass
14
18
 
15
19
 
16
- __all__ = ("APIError", "InvalidTokenError")
20
+ __all__ = ("APIError", "APIServerError", "InvalidTokenError")
@@ -8,8 +8,8 @@ from telegrinder.model import Model
8
8
  class APIResponse(Model):
9
9
  ok: bool = False
10
10
  result: msgspec.Raw = msgspec.Raw(b"")
11
- error_code: int = 0
12
- description: str = ""
11
+ error_code: int = 400
12
+ description: str = "Something went wrong"
13
13
 
14
14
  def to_result(self) -> Result[msgspec.Raw, APIError]:
15
15
  if self.ok:
telegrinder/api/token.py CHANGED
@@ -8,9 +8,9 @@ from .error import InvalidTokenError
8
8
 
9
9
 
10
10
  class Token(str):
11
- def __new__(cls, token: str) -> typing.Self:
11
+ def __new__(cls, token: str, /) -> typing.Self:
12
12
  if token.count(":") != 1 or not token.split(":")[0].isdigit():
13
- raise InvalidTokenError("Invalid token, it should look like this '123:ABC'.")
13
+ raise InvalidTokenError("Invalid token, it should look like this: 12345:ABCdef")
14
14
  return super().__new__(cls, token)
15
15
 
16
16
  def __repr__(self) -> str:
@@ -6,6 +6,7 @@ from telegrinder.bot.cute_types import (
6
6
  ChatMemberUpdatedCute,
7
7
  InlineQueryCute,
8
8
  MessageCute,
9
+ PreCheckoutQueryCute,
9
10
  UpdateCute,
10
11
  )
11
12
  from telegrinder.bot.dispatch import (
@@ -41,6 +42,8 @@ from telegrinder.bot.dispatch import (
41
42
  MessageReturnManager,
42
43
  MessageView,
43
44
  PhotoReplyHandler,
45
+ PreCheckoutQueryManager,
46
+ PreCheckoutQueryView,
44
47
  RawEventView,
45
48
  ShortState,
46
49
  StateViewHasher,
@@ -110,6 +113,9 @@ __all__ = (
110
113
  "MessageView",
111
114
  "PhotoReplyHandler",
112
115
  "Polling",
116
+ "PreCheckoutQueryCute",
117
+ "PreCheckoutQueryManager",
118
+ "PreCheckoutQueryView",
113
119
  "RawEventView",
114
120
  "ShortState",
115
121
  "StateViewHasher",
telegrinder/bot/bot.py CHANGED
@@ -1,32 +1,32 @@
1
1
  import typing_extensions as typing
2
2
 
3
- from telegrinder.api.api import API
3
+ from telegrinder.api.api import API, HTTPClient
4
+ from telegrinder.bot.dispatch import dispatch as dp
4
5
  from telegrinder.bot.dispatch.abc import ABCDispatch
5
- from telegrinder.bot.dispatch.dispatch import Dispatch
6
+ from telegrinder.bot.polling import polling as pg
6
7
  from telegrinder.bot.polling.abc import ABCPolling
7
- from telegrinder.bot.polling.polling import Polling
8
8
  from telegrinder.modules import logger
9
9
  from telegrinder.tools.loop_wrapper import ABCLoopWrapper
10
- from telegrinder.tools.loop_wrapper.loop_wrapper import LoopWrapper
10
+ from telegrinder.tools.loop_wrapper import loop_wrapper as lw
11
11
 
12
- DispatchT = typing.TypeVar("DispatchT", bound=ABCDispatch, default=Dispatch)
13
- PollingT = typing.TypeVar("PollingT", bound=ABCPolling, default=Polling)
14
- LoopWrapperT = typing.TypeVar("LoopWrapperT", bound=ABCLoopWrapper, default=LoopWrapper)
12
+ Dispatch = typing.TypeVar("Dispatch", bound=ABCDispatch, default=dp.Dispatch[HTTPClient])
13
+ Polling = typing.TypeVar("Polling", bound=ABCPolling, default=pg.Polling[HTTPClient])
14
+ LoopWrapper = typing.TypeVar("LoopWrapper", bound=ABCLoopWrapper, default=lw.LoopWrapper)
15
15
 
16
16
 
17
- class Telegrinder(typing.Generic[DispatchT, PollingT, LoopWrapperT]):
17
+ class Telegrinder(typing.Generic[HTTPClient, Dispatch, Polling, LoopWrapper]):
18
18
  def __init__(
19
19
  self,
20
- api: API,
20
+ api: API[HTTPClient],
21
21
  *,
22
- polling: PollingT | None = None,
23
- dispatch: DispatchT | None = None,
24
- loop_wrapper: LoopWrapperT | None = None,
22
+ dispatch: Dispatch | None = None,
23
+ polling: Polling | None = None,
24
+ loop_wrapper: LoopWrapper | None = None,
25
25
  ) -> None:
26
26
  self.api = api
27
- self.dispatch = typing.cast(DispatchT, dispatch or Dispatch())
28
- self.polling = typing.cast(PollingT, polling or Polling(api))
29
- self.loop_wrapper = typing.cast(LoopWrapperT, loop_wrapper or LoopWrapper())
27
+ self.dispatch = typing.cast(Dispatch, dispatch or dp.Dispatch())
28
+ self.polling = typing.cast(Polling, polling or pg.Polling(api))
29
+ self.loop_wrapper = typing.cast(LoopWrapper, loop_wrapper or lw.LoopWrapper())
30
30
 
31
31
  def __repr__(self) -> str:
32
32
  return "<{}: api={!r}, dispatch={!r}, polling={!r}, loop_wrapper={!r}>".format(
@@ -38,7 +38,7 @@ class Telegrinder(typing.Generic[DispatchT, PollingT, LoopWrapperT]):
38
38
  )
39
39
 
40
40
  @property
41
- def on(self) -> DispatchT:
41
+ def on(self) -> Dispatch:
42
42
  return self.dispatch
43
43
 
44
44
  async def reset_webhook(self) -> None:
@@ -51,23 +51,30 @@ class Telegrinder(typing.Generic[DispatchT, PollingT, LoopWrapperT]):
51
51
  *,
52
52
  offset: int = 0,
53
53
  skip_updates: bool = False,
54
- ) -> None:
55
- if skip_updates:
56
- logger.debug("Dropping pending updates")
57
- await self.reset_webhook()
58
- await self.api.delete_webhook(drop_pending_updates=True)
59
- self.polling.offset = offset
54
+ ) -> typing.NoReturn:
55
+ async def polling() -> typing.NoReturn:
56
+ if skip_updates:
57
+ logger.debug("Dropping pending updates")
58
+ await self.reset_webhook()
59
+ await self.api.delete_webhook(drop_pending_updates=True)
60
+ self.polling.offset = offset
61
+
62
+ async for updates in self.polling.listen():
63
+ for update in updates:
64
+ logger.debug(
65
+ "Received update (update_id={}, update_type={!r})",
66
+ update.update_id,
67
+ update.update_type.name,
68
+ )
69
+ self.loop_wrapper.add_task(self.dispatch.feed(update, self.api))
60
70
 
61
- async for updates in self.polling.listen():
62
- for update in updates:
63
- logger.debug(
64
- "Received update (update_id={}, update_type={!r})",
65
- update.update_id,
66
- update.update_type.name,
67
- )
68
- self.loop_wrapper.add_task(self.dispatch.feed(update, self.api))
71
+ if self.loop_wrapper.is_running:
72
+ await polling()
73
+ else:
74
+ self.loop_wrapper.add_task(polling())
75
+ self.loop_wrapper.run_event_loop()
69
76
 
70
- def run_forever(self, *, offset: int = 0, skip_updates: bool = False) -> None:
77
+ def run_forever(self, *, offset: int = 0, skip_updates: bool = False) -> typing.NoReturn:
71
78
  logger.debug("Running blocking polling (id={})", self.api.id)
72
79
  self.loop_wrapper.add_task(self.run_polling(offset=offset, skip_updates=skip_updates))
73
80
  self.loop_wrapper.run_event_loop()
@@ -4,6 +4,7 @@ from telegrinder.bot.cute_types.chat_join_request import ChatJoinRequestCute
4
4
  from telegrinder.bot.cute_types.chat_member_updated import ChatMemberUpdatedCute
5
5
  from telegrinder.bot.cute_types.inline_query import InlineQueryCute
6
6
  from telegrinder.bot.cute_types.message import MessageCute
7
+ from telegrinder.bot.cute_types.pre_checkout_query import PreCheckoutQueryCute
7
8
  from telegrinder.bot.cute_types.update import UpdateCute
8
9
 
9
10
  __all__ = (
@@ -13,5 +14,6 @@ __all__ = (
13
14
  "ChatMemberUpdatedCute",
14
15
  "InlineQueryCute",
15
16
  "MessageCute",
17
+ "PreCheckoutQueryCute",
16
18
  "UpdateCute",
17
19
  )