Pytdbot 0.9.6.dev0__tar.gz → 0.9.7__tar.gz

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.
Files changed (47) hide show
  1. {pytdbot-0.9.6.dev0 → pytdbot-0.9.7}/PKG-INFO +2 -2
  2. {pytdbot-0.9.6.dev0 → pytdbot-0.9.7}/Pytdbot.egg-info/PKG-INFO +2 -2
  3. {pytdbot-0.9.6.dev0 → pytdbot-0.9.7}/Pytdbot.egg-info/SOURCES.txt +6 -7
  4. {pytdbot-0.9.6.dev0 → pytdbot-0.9.7}/README.md +1 -1
  5. {pytdbot-0.9.6.dev0 → pytdbot-0.9.7}/pytdbot/__init__.py +1 -1
  6. {pytdbot-0.9.6.dev0 → pytdbot-0.9.7}/pytdbot/client.py +99 -18
  7. {pytdbot-0.9.6.dev0 → pytdbot-0.9.7}/pytdbot/handlers/decorators.py +95 -15
  8. {pytdbot-0.9.6.dev0 → pytdbot-0.9.7}/pytdbot/handlers/handler.py +3 -1
  9. {pytdbot-0.9.6.dev0 → pytdbot-0.9.7}/pytdbot/handlers/td_updates.py +4193 -492
  10. {pytdbot-0.9.6.dev0 → pytdbot-0.9.7}/pytdbot/methods/td_functions.py +971 -87
  11. {pytdbot-0.9.6.dev0 → pytdbot-0.9.7}/pytdbot/tdjson/tdjson.py +15 -2
  12. {pytdbot-0.9.6.dev0 → pytdbot-0.9.7}/pytdbot/types/__init__.py +207 -17
  13. {pytdbot-0.9.6.dev0/pytdbot/types/td_types → pytdbot-0.9.7/pytdbot/types}/bound_methods/__init__.py +4 -4
  14. {pytdbot-0.9.6.dev0/pytdbot/types/td_types → pytdbot-0.9.7/pytdbot/types}/bound_methods/callback_query.py +128 -110
  15. {pytdbot-0.9.6.dev0/pytdbot/types/td_types → pytdbot-0.9.7/pytdbot/types}/bound_methods/file.py +36 -36
  16. {pytdbot-0.9.6.dev0/pytdbot/types/td_types → pytdbot-0.9.7/pytdbot/types}/bound_methods/message.py +881 -881
  17. pytdbot-0.9.6.dev0/pytdbot/types/td_types/types.py → pytdbot-0.9.7/pytdbot/types/td_types.py +4459 -273
  18. {pytdbot-0.9.6.dev0 → pytdbot-0.9.7}/pytdbot/types/tdserver/schedule.py +8 -0
  19. {pytdbot-0.9.6.dev0 → pytdbot-0.9.7}/pytdbot/utils/__init__.py +13 -1
  20. pytdbot-0.9.7/pytdbot/utils/json_utils.py +83 -0
  21. pytdbot-0.9.6.dev0/pytdbot/types/td_types/__init__.py +0 -1
  22. pytdbot-0.9.6.dev0/pytdbot/utils/json_utils.py +0 -27
  23. {pytdbot-0.9.6.dev0 → pytdbot-0.9.7}/LICENSE +0 -0
  24. {pytdbot-0.9.6.dev0 → pytdbot-0.9.7}/MANIFEST.in +0 -0
  25. {pytdbot-0.9.6.dev0 → pytdbot-0.9.7}/Pytdbot.egg-info/dependency_links.txt +0 -0
  26. {pytdbot-0.9.6.dev0 → pytdbot-0.9.7}/Pytdbot.egg-info/requires.txt +0 -0
  27. {pytdbot-0.9.6.dev0 → pytdbot-0.9.7}/Pytdbot.egg-info/top_level.txt +0 -0
  28. {pytdbot-0.9.6.dev0 → pytdbot-0.9.7}/pytdbot/client_manager.py +0 -0
  29. {pytdbot-0.9.6.dev0 → pytdbot-0.9.7}/pytdbot/exception/__init__.py +0 -0
  30. {pytdbot-0.9.6.dev0 → pytdbot-0.9.7}/pytdbot/filters.py +0 -0
  31. {pytdbot-0.9.6.dev0 → pytdbot-0.9.7}/pytdbot/handlers/__init__.py +0 -0
  32. {pytdbot-0.9.6.dev0 → pytdbot-0.9.7}/pytdbot/methods/__init__.py +0 -0
  33. {pytdbot-0.9.6.dev0 → pytdbot-0.9.7}/pytdbot/methods/methods.py +0 -0
  34. {pytdbot-0.9.6.dev0 → pytdbot-0.9.7}/pytdbot/tdjson/__init__.py +0 -0
  35. {pytdbot-0.9.6.dev0/pytdbot/types/td_types → pytdbot-0.9.7/pytdbot/types}/bound_methods/chatActions.py +0 -0
  36. {pytdbot-0.9.6.dev0 → pytdbot-0.9.7}/pytdbot/types/plugins/__init__.py +0 -0
  37. {pytdbot-0.9.6.dev0 → pytdbot-0.9.7}/pytdbot/types/tdserver/__init__.py +0 -0
  38. {pytdbot-0.9.6.dev0 → pytdbot-0.9.7}/pytdbot/types/tdserver/stats.py +0 -0
  39. {pytdbot-0.9.6.dev0 → pytdbot-0.9.7}/pytdbot/utils/asyncio_utils.py +0 -0
  40. {pytdbot-0.9.6.dev0 → pytdbot-0.9.7}/pytdbot/utils/escape.py +0 -0
  41. {pytdbot-0.9.6.dev0 → pytdbot-0.9.7}/pytdbot/utils/obj_encoder.py +0 -0
  42. {pytdbot-0.9.6.dev0 → pytdbot-0.9.7}/pytdbot/utils/strings.py +0 -0
  43. {pytdbot-0.9.6.dev0 → pytdbot-0.9.7}/pytdbot/utils/text_format.py +0 -0
  44. {pytdbot-0.9.6.dev0 → pytdbot-0.9.7}/pytdbot/utils/webapps.py +0 -0
  45. {pytdbot-0.9.6.dev0 → pytdbot-0.9.7}/requirements.txt +0 -0
  46. {pytdbot-0.9.6.dev0 → pytdbot-0.9.7}/setup.cfg +0 -0
  47. {pytdbot-0.9.6.dev0 → pytdbot-0.9.7}/setup.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: Pytdbot
