Pytdbot 0.9.3__tar.gz → 0.9.4__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.
- {pytdbot-0.9.3 → pytdbot-0.9.4}/PKG-INFO +2 -2
- {pytdbot-0.9.3 → pytdbot-0.9.4}/Pytdbot.egg-info/PKG-INFO +2 -2
- {pytdbot-0.9.3 → pytdbot-0.9.4}/README.md +1 -1
- {pytdbot-0.9.3 → pytdbot-0.9.4}/pytdbot/__init__.py +1 -1
- {pytdbot-0.9.3 → pytdbot-0.9.4}/pytdbot/client.py +61 -14
- {pytdbot-0.9.3 → pytdbot-0.9.4}/pytdbot/handlers/handler.py +3 -1
- {pytdbot-0.9.3 → pytdbot-0.9.4}/pytdbot/handlers/td_updates.py +76 -0
- {pytdbot-0.9.3 → pytdbot-0.9.4}/pytdbot/methods/td_functions.py +378 -45
- {pytdbot-0.9.3 → pytdbot-0.9.4}/pytdbot/types/__init__.py +19 -1
- {pytdbot-0.9.3 → pytdbot-0.9.4}/pytdbot/types/td_types/types.py +583 -42
- {pytdbot-0.9.3 → pytdbot-0.9.4}/LICENSE +0 -0
- {pytdbot-0.9.3 → pytdbot-0.9.4}/MANIFEST.in +0 -0
- {pytdbot-0.9.3 → pytdbot-0.9.4}/Pytdbot.egg-info/SOURCES.txt +0 -0
- {pytdbot-0.9.3 → pytdbot-0.9.4}/Pytdbot.egg-info/dependency_links.txt +0 -0
- {pytdbot-0.9.3 → pytdbot-0.9.4}/Pytdbot.egg-info/requires.txt +0 -0
- {pytdbot-0.9.3 → pytdbot-0.9.4}/Pytdbot.egg-info/top_level.txt +0 -0
- {pytdbot-0.9.3 → pytdbot-0.9.4}/pytdbot/client_manager.py +0 -0
- {pytdbot-0.9.3 → pytdbot-0.9.4}/pytdbot/exception/__init__.py +0 -0
- {pytdbot-0.9.3 → pytdbot-0.9.4}/pytdbot/filters.py +0 -0
- {pytdbot-0.9.3 → pytdbot-0.9.4}/pytdbot/handlers/__init__.py +0 -0
- {pytdbot-0.9.3 → pytdbot-0.9.4}/pytdbot/handlers/decorators.py +0 -0
- {pytdbot-0.9.3 → pytdbot-0.9.4}/pytdbot/methods/__init__.py +0 -0
- {pytdbot-0.9.3 → pytdbot-0.9.4}/pytdbot/methods/methods.py +0 -0
- {pytdbot-0.9.3 → pytdbot-0.9.4}/pytdbot/tdjson/__init__.py +0 -0
- {pytdbot-0.9.3 → pytdbot-0.9.4}/pytdbot/tdjson/tdjson.py +0 -0
- {pytdbot-0.9.3 → pytdbot-0.9.4}/pytdbot/types/plugins/__init__.py +0 -0
- {pytdbot-0.9.3 → pytdbot-0.9.4}/pytdbot/types/td_types/__init__.py +0 -0
- {pytdbot-0.9.3 → pytdbot-0.9.4}/pytdbot/types/td_types/bound_methods/__init__.py +0 -0
- {pytdbot-0.9.3 → pytdbot-0.9.4}/pytdbot/types/td_types/bound_methods/callback_query.py +0 -0
- {pytdbot-0.9.3 → pytdbot-0.9.4}/pytdbot/types/td_types/bound_methods/chatActions.py +0 -0
- {pytdbot-0.9.3 → pytdbot-0.9.4}/pytdbot/types/td_types/bound_methods/file.py +0 -0
- {pytdbot-0.9.3 → pytdbot-0.9.4}/pytdbot/types/td_types/bound_methods/message.py +0 -0
- {pytdbot-0.9.3 → pytdbot-0.9.4}/pytdbot/utils/__init__.py +0 -0
- {pytdbot-0.9.3 → pytdbot-0.9.4}/pytdbot/utils/asyncio_utils.py +0 -0
- {pytdbot-0.9.3 → pytdbot-0.9.4}/pytdbot/utils/escape.py +0 -0
- {pytdbot-0.9.3 → pytdbot-0.9.4}/pytdbot/utils/json_utils.py +0 -0
- {pytdbot-0.9.3 → pytdbot-0.9.4}/pytdbot/utils/obj_encoder.py +0 -0
- {pytdbot-0.9.3 → pytdbot-0.9.4}/pytdbot/utils/strings.py +0 -0
- {pytdbot-0.9.3 → pytdbot-0.9.4}/pytdbot/utils/text_format.py +0 -0
- {pytdbot-0.9.3 → pytdbot-0.9.4}/pytdbot/utils/webapps.py +0 -0
- {pytdbot-0.9.3 → pytdbot-0.9.4}/requirements.txt +0 -0
- {pytdbot-0.9.3 → pytdbot-0.9.4}/setup.cfg +0 -0
- {pytdbot-0.9.3 → pytdbot-0.9.4}/setup.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: Pytdbot
|
|
3
|
-
Version: 0.9.
|
|
3
|
+
Version: 0.9.4
|
|
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 [](https://pypi.org/project/Pytdbot) [](https://pypi.org/project/Pytdbot) [](https://github.com/tdlib/td) [](https://pepy.tech/project/pytdbot) [](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.
|
|
3
|
+
Version: 0.9.4
|
|
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 [](https://pypi.org/project/Pytdbot) [](https://pypi.org/project/Pytdbot) [](https://github.com/tdlib/td) [](https://pepy.tech/project/pytdbot) [](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 [](https://pypi.org/project/Pytdbot) [](https://pypi.org/project/Pytdbot) [](https://github.com/tdlib/td) [](https://pepy.tech/project/pytdbot) [](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
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import asyncio
|
|
2
2
|
import signal
|
|
3
|
-
from importlib import import_module
|
|
3
|
+
from importlib import import_module, reload as reload_module
|
|
4
4
|
from json import dumps
|
|
5
5
|
from logging import DEBUG, getLogger
|
|
6
6
|
from os.path import join as join_path
|
|
@@ -172,12 +172,15 @@ class Client(Decorators, Methods):
|
|
|
172
172
|
self.is_running = None
|
|
173
173
|
self.me: types.User = None
|
|
174
174
|
self.is_authenticated = False
|
|
175
|
+
self.is_reloading_plugins = False
|
|
175
176
|
self.is_rabbitmq = True if rabbitmq_url else False
|
|
176
177
|
self.options = {}
|
|
178
|
+
self.allow_outgoing_message_types: tuple = (types.MessagePaymentRefunded,)
|
|
177
179
|
|
|
178
180
|
self._check_init_args()
|
|
179
181
|
|
|
180
182
|
self._handlers = {"initializer": [], "finalizer": []}
|
|
183
|
+
self._current_handlers = {}
|
|
181
184
|
self._results: Dict[str, asyncio.Future] = {}
|
|
182
185
|
self._workers_tasks = None
|
|
183
186
|
self.__authorization_state = None
|
|
@@ -268,6 +271,7 @@ class Client(Decorators, Methods):
|
|
|
268
271
|
filters: pytdbot.filters.Filter = None,
|
|
269
272
|
position: int = None,
|
|
270
273
|
inner_object: bool = False,
|
|
274
|
+
is_from_plugin: bool = False,
|
|
271
275
|
) -> None:
|
|
272
276
|
r"""Add an update handler
|
|
273
277
|
|
|
@@ -287,6 +291,9 @@ class Client(Decorators, Methods):
|
|
|
287
291
|
inner_object (``bool``, *optional*):
|
|
288
292
|
Wether to pass an inner object of update or not; for example ``UpdateNewMessage.message``. Default is ``False``
|
|
289
293
|
|
|
294
|
+
is_from_plugin (``bool``, *optional*):
|
|
295
|
+
Wether this handler is from a loaded plugin (this can help reloading plugin during runtime; for development only). Default is ``False``
|
|
296
|
+
|
|
290
297
|
Raises:
|
|
291
298
|
TypeError
|
|
292
299
|
"""
|
|
@@ -298,14 +305,38 @@ class Client(Decorators, Methods):
|
|
|
298
305
|
elif filters is not None and not isinstance(filters, Filter):
|
|
299
306
|
raise TypeError("filters must be instance of pytdbot.filters.Filter")
|
|
300
307
|
else:
|
|
301
|
-
|
|
308
|
+
handler = Handler(
|
|
309
|
+
func, update_type, filters, position, inner_object, is_from_plugin
|
|
310
|
+
)
|
|
311
|
+
|
|
302
312
|
if update_type not in self._handlers:
|
|
303
313
|
self._handlers[update_type] = []
|
|
314
|
+
|
|
304
315
|
if isinstance(position, int):
|
|
305
|
-
self._handlers[update_type].insert(position,
|
|
316
|
+
self._handlers[update_type].insert(position, handler)
|
|
306
317
|
else:
|
|
307
|
-
self._handlers[update_type].append(
|
|
308
|
-
|
|
318
|
+
self._handlers[update_type].append(handler)
|
|
319
|
+
|
|
320
|
+
self._update_handlers()
|
|
321
|
+
|
|
322
|
+
def reload_plugins(self):
|
|
323
|
+
"""Reload all plugins, non-plugin handlers are not ``reloaded``
|
|
324
|
+
.. note::
|
|
325
|
+
This is for ``development purposes only`` and should not be used
|
|
326
|
+
in production environments
|
|
327
|
+
"""
|
|
328
|
+
|
|
329
|
+
if self.is_reloading_plugins:
|
|
330
|
+
return
|
|
331
|
+
|
|
332
|
+
self.is_reloading_plugins = True
|
|
333
|
+
for handlers in self._handlers.values():
|
|
334
|
+
for handler in handlers.copy():
|
|
335
|
+
if handler.is_from_plugin:
|
|
336
|
+
self.remove_handler(handler.func)
|
|
337
|
+
|
|
338
|
+
self._load_plugins(reload_plugins=True)
|
|
339
|
+
self.is_reloading_plugins = False
|
|
309
340
|
|
|
310
341
|
def remove_handler(self, func: Callable) -> bool:
|
|
311
342
|
r"""Remove an update handler
|
|
@@ -323,13 +354,17 @@ class Client(Decorators, Methods):
|
|
|
323
354
|
|
|
324
355
|
if not isinstance(func, Callable):
|
|
325
356
|
raise TypeError("func must be callable")
|
|
326
|
-
|
|
357
|
+
|
|
358
|
+
removed = False
|
|
359
|
+
for handlers in self._handlers.values():
|
|
327
360
|
for handler in handlers.copy():
|
|
328
361
|
if handler.func == func:
|
|
329
362
|
handlers.remove(handler)
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
363
|
+
removed = True
|
|
364
|
+
|
|
365
|
+
if removed:
|
|
366
|
+
self._update_handlers()
|
|
367
|
+
return removed
|
|
333
368
|
|
|
334
369
|
async def invoke(
|
|
335
370
|
self,
|
|
@@ -554,7 +589,13 @@ class Client(Decorators, Methods):
|
|
|
554
589
|
if isinstance(self.workers, int) and self.workers < 1:
|
|
555
590
|
raise ValueError("workers must be greater than 0")
|
|
556
591
|
|
|
557
|
-
def
|
|
592
|
+
def _update_handlers(self):
|
|
593
|
+
self._current_handlers = {
|
|
594
|
+
k: tuple(sorted(v, key=lambda x: (x.position is None, x.position)))
|
|
595
|
+
for k, v in self._handlers.items()
|
|
596
|
+
}
|
|
597
|
+
|
|
598
|
+
def _load_plugins(self, reload_plugins: bool = False):
|
|
558
599
|
count = 0
|
|
559
600
|
handlers = 0
|
|
560
601
|
plugin_paths = sorted(Path(self.plugins.folder).rglob("*.py"))
|
|
@@ -578,6 +619,8 @@ class Client(Decorators, Methods):
|
|
|
578
619
|
|
|
579
620
|
try:
|
|
580
621
|
module = import_module(module_path)
|
|
622
|
+
if reload_plugins:
|
|
623
|
+
reload_module(module)
|
|
581
624
|
except Exception:
|
|
582
625
|
self.logger.exception(f"Failed to import plugin {module_path}")
|
|
583
626
|
continue
|
|
@@ -600,6 +643,7 @@ class Client(Decorators, Methods):
|
|
|
600
643
|
handler.filter,
|
|
601
644
|
handler.position,
|
|
602
645
|
handler.inner_object,
|
|
646
|
+
True,
|
|
603
647
|
)
|
|
604
648
|
handlers += 1
|
|
605
649
|
plugin_handlers_count += 1
|
|
@@ -665,7 +709,7 @@ class Client(Decorators, Methods):
|
|
|
665
709
|
async def __run_initializers(self, update):
|
|
666
710
|
inner_object = self.get_inner_object(update)
|
|
667
711
|
|
|
668
|
-
for initializer in self.
|
|
712
|
+
for initializer in self._current_handlers["initializer"]:
|
|
669
713
|
try:
|
|
670
714
|
handler_value = inner_object if initializer.inner_object else update
|
|
671
715
|
|
|
@@ -687,7 +731,7 @@ class Client(Decorators, Methods):
|
|
|
687
731
|
async def __run_handlers(self, update):
|
|
688
732
|
inner_object = self.get_inner_object(update)
|
|
689
733
|
|
|
690
|
-
for handler in self.
|
|
734
|
+
for handler in self._current_handlers[update.getType()]:
|
|
691
735
|
try:
|
|
692
736
|
handler_value = inner_object if handler.inner_object else update
|
|
693
737
|
|
|
@@ -708,7 +752,7 @@ class Client(Decorators, Methods):
|
|
|
708
752
|
async def __run_finalizers(self, update):
|
|
709
753
|
inner_object = self.get_inner_object(update)
|
|
710
754
|
|
|
711
|
-
for finalizer in self.
|
|
755
|
+
for finalizer in self._current_handlers["finalizer"]:
|
|
712
756
|
try:
|
|
713
757
|
handler_value = inner_object if finalizer.inner_object else update
|
|
714
758
|
|
|
@@ -728,10 +772,13 @@ class Client(Decorators, Methods):
|
|
|
728
772
|
self.logger.exception(f"Finalizer {finalizer} failed")
|
|
729
773
|
|
|
730
774
|
async def _handle_update(self, update):
|
|
731
|
-
if update.getType() in self.
|
|
775
|
+
if update.getType() in self._current_handlers:
|
|
732
776
|
if (
|
|
733
777
|
not self.user_bot
|
|
734
778
|
and isinstance(update, types.UpdateNewMessage)
|
|
779
|
+
and not isinstance(
|
|
780
|
+
update.message.content, self.allow_outgoing_message_types
|
|
781
|
+
)
|
|
735
782
|
and update.message.is_outgoing
|
|
736
783
|
):
|
|
737
784
|
return
|
|
@@ -15,18 +15,20 @@ class Handler:
|
|
|
15
15
|
filter: Filter = None,
|
|
16
16
|
position: int = None,
|
|
17
17
|
inner_object: bool = False,
|
|
18
|
+
is_from_plugin: bool = False,
|
|
18
19
|
) -> None:
|
|
19
20
|
self.func = func
|
|
20
21
|
self.update_type = update_type
|
|
21
22
|
self.filter = filter
|
|
22
23
|
self.position = position
|
|
23
24
|
self.inner_object = inner_object
|
|
25
|
+
self.is_from_plugin = is_from_plugin
|
|
24
26
|
|
|
25
27
|
def __call__(self, client: "pytdbot.Client", update: "pytdbot.types.Update"):
|
|
26
28
|
return self.func(client, update)
|
|
27
29
|
|
|
28
30
|
def __str__(self) -> str:
|
|
29
|
-
return f"Handler(func={self.func}, update_type={self.update_type}, filter={self.filter}, position={self.position}, inner_object={self.inner_object})"
|
|
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})"
|
|
30
32
|
|
|
31
33
|
def __repr__(self) -> str:
|
|
32
34
|
return str(self)
|
|
@@ -1947,6 +1947,82 @@ class Updates:
|
|
|
1947
1947
|
|
|
1948
1948
|
return decorator
|
|
1949
1949
|
|
|
1950
|
+
def on_updateDirectMessagesChatTopic(
|
|
1951
|
+
self: "pytdbot.Client" = None,
|
|
1952
|
+
filters: "pytdbot.filters.Filter" = None,
|
|
1953
|
+
position: int = None,
|
|
1954
|
+
) -> Callable:
|
|
1955
|
+
r"""Basic information about a topic in a channel direct messages chat administered by the current user has changed\. This update is guaranteed to come before the topic identifier is returned to the application
|
|
1956
|
+
|
|
1957
|
+
Parameters:
|
|
1958
|
+
filters (:class:`pytdbot.filters.Filter`, *optional*):
|
|
1959
|
+
An update filter
|
|
1960
|
+
|
|
1961
|
+
position (``int``, *optional*):
|
|
1962
|
+
The function position in handlers list. Default is ``None`` (append)
|
|
1963
|
+
|
|
1964
|
+
Raises:
|
|
1965
|
+
:py:class:`TypeError`
|
|
1966
|
+
"""
|
|
1967
|
+
|
|
1968
|
+
def decorator(func: Callable) -> Callable:
|
|
1969
|
+
if hasattr(func, "_handler"):
|
|
1970
|
+
return func
|
|
1971
|
+
elif isinstance(self, pytdbot.Client):
|
|
1972
|
+
if iscoroutinefunction(func):
|
|
1973
|
+
self.add_handler(
|
|
1974
|
+
"updateDirectMessagesChatTopic", func, filters, position
|
|
1975
|
+
)
|
|
1976
|
+
else:
|
|
1977
|
+
raise TypeError("Handler must be async")
|
|
1978
|
+
elif isinstance(self, pytdbot.filters.Filter):
|
|
1979
|
+
func._handler = Handler(
|
|
1980
|
+
func, "updateDirectMessagesChatTopic", self, position
|
|
1981
|
+
)
|
|
1982
|
+
else:
|
|
1983
|
+
func._handler = Handler(
|
|
1984
|
+
func, "updateDirectMessagesChatTopic", filters, position
|
|
1985
|
+
)
|
|
1986
|
+
return func
|
|
1987
|
+
|
|
1988
|
+
return decorator
|
|
1989
|
+
|
|
1990
|
+
def on_updateTopicMessageCount(
|
|
1991
|
+
self: "pytdbot.Client" = None,
|
|
1992
|
+
filters: "pytdbot.filters.Filter" = None,
|
|
1993
|
+
position: int = None,
|
|
1994
|
+
) -> Callable:
|
|
1995
|
+
r"""Number of messages in a topic has changed; for Saved Messages and channel direct messages chat topics only
|
|
1996
|
+
|
|
1997
|
+
Parameters:
|
|
1998
|
+
filters (:class:`pytdbot.filters.Filter`, *optional*):
|
|
1999
|
+
An update filter
|
|
2000
|
+
|
|
2001
|
+
position (``int``, *optional*):
|
|
2002
|
+
The function position in handlers list. Default is ``None`` (append)
|
|
2003
|
+
|
|
2004
|
+
Raises:
|
|
2005
|
+
:py:class:`TypeError`
|
|
2006
|
+
"""
|
|
2007
|
+
|
|
2008
|
+
def decorator(func: Callable) -> Callable:
|
|
2009
|
+
if hasattr(func, "_handler"):
|
|
2010
|
+
return func
|
|
2011
|
+
elif isinstance(self, pytdbot.Client):
|
|
2012
|
+
if iscoroutinefunction(func):
|
|
2013
|
+
self.add_handler("updateTopicMessageCount", func, filters, position)
|
|
2014
|
+
else:
|
|
2015
|
+
raise TypeError("Handler must be async")
|
|
2016
|
+
elif isinstance(self, pytdbot.filters.Filter):
|
|
2017
|
+
func._handler = Handler(func, "updateTopicMessageCount", self, position)
|
|
2018
|
+
else:
|
|
2019
|
+
func._handler = Handler(
|
|
2020
|
+
func, "updateTopicMessageCount", filters, position
|
|
2021
|
+
)
|
|
2022
|
+
return func
|
|
2023
|
+
|
|
2024
|
+
return decorator
|
|
2025
|
+
|
|
1950
2026
|
def on_updateQuickReplyShortcut(
|
|
1951
2027
|
self: "pytdbot.Client" = None,
|
|
1952
2028
|
filters: "pytdbot.filters.Filter" = None,
|