Pytdbot 0.9.0.dev6__tar.gz → 0.9.0.dev7__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.0.dev6 → pytdbot-0.9.0.dev7}/LICENSE +1 -1
- {pytdbot-0.9.0.dev6 → pytdbot-0.9.0.dev7}/PKG-INFO +44 -15
- {pytdbot-0.9.0.dev6 → pytdbot-0.9.0.dev7}/Pytdbot.egg-info/PKG-INFO +44 -15
- {pytdbot-0.9.0.dev6 → pytdbot-0.9.0.dev7}/Pytdbot.egg-info/requires.txt +3 -0
- {pytdbot-0.9.0.dev6 → pytdbot-0.9.0.dev7}/README.md +26 -11
- {pytdbot-0.9.0.dev6 → pytdbot-0.9.0.dev7}/pytdbot/__init__.py +2 -2
- {pytdbot-0.9.0.dev6 → pytdbot-0.9.0.dev7}/pytdbot/client.py +47 -82
- {pytdbot-0.9.0.dev6 → pytdbot-0.9.0.dev7}/pytdbot/methods/methods.py +0 -65
- {pytdbot-0.9.0.dev6 → pytdbot-0.9.0.dev7}/pytdbot/methods/td_functions.py +244 -82
- {pytdbot-0.9.0.dev6 → pytdbot-0.9.0.dev7}/pytdbot/tdjson/tdjson.py +59 -36
- {pytdbot-0.9.0.dev6 → pytdbot-0.9.0.dev7}/pytdbot/types/__init__.py +23 -5
- {pytdbot-0.9.0.dev6 → pytdbot-0.9.0.dev7}/pytdbot/types/td_types/bound_methods/message.py +7 -20
- {pytdbot-0.9.0.dev6 → pytdbot-0.9.0.dev7}/pytdbot/types/td_types/types.py +713 -155
- {pytdbot-0.9.0.dev6 → pytdbot-0.9.0.dev7}/pytdbot/utils/__init__.py +9 -1
- pytdbot-0.9.0.dev7/pytdbot/utils/json_utils.py +27 -0
- {pytdbot-0.9.0.dev6 → pytdbot-0.9.0.dev7}/pytdbot/utils/strings.py +19 -0
- {pytdbot-0.9.0.dev6 → pytdbot-0.9.0.dev7}/setup.py +4 -1
- pytdbot-0.9.0.dev6/pytdbot/utils/json_utils.py +0 -23
- {pytdbot-0.9.0.dev6 → pytdbot-0.9.0.dev7}/MANIFEST.in +0 -0
- {pytdbot-0.9.0.dev6 → pytdbot-0.9.0.dev7}/Pytdbot.egg-info/SOURCES.txt +0 -0
- {pytdbot-0.9.0.dev6 → pytdbot-0.9.0.dev7}/Pytdbot.egg-info/dependency_links.txt +0 -0
- {pytdbot-0.9.0.dev6 → pytdbot-0.9.0.dev7}/Pytdbot.egg-info/top_level.txt +0 -0
- {pytdbot-0.9.0.dev6 → pytdbot-0.9.0.dev7}/pytdbot/exception/__init__.py +0 -0
- {pytdbot-0.9.0.dev6 → pytdbot-0.9.0.dev7}/pytdbot/filters.py +0 -0
- {pytdbot-0.9.0.dev6 → pytdbot-0.9.0.dev7}/pytdbot/handlers/__init__.py +0 -0
- {pytdbot-0.9.0.dev6 → pytdbot-0.9.0.dev7}/pytdbot/handlers/decorators.py +0 -0
- {pytdbot-0.9.0.dev6 → pytdbot-0.9.0.dev7}/pytdbot/handlers/handler.py +0 -0
- {pytdbot-0.9.0.dev6 → pytdbot-0.9.0.dev7}/pytdbot/handlers/td_updates.py +0 -0
- {pytdbot-0.9.0.dev6 → pytdbot-0.9.0.dev7}/pytdbot/methods/__init__.py +0 -0
- {pytdbot-0.9.0.dev6 → pytdbot-0.9.0.dev7}/pytdbot/tdjson/__init__.py +0 -0
- {pytdbot-0.9.0.dev6 → pytdbot-0.9.0.dev7}/pytdbot/types/plugins/__init__.py +0 -0
- {pytdbot-0.9.0.dev6 → pytdbot-0.9.0.dev7}/pytdbot/types/td_types/__init__.py +0 -0
- {pytdbot-0.9.0.dev6 → pytdbot-0.9.0.dev7}/pytdbot/types/td_types/bound_methods/__init__.py +0 -0
- {pytdbot-0.9.0.dev6 → pytdbot-0.9.0.dev7}/pytdbot/types/td_types/bound_methods/callback_query.py +0 -0
- {pytdbot-0.9.0.dev6 → pytdbot-0.9.0.dev7}/pytdbot/types/td_types/bound_methods/chatActions.py +0 -0
- {pytdbot-0.9.0.dev6 → pytdbot-0.9.0.dev7}/pytdbot/types/td_types/bound_methods/file.py +0 -0
- {pytdbot-0.9.0.dev6 → pytdbot-0.9.0.dev7}/pytdbot/utils/escape.py +0 -0
- {pytdbot-0.9.0.dev6 → pytdbot-0.9.0.dev7}/pytdbot/utils/obj_encoder.py +0 -0
- {pytdbot-0.9.0.dev6 → pytdbot-0.9.0.dev7}/pytdbot/utils/text_format.py +0 -0
- {pytdbot-0.9.0.dev6 → pytdbot-0.9.0.dev7}/pytdbot/utils/webapps.py +0 -0
- {pytdbot-0.9.0.dev6 → pytdbot-0.9.0.dev7}/requirements.txt +0 -0
- {pytdbot-0.9.0.dev6 → pytdbot-0.9.0.dev7}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.2
|
|
2
2
|
Name: Pytdbot
|
|
3
|
-
Version: 0.9.0.
|
|
3
|
+
Version: 0.9.0.dev7
|
|
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
|
-
|
|
19
|
-
|
|
20
|
-
|
|
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 [](https://pypi.org/project/Pytdbot) [](https://github.com/tdlib/td) [](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
|
-
|
|
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 pytdbot[tdjson]
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
or without **pre-built** TDLib:
|
|
68
|
+
|
|
49
69
|
```bash
|
|
50
70
|
pip install pytdbot
|
|
51
71
|
```
|
|
52
|
-
|
|
72
|
+
|
|
73
|
+
If the install fails, then you need to build TDLib from [source](https://github.com/tdlib/td#building) and pass it to `Client(lib_path="/path/to/libtdjson")`.
|
|
74
|
+
|
|
75
|
+
You could also install the development version from Github, using the following command:
|
|
76
|
+
|
|
53
77
|
```bash
|
|
54
|
-
pip install
|
|
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
|
|
@@ -64,8 +90,8 @@ from pytdbot import Client, types
|
|
|
64
90
|
|
|
65
91
|
client = Client(
|
|
66
92
|
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",
|
|
93
|
+
api_id=0,
|
|
94
|
+
api_hash="API_HASH",
|
|
69
95
|
lib_path="/path/to/libtdjson.so", # Path to TDjson shared library
|
|
70
96
|
files_directory="BotDB", # Path where to store TDLib files
|
|
71
97
|
database_encryption_key="1234echobot$",
|
|
@@ -94,12 +120,15 @@ async def say_hello(c: Client, message: types.Message):
|
|
|
94
120
|
client.run()
|
|
95
121
|
|
|
96
122
|
```
|
|
123
|
+
|
|
97
124
|
For more examples, check the [examples](https://github.com/pytdbot/client/tree/main/examples) folder.
|
|
98
125
|
|
|
99
126
|
# Thanks to
|
|
127
|
+
|
|
100
128
|
- You for viewing or using this project.
|
|
101
129
|
|
|
102
130
|
- [@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).
|
|
131
|
+
|
|
103
132
|
# License
|
|
104
133
|
|
|
105
134
|
MIT [License](https://github.com/pytdbot/client/blob/main/LICENSE)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.2
|
|
2
2
|
Name: Pytdbot
|
|
3
|
-
Version: 0.9.0.
|
|
3
|
+
Version: 0.9.0.dev7
|
|
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
|
-
|
|
19
|
-
|
|
20
|
-
|
|
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 [](https://pypi.org/project/Pytdbot) [](https://github.com/tdlib/td) [](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
|
-
|
|
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 pytdbot[tdjson]
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
or without **pre-built** TDLib:
|
|
68
|
+
|
|
49
69
|
```bash
|
|
50
70
|
pip install pytdbot
|
|
51
71
|
```
|
|
52
|
-
|
|
72
|
+
|
|
73
|
+
If the install fails, then you need to build TDLib from [source](https://github.com/tdlib/td#building) and pass it to `Client(lib_path="/path/to/libtdjson")`.
|
|
74
|
+
|
|
75
|
+
You could also install the development version from Github, using the following command:
|
|
76
|
+
|
|
53
77
|
```bash
|
|
54
|
-
pip install
|
|
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
|
|
@@ -64,8 +90,8 @@ from pytdbot import Client, types
|
|
|
64
90
|
|
|
65
91
|
client = Client(
|
|
66
92
|
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",
|
|
93
|
+
api_id=0,
|
|
94
|
+
api_hash="API_HASH",
|
|
69
95
|
lib_path="/path/to/libtdjson.so", # Path to TDjson shared library
|
|
70
96
|
files_directory="BotDB", # Path where to store TDLib files
|
|
71
97
|
database_encryption_key="1234echobot$",
|
|
@@ -94,12 +120,15 @@ async def say_hello(c: Client, message: types.Message):
|
|
|
94
120
|
client.run()
|
|
95
121
|
|
|
96
122
|
```
|
|
123
|
+
|
|
97
124
|
For more examples, check the [examples](https://github.com/pytdbot/client/tree/main/examples) folder.
|
|
98
125
|
|
|
99
126
|
# Thanks to
|
|
127
|
+
|
|
100
128
|
- You for viewing or using this project.
|
|
101
129
|
|
|
102
130
|
- [@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).
|
|
131
|
+
|
|
103
132
|
# License
|
|
104
133
|
|
|
105
134
|
MIT [License](https://github.com/pytdbot/client/blob/main/LICENSE)
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
# Pytdbot [](https://pypi.org/project/Pytdbot) [](https://pypi.org/project/Pytdbot) [](https://github.com/tdlib/td) [](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
|
-
|
|
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 pytdbot[tdjson]
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
or without **pre-built** TDLib:
|
|
37
|
+
|
|
32
38
|
```bash
|
|
33
39
|
pip install pytdbot
|
|
34
40
|
```
|
|
35
|
-
|
|
41
|
+
|
|
42
|
+
If the install fails, then you need to build TDLib from [source](https://github.com/tdlib/td#building) and pass it to `Client(lib_path="/path/to/libtdjson")`.
|
|
43
|
+
|
|
44
|
+
You could also install the development version from Github, using the following command:
|
|
45
|
+
|
|
36
46
|
```bash
|
|
37
|
-
pip install
|
|
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
|
|
@@ -47,8 +59,8 @@ from pytdbot import Client, types
|
|
|
47
59
|
|
|
48
60
|
client = Client(
|
|
49
61
|
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",
|
|
62
|
+
api_id=0,
|
|
63
|
+
api_hash="API_HASH",
|
|
52
64
|
lib_path="/path/to/libtdjson.so", # Path to TDjson shared library
|
|
53
65
|
files_directory="BotDB", # Path where to store TDLib files
|
|
54
66
|
database_encryption_key="1234echobot$",
|
|
@@ -77,12 +89,15 @@ async def say_hello(c: Client, message: types.Message):
|
|
|
77
89
|
client.run()
|
|
78
90
|
|
|
79
91
|
```
|
|
92
|
+
|
|
80
93
|
For more examples, check the [examples](https://github.com/pytdbot/client/tree/main/examples) folder.
|
|
81
94
|
|
|
82
95
|
# Thanks to
|
|
96
|
+
|
|
83
97
|
- You for viewing or using this project.
|
|
84
98
|
|
|
85
99
|
- [@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).
|
|
100
|
+
|
|
86
101
|
# License
|
|
87
102
|
|
|
88
103
|
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.
|
|
8
|
-
__copyright__ = "Copyright (c) 2022-2025
|
|
7
|
+
__version__ = "0.9.0dev7"
|
|
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.
|
|
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,47 @@ 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
|
-
|
|
403
|
-
result = await future
|
|
404
|
-
|
|
405
|
-
if isinstance(result, types.Error):
|
|
406
|
-
if result.code == 429:
|
|
407
|
-
retry_after = self.get_retry_after_time(result.message)
|
|
408
|
-
|
|
409
|
-
if retry_after <= self.sleep_threshold:
|
|
410
|
-
self.logger.error(
|
|
411
|
-
f"Sleeping for {retry_after}s (Caused by {request['@type']})"
|
|
412
|
-
)
|
|
399
|
+
is_chat_attempted_load = False
|
|
413
400
|
|
|
414
|
-
|
|
401
|
+
while True:
|
|
402
|
+
future = self._create_request_future(request)
|
|
403
|
+
await self.__send(request)
|
|
404
|
+
result = await future
|
|
415
405
|
|
|
416
|
-
|
|
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)
|
|
412
|
+
elif not is_chat_attempted_load and (
|
|
413
|
+
result.message == "Chat not found" and "chat_id" in request
|
|
414
|
+
):
|
|
415
|
+
is_chat_attempted_load = True
|
|
417
416
|
|
|
418
|
-
|
|
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"]
|
|
417
|
+
chat_id = request["chat_id"]
|
|
426
418
|
|
|
427
|
-
|
|
419
|
+
self.logger.debug(f"Attempt to load chat {chat_id}")
|
|
428
420
|
|
|
429
|
-
|
|
421
|
+
load_chat = await self.getChat(chat_id)
|
|
430
422
|
|
|
431
|
-
|
|
432
|
-
|
|
423
|
+
if not isinstance(load_chat, types.Error):
|
|
424
|
+
self.logger.debug(f"Chat {chat_id} is loaded")
|
|
433
425
|
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
426
|
+
reply_to_message_id = (request.get("reply_to") or {}).get(
|
|
427
|
+
"message_id", 0
|
|
428
|
+
)
|
|
437
429
|
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
430
|
+
# if the request is a reply to another message
|
|
431
|
+
# load the replied message to avoid "Message not found"
|
|
432
|
+
if reply_to_message_id > 0:
|
|
433
|
+
await self.getMessage(chat_id, reply_to_message_id)
|
|
442
434
|
|
|
443
|
-
|
|
444
|
-
|
|
435
|
+
continue
|
|
436
|
+
else:
|
|
437
|
+
self.logger.error(f"Couldn't load chat {chat_id}")
|
|
445
438
|
|
|
446
|
-
|
|
447
|
-
result = await future
|
|
448
|
-
else:
|
|
449
|
-
self.logger.error(f"Couldn't load chat {chat_id}")
|
|
439
|
+
break
|
|
450
440
|
|
|
451
441
|
return result
|
|
452
442
|
|
|
@@ -592,22 +582,6 @@ class Client(Decorators, Methods):
|
|
|
592
582
|
if isinstance(self.workers, int) and self.workers < 1:
|
|
593
583
|
raise ValueError("workers must be greater than 0")
|
|
594
584
|
|
|
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
585
|
def _load_plugins(self):
|
|
612
586
|
count = 0
|
|
613
587
|
handlers = 0
|
|
@@ -694,7 +668,7 @@ class Client(Decorators, Methods):
|
|
|
694
668
|
update = await self.loop.run_in_executor(
|
|
695
669
|
thread,
|
|
696
670
|
self._tdjson.receive,
|
|
697
|
-
|
|
671
|
+
1.0, # Seconds
|
|
698
672
|
)
|
|
699
673
|
if update is None:
|
|
700
674
|
continue
|
|
@@ -858,6 +832,7 @@ class Client(Decorators, Methods):
|
|
|
858
832
|
application_version=f"Pytdbot {pytdbot.__version__}",
|
|
859
833
|
)
|
|
860
834
|
if isinstance(res, types.Error):
|
|
835
|
+
await self.stop()
|
|
861
836
|
raise AuthorizationError(res.message)
|
|
862
837
|
|
|
863
838
|
async def _set_options(self):
|
|
@@ -929,20 +904,7 @@ class Client(Decorators, Methods):
|
|
|
929
904
|
m_id = f"{update.message.chat_id}:{update.old_message_id}"
|
|
930
905
|
|
|
931
906
|
if result := self._results.pop(m_id, None):
|
|
932
|
-
|
|
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)
|
|
907
|
+
result.set_result(update.error)
|
|
946
908
|
|
|
947
909
|
async def __handle_update_option(self, update: types.UpdateOption):
|
|
948
910
|
if isinstance(update.value, types.OptionValueBoolean):
|
|
@@ -1067,6 +1029,7 @@ class Client(Decorators, Methods):
|
|
|
1067
1029
|
res = await self.checkAuthenticationBotToken(self.__token)
|
|
1068
1030
|
|
|
1069
1031
|
if isinstance(res, types.Error):
|
|
1032
|
+
await self.stop()
|
|
1070
1033
|
raise AuthorizationError(res.message)
|
|
1071
1034
|
|
|
1072
1035
|
def __stop_client(self) -> None:
|
|
@@ -1077,6 +1040,8 @@ class Client(Decorators, Methods):
|
|
|
1077
1040
|
for worker_task in self._workers_tasks:
|
|
1078
1041
|
worker_task.cancel()
|
|
1079
1042
|
|
|
1043
|
+
self.__listen_loop_task.cancel()
|
|
1044
|
+
|
|
1080
1045
|
def _register_signal_handlers(self):
|
|
1081
1046
|
def _handle_signal():
|
|
1082
1047
|
self.loop.create_task(self.stop())
|