Pytdbot 0.9.0.dev6__tar.gz → 0.9.1__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 (42) hide show
  1. {pytdbot-0.9.0.dev6 → pytdbot-0.9.1}/LICENSE +1 -1
  2. {pytdbot-0.9.0.dev6 → pytdbot-0.9.1}/PKG-INFO +45 -17
  3. {pytdbot-0.9.0.dev6 → pytdbot-0.9.1}/Pytdbot.egg-info/PKG-INFO +45 -17
  4. {pytdbot-0.9.0.dev6 → pytdbot-0.9.1}/Pytdbot.egg-info/requires.txt +3 -0
  5. {pytdbot-0.9.0.dev6 → pytdbot-0.9.1}/README.md +27 -13
  6. {pytdbot-0.9.0.dev6 → pytdbot-0.9.1}/pytdbot/__init__.py +2 -2
  7. {pytdbot-0.9.0.dev6 → pytdbot-0.9.1}/pytdbot/client.py +49 -81
  8. {pytdbot-0.9.0.dev6 → pytdbot-0.9.1}/pytdbot/handlers/td_updates.py +89 -0
  9. {pytdbot-0.9.0.dev6 → pytdbot-0.9.1}/pytdbot/methods/methods.py +0 -65
  10. {pytdbot-0.9.0.dev6 → pytdbot-0.9.1}/pytdbot/methods/td_functions.py +413 -122
  11. {pytdbot-0.9.0.dev6 → pytdbot-0.9.1}/pytdbot/tdjson/tdjson.py +59 -36
  12. {pytdbot-0.9.0.dev6 → pytdbot-0.9.1}/pytdbot/types/__init__.py +69 -9
  13. {pytdbot-0.9.0.dev6 → pytdbot-0.9.1}/pytdbot/types/td_types/bound_methods/callback_query.py +1 -1
  14. {pytdbot-0.9.0.dev6 → pytdbot-0.9.1}/pytdbot/types/td_types/bound_methods/message.py +8 -21
  15. {pytdbot-0.9.0.dev6 → pytdbot-0.9.1}/pytdbot/types/td_types/types.py +1853 -208
  16. {pytdbot-0.9.0.dev6 → pytdbot-0.9.1}/pytdbot/utils/__init__.py +9 -1
  17. pytdbot-0.9.1/pytdbot/utils/json_utils.py +27 -0
  18. {pytdbot-0.9.0.dev6 → pytdbot-0.9.1}/pytdbot/utils/strings.py +19 -0
  19. {pytdbot-0.9.0.dev6 → pytdbot-0.9.1}/setup.py +4 -1
  20. pytdbot-0.9.0.dev6/pytdbot/utils/json_utils.py +0 -23
  21. {pytdbot-0.9.0.dev6 → pytdbot-0.9.1}/MANIFEST.in +0 -0
  22. {pytdbot-0.9.0.dev6 → pytdbot-0.9.1}/Pytdbot.egg-info/SOURCES.txt +0 -0
  23. {pytdbot-0.9.0.dev6 → pytdbot-0.9.1}/Pytdbot.egg-info/dependency_links.txt +0 -0
  24. {pytdbot-0.9.0.dev6 → pytdbot-0.9.1}/Pytdbot.egg-info/top_level.txt +0 -0
  25. {pytdbot-0.9.0.dev6 → pytdbot-0.9.1}/pytdbot/exception/__init__.py +0 -0
  26. {pytdbot-0.9.0.dev6 → pytdbot-0.9.1}/pytdbot/filters.py +0 -0
  27. {pytdbot-0.9.0.dev6 → pytdbot-0.9.1}/pytdbot/handlers/__init__.py +0 -0
  28. {pytdbot-0.9.0.dev6 → pytdbot-0.9.1}/pytdbot/handlers/decorators.py +0 -0
  29. {pytdbot-0.9.0.dev6 → pytdbot-0.9.1}/pytdbot/handlers/handler.py +0 -0
  30. {pytdbot-0.9.0.dev6 → pytdbot-0.9.1}/pytdbot/methods/__init__.py +0 -0
  31. {pytdbot-0.9.0.dev6 → pytdbot-0.9.1}/pytdbot/tdjson/__init__.py +0 -0
  32. {pytdbot-0.9.0.dev6 → pytdbot-0.9.1}/pytdbot/types/plugins/__init__.py +0 -0
  33. {pytdbot-0.9.0.dev6 → pytdbot-0.9.1}/pytdbot/types/td_types/__init__.py +0 -0
  34. {pytdbot-0.9.0.dev6 → pytdbot-0.9.1}/pytdbot/types/td_types/bound_methods/__init__.py +0 -0
  35. {pytdbot-0.9.0.dev6 → pytdbot-0.9.1}/pytdbot/types/td_types/bound_methods/chatActions.py +0 -0
  36. {pytdbot-0.9.0.dev6 → pytdbot-0.9.1}/pytdbot/types/td_types/bound_methods/file.py +0 -0
  37. {pytdbot-0.9.0.dev6 → pytdbot-0.9.1}/pytdbot/utils/escape.py +0 -0
  38. {pytdbot-0.9.0.dev6 → pytdbot-0.9.1}/pytdbot/utils/obj_encoder.py +0 -0
  39. {pytdbot-0.9.0.dev6 → pytdbot-0.9.1}/pytdbot/utils/text_format.py +0 -0
  40. {pytdbot-0.9.0.dev6 → pytdbot-0.9.1}/pytdbot/utils/webapps.py +0 -0
  41. {pytdbot-0.9.0.dev6 → pytdbot-0.9.1}/requirements.txt +0 -0
  42. {pytdbot-0.9.0.dev6 → pytdbot-0.9.1}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  MIT License
