Pytdbot 0.9.5.dev0__tar.gz → 0.9.6.dev1__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 (46) hide show
  1. {pytdbot-0.9.5.dev0 → pytdbot-0.9.6.dev1}/PKG-INFO +2 -2
  2. {pytdbot-0.9.5.dev0 → pytdbot-0.9.6.dev1}/Pytdbot.egg-info/PKG-INFO +2 -2
  3. {pytdbot-0.9.5.dev0 → pytdbot-0.9.6.dev1}/README.md +1 -1
  4. {pytdbot-0.9.5.dev0 → pytdbot-0.9.6.dev1}/pytdbot/__init__.py +1 -1
  5. {pytdbot-0.9.5.dev0 → pytdbot-0.9.6.dev1}/pytdbot/client.py +125 -53
  6. {pytdbot-0.9.5.dev0 → pytdbot-0.9.6.dev1}/pytdbot/methods/methods.py +6 -1
  7. {pytdbot-0.9.5.dev0 → pytdbot-0.9.6.dev1}/pytdbot/methods/td_functions.py +296 -4
  8. {pytdbot-0.9.5.dev0 → pytdbot-0.9.6.dev1}/pytdbot/types/__init__.py +33 -3
  9. {pytdbot-0.9.5.dev0 → pytdbot-0.9.6.dev1}/pytdbot/types/td_types/types.py +4484 -23
  10. {pytdbot-0.9.5.dev0 → pytdbot-0.9.6.dev1}/pytdbot/types/tdserver/schedule.py +11 -11
  11. {pytdbot-0.9.5.dev0 → pytdbot-0.9.6.dev1}/LICENSE +0 -0
  12. {pytdbot-0.9.5.dev0 → pytdbot-0.9.6.dev1}/MANIFEST.in +0 -0
  13. {pytdbot-0.9.5.dev0 → pytdbot-0.9.6.dev1}/Pytdbot.egg-info/SOURCES.txt +0 -0
  14. {pytdbot-0.9.5.dev0 → pytdbot-0.9.6.dev1}/Pytdbot.egg-info/dependency_links.txt +0 -0
  15. {pytdbot-0.9.5.dev0 → pytdbot-0.9.6.dev1}/Pytdbot.egg-info/requires.txt +0 -0
  16. {pytdbot-0.9.5.dev0 → pytdbot-0.9.6.dev1}/Pytdbot.egg-info/top_level.txt +0 -0
  17. {pytdbot-0.9.5.dev0 → pytdbot-0.9.6.dev1}/pytdbot/client_manager.py +0 -0
  18. {pytdbot-0.9.5.dev0 → pytdbot-0.9.6.dev1}/pytdbot/exception/__init__.py +0 -0
  19. {pytdbot-0.9.5.dev0 → pytdbot-0.9.6.dev1}/pytdbot/filters.py +0 -0
  20. {pytdbot-0.9.5.dev0 → pytdbot-0.9.6.dev1}/pytdbot/handlers/__init__.py +0 -0
  21. {pytdbot-0.9.5.dev0 → pytdbot-0.9.6.dev1}/pytdbot/handlers/decorators.py +0 -0
  22. {pytdbot-0.9.5.dev0 → pytdbot-0.9.6.dev1}/pytdbot/handlers/handler.py +0 -0
  23. {pytdbot-0.9.5.dev0 → pytdbot-0.9.6.dev1}/pytdbot/handlers/td_updates.py +0 -0
  24. {pytdbot-0.9.5.dev0 → pytdbot-0.9.6.dev1}/pytdbot/methods/__init__.py +0 -0
  25. {pytdbot-0.9.5.dev0 → pytdbot-0.9.6.dev1}/pytdbot/tdjson/__init__.py +0 -0
  26. {pytdbot-0.9.5.dev0 → pytdbot-0.9.6.dev1}/pytdbot/tdjson/tdjson.py +0 -0
  27. {pytdbot-0.9.5.dev0 → pytdbot-0.9.6.dev1}/pytdbot/types/plugins/__init__.py +0 -0
  28. {pytdbot-0.9.5.dev0 → pytdbot-0.9.6.dev1}/pytdbot/types/td_types/__init__.py +0 -0
  29. {pytdbot-0.9.5.dev0 → pytdbot-0.9.6.dev1}/pytdbot/types/td_types/bound_methods/__init__.py +0 -0
  30. {pytdbot-0.9.5.dev0 → pytdbot-0.9.6.dev1}/pytdbot/types/td_types/bound_methods/callback_query.py +0 -0
  31. {pytdbot-0.9.5.dev0 → pytdbot-0.9.6.dev1}/pytdbot/types/td_types/bound_methods/chatActions.py +0 -0
  32. {pytdbot-0.9.5.dev0 → pytdbot-0.9.6.dev1}/pytdbot/types/td_types/bound_methods/file.py +0 -0
  33. {pytdbot-0.9.5.dev0 → pytdbot-0.9.6.dev1}/pytdbot/types/td_types/bound_methods/message.py +0 -0
  34. {pytdbot-0.9.5.dev0 → pytdbot-0.9.6.dev1}/pytdbot/types/tdserver/__init__.py +0 -0
  35. {pytdbot-0.9.5.dev0 → pytdbot-0.9.6.dev1}/pytdbot/types/tdserver/stats.py +0 -0
  36. {pytdbot-0.9.5.dev0 → pytdbot-0.9.6.dev1}/pytdbot/utils/__init__.py +0 -0
  37. {pytdbot-0.9.5.dev0 → pytdbot-0.9.6.dev1}/pytdbot/utils/asyncio_utils.py +0 -0
  38. {pytdbot-0.9.5.dev0 → pytdbot-0.9.6.dev1}/pytdbot/utils/escape.py +0 -0
  39. {pytdbot-0.9.5.dev0 → pytdbot-0.9.6.dev1}/pytdbot/utils/json_utils.py +0 -0
  40. {pytdbot-0.9.5.dev0 → pytdbot-0.9.6.dev1}/pytdbot/utils/obj_encoder.py +0 -0
  41. {pytdbot-0.9.5.dev0 → pytdbot-0.9.6.dev1}/pytdbot/utils/strings.py +0 -0
  42. {pytdbot-0.9.5.dev0 → pytdbot-0.9.6.dev1}/pytdbot/utils/text_format.py +0 -0
  43. {pytdbot-0.9.5.dev0 → pytdbot-0.9.6.dev1}/pytdbot/utils/webapps.py +0 -0
  44. {pytdbot-0.9.5.dev0 → pytdbot-0.9.6.dev1}/requirements.txt +0 -0
  45. {pytdbot-0.9.5.dev0 → pytdbot-0.9.6.dev1}/setup.cfg +0 -0
  46. {pytdbot-0.9.5.dev0 → pytdbot-0.9.6.dev1}/setup.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: Pytdbot