3
- Version: 0.9.6.dev0
3
+ Version: 0.9.7
4
4
  Summary: Easy-to-use asynchronous TDLib wrapper for Python.
5
5
  Home-page: https://github.com/pytdbot/client
6
6
  Author: AYMEN Mohammed
@@ -30,7 +30,7 @@ Dynamic: requires-dist
30
30
  Dynamic: requires-python
31
31
  Dynamic: summary
32
32
 
33
- # Pytdbot [![Version](https://img.shields.io/pypi/v/Pytdbot?style=flat&logo=pypi)](https://pypi.org/project/Pytdbot) [![TDLib version](https://img.shields.io/badge/TDLib-v1.8.51-blue?logo=telegram)](https://github.com/tdlib/td) [![Downloads](https://static.pepy.tech/personalized-badge/pytdbot?period=month&units=none&left_color=grey&right_color=brightgreen&left_text=Downloads)](https://pepy.tech/project/pytdbot) [![Telegram Chat](https://img.shields.io/badge/Pytdbot%20chat-blue?logo=telegram&label=Telegram)](https://t.me/pytdbotchat)
33
+ # Pytdbot [![Version](https://img.shields.io/pypi/v/Pytdbot?style=flat&logo=pypi)](https://pypi.org/project/Pytdbot) [![TDLib version](https://img.shields.io/badge/TDLib-v1.8.55-blue?logo=telegram)](https://github.com/tdlib/td) [![Downloads](https://static.pepy.tech/personalized-badge/pytdbot?period=month&units=none&left_color=grey&right_color=brightgreen&left_text=Downloads)](https://pepy.tech/project/pytdbot) [![Telegram Chat](https://img.shields.io/badge/Pytdbot%20chat-blue?logo=telegram&label=Telegram)](https://t.me/pytdbotchat)
34
34
 
35
35
  Pytdbot (Python TDLib) is an asynchronous [**TDLib**](https://github.com/tdlib/td) wrapper for **Telegram** users/bots written in **Python**.
36
36
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: Pytdbot
3
- Version: 0.9.6.dev0
3
+ Version: 0.9.7
4
4
  Summary: Easy-to-use asynchronous TDLib wrapper for Python.
5
5
  Home-page: https://github.com/pytdbot/client
6
6
  Author: AYMEN Mohammed
@@ -30,7 +30,7 @@ Dynamic: requires-dist
30
30
  Dynamic: requires-python
31
31
  Dynamic: summary
32
32
 
33
- # Pytdbot [![Version](https://img.shields.io/pypi/v/Pytdbot?style=flat&logo=pypi)](https://pypi.org/project/Pytdbot) [![TDLib version](https://img.shields.io/badge/TDLib-v1.8.51-blue?logo=telegram)](https://github.com/tdlib/td) [![Downloads](https://static.pepy.tech/personalized-badge/pytdbot?period=month&units=none&left_color=grey&right_color=brightgreen&left_text=Downloads)](https://pepy.tech/project/pytdbot) [![Telegram Chat](https://img.shields.io/badge/Pytdbot%20chat-blue?logo=telegram&label=Telegram)](https://t.me/pytdbotchat)
33
+ # Pytdbot [![Version](https://img.shields.io/pypi/v/Pytdbot?style=flat&logo=pypi)](https://pypi.org/project/Pytdbot) [![TDLib version](https://img.shields.io/badge/TDLib-v1.8.55-blue?logo=telegram)](https://github.com/tdlib/td) [![Downloads](https://static.pepy.tech/personalized-badge/pytdbot?period=month&units=none&left_color=grey&right_color=brightgreen&left_text=Downloads)](https://pepy.tech/project/pytdbot) [![Telegram Chat](https://img.shields.io/badge/Pytdbot%20chat-blue?logo=telegram&label=Telegram)](https://t.me/pytdbotchat)
34
34
 
35
35
  Pytdbot (Python TDLib) is an asynchronous [**TDLib**](https://github.com/tdlib/td) wrapper for **Telegram** users/bots written in **Python**.
36
36
 
@@ -23,14 +23,13 @@ pytdbot/methods/td_functions.py
23
23
  pytdbot/tdjson/__init__.py
24
24
  pytdbot/tdjson/tdjson.py
25
25
  pytdbot/types/__init__.py
26
+ pytdbot/types/td_types.py
27
+ pytdbot/types/bound_methods/__init__.py
28
+ pytdbot/types/bound_methods/callback_query.py
29
+ pytdbot/types/bound_methods/chatActions.py
30
+ pytdbot/types/bound_methods/file.py
31
+ pytdbot/types/bound_methods/message.py
26
32
  pytdbot/types/plugins/__init__.py
27
- pytdbot/types/td_types/__init__.py
28
- pytdbot/types/td_types/types.py
29
- pytdbot/types/td_types/bound_methods/__init__.py
30
- pytdbot/types/td_types/bound_methods/callback_query.py
31
- pytdbot/types/td_types/bound_methods/chatActions.py
32
- pytdbot/types/td_types/bound_methods/file.py
33
- pytdbot/types/td_types/bound_methods/message.py
34
33
  pytdbot/types/tdserver/__init__.py
35
34
  pytdbot/types/tdserver/schedule.py
36
35
  pytdbot/types/tdserver/stats.py
@@ -1,4 +1,4 @@
1
- # Pytdbot [![Version](https://img.shields.io/pypi/v/Pytdbot?style=flat&logo=pypi)](https://pypi.org/project/Pytdbot) [![TDLib version](https://img.shields.io/badge/TDLib-v1.8.51-blue?logo=telegram)](https://github.com/tdlib/td) [![Downloads](https://static.pepy.tech/personalized-badge/pytdbot?period=month&units=none&left_color=grey&right_color=brightgreen&left_text=Downloads)](https://pepy.tech/project/pytdbot) [![Telegram Chat](https://img.shields.io/badge/Pytdbot%20chat-blue?logo=telegram&label=Telegram)](https://t.me/pytdbotchat)
1
+ # Pytdbot [![Version](https://img.shields.io/pypi/v/Pytdbot?style=flat&logo=pypi)](https://pypi.org/project/Pytdbot) [![TDLib version](https://img.shields.io/badge/TDLib-v1.8.55-blue?logo=telegram)](https://github.com/tdlib/td) [![Downloads](https://static.pepy.tech/personalized-badge/pytdbot?period=month&units=none&left_color=grey&right_color=brightgreen&left_text=Downloads)](https://pepy.tech/project/pytdbot) [![Telegram Chat](https://img.shields.io/badge/Pytdbot%20chat-blue?logo=telegram&label=Telegram)](https://t.me/pytdbotchat)
2
2
 
3
3
  Pytdbot (Python TDLib) is an asynchronous [**TDLib**](https://github.com/tdlib/td) wrapper for **Telegram** users/bots written in **Python**.
4
4
 
@@ -13,7 +13,7 @@ __all__ = [
13
13
  "Client",
14
14
  ]
15
15
 
16
- __version__ = "0.9.6.dev0"
16
+ __version__ = "0.9.7"
17
17
  __copyright__ = "Copyright (c) 2022-2025 Pytdbot, AYMENJD"
18
18
  __license__ = "MIT License"
19
19
 
@@ -94,6 +94,9 @@ class Client(Decorators, Methods):
94
94
  workers (``int``, *optional*):
95
95
  Number of workers to handle updates. Default is ``5``. If set to ``None``, updates will be immediately handled instead of being queued, which can impact performance.
96
96
 
97
+ default_handlers_timeout (``float``, *optional*):
98
+ Default timeout for handlers. If set, each handler will be awaited with this timeout (ignored if ``timeout`` is set when registering handler). Default is ``None`` (no timeout)
99
+
97
100
  no_updates (``bool``, *optional*):
98
101
  Whether the client should handle updates or not. Applicable only when using [TDLib Server](https://github.com/pytdbot/tdlib-server). Default is ``False``
99
102
 
@@ -128,11 +131,14 @@ class Client(Decorators, Methods):
128
131
  loop: asyncio.AbstractEventLoop = None,
129
132
  options: dict = None,
130
133
  workers: int = 5,
134
+ queue_size: int = 1000,
135
+ default_handlers_timeout: float = None,
131
136
  no_updates: bool = False,
132
137
  load_messages_before_reply: bool = False,
133
138
  td_verbosity: int = 2,
134
139
  td_log: LogStream = None,
135
140
  user_bot: bool = False,
141
+ server_ack: bool = True,
136
142
  ) -> None:
137
143
  self.__api_id = api_id
138
144
  self.__api_hash = api_hash
@@ -159,10 +165,13 @@ class Client(Decorators, Methods):
159
165
  self.use_message_database = use_message_database
160
166
  self.td_options = options
161
167
  self.workers = workers
168
+ self.queue_size = queue_size
169
+ self.default_handlers_timeout = default_handlers_timeout
162
170
  self.no_updates = no_updates
163
171
  self.load_messages_before_reply = load_messages_before_reply
164
172
  self.queue = asyncio.Queue()
165
173
  self.user_bot = user_bot
174
+ self.server_ack = server_ack
166
175
  self.my_id = (
167
176
  get_bot_id_from_token(self.__token)
168
177
  if isinstance(self.__token, str)
@@ -248,11 +257,14 @@ class Client(Decorators, Methods):
248
257
  return await self.invoke({"@type": "getServerStats"})
249
258
 
250
259
  async def scheduleEvent(
251
- self, payload: str, send_at: int
260
+ self, name: str, payload: str, send_at: int
252
261
  ) -> Union["pytdbot.types.ScheduledEvent", "pytdbot.types.Error"]:
253
262
  """Schedule an event
254
263
 
255
264
  Parameters:
265
+ name (:class:`str`):
266
+ Event name
267
+
256
268
  payload (:class:`str`):
257
269
  The event payload to be scheduled
258
270
 
@@ -262,13 +274,20 @@ class Client(Decorators, Methods):
262
274
 
263
275
  self._check_rabbitmq()
264
276
 
277
+ if not isinstance(name, str):
278
+ raise ValueError("name must be str")
265
279
  if not isinstance(payload, str):
266
280
  raise ValueError("payload must be str")
267
281
  if not isinstance(send_at, (int, float)):
268
282
  raise ValueError("send_at must be int")
269
283
 
270
284
  return await self.invoke(
271
- {"@type": "scheduleEvent", "payload": payload, "send_at": send_at}
285
+ {
286
+ "@type": "scheduleEvent",
287
+ "name": name,
288
+ "payload": payload,
289
+ "send_at": send_at,
290
+ }
272
291
  )
273
292
 
274
293
  async def cancelScheduledEvent(
@@ -339,6 +358,7 @@ class Client(Decorators, Methods):
339
358
  filters: pytdbot.filters.Filter = None,
340
359
  position: int = None,
341
360
  inner_object: bool = False,
361
+ timeout: float = None,
342
362
  is_from_plugin: bool = False,
343
363
  ) -> None:
344
364
  r"""Add an update handler
@@ -359,6 +379,9 @@ class Client(Decorators, Methods):
359
379
  inner_object (``bool``, *optional*):
360
380
  Wether to pass an inner object of update or not; for example ``UpdateNewMessage.message``. Default is ``False``
361
381
 
382
+ timeout (``float``, *optional*):
383
+ Max execution time for the handler before it timeout. If ``None``, ``Client.default_handlers_timeout`` is preferred. Default is ``None``
384
+
362
385
  is_from_plugin (``bool``, *optional*):
363
386
  Wether this handler is from a loaded plugin (this can help reloading plugin during runtime; for development only). Default is ``False``
364
387
 
@@ -379,7 +402,13 @@ class Client(Decorators, Methods):
379
402
  raise TypeError("filters must be instance of pytdbot.filters.Filter")
380
403
 
381
404
  handler = Handler(
382
- func, update_type, filters, position, inner_object, is_from_plugin
405
+ func=func,
406
+ update_type=update_type,
407
+ filter=filters,
408
+ position=position,
409
+ inner_object=inner_object,
410
+ timeout=timeout,
411
+ is_from_plugin=is_from_plugin,
383
412
  )
384
413
 
385
414
  if update_type not in self._handlers:
@@ -736,12 +765,13 @@ class Client(Decorators, Methods):
736
765
  for handler in handlers_to_load:
737
766
  if asyncio.iscoroutinefunction(handler.func):
738
767
  self.add_handler(
739
- handler.update_type,
740
- handler.func,
741
- handler.filter,
742
- handler.position,
743
- handler.inner_object,
744
- True,
768
+ update_type=handler.update_type,
769
+ func=handler.func,
770
+ filters=handler.filter,
771
+ position=handler.position,
772
+ inner_object=handler.inner_object,
773
+ timeout=handler.timeout,
774
+ is_from_plugin=True,
745
775
  )
746
776
  handlers += 1
747
777
  plugin_handlers_count += 1
@@ -820,7 +850,22 @@ class Client(Decorators, Methods):
820
850
  elif not filter_function(self, handler_value):
821
851
  continue
822
852
 
823
- await initializer(self, handler_value)
853
+ if (
854
+ self.default_handlers_timeout is None
855
+ and initializer.timeout is None
856
+ ):
857
+ await initializer(self, handler_value)
858
+ else:
859
+ timeout = initializer.timeout or self.default_handlers_timeout
860
+ try:
861
+ await asyncio.wait_for(
862
+ initializer(self, handler_value),
863
+ timeout=timeout,
864
+ )
865
+ except asyncio.TimeoutError:
866
+ self.logger.warning(
867
+ f"Initializer {initializer} timed out after {timeout} seconds"
868
+ )
824
869
  except StopHandlers as e:
825
870
  raise e
826
871
  except Exception:
@@ -841,7 +886,18 @@ class Client(Decorators, Methods):
841
886
  elif not filter_function(self, handler_value):
842
887
  continue
843
888
 
844
- await handler(self, handler_value)
889
+ if self.default_handlers_timeout is None and handler.timeout is None:
890
+ await handler(self, handler_value)
891
+ else:
892
+ timeout = handler.timeout or self.default_handlers_timeout
893
+ try:
894
+ await asyncio.wait_for(
895
+ handler(self, handler_value), timeout=timeout
896
+ )
897
+ except asyncio.TimeoutError:
898
+ self.logger.warning(
899
+ f"Handler {handler} timed out after {timeout} seconds"
900
+ )
845
901
  except StopHandlers as e:
846
902
  raise e
847
903
  except Exception:
@@ -863,7 +919,19 @@ class Client(Decorators, Methods):
863
919
  elif not filter_function(self, handler_value):
864
920
  continue
865
921
 
866
- await finalizer(self, handler_value)
922
+ if self.default_handlers_timeout is None and finalizer.timeout is None:
923
+ await finalizer(self, handler_value)
924
+ else:
925
+ try:
926
+ timeout = finalizer.timeout or self.default_handlers_timeout
927
+ await asyncio.wait_for(
928
+ finalizer(self, handler_value),
929
+ timeout=timeout,
930
+ )
931
+ except asyncio.TimeoutError:
932
+ self.logger.warning(
933
+ f"Finalizer {finalizer} timed out after {timeout} seconds"
934
+ )
867
935
  except StopHandlers as e:
868
936
  raise e
869
937
  except Exception:
@@ -904,6 +972,9 @@ class Client(Decorators, Methods):
904
972
  `AuthorizationError`
905
973
  """
906
974
 
975
+ if self.is_rabbitmq:
976
+ return
977
+
907
978
  if isinstance(self.__database_encryption_key, str):
908
979
  self.__database_encryption_key = self.__database_encryption_key.encode(
909
980
  "utf-8"
@@ -1060,12 +1131,12 @@ class Client(Decorators, Methods):
1060
1131
  updates_queue = await self.__get_updates_queue()
1061
1132
 
1062
1133
  notify_queue = await self.__rchannel.declare_queue(
1063
- f"notify_{self._rabbitmq_instance_id}", exclusive=True
1134
+ f"{self.my_id}_notify_{self._rabbitmq_instance_id}", exclusive=True
1064
1135
  )
1065
1136
  await notify_queue.bind(await self.__rchannel.get_exchange("broadcast"))
1066
1137
 
1067
1138
  responses_queue = await self.__rchannel.declare_queue(
1068
- f"res_{self._rabbitmq_instance_id}", exclusive=True
1139
+ f"{self.my_id}_res_{self._rabbitmq_instance_id}", exclusive=True
1069
1140
  )
1070
1141
 
1071
1142
  self.__rqueues = {
@@ -1095,13 +1166,22 @@ class Client(Decorators, Methods):
1095
1166
  await self.__rqueues["notify"].consume(self.__on_update, no_ack=True)
1096
1167
 
1097
1168
  async def __rabbitmq_iterator(self):
1098
- async with self.__rqueues["updates"].iterator() as iterator:
1169
+ async with self.__rqueues["updates"].iterator(
1170
+ no_ack=not self.server_ack
1171
+ ) as iterator:
1099
1172
  async for message in iterator:
1100
- await self.queue.put(message)
1173
+ if self.queue.qsize() > self.queue_size:
1174
+ await message.nack(requeue=True)
1175
+ continue
1176
+
1177
+ self.queue.put_nowait(message)
1101
1178
 
1102
1179
  async def __rabbitmq_worker(self):
1103
1180
  while self.is_running:
1104
- message: aio_pika.IncomingMessage = await self.queue.get()
1181
+ try:
1182
+ message: aio_pika.IncomingMessage = self.queue.get_nowait()
1183
+ except asyncio.QueueEmpty:
1184
+ message: aio_pika.IncomingMessage = await self.queue.get()
1105
1185
 
1106
1186
  try:
1107
1187
  update = json_loads(message.body)
@@ -1138,7 +1218,8 @@ class Client(Decorators, Methods):
1138
1218
 
1139
1219
  async def __handle_authorization_state_wait_phone_number(self):
1140
1220
  if (
1141
- self.authorization_state != "authorizationStateWaitPhoneNumber"
1221
+ self.is_rabbitmq
1222
+ or self.authorization_state != "authorizationStateWaitPhoneNumber"
1142
1223
  or not self.__token
1143
1224
  ):
1144
1225
  return
@@ -18,6 +18,7 @@ class Decorators(Updates):
18
18
  filters: "pytdbot.filters.Filter" = None,
19
19
  position: int = None,
20
20
  inner_object: bool = False,
21
+ timeout: float = None,
21
22
  ) -> None:
22
23
  r"""A decorator to initialize an event object before running other handlers
23
24
 
@@ -31,6 +32,9 @@ class Decorators(Updates):
31
32
  inner_object (``bool``, *optional*):
32
33
  Wether to pass an inner object of update or not; for example ``UpdateNewMessage.message``. Default is ``False``
33
34
 
35
+ timeout (``float``, *optional*):
36
+ Max execution time for the initializer before it timeout. Default is ``None``
37
+
34
38
  Raises:
35
39
  :py:class:`TypeError`
36
40
  """
@@ -41,17 +45,32 @@ class Decorators(Updates):
41
45
  elif isinstance(self, pytdbot.Client):
42
46
  if iscoroutinefunction(func):
43
47
  self.add_handler(
44
- "initializer", func, filters, position, inner_object
48
+ update_type="initializer",
49
+ func=func,
50
+ filters=filters,
51
+ position=position,
52
+ inner_object=inner_object,
53
+ timeout=timeout,
45
54
  )
46
55
  else:
47
56
  raise TypeError("Handler must be async")
48
57
  elif isinstance(self, pytdbot.filters.Filter):
49
58
  func._handler = Handler(
50
- func, "initializer", self, position, inner_object
59
+ func=func,
60
+ update_type="initializer",
61
+ filter=self,
62
+ position=position,
63
+ inner_object=inner_object,
64
+ timeout=timeout,
51
65
  )
52
66
  else:
53
67
  func._handler = Handler(
54
- func, "initializer", filters, position, inner_object
68
+ func=func,
69
+ update_type="initializer",
70
+ filter=filters,
71
+ position=position,
72
+ inner_object=inner_object,
73
+ timeout=timeout,
55
74
  )
56
75
 
57
76
  return func
@@ -63,6 +82,7 @@ class Decorators(Updates):
63
82
  filters: "pytdbot.filters.Filter" = None,
64
83
  position: int = None,
65
84
  inner_object: bool = False,
85
+ timeout: float = None,
66
86
  ) -> None:
67
87
  r"""A decorator to finalize an event object after running all handlers
68
88
 
@@ -76,6 +96,9 @@ class Decorators(Updates):
76
96
  inner_object (``bool``, *optional*):
77
97
  Wether to pass an inner object of update or not; for example ``UpdateNewMessage.message``. Default is ``False``
78
98
 
99
+ timeout (``float``, *optional*):
100
+ Max execution time for the finalizer before it timeout. Default is ``None``
101
+
79
102
  Raises:
80
103
  :py:class:`TypeError`
81
104
  """
@@ -85,14 +108,33 @@ class Decorators(Updates):
85
108
  return func
86
109
  elif isinstance(self, pytdbot.Client):
87
110
  if iscoroutinefunction(func):
88
- self.add_handler("finalizer", func, filters, position, inner_object)
111
+ self.add_handler(
112
+ update_type="finalizer",
113
+ func=func,
114
+ filters=filters,
115
+ position=position,
116
+ inner_object=inner_object,
117
+ timeout=timeout,
118
+ )
89
119
  else:
90
120
  raise TypeError("Handler must be async")
91
121
  elif isinstance(self, pytdbot.filters.Filter):
92
- func._handler = Handler(func, "finalizer", self, position, inner_object)
122
+ func._handler = Handler(
123
+ func=func,
124
+ update_type="finalizer",
125
+ filter=self,
126
+ position=position,
127
+ inner_object=inner_object,
128
+ timeout=timeout,
129
+ )
93
130
  else:
94
131
  func._handler = Handler(
95
- func, "finalizer", filters, position, inner_object
132
+ func=func,
133
+ update_type="finalizer",
134
+ filter=filters,
135
+ position=position,
136
+ inner_object=inner_object,
137
+ timeout=timeout,
96
138
  )
97
139
  return func
98
140
 
@@ -102,6 +144,7 @@ class Decorators(Updates):
102
144
  self: "pytdbot.Client" = None,
103
145
  filters: "pytdbot.filters.Filter" = None,
104
146
  position: int = None,
147
+ timeout: float = None,
105
148
  ) -> None:
106
149
  r"""A decorator to handle ``updateNewMessage`` but with ``Message`` object.
107
150
 
@@ -112,6 +155,9 @@ class Decorators(Updates):
112
155
  position (``int``, *optional*):
113
156
  The function position in handlers list. Default is ``None`` (append)
114
157
 
158
+ timeout (``float``, *optional*):
159
+ Max execution time for the handler before it timeout. Default is ``None``
160
+
115
161
  Raises:
116
162
  :py:class:`TypeError`
117
163
  """
@@ -121,14 +167,33 @@ class Decorators(Updates):
121
167
  return func
122
168
  elif isinstance(self, pytdbot.Client):
123
169
  if iscoroutinefunction(func):
124
- self.add_handler("updateNewMessage", func, filters, position, True)
170
+ self.add_handler(
171
+ update_type="updateNewMessage",
172
+ func=func,
173
+ filters=filters,
174
+ position=position,
175
+ inner_object=True,
176
+ timeout=timeout,
177
+ )
125
178
  else:
126
179
  raise TypeError("Handler must be async")
127
180
  elif isinstance(self, pytdbot.filters.Filter):
128
- func._handler = Handler(func, "updateNewMessage", self, position, True)
181
+ func._handler = Handler(
182
+ func=func,
183
+ update_type="updateNewMessage",
184
+ filter=self,
185
+ position=position,
186
+ inner_object=True,
187
+ timeout=timeout,
188
+ )
129
189
  else:
130
190
  func._handler = Handler(
131
- func, "updateNewMessage", filters, position, True
191
+ func=func,
192
+ update_type="updateNewMessage",
193
+ filter=filters,
194
+ position=position,
195
+ inner_object=True,
196
+ timeout=timeout,
132
197
  )
133
198
 
134
199
  return func
@@ -139,7 +204,7 @@ class Decorators(Updates):
139
204
  self: "pytdbot.Client" = None,
140
205
  filters: "pytdbot.filters.Filter" = None,
141
206
  position: int = None,
142
- inner_object: bool = False,
207
+ timeout: float = None,
143
208
  ) -> None:
144
209
  r"""A scheduled event has been triggered
145
210
 
@@ -150,8 +215,8 @@ class Decorators(Updates):
150
215
  position (``int``, *optional*):
151
216
  The function position in handlers list. Default is ``None`` (append)
152
217
 
153
- inner_object (``bool``, *optional*):
154
- Wether to pass an inner object of update or not; for example ``UpdateNewMessage.message``. Default is ``False``
218
+ timeout (``float``, *optional*):
219
+ Max execution time for the handler before it timeout. Default is ``None``
155
220
 
156
221
  Raises:
157
222
  :py:class:`TypeError`
@@ -163,17 +228,32 @@ class Decorators(Updates):
163
228
  elif isinstance(self, pytdbot.Client):
164
229
  if iscoroutinefunction(func):
165
230
  self.add_handler(
166
- "updateScheduledEvent", func, filters, position, inner_object
231
+ update_type="updateScheduledEvent",
232
+ func=func,
233
+ filters=filters,
234
+ position=position,
235
+ inner_object=False,
236
+ timeout=timeout,
167
237
  )
168
238
  else:
169
239
  raise TypeError("Handler must be async")
170
240
  elif isinstance(self, pytdbot.filters.Filter):
171
241
  func._handler = Handler(
172
- func, "updateScheduledEvent", self, position, inner_object
242
+ func=func,
243
+ update_type="updateScheduledEvent",
244
+ filter=self,
245
+ position=position,
246
+ inner_object=False,
247
+ timeout=timeout,
173
248
  )
174
249
  else:
175
250
  func._handler = Handler(
176
- func, "updateScheduledEvent", filters, position, inner_object
251
+ func=func,
252
+ update_type="updateScheduledEvent",
253
+ filter=filters,
254
+ position=position,
255
+ inner_object=False,
256
+ timeout=timeout,
177
257
  )
178
258
 
179
259
  return func
@@ -15,6 +15,7 @@ class Handler:
15
15
  filter: Filter = None,
16
16
  position: int = None,
17
17
  inner_object: bool = False,
18
+ timeout: float = None,
18
19
  is_from_plugin: bool = False,
19
20
  ) -> None:
20
21
  self.func = func
@@ -22,13 +23,14 @@ class Handler:
22
23
  self.filter = filter
23
24
  self.position = position
24
25
  self.inner_object = inner_object
26
+ self.timeout = timeout
25
27
  self.is_from_plugin = is_from_plugin
26
28
 
27
29
  def __call__(self, client: "pytdbot.Client", update: "pytdbot.types.Update"):
28
30
  return self.func(client, update)
29
31
 
30
32
  def __str__(self) -> str:
31
- return f"Handler(func={self.func}, update_type={self.update_type}, filter={self.filter}, position={self.position}, inner_object={self.inner_object}, is_from_plugin={self.is_from_plugin})"
33
+ return f"Handler(func={self.func}, update_type={self.update_type}, filter={self.filter}, position={self.position}, inner_object={self.inner_object}, timeout={self.timeout}, is_from_plugin={self.is_from_plugin})"
32
34
 
33
35
  def __repr__(self) -> str:
34
36
  return str(self)