2
2
 
3
- Copyright (c) 2022-2025 Python TDLib
3
+ Copyright (c) 2022-2025 Pytdbot, AYMENJD
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.1
1
+ Metadata-Version: 2.2
2
2
  Name: Pytdbot
3
- Version: 0.9.0.dev6
3
+ Version: 0.9.1
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
@@ -14,14 +14,28 @@ Description-Content-Type: text/markdown
14
14
  License-File: LICENSE
15
15
  Requires-Dist: deepdiff
16
16
  Requires-Dist: aio-pika
17
-
18
- # 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.42-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)
19
-
20
- Pytdbot (Python TDLib) is an asynchronous [**TDLib**](https://github.com/tdlib/td) wrapper for **Telegram** users/bots written in **Python**.
17
+ Provides-Extra: tdjson
18
+ Requires-Dist: tdjson; extra == "tdjson"
19
+ Dynamic: author
20
+ Dynamic: author-email
21
+ Dynamic: description
22
+ Dynamic: description-content-type
23
+ Dynamic: home-page
24
+ Dynamic: keywords
25
+ Dynamic: license
26
+ Dynamic: project-url
27
+ Dynamic: provides-extra
28
+ Dynamic: requires-dist
29
+ Dynamic: requires-python
30
+ Dynamic: summary
31
+
32
+ # 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.46-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)
33
+
34
+ Pytdbot (Python TDLib) is an asynchronous [**TDLib**](https://github.com/tdlib/td) wrapper for **Telegram** users/bots written in **Python**.
21
35
 
22
36
  ### Features
23
37
 
24
- ``Pytdbot`` offers numerous advantages, including:
38
+ `Pytdbot` offers numerous advantages, including:
25
39
 
26
40
  - **Easy to Use**: Designed with simplicity in mind, making it accessible for developers
27
41
  - **Performance**: Fast and powerful, making it ready to fight
@@ -32,30 +46,42 @@ Pytdbot (Python TDLib) is an asynchronous [**TDLib**](https://github.com/tdlib/t
32
46
  - **Bound Methods**: Features types bound methods for improved usability
33
47
  - **Unlimited Support**: Supports **Plugins**, [**filters**](pytdbot/filters.py#L23), [**TDLib**](https://github.com/tdlib/td) types/functions and much more
34
48
 
35
-
36
-
37
49
  ### Requirements
38
50
 
39
51
  - Python 3.9+
40
52
  - Telegram [API key](https://my.telegram.org/apps)
41
- - [tdjson](https://github.com/tdlib/td#building)
53
+ - [tdjson](https://github.com/AYMENJD/tdjson) or [TDLib](https://github.com/tdlib/td#building)
42
54
  - [deepdiff](https://github.com/seperman/deepdiff)
43
55
  - [aio-pika](https://github.com/mosquito/aio-pika)
44
56
 
45
57
  ### Installation
58
+
46
59
  > For better performance, it's recommended to install [orjson](https://github.com/ijl/orjson#install) or [ujson](https://github.com/ultrajson/ultrajson#ultrajson).
47
60
 
48
- You can install Pytdbot using pip:
61
+ You can install Pytdbot with TDLib included using pip:
62
+
63
+ ```bash
64
+ pip install --upgrade pytdbot[tdjson]
65
+ ```
66
+
67
+ If the installation fails, then install without **pre-built** TDLib:
68
+
49
69
  ```bash
50
70
  pip install pytdbot
51
71
  ```
52
- To install the development version from Github, use the following command:
72
+
73
+ Then you need to build TDLib from [source](https://github.com/tdlib/td#building) and pass it to `Client.lib_path`.
74
+
75
+ You could also install the development version using the following command:
76
+
53
77
  ```bash
54
- pip install git+https://github.com/pytdbot/client.git
78
+ pip install --pre pytdbot
55
79
  ```
56
80
 
57
81
  ### Examples
82
+
58
83
  Basic example:
84
+
59
85
  ```python
60
86
 
61
87
  import asyncio
@@ -63,10 +89,9 @@ import asyncio
63
89
  from pytdbot import Client, types
64
90
 
65
91
  client = Client(
66
- token="1088394097:AAQX2DnWiw4ihwiJUhIHOGog8gGOI", # Your bot token or phone number if you want to login as user
67
- api_id=0,
68
- api_hash="API_HASH",
69
- lib_path="/path/to/libtdjson.so", # Path to TDjson shared library
92
+ token="1088394097:AAQX2DnWiw4ihwiJUhIHOGog8gGOI", # Your bot token
93
+ api_id=0,
94
+ api_hash="API_HASH",
70
95
  files_directory="BotDB", # Path where to store TDLib files
71
96
  database_encryption_key="1234echobot$",
72
97
  td_verbosity=2, # TDLib verbosity level
@@ -94,12 +119,15 @@ async def say_hello(c: Client, message: types.Message):
94
119
  client.run()
95
120
 
96
121
  ```
122
+
97
123
  For more examples, check the [examples](https://github.com/pytdbot/client/tree/main/examples) folder.
98
124
 
99
125
  # Thanks to
126
+
100
127
  - You for viewing or using this project.
101
128
 
102
129
  - [@levlam](https://github.com/levlam) for maintaining [TDLib](https://github.com/tdlib/td) and for the help to create [Pytdbot](https://github.com/pytdbot/client).
130
+
103
131
  # License
104
132
 
105
133
  MIT [License](https://github.com/pytdbot/client/blob/main/LICENSE)
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.1
1
+ Metadata-Version: 2.2
2
2
  Name: Pytdbot
3
- Version: 0.9.0.dev6
3
+ Version: 0.9.1
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
@@ -14,14 +14,28 @@ Description-Content-Type: text/markdown
14
14
  License-File: LICENSE
15
15
  Requires-Dist: deepdiff
16
16
  Requires-Dist: aio-pika
17
-
18
- # 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.42-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)
19
-
20
- Pytdbot (Python TDLib) is an asynchronous [**TDLib**](https://github.com/tdlib/td) wrapper for **Telegram** users/bots written in **Python**.
17
+ Provides-Extra: tdjson
18
+ Requires-Dist: tdjson; extra == "tdjson"
19
+ Dynamic: author
20
+ Dynamic: author-email
21
+ Dynamic: description
22
+ Dynamic: description-content-type
23
+ Dynamic: home-page
24
+ Dynamic: keywords
25
+ Dynamic: license
26
+ Dynamic: project-url
27
+ Dynamic: provides-extra
28
+ Dynamic: requires-dist
29
+ Dynamic: requires-python
30
+ Dynamic: summary
31
+
32
+ # 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.46-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)
33
+
34
+ Pytdbot (Python TDLib) is an asynchronous [**TDLib**](https://github.com/tdlib/td) wrapper for **Telegram** users/bots written in **Python**.
21
35
 
22
36
  ### Features
23
37
 
24
- ``Pytdbot`` offers numerous advantages, including:
38
+ `Pytdbot` offers numerous advantages, including:
25
39
 
26
40
  - **Easy to Use**: Designed with simplicity in mind, making it accessible for developers
27
41
  - **Performance**: Fast and powerful, making it ready to fight
@@ -32,30 +46,42 @@ Pytdbot (Python TDLib) is an asynchronous [**TDLib**](https://github.com/tdlib/t
32
46
  - **Bound Methods**: Features types bound methods for improved usability
33
47
  - **Unlimited Support**: Supports **Plugins**, [**filters**](pytdbot/filters.py#L23), [**TDLib**](https://github.com/tdlib/td) types/functions and much more
34
48
 
35
-
36
-
37
49
  ### Requirements
38
50
 
39
51
  - Python 3.9+
40
52
  - Telegram [API key](https://my.telegram.org/apps)
41
- - [tdjson](https://github.com/tdlib/td#building)
53
+ - [tdjson](https://github.com/AYMENJD/tdjson) or [TDLib](https://github.com/tdlib/td#building)
42
54
  - [deepdiff](https://github.com/seperman/deepdiff)
43
55
  - [aio-pika](https://github.com/mosquito/aio-pika)
44
56
 
45
57
  ### Installation
58
+
46
59
  > For better performance, it's recommended to install [orjson](https://github.com/ijl/orjson#install) or [ujson](https://github.com/ultrajson/ultrajson#ultrajson).
47
60
 
48
- You can install Pytdbot using pip:
61
+ You can install Pytdbot with TDLib included using pip:
62
+
63
+ ```bash
64
+ pip install --upgrade pytdbot[tdjson]
65
+ ```
66
+
67
+ If the installation fails, then install without **pre-built** TDLib:
68
+
49
69
  ```bash
50
70
  pip install pytdbot
51
71
  ```
52
- To install the development version from Github, use the following command:
72
+
73
+ Then you need to build TDLib from [source](https://github.com/tdlib/td#building) and pass it to `Client.lib_path`.
74
+
75
+ You could also install the development version using the following command:
76
+
53
77
  ```bash
54
- pip install git+https://github.com/pytdbot/client.git
78
+ pip install --pre pytdbot
55
79
  ```
56
80
 
57
81
  ### Examples
82
+
58
83
  Basic example:
84
+
59
85
  ```python
60
86
 
61
87
  import asyncio
@@ -63,10 +89,9 @@ import asyncio
63
89
  from pytdbot import Client, types
64
90
 
65
91
  client = Client(
66
- token="1088394097:AAQX2DnWiw4ihwiJUhIHOGog8gGOI", # Your bot token or phone number if you want to login as user
67
- api_id=0,
68
- api_hash="API_HASH",
69
- lib_path="/path/to/libtdjson.so", # Path to TDjson shared library
92
+ token="1088394097:AAQX2DnWiw4ihwiJUhIHOGog8gGOI", # Your bot token
93
+ api_id=0,
94
+ api_hash="API_HASH",
70
95
  files_directory="BotDB", # Path where to store TDLib files
71
96
  database_encryption_key="1234echobot$",
72
97
  td_verbosity=2, # TDLib verbosity level
@@ -94,12 +119,15 @@ async def say_hello(c: Client, message: types.Message):
94
119
  client.run()
95
120
 
96
121
  ```
122
+
97
123
  For more examples, check the [examples](https://github.com/pytdbot/client/tree/main/examples) folder.
98
124
 
99
125
  # Thanks to
126
+
100
127
  - You for viewing or using this project.
101
128
 
102
129
  - [@levlam](https://github.com/levlam) for maintaining [TDLib](https://github.com/tdlib/td) and for the help to create [Pytdbot](https://github.com/pytdbot/client).
130
+
103
131
  # License
104
132
 
105
133
  MIT [License](https://github.com/pytdbot/client/blob/main/LICENSE)
@@ -1,2 +1,5 @@
1
1
  deepdiff
2
2
  aio-pika
3
+
4
+ [tdjson]
5
+ tdjson
@@ -1,10 +1,10 @@
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.42-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)
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.46-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)
2
2
 
3
- Pytdbot (Python TDLib) is an asynchronous [**TDLib**](https://github.com/tdlib/td) wrapper for **Telegram** users/bots written in **Python**.
3
+ Pytdbot (Python TDLib) is an asynchronous [**TDLib**](https://github.com/tdlib/td) wrapper for **Telegram** users/bots written in **Python**.
4
4
 
5
5
  ### Features
6
6
 
7
- ``Pytdbot`` offers numerous advantages, including:
7
+ `Pytdbot` offers numerous advantages, including:
8
8
 
9
9
  - **Easy to Use**: Designed with simplicity in mind, making it accessible for developers
10
10
  - **Performance**: Fast and powerful, making it ready to fight
@@ -15,30 +15,42 @@ Pytdbot (Python TDLib) is an asynchronous [**TDLib**](https://github.com/tdlib/t
15
15
  - **Bound Methods**: Features types bound methods for improved usability
16
16
  - **Unlimited Support**: Supports **Plugins**, [**filters**](pytdbot/filters.py#L23), [**TDLib**](https://github.com/tdlib/td) types/functions and much more
17
17
 
18
-
19
-
20
18
  ### Requirements
21
19
 
22
20
  - Python 3.9+
23
21
  - Telegram [API key](https://my.telegram.org/apps)
24
- - [tdjson](https://github.com/tdlib/td#building)
22
+ - [tdjson](https://github.com/AYMENJD/tdjson) or [TDLib](https://github.com/tdlib/td#building)
25
23
  - [deepdiff](https://github.com/seperman/deepdiff)
26
24
  - [aio-pika](https://github.com/mosquito/aio-pika)
27
25
 
28
26
  ### Installation
27
+
29
28
  > For better performance, it's recommended to install [orjson](https://github.com/ijl/orjson#install) or [ujson](https://github.com/ultrajson/ultrajson#ultrajson).
30
29
 
31
- You can install Pytdbot using pip:
30
+ You can install Pytdbot with TDLib included using pip:
31
+
32
+ ```bash
33
+ pip install --upgrade pytdbot[tdjson]
34
+ ```
35
+
36
+ If the installation fails, then install without **pre-built** TDLib:
37
+
32
38
  ```bash
33
39
  pip install pytdbot
34
40
  ```
35
- To install the development version from Github, use the following command:
41
+
42
+ Then you need to build TDLib from [source](https://github.com/tdlib/td#building) and pass it to `Client.lib_path`.
43
+
44
+ You could also install the development version using the following command:
45
+
36
46
  ```bash
37
- pip install git+https://github.com/pytdbot/client.git
47
+ pip install --pre pytdbot
38
48
  ```
39
49
 
40
50
  ### Examples
51
+
41
52
  Basic example:
53
+
42
54
  ```python
43
55
 
44
56
  import asyncio
@@ -46,10 +58,9 @@ import asyncio
46
58
  from pytdbot import Client, types
47
59
 
48
60
  client = Client(
49
- token="1088394097:AAQX2DnWiw4ihwiJUhIHOGog8gGOI", # Your bot token or phone number if you want to login as user
50
- api_id=0,
51
- api_hash="API_HASH",
52
- lib_path="/path/to/libtdjson.so", # Path to TDjson shared library
61
+ token="1088394097:AAQX2DnWiw4ihwiJUhIHOGog8gGOI", # Your bot token
62
+ api_id=0,
63
+ api_hash="API_HASH",
53
64
  files_directory="BotDB", # Path where to store TDLib files
54
65
  database_encryption_key="1234echobot$",
55
66
  td_verbosity=2, # TDLib verbosity level
@@ -77,12 +88,15 @@ async def say_hello(c: Client, message: types.Message):
77
88
  client.run()
78
89
 
79
90
  ```
91
+
80
92
  For more examples, check the [examples](https://github.com/pytdbot/client/tree/main/examples) folder.
81
93
 
82
94
  # Thanks to
95
+
83
96
  - You for viewing or using this project.
84
97
 
85
98
  - [@levlam](https://github.com/levlam) for maintaining [TDLib](https://github.com/tdlib/td) and for the help to create [Pytdbot](https://github.com/pytdbot/client).
99
+
86
100
  # License
87
101
 
88
102
  MIT [License](https://github.com/pytdbot/client/blob/main/LICENSE)
@@ -4,8 +4,8 @@ from .client import Client
4
4
 
5
5
  __all__ = ["types", "utils", "filters", "exception", "TdJson", "Client"]
6
6
 
7
- __version__ = "0.9.0dev6"
8
- __copyright__ = "Copyright (c) 2022-2025 AYMEN Mohammed ~ https://github.com/AYMENJD"
7
+ __version__ = "0.9.1"
8
+ __copyright__ = "Copyright (c) 2022-2025 Pytdbot, AYMENJD"
9
9
  __license__ = "MIT License"
10
10
 
11
11
  VERSION = __version__
@@ -33,6 +33,13 @@ from .utils import (
33
33
  )
34
34
 
35
35
 
36
+ def get_running_loop():
37
+ try:
38
+ return asyncio.get_running_loop()
39
+ except RuntimeError:
40
+ return asyncio.new_event_loop()
41
+
42
+
36
43
  class Client(Decorators, Methods):
37
44
  r"""Pytdbot, a TDLib client
38
45
 
@@ -92,10 +99,6 @@ class Client(Decorators, Methods):
92
99
  options (``dict``, *optional*):
93
100
  Pass key-value dictionary to set TDLib options. Check the list of available options at https://core.telegram.org/tdlib/options
94
101
 
95
- sleep_threshold (``int``, *optional*):
96
- Sleep threshold for all ``FLOOD_WAIT_X`` a.k.a ``Too Many Requests: retry after`` errors occur to this client.
97
- If any request is rate limited (flood waited) the client will repeat the request after sleeping the required amount of seconds returned by the error. If the ``retry after`` value is higher than ``sleep_threshold`` the error is returned. Default is ``None`` (Disabled)
98
-
99
102
  workers (``int``, *optional*):
100
103
  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.
101
104
 
@@ -129,7 +132,6 @@ class Client(Decorators, Methods):
129
132
  use_message_database: bool = True,
130
133
  loop: asyncio.AbstractEventLoop = None,
131
134
  options: dict = None,
132
- sleep_threshold: int = None,
133
135
  workers: int = 5,
134
136
  no_updates: bool = False,
135
137
  td_verbosity: int = 2,
@@ -159,9 +161,6 @@ class Client(Decorators, Methods):
159
161
  self.use_chat_info_database = use_chat_info_database
160
162
  self.use_message_database = use_message_database
161
163
  self.td_options = options
162
- self.sleep_threshold = (
163
- sleep_threshold if isinstance(sleep_threshold, int) else 0
164
- )
165
164
  self.workers = workers
166
165
  self.no_updates = no_updates
167
166
  self.queue = asyncio.Queue()
@@ -180,7 +179,7 @@ class Client(Decorators, Methods):
180
179
  self._handlers = {"initializer": [], "finalizer": []}
181
180
  self._results: Dict[str, asyncio.Future] = {}
182
181
  self._tdjson = None if self.is_rabbitmq else TdJson(lib_path, td_verbosity)
183
- self._retry_after_prefex = "Too Many Requests: retry after "
182
+ self.__listen_loop_task = None
184
183
  self._workers_tasks = None
185
184
  self.__authorization_state = None
186
185
  self.__cache = {"is_coro_filter": {}}
@@ -196,9 +195,7 @@ class Client(Decorators, Methods):
196
195
  self.__is_closing = False
197
196
 
198
197
  self.loop = (
199
- loop
200
- if isinstance(loop, asyncio.AbstractEventLoop)
201
- else asyncio.get_event_loop()
198
+ loop if isinstance(loop, asyncio.AbstractEventLoop) else get_running_loop()
202
199
  )
203
200
 
204
201
  if plugins is not None:
@@ -254,7 +251,7 @@ class Client(Decorators, Methods):
254
251
  if self.is_rabbitmq:
255
252
  await self.__startRabbitMQ()
256
253
  else:
257
- self.loop.create_task(self.__listen_loop())
254
+ self.__listen_loop_task = self.loop.create_task(self.__listen_loop())
258
255
 
259
256
  if login:
260
257
  await self.login()
@@ -399,54 +396,48 @@ class Client(Decorators, Methods):
399
396
  ): # dumping all requests may create performance issues
400
397
  self.logger.debug(f"Sending: {dumps(request, indent=4)}")
401
398
 
402
- await self.__send(request)
403
- result = await future
399
+ is_chat_attempted_load = request["@type"].lower() == "getchat"
404
400
 
405
- if isinstance(result, types.Error):
406
- if result.code == 429:
407
- retry_after = self.get_retry_after_time(result.message)
401
+ while True:
402
+ future = self._create_request_future(request)
403
+ await self.__send(request)
404
+ result = await future
408
405
 
409
- if retry_after <= self.sleep_threshold:
410
- self.logger.error(
411
- f"Sleeping for {retry_after}s (Caused by {request['@type']})"
412
- )
406
+ if isinstance(result, types.Error):
407
+ if result.code == 400:
408
+ if result.message.startswith(
409
+ "Failed to parse JSON object as TDLib request:"
410
+ ):
411
+ raise ValueError(result.message)
413
412
 
414
- await asyncio.sleep(retry_after)
413
+ if not is_chat_attempted_load and (
414
+ result.message == "Chat not found" and "chat_id" in request
415
+ ):
416
+ is_chat_attempted_load = True
415
417
 
416
- future = self._create_request_future(request)
418
+ chat_id = request["chat_id"]
417
419
 
418
- await self.__send(request)
419
- result = await future
420
- elif not self.use_message_database and (
421
- result.code == 400
422
- and result.message == "Chat not found"
423
- and "chat_id" in request
424
- ):
425
- chat_id = request["chat_id"]
420
+ self.logger.debug(f"Attempt to load chat {chat_id}")
426
421
 
427
- self.logger.debug(f"Attempt to load chat {chat_id}")
422
+ load_chat = await self.getChat(chat_id)
428
423
 
429
- load_chat = await self.getChat(chat_id)
424
+ if not isinstance(load_chat, types.Error):
425
+ self.logger.debug(f"Chat {chat_id} is loaded")
430
426
 
431
- if not isinstance(load_chat, types.Error):
432
- self.logger.debug(f"Chat {chat_id} is loaded")
427
+ reply_to_message_id = (request.get("reply_to") or {}).get(
428
+ "message_id", 0
429
+ )
433
430
 
434
- reply_to_message_id = (request.get("reply_to") or {}).get(
435
- "message_id", 0
436
- )
431
+ # if the request is a reply to another message
432
+ # load the replied message to avoid "Message not found"
433
+ if reply_to_message_id > 0:
434
+ await self.getMessage(chat_id, reply_to_message_id)
437
435
 
438
- # if the request is a reply to another message
439
- # load the replied message to avoid "Message not found"
440
- if reply_to_message_id > 0:
441
- await self.getMessage(chat_id, reply_to_message_id)
436
+ continue
442
437
 
443
- # repeat the first request
444
- future = self._create_request_future(request)
438
+ self.logger.error(f"Couldn't load chat {chat_id}")
445
439
 
446
- await self.__send(request)
447
- result = await future
448
- else:
449
- self.logger.error(f"Couldn't load chat {chat_id}")
440
+ break
450
441
 
451
442
  return result
452
443
 
@@ -568,7 +559,8 @@ class Client(Decorators, Methods):
568
559
  else:
569
560
  await self.__rchannel.default_exchange.publish(
570
561
  aio_pika.Message(
571
- json_dumps(request), reply_to=self.__rqueues["responses"].name
562
+ json_dumps(request, encode=True),
563
+ reply_to=self.__rqueues["responses"].name,
572
564
  ),
573
565
  routing_key=self.__rqueues["requests"].name,
574
566
  )
@@ -592,22 +584,6 @@ class Client(Decorators, Methods):
592
584
  if isinstance(self.workers, int) and self.workers < 1:
593
585
  raise ValueError("workers must be greater than 0")
594
586
 
595
- def get_retry_after_time(self, error_message: str) -> int:
596
- r"""Get the retry after time from flood wait error message
597
-
598
- Parameters:
599
- error_message (``str``):
600
- The returned error message from TDLib
601
-
602
- Returns:
603
- py:class:`int`
604
- """
605
-
606
- try:
607
- return int(error_message.removeprefix(self._retry_after_prefex))
608
- except Exception:
609
- return 0
610
-
611
587
  def _load_plugins(self):
612
588
  count = 0
613
589
  handlers = 0
@@ -694,7 +670,7 @@ class Client(Decorators, Methods):
694
670
  update = await self.loop.run_in_executor(
695
671
  thread,
696
672
  self._tdjson.receive,
697
- 100000.0, # Seconds
673
+ 1.0, # Seconds
698
674
  )
699
675
  if update is None:
700
676
  continue
@@ -858,6 +834,7 @@ class Client(Decorators, Methods):
858
834
  application_version=f"Pytdbot {pytdbot.__version__}",
859
835
  )
860
836
  if isinstance(res, types.Error):
837
+ await self.stop()
861
838
  raise AuthorizationError(res.message)
862
839
 
863
840
  async def _set_options(self):
@@ -929,20 +906,7 @@ class Client(Decorators, Methods):
929
906
  m_id = f"{update.message.chat_id}:{update.old_message_id}"
930
907
 
931
908
  if result := self._results.pop(m_id, None):
932
- if update.error.code == 429:
933
- retry_after = update.message.sending_state.retry_after
934
-
935
- if retry_after <= self.sleep_threshold:
936
- self.logger.error(
937
- f"Sleeping for {retry_after}s (Caused by {result.request['@type']})"
938
- )
939
-
940
- await asyncio.sleep(retry_after)
941
- res = await self.invoke(result.request)
942
-
943
- self._results[f"{res.id}{update.message.chat_id}"] = result
944
- else:
945
- result.set_result(update.error)
909
+ result.set_result(update.error)
946
910
 
947
911
  async def __handle_update_option(self, update: types.UpdateOption):
948
912
  if isinstance(update.value, types.OptionValueBoolean):
@@ -1067,6 +1031,7 @@ class Client(Decorators, Methods):
1067
1031
  res = await self.checkAuthenticationBotToken(self.__token)
1068
1032
 
1069
1033
  if isinstance(res, types.Error):
1034
+ await self.stop()
1070
1035
  raise AuthorizationError(res.message)
1071
1036
 
1072
1037
  def __stop_client(self) -> None:
@@ -1077,6 +1042,9 @@ class Client(Decorators, Methods):
1077
1042
  for worker_task in self._workers_tasks:
1078
1043
  worker_task.cancel()
1079
1044
 
1045
+ if self.__listen_loop_task:
1046
+ self.__listen_loop_task.cancel()
1047
+
1080
1048
  def _register_signal_handlers(self):
1081
1049
  def _handle_signal():
1082
1050
  self.loop.create_task(self.stop())