3
- Version: 0.9.5.dev0
3
+ Version: 0.9.6.dev1
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.50-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.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)
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.5.dev0
3
+ Version: 0.9.6.dev1
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.50-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.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)
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,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.50-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.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)
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.5.dev0"
16
+ __version__ = "0.9.6.dev1"
17
17
  __copyright__ = "Copyright (c) 2022-2025 Pytdbot, AYMENJD"
18
18
  __license__ = "MIT License"
19
19
 
@@ -7,7 +7,7 @@ from os.path import join as join_path
7
7
  from pathlib import Path
8
8
  from platform import python_implementation, python_version
9
9
  from threading import current_thread, main_thread
10
- from typing import Callable, Dict, Union
10
+ from typing import Callable, Dict, Type, Union
11
11
 
12
12
  import aio_pika
13
13
  from deepdiff import DeepDiff
@@ -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
+ handlers_timeout (``float``, *optional*):
98
+ Timeout for handlers. If set, each handler will be awaited with this timeout. 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,7 +131,9 @@ class Client(Decorators, Methods):
128
131
  loop: asyncio.AbstractEventLoop = None,
129
132
  options: dict = None,
130
133
  workers: int = 5,
134
+ handlers_timeout: float = None,
131
135
  no_updates: bool = False,
136
+ load_messages_before_reply: bool = False,
132
137
  td_verbosity: int = 2,
133
138
  td_log: LogStream = None,
134
139
  user_bot: bool = False,
@@ -158,7 +163,9 @@ class Client(Decorators, Methods):
158
163
  self.use_message_database = use_message_database
159
164
  self.td_options = options
160
165
  self.workers = workers
166
+ self.handlers_timeout = handlers_timeout
161
167
  self.no_updates = no_updates
168
+ self.load_messages_before_reply = load_messages_before_reply
162
169
  self.queue = asyncio.Queue()
163
170
  self.user_bot = user_bot
164
171
  self.my_id = (
@@ -179,6 +186,12 @@ class Client(Decorators, Methods):
179
186
  self.is_rabbitmq = True if rabbitmq_url else False
180
187
  self.options = {}
181
188
  self.allow_outgoing_message_types: tuple = (types.MessagePaymentRefunded,)
189
+ self.get_message_methods = {
190
+ "getmessage",
191
+ "getmessagelocally",
192
+ "getrepliedmessage",
193
+ "getcallbackquerymessage",
194
+ } # TODO: improve this
182
195
 
183
196
  self._check_init_args()
184
197
 
@@ -240,13 +253,13 @@ class Client(Decorators, Methods):
240
253
  return await self.invoke({"@type": "getServerStats"})
241
254
 
242
255
  async def scheduleEvent(
243
- self, data: dict, send_at: int
256
+ self, payload: str, send_at: int
244
257
  ) -> Union["pytdbot.types.ScheduledEvent", "pytdbot.types.Error"]:
245
258
  """Schedule an event
246
259
 
247
260
  Parameters:
248
- data (:class:`dict`):
249
- The event data to be scheduled
261
+ payload (:class:`str`):
262
+ The event payload to be scheduled
250
263
 
251
264
  send_at (:class:`int`):
252
265
  Unix timestamp when the event should be sent
@@ -254,13 +267,13 @@ class Client(Decorators, Methods):
254
267
 
255
268
  self._check_rabbitmq()
256
269
 
257
- if not isinstance(data, dict):
258
- raise ValueError("data must be dict")
270
+ if not isinstance(payload, str):
271
+ raise ValueError("payload must be str")
259
272
  if not isinstance(send_at, (int, float)):
260
273
  raise ValueError("send_at must be int")
261
274
 
262
275
  return await self.invoke(
263
- {"@type": "scheduleEvent", "data": data, "send_at": send_at}
276
+ {"@type": "scheduleEvent", "payload": payload, "send_at": send_at}
264
277
  )
265
278
 
266
279
  async def cancelScheduledEvent(
@@ -326,7 +339,7 @@ class Client(Decorators, Methods):
326
339
 
327
340
  def add_handler(
328
341
  self,
329
- update_type: str,
342
+ update_type: Union[Type["pytdbot.types.Update"], str],
330
343
  func: Callable,
331
344
  filters: pytdbot.filters.Filter = None,
332
345
  position: int = None,
@@ -336,7 +349,7 @@ class Client(Decorators, Methods):
336
349
  r"""Add an update handler
337
350
 
338
351
  Parameters:
339
- update_type (``str``):
352
+ update_type (``str`` || :class:`~pytdbot.types.Update`):
340
353
  An update type
341
354
 
342
355
  func (``Callable``):
@@ -359,23 +372,28 @@ class Client(Decorators, Methods):
359
372
  """
360
373
 
361
374
  if not isinstance(update_type, str):
362
- raise TypeError("update_type must be str")
363
- elif not isinstance(func, Callable):
375
+ if issubclass(update_type, types.Update):
376
+ update_type = update_type.getType()
377
+ else:
378
+ raise TypeError(
379
+ "update_type must be str or subclass of pytdbot.types.Update"
380
+ )
381
+ if not isinstance(func, Callable):
364
382
  raise TypeError("func must be callable")
365
- elif filters is not None and not isinstance(filters, Filter):
383
+ if filters is not None and not isinstance(filters, Filter):
366
384
  raise TypeError("filters must be instance of pytdbot.filters.Filter")
367
- else:
368
- handler = Handler(
369
- func, update_type, filters, position, inner_object, is_from_plugin
370
- )
371
385
 
372
- if update_type not in self._handlers:
373
- self._handlers[update_type] = []
386
+ handler = Handler(
387
+ func, update_type, filters, position, inner_object, is_from_plugin
388
+ )
374
389
 
375
- if isinstance(position, int):
376
- self._handlers[update_type].insert(position, handler)
377
- else:
378
- self._handlers[update_type].append(handler)
390
+ if update_type not in self._handlers:
391
+ self._handlers[update_type] = []
392
+
393
+ if isinstance(position, int):
394
+ self._handlers[update_type].insert(position, handler)
395
+ else:
396
+ self._handlers[update_type].append(handler)
379
397
 
380
398
  self._update_handlers()
381
399
 
@@ -451,56 +469,78 @@ class Client(Decorators, Methods):
451
469
  """
452
470
 
453
471
  request = obj_to_dict(request)
454
-
455
472
  request["@extra"] = {"id": create_extra_id()}
456
-
457
- future = self._create_request_future(request)
473
+ request_method = request["@type"].lower()
458
474
 
459
475
  if (
460
476
  self.logger.root.level >= DEBUG or self.logger.level >= DEBUG
461
477
  ): # dumping all requests may create performance issues
462
478
  self.logger.debug(f"Sending: {dumps(request, indent=4)}")
463
479
 
464
- is_chat_attempted_load = request["@type"].lower() == "getchat"
480
+ is_chat_attempted_load = request_method == "getchat"
481
+ is_message_attempted_load = request_method in self.get_message_methods
465
482
 
466
483
  while True:
467
484
  future = self._create_request_future(request)
468
485
  await self.__send(request)
469
486
  result = await future
470
487
 
471
- if isinstance(result, types.Error):
472
- if result.code == 400:
473
- if result.message.startswith(
474
- "Failed to parse JSON object as TDLib request:"
475
- ):
476
- raise ValueError(result.message)
488
+ if not isinstance(result, types.Error):
489
+ break
490
+
491
+ error_code = result.code
492
+ error_message = result.message
493
+
494
+ if error_message.startswith(
495
+ "Failed to parse JSON object as TDLib request:"
496
+ ):
497
+ raise ValueError(error_message)
498
+
499
+ if error_code != 400:
500
+ break
477
501
 
478
- if not is_chat_attempted_load and (
479
- result.message == "Chat not found" and "chat_id" in request
480
- ):
481
- is_chat_attempted_load = True
502
+ chat_id = request.get("chat_id")
503
+ message_id = request.get("message_id")
482
504
 
483
- chat_id = request["chat_id"]
505
+ if not is_message_attempted_load and (
506
+ error_message == "Message not found" and (chat_id and message_id)
507
+ ):
508
+ is_message_attempted_load = True
484
509
 
485
- self.logger.debug(f"Attempt to load chat {chat_id}")
510
+ self.logger.debug(f"Attempt to load message {message_id} in {chat_id}")
486
511
 
487
- load_chat = await self.getChat(chat_id)
512
+ message = await self.getMessage(chat_id=chat_id, message_id=message_id)
513
+ if message:
514
+ self.logger.debug(f"Message {message_id} in {chat_id} is loaded")
515
+ continue
516
+ else:
517
+ self.logger.debug(
518
+ f"Failed to load message {message_id} in {chat_id}"
519
+ )
488
520
 
489
- if not isinstance(load_chat, types.Error):
490
- self.logger.debug(f"Chat {chat_id} is loaded")
521
+ if not is_chat_attempted_load and (
522
+ error_message == "Chat not found" and chat_id
523
+ ):
524
+ is_chat_attempted_load = True
491
525
 
492
- reply_to_message_id = (request.get("reply_to") or {}).get(
493
- "message_id", 0
494
- )
526
+ self.logger.debug(f"Attempt to load chat {chat_id}")
495
527
 
496
- # if the request is a reply to another message
497
- # load the replied message to avoid "Message not found"
498
- if reply_to_message_id > 0:
499
- await self.getMessage(chat_id, reply_to_message_id)
528
+ chat = await self.getChat(chat_id)
529
+ if not isinstance(chat, types.Error):
530
+ self.logger.debug(f"Chat {chat_id} is loaded")
500
531
 
501
- continue
532
+ reply_to_message_id = (request.get("reply_to") or {}).get(
533
+ "message_id", 0
534
+ )
535
+
536
+ # if the request is a reply to another message
537
+ # load the replied message to avoid "Message not found"
538
+ if reply_to_message_id > 0:
539
+ await self.getMessage(chat_id, reply_to_message_id)
502
540
 
503
- self.logger.error(f"Couldn't load chat {chat_id}")
541
+ continue
542
+ else:
543
+ self.logger.error(f"Couldn't load chat {chat_id}")
504
544
 
505
545
  break
506
546
 
@@ -785,7 +825,18 @@ class Client(Decorators, Methods):
785
825
  elif not filter_function(self, handler_value):
786
826
  continue
787
827
 
788
- await initializer(self, handler_value)
828
+ if self.handlers_timeout is None:
829
+ await initializer(self, handler_value)
830
+ else:
831
+ try:
832
+ await asyncio.wait_for(
833
+ initializer(self, handler_value),
834
+ timeout=self.handlers_timeout,
835
+ )
836
+ except asyncio.TimeoutError:
837
+ self.logger.warning(
838
+ f"Initializer {initializer} timed out after {self.handlers_timeout} seconds"
839
+ )
789
840
  except StopHandlers as e:
790
841
  raise e
791
842
  except Exception:
@@ -806,7 +857,17 @@ class Client(Decorators, Methods):
806
857
  elif not filter_function(self, handler_value):
807
858
  continue
808
859
 
809
- await handler(self, handler_value)
860
+ if self.handlers_timeout is None:
861
+ await handler(self, handler_value)
862
+ else:
863
+ try:
864
+ await asyncio.wait_for(
865
+ handler(self, handler_value), timeout=self.handlers_timeout
866
+ )
867
+ except asyncio.TimeoutError:
868
+ self.logger.warning(
869
+ f"Handler {handler} timed out after {self.handlers_timeout} seconds"
870
+ )
810
871
  except StopHandlers as e:
811
872
  raise e
812
873
  except Exception:
@@ -828,7 +889,18 @@ class Client(Decorators, Methods):
828
889
  elif not filter_function(self, handler_value):
829
890
  continue
830
891
 
831
- await finalizer(self, handler_value)
892
+ if self.handlers_timeout is None:
893
+ await finalizer(self, handler_value)
894
+ else:
895
+ try:
896
+ await asyncio.wait_for(
897
+ finalizer(self, handler_value),
898
+ timeout=self.handlers_timeout,
899
+ )
900
+ except asyncio.TimeoutError:
901
+ self.logger.warning(
902
+ f"Finalizer {finalizer} timed out after {self.handlers_timeout} seconds"
903
+ )
832
904
  except StopHandlers as e:
833
905
  raise e
834
906
  except Exception:
@@ -1027,7 +1027,7 @@ class Methods(TDLibFunctions):
1027
1027
  return await self.sendMessageWithContent(
1028
1028
  chat_id=chat_id,
1029
1029
  content=InputMessageVoiceNote(
1030
- voice=voice,
1030
+ voice_note=voice,
1031
1031
  waveform=waveform,
1032
1032
  duration=duration,
1033
1033
  caption=caption,
@@ -1389,6 +1389,11 @@ class Methods(TDLibFunctions):
1389
1389
  message_id=reply_to_message_id, quote=quote
1390
1390
  )
1391
1391
 
1392
+ if self.load_messages_before_reply and isinstance(
1393
+ reply_to, InputMessageReplyToMessage
1394
+ ):
1395
+ await self.getMessage(chat_id=chat_id, message_id=reply_to.message_id)
1396
+
1392
1397
  res = await self.sendMessage(
1393
1398
  chat_id=chat_id,
1394
1399
  message_thread_id=message_thread_id,