kurigram-addons 0.1.0__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.
- kurigram_addons-0.1.0/LICENSE +21 -0
- kurigram_addons-0.1.0/PKG-INFO +33 -0
- kurigram_addons-0.1.0/README.md +15 -0
- kurigram_addons-0.1.0/pykeyboard/README.md +308 -0
- kurigram_addons-0.1.0/pykeyboard/__init__.py +21 -0
- kurigram_addons-0.1.0/pykeyboard/inline_keyboard.py +187 -0
- kurigram_addons-0.1.0/pykeyboard/keyboard_base.py +64 -0
- kurigram_addons-0.1.0/pykeyboard/reply_keyboard.py +74 -0
- kurigram_addons-0.1.0/pyproject.toml +18 -0
- kurigram_addons-0.1.0/pyrogram_patch/README.md +231 -0
- kurigram_addons-0.1.0/pyrogram_patch/__init__.py +4 -0
- kurigram_addons-0.1.0/pyrogram_patch/dispatcher.py +124 -0
- kurigram_addons-0.1.0/pyrogram_patch/fsm/__init__.py +4 -0
- kurigram_addons-0.1.0/pyrogram_patch/fsm/base_storage.py +25 -0
- kurigram_addons-0.1.0/pyrogram_patch/fsm/filter.py +15 -0
- kurigram_addons-0.1.0/pyrogram_patch/fsm/states.py +43 -0
- kurigram_addons-0.1.0/pyrogram_patch/fsm/storages/__init__.py +4 -0
- kurigram_addons-0.1.0/pyrogram_patch/fsm/storages/memory_storage.py +33 -0
- kurigram_addons-0.1.0/pyrogram_patch/fsm/storages/redis_storage.py +54 -0
- kurigram_addons-0.1.0/pyrogram_patch/middlewares/__init__.py +5 -0
- kurigram_addons-0.1.0/pyrogram_patch/middlewares/middleware_types/__init__.py +19 -0
- kurigram_addons-0.1.0/pyrogram_patch/middlewares/middleware_types/middlewares.py +122 -0
- kurigram_addons-0.1.0/pyrogram_patch/patch.py +36 -0
- kurigram_addons-0.1.0/pyrogram_patch/patch_data_pool.py +32 -0
- kurigram_addons-0.1.0/pyrogram_patch/patch_helper.py +71 -0
- kurigram_addons-0.1.0/pyrogram_patch/router/__init__.py +3 -0
- kurigram_addons-0.1.0/pyrogram_patch/router/patched_decorators/__init__.py +47 -0
- kurigram_addons-0.1.0/pyrogram_patch/router/patched_decorators/on_callback_query.py +58 -0
- kurigram_addons-0.1.0/pyrogram_patch/router/patched_decorators/on_chat_join_request.py +56 -0
- kurigram_addons-0.1.0/pyrogram_patch/router/patched_decorators/on_chat_member_updated.py +56 -0
- kurigram_addons-0.1.0/pyrogram_patch/router/patched_decorators/on_chosen_inline_result.py +57 -0
- kurigram_addons-0.1.0/pyrogram_patch/router/patched_decorators/on_deleted_messages.py +57 -0
- kurigram_addons-0.1.0/pyrogram_patch/router/patched_decorators/on_disconnect.py +47 -0
- kurigram_addons-0.1.0/pyrogram_patch/router/patched_decorators/on_edited_message.py +57 -0
- kurigram_addons-0.1.0/pyrogram_patch/router/patched_decorators/on_inline_query.py +58 -0
- kurigram_addons-0.1.0/pyrogram_patch/router/patched_decorators/on_message.py +57 -0
- kurigram_addons-0.1.0/pyrogram_patch/router/patched_decorators/on_poll.py +57 -0
- kurigram_addons-0.1.0/pyrogram_patch/router/patched_decorators/on_raw_update.py +51 -0
- kurigram_addons-0.1.0/pyrogram_patch/router/patched_decorators/on_user_status.py +56 -0
- kurigram_addons-0.1.0/pyrogram_patch/router/router.py +16 -0
- kurigram_addons-0.1.0/setup.py +37 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2020 PyMaster
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the 'Software'), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
Metadata-Version: 2.1
|
|
2
|
+
Name: kurigram-addons
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: This package brings together several addons to kurigram including pykeyboard and FSM
|
|
5
|
+
License: MIT
|
|
6
|
+
Author: Johnnie
|
|
7
|
+
Author-email: 99084912+johnnie-610@users.noreply.github.com
|
|
8
|
+
Requires-Python: >=3.8,<4.0
|
|
9
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
10
|
+
Classifier: Programming Language :: Python :: 3
|
|
11
|
+
Classifier: Programming Language :: Python :: 3.8
|
|
12
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
13
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
15
|
+
Requires-Dist: kurigram (>=2.1.35,<3.0.0)
|
|
16
|
+
Description-Content-Type: text/markdown
|
|
17
|
+
|
|
18
|
+
<img align=center src=./logo.png length=80 width = 400>
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
> This library is a collection of popular Addons and patches for pyrogram/Kurigram.
|
|
22
|
+
> Currently, Pykeyboard and Pyrogram-patch have been added. You're welcome to add more.
|
|
23
|
+
|
|
24
|
+
# Installation
|
|
25
|
+
|
|
26
|
+
```shell
|
|
27
|
+
pip install kurigram-addons
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
# Usage
|
|
31
|
+
|
|
32
|
+
Please refer to specific readme.md for each addon.
|
|
33
|
+
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
<img align=center src=./logo.png length=80 width = 400>
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
> This library is a collection of popular Addons and patches for pyrogram/Kurigram.
|
|
5
|
+
> Currently, Pykeyboard and Pyrogram-patch have been added. You're welcome to add more.
|
|
6
|
+
|
|
7
|
+
# Installation
|
|
8
|
+
|
|
9
|
+
```shell
|
|
10
|
+
pip install kurigram-addons
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
# Usage
|
|
14
|
+
|
|
15
|
+
Please refer to specific readme.md for each addon.
|
|
@@ -0,0 +1,308 @@
|
|
|
1
|
+
<div align="center">
|
|
2
|
+
<p align="center">
|
|
3
|
+
<img src="https://raw.githubusercontent.com/johnnie-610/pykeyboard/main/docs/source/images/logo.png" alt="pykeyboard">
|
|
4
|
+
</p>
|
|
5
|
+
|
|
6
|
+
<p><h2>🎉This is pykeyboard for <a href="https://pypi.org/project/Kurigram/"</a>Kuigram 🎉</h2></p>
|
|
7
|
+
<br>
|
|
8
|
+
<p><strong><em>No need to change your code, just install the library and you're good to go.</em></strong></p>
|
|
9
|
+
|
|
10
|
+
</div>
|
|
11
|
+
|
|
12
|
+
# Pykeyboard
|
|
13
|
+
|
|
14
|
+
- [Pykeyboard](#pykeyboard)
|
|
15
|
+
- [What's new?](#whats-new)
|
|
16
|
+
- [Installation](#installation)
|
|
17
|
+
- [Documentation](#documentation)
|
|
18
|
+
- [Inline Keyboard](#inline-keyboard)
|
|
19
|
+
- [Parameters:](#parameters)
|
|
20
|
+
- [Inline Keyboard add buttons](#inline-keyboard-add-buttons)
|
|
21
|
+
- [Code](#code)
|
|
22
|
+
- [Result](#result)
|
|
23
|
+
- [Inline Keyboard row buttons](#inline-keyboard-row-buttons)
|
|
24
|
+
- [Code](#code-1)
|
|
25
|
+
- [Result](#result-1)
|
|
26
|
+
- [Pagination inline keyboard](#pagination-inline-keyboard)
|
|
27
|
+
- [Parameters:](#parameters-1)
|
|
28
|
+
- [Pagination 3 pages](#pagination-3-pages)
|
|
29
|
+
- [Code](#code-2)
|
|
30
|
+
- [Result](#result-2)
|
|
31
|
+
- [Pagination 5 pages](#pagination-5-pages)
|
|
32
|
+
- [Code](#code-3)
|
|
33
|
+
- [Result](#result-3)
|
|
34
|
+
- [Pagination 9 pages](#pagination-9-pages)
|
|
35
|
+
- [Code](#code-4)
|
|
36
|
+
- [Result](#result-4)
|
|
37
|
+
- [Pagination 100 pages](#pagination-100-pages)
|
|
38
|
+
- [Code](#code-5)
|
|
39
|
+
- [Result](#result-5)
|
|
40
|
+
- [Pagination 150 pages and buttons](#pagination-150-pages-and-buttons)
|
|
41
|
+
- [Code](#code-6)
|
|
42
|
+
- [Result](#result-6)
|
|
43
|
+
- [Languages inline keyboard](#languages-inline-keyboard)
|
|
44
|
+
- [Parameters:](#parameters-2)
|
|
45
|
+
- [Code](#code-7)
|
|
46
|
+
- [Result](#result-7)
|
|
47
|
+
- [Reply Keyboard](#reply-keyboard)
|
|
48
|
+
- [Parameters:](#parameters-3)
|
|
49
|
+
- [Reply Keyboard add buttons](#reply-keyboard-add-buttons)
|
|
50
|
+
- [Code](#code-8)
|
|
51
|
+
- [Result](#result-8)
|
|
52
|
+
- [Reply Keyboard row buttons](#reply-keyboard-row-buttons)
|
|
53
|
+
- [Code](#code-9)
|
|
54
|
+
- [Result](#result-9)
|
|
55
|
+
|
|
56
|
+
# What's new?
|
|
57
|
+
|
|
58
|
+
- Minor changes due to update in Kurigram.
|
|
59
|
+
|
|
60
|
+
# Documentation
|
|
61
|
+
|
|
62
|
+
## Inline Keyboard
|
|
63
|
+
|
|
64
|
+
```python
|
|
65
|
+
from pykeyboard import InlineKeyboard
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
##### Parameters:
|
|
69
|
+
|
|
70
|
+
- row_width (integer, default 3)
|
|
71
|
+
|
|
72
|
+
### Inline Keyboard add buttons
|
|
73
|
+
|
|
74
|
+
#### Code
|
|
75
|
+
|
|
76
|
+
```python
|
|
77
|
+
from pykeyboard import InlineKeyboard, InlineButton
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
keyboard = InlineKeyboard(row_width=3)
|
|
81
|
+
keyboard.add(
|
|
82
|
+
InlineButton('1', 'inline_keyboard:1'),
|
|
83
|
+
InlineButton('2', 'inline_keyboard:2'),
|
|
84
|
+
InlineButton('3', 'inline_keyboard:3'),
|
|
85
|
+
InlineButton('4', 'inline_keyboard:4'),
|
|
86
|
+
InlineButton('5', 'inline_keyboard:5'),
|
|
87
|
+
InlineButton('6', 'inline_keyboard:6'),
|
|
88
|
+
InlineButton('7', 'inline_keyboard:7')
|
|
89
|
+
)
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
#### Result
|
|
93
|
+
|
|
94
|
+
<p><img src="https://raw.githubusercontent.com/johnnie-610/pykeyboard/main/docs/source/images/add_inline_button.png" alt="add_inline_button"></p>
|
|
95
|
+
|
|
96
|
+
### Inline Keyboard row buttons
|
|
97
|
+
|
|
98
|
+
#### Code
|
|
99
|
+
|
|
100
|
+
```python
|
|
101
|
+
from pykeyboard import InlineKeyboard, InlineButton
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
keyboard = InlineKeyboard()
|
|
105
|
+
keyboard.row(InlineButton('1', 'inline_keyboard:1'))
|
|
106
|
+
keyboard.row(
|
|
107
|
+
InlineButton('2', 'inline_keyboard:2'),
|
|
108
|
+
InlineButton('3', 'inline_keyboard:3')
|
|
109
|
+
)
|
|
110
|
+
keyboard.row(InlineButton('4', 'inline_keyboard:4'))
|
|
111
|
+
keyboard.row(
|
|
112
|
+
InlineButton('5', 'inline_keyboard:5'),
|
|
113
|
+
InlineButton('6', 'inline_keyboard:6')
|
|
114
|
+
)
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
#### Result
|
|
118
|
+
|
|
119
|
+
<p><img src="https://raw.githubusercontent.com/johnnie-610/pykeyboard/main/docs/source/images/row_inline_button.png" alt="row_inline_button"></p>
|
|
120
|
+
|
|
121
|
+
### Pagination inline keyboard
|
|
122
|
+
|
|
123
|
+
```python
|
|
124
|
+
from pykeyboard import InlineKeyboard
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
#### Parameters:
|
|
128
|
+
|
|
129
|
+
- count_pages (integer)
|
|
130
|
+
- current_page (integer)
|
|
131
|
+
- callback_pattern (string) - use of the `{number}` pattern is `<ins>`required`</ins>`
|
|
132
|
+
|
|
133
|
+
#### Pagination 3 pages
|
|
134
|
+
|
|
135
|
+
#### Code
|
|
136
|
+
|
|
137
|
+
```python
|
|
138
|
+
from pykeyboard import InlineKeyboard
|
|
139
|
+
|
|
140
|
+
keyboard = InlineKeyboard()
|
|
141
|
+
keyboard.paginate(3, 3, 'pagination_keyboard:{number}')
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
#### Result
|
|
145
|
+
|
|
146
|
+
<p><img src="https://raw.githubusercontent.com/johnnie-610/pykeyboard/main/docs/source/images/pagination_keyboard_3.png" alt="pagination_keyboard_3"></p>
|
|
147
|
+
|
|
148
|
+
#### Pagination 5 pages
|
|
149
|
+
|
|
150
|
+
#### Code
|
|
151
|
+
|
|
152
|
+
```python
|
|
153
|
+
from pykeyboard import InlineKeyboard
|
|
154
|
+
|
|
155
|
+
keyboard = InlineKeyboard()
|
|
156
|
+
keyboard.paginate(5, 3, 'pagination_keyboard:{number}')
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
#### Result
|
|
160
|
+
|
|
161
|
+
<p><img src="https://raw.githubusercontent.com/johnnie-610/pykeyboard/main/docs/source/images/pagination_keyboard_5.png" alt="pagination_keyboard_5"></p>
|
|
162
|
+
|
|
163
|
+
#### Pagination 9 pages
|
|
164
|
+
|
|
165
|
+
#### Code
|
|
166
|
+
|
|
167
|
+
```python
|
|
168
|
+
from pykeyboard import InlineKeyboard
|
|
169
|
+
|
|
170
|
+
keyboard = InlineKeyboard()
|
|
171
|
+
keyboard.paginate(9, 5, 'pagination_keyboard:{number}')
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
#### Result
|
|
175
|
+
|
|
176
|
+
<p><img src="https://raw.githubusercontent.com/johnnie-610/pykeyboard/main/docs/source/images/pagination_keyboard_9.png" alt="pagination_keyboard_9"></p>
|
|
177
|
+
|
|
178
|
+
#### Pagination 100 pages
|
|
179
|
+
|
|
180
|
+
#### Code
|
|
181
|
+
|
|
182
|
+
```python
|
|
183
|
+
from pykeyboard import InlineKeyboard
|
|
184
|
+
|
|
185
|
+
keyboard = InlineKeyboard()
|
|
186
|
+
keyboard.paginate(100, 100, 'pagination_keyboard:{number}')
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
#### Result
|
|
190
|
+
|
|
191
|
+
<p><img src="https://raw.githubusercontent.com/johnnie-610/pykeyboard/main/docs/source/images/pagination_keyboard_100.png" alt="pagination_keyboard_100"></p>
|
|
192
|
+
|
|
193
|
+
#### Pagination 150 pages and buttons
|
|
194
|
+
|
|
195
|
+
#### Code
|
|
196
|
+
|
|
197
|
+
```python
|
|
198
|
+
from pykeyboard import InlineKeyboard, InlineButton
|
|
199
|
+
|
|
200
|
+
keyboard = InlineKeyboard()
|
|
201
|
+
keyboard.paginate(150, 123, 'pagination_keyboard:{number}')
|
|
202
|
+
keyboard.row(
|
|
203
|
+
InlineButton('Back', 'pagination_keyboard:back'),
|
|
204
|
+
InlineButton('Close', 'pagination_keyboard:close')
|
|
205
|
+
)
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
#### Result
|
|
209
|
+
|
|
210
|
+
<p><img src="https://raw.githubusercontent.com/johnnie-610/pykeyboard/main/docs/source/images/pagination_keyboard_150.png" alt="pagination_keyboard_150"></p>
|
|
211
|
+
|
|
212
|
+
### Languages inline keyboard
|
|
213
|
+
|
|
214
|
+
```python
|
|
215
|
+
from pykeyboard import InlineKeyboard
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
#### Parameters:
|
|
219
|
+
|
|
220
|
+
- callback_pattern (string) - use of the `{locale}` pattern is `<ins>`required`</ins>`
|
|
221
|
+
- locales (string | list) - list of language codes
|
|
222
|
+
- be_BY - Belarusian
|
|
223
|
+
- de_DE - German
|
|
224
|
+
- zh_CN - Chinese
|
|
225
|
+
- en_US - English
|
|
226
|
+
- fr_FR - French
|
|
227
|
+
- id_ID - Indonesian
|
|
228
|
+
- it_IT - Italian
|
|
229
|
+
- ko_KR - Korean
|
|
230
|
+
- tr_TR - Turkish
|
|
231
|
+
- ru_RU - Russian
|
|
232
|
+
- es_ES - Spanish
|
|
233
|
+
- uk_UA - Ukrainian
|
|
234
|
+
- uz_UZ - Uzbek
|
|
235
|
+
- row_width (integer, default 2)
|
|
236
|
+
|
|
237
|
+
#### Code
|
|
238
|
+
|
|
239
|
+
```python
|
|
240
|
+
from pykeyboard import InlineKeyboard
|
|
241
|
+
|
|
242
|
+
|
|
243
|
+
keyboard = InlineKeyboard(row_width=3)
|
|
244
|
+
keyboard.languages(
|
|
245
|
+
'languages:{locale}', ['en_US', 'ru_RU', 'id_ID'], 2
|
|
246
|
+
)
|
|
247
|
+
```
|
|
248
|
+
|
|
249
|
+
#### Result
|
|
250
|
+
|
|
251
|
+
<p><img src="https://raw.githubusercontent.com/johnnie-610/pykeyboard/main/docs/source/images/languages_keyboard.png" alt="languages_keyboard"></p>
|
|
252
|
+
|
|
253
|
+
## Reply Keyboard
|
|
254
|
+
|
|
255
|
+
```python
|
|
256
|
+
from pykeyboard import ReplyKeyboard
|
|
257
|
+
```
|
|
258
|
+
|
|
259
|
+
#### Parameters:
|
|
260
|
+
|
|
261
|
+
- resize_keyboard (bool, optional)
|
|
262
|
+
- one_time_keyboard (bool, optional)
|
|
263
|
+
- selective (bool, optional)
|
|
264
|
+
- row_width (integer, default 3)
|
|
265
|
+
|
|
266
|
+
### Reply Keyboard add buttons
|
|
267
|
+
|
|
268
|
+
#### Code
|
|
269
|
+
|
|
270
|
+
```python
|
|
271
|
+
from pykeyboard import ReplyKeyboard, ReplyButton
|
|
272
|
+
|
|
273
|
+
|
|
274
|
+
keyboard = ReplyKeyboard(row_width=3)
|
|
275
|
+
keyboard.add(
|
|
276
|
+
ReplyButton('Reply button 1'),
|
|
277
|
+
ReplyButton('Reply button 2'),
|
|
278
|
+
ReplyButton('Reply button 3'),
|
|
279
|
+
ReplyButton('Reply button 4'),
|
|
280
|
+
ReplyButton('Reply button 5')
|
|
281
|
+
)
|
|
282
|
+
```
|
|
283
|
+
|
|
284
|
+
#### Result
|
|
285
|
+
|
|
286
|
+
<p><img src="https://raw.githubusercontent.com/johnnie-610/pykeyboard/main/docs/source/images/add_reply_button.png" alt="add_reply_button"></p>
|
|
287
|
+
|
|
288
|
+
### Reply Keyboard row buttons
|
|
289
|
+
|
|
290
|
+
#### Code
|
|
291
|
+
|
|
292
|
+
```python
|
|
293
|
+
from pykeyboard import ReplyKeyboard, ReplyButton
|
|
294
|
+
|
|
295
|
+
|
|
296
|
+
keyboard = ReplyKeyboard()
|
|
297
|
+
keyboard.row(ReplyButton('Reply button 1'))
|
|
298
|
+
keyboard.row(
|
|
299
|
+
ReplyButton('Reply button 2'),
|
|
300
|
+
ReplyButton('Reply button 3')
|
|
301
|
+
)
|
|
302
|
+
keyboard.row(ReplyButton('Reply button 4'))
|
|
303
|
+
keyboard.row(ReplyButton('Reply button 5'))
|
|
304
|
+
```
|
|
305
|
+
|
|
306
|
+
#### Result
|
|
307
|
+
|
|
308
|
+
<p><img src="https://raw.githubusercontent.com/johnnie-610/pykeyboard/main/docs/source/images/row_reply_button.png" alt="row_reply_button"></p>
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# Copyright (c) 2025 Johnnie
|
|
2
|
+
#
|
|
3
|
+
# This software is released under the MIT License.
|
|
4
|
+
# https://opensource.org/licenses/MIT
|
|
5
|
+
|
|
6
|
+
from .keyboard_base import Button, InlineButton
|
|
7
|
+
from .inline_keyboard import InlineKeyboard
|
|
8
|
+
from .reply_keyboard import ReplyKeyboard, ReplyButton, ReplyKeyboardRemove, ForceReply
|
|
9
|
+
|
|
10
|
+
__version__ = "0.1.2"
|
|
11
|
+
__all__ = [
|
|
12
|
+
"Button",
|
|
13
|
+
"InlineButton",
|
|
14
|
+
"InlineKeyboard",
|
|
15
|
+
"ReplyKeyboard",
|
|
16
|
+
"ReplyButton",
|
|
17
|
+
"ReplyKeyboardRemove",
|
|
18
|
+
"ForceReply",
|
|
19
|
+
]
|
|
20
|
+
|
|
21
|
+
__author__ = "Johnnie"
|
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
# Copyright (c) 2025 Johnnie
|
|
2
|
+
#
|
|
3
|
+
# This software is released under the MIT License.
|
|
4
|
+
# https://opensource.org/licenses/MIT
|
|
5
|
+
|
|
6
|
+
from pyrogram.emoji import *
|
|
7
|
+
from pyrogram.types import InlineKeyboardMarkup, InlineKeyboardButton
|
|
8
|
+
from dataclasses import dataclass
|
|
9
|
+
from .keyboard_base import KeyboardBase, InlineButton
|
|
10
|
+
from functools import lru_cache
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
@dataclass
|
|
14
|
+
class InlineKeyboard(InlineKeyboardMarkup, KeyboardBase):
|
|
15
|
+
_PAGINATION_SYMBOLS = {
|
|
16
|
+
"first": "« {}",
|
|
17
|
+
"prev": "‹ {}",
|
|
18
|
+
"current": "· {} ·",
|
|
19
|
+
"next": "{} ›",
|
|
20
|
+
"last": "{} »",
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
_LOCALES: dict[str, str] = {
|
|
24
|
+
"be_BY": f"{FLAG_BELARUS} Беларуская", # Belarusian - Belarus
|
|
25
|
+
"de_DE": f"{FLAG_GERMANY} Deutsch", # German - Germany
|
|
26
|
+
"zh_CN": f"{FLAG_CHINA} 中文", # Chinese - China
|
|
27
|
+
# English - United States
|
|
28
|
+
"en_US": f"{FLAG_UNITED_KINGDOM} English",
|
|
29
|
+
"fr_FR": f"{FLAG_FRANCE} Français", # French - France
|
|
30
|
+
# Indonesian - Indonesia
|
|
31
|
+
"id_ID": f"{FLAG_INDONESIA} Bahasa Indonesia",
|
|
32
|
+
"it_IT": f"{FLAG_ITALY} Italiano", # Italian - Italy
|
|
33
|
+
"ko_KR": f"{FLAG_SOUTH_KOREA} 한국어", # Korean - Korea
|
|
34
|
+
"tr_TR": f"{FLAG_TURKEY} Türkçe", # Turkish - Turkey
|
|
35
|
+
"ru_RU": f"{FLAG_RUSSIA} Русский", # Russian - Russia
|
|
36
|
+
"es_ES": f"{FLAG_SPAIN} Español", # Spanish - Spain
|
|
37
|
+
"uk_UA": f"{FLAG_UKRAINE} Українська", # Ukrainian - Ukraine
|
|
38
|
+
"uz_UZ": f"{FLAG_UZBEKISTAN} Oʻzbekcha", # Uzbek - Uzbekistan
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
def __post_init__(self):
|
|
42
|
+
super().__init__(inline_keyboard=self.keyboard)
|
|
43
|
+
|
|
44
|
+
@lru_cache(maxsize=128)
|
|
45
|
+
def _create_button(
|
|
46
|
+
self, text: str, callback_data: str | int
|
|
47
|
+
) -> InlineKeyboardButton:
|
|
48
|
+
"""Create cached button to avoid recreation of identical buttons."""
|
|
49
|
+
return InlineButton(
|
|
50
|
+
text=text, callback_data=self.callback_pattern.format(number=callback_data)
|
|
51
|
+
)
|
|
52
|
+
|
|
53
|
+
def paginate(
|
|
54
|
+
self, count_pages: int, current_page: int, callback_pattern: str
|
|
55
|
+
) -> None:
|
|
56
|
+
"""Optimized pagination with better edge case handling.
|
|
57
|
+
|
|
58
|
+
Args:
|
|
59
|
+
count_pages (int): Total number of pages.
|
|
60
|
+
current_page (int): The page number currently being viewed.
|
|
61
|
+
callback_pattern (str): The pattern used for callback data.
|
|
62
|
+
|
|
63
|
+
Example:
|
|
64
|
+
>>> keyboard = InlineKeyboard()
|
|
65
|
+
>>> keyboard.paginate(10, 1, 'page_{number}')
|
|
66
|
+
>>> print(keyboard.keyboard)
|
|
67
|
+
[[InlineKeyboardButton(text='· 1 ·', callback_data='page_1'), ...]]
|
|
68
|
+
|
|
69
|
+
"""
|
|
70
|
+
self.count_pages = max(1, count_pages)
|
|
71
|
+
self.current_page = max(1, min(current_page, self.count_pages))
|
|
72
|
+
self.callback_pattern = callback_pattern
|
|
73
|
+
|
|
74
|
+
if self.count_pages <= 5:
|
|
75
|
+
pagination = self._build_small_pagination()
|
|
76
|
+
else:
|
|
77
|
+
pagination = self._build_large_pagination()
|
|
78
|
+
|
|
79
|
+
self.keyboard.append(pagination)
|
|
80
|
+
|
|
81
|
+
def _build_small_pagination(self) -> list[InlineKeyboardButton]:
|
|
82
|
+
return [
|
|
83
|
+
self._create_button(
|
|
84
|
+
(
|
|
85
|
+
self._PAGINATION_SYMBOLS["current"].format(i)
|
|
86
|
+
if i == self.current_page
|
|
87
|
+
else str(i)
|
|
88
|
+
),
|
|
89
|
+
i,
|
|
90
|
+
)
|
|
91
|
+
for i in range(1, self.count_pages + 1)
|
|
92
|
+
]
|
|
93
|
+
|
|
94
|
+
def _build_large_pagination(self) -> list[InlineKeyboardButton]:
|
|
95
|
+
if self.current_page <= 3:
|
|
96
|
+
return self._build_left_pagination()
|
|
97
|
+
elif self.current_page > self.count_pages - 3:
|
|
98
|
+
return self._build_right_pagination()
|
|
99
|
+
return self._build_middle_pagination()
|
|
100
|
+
|
|
101
|
+
def _build_left_pagination(self) -> list[InlineKeyboardButton]:
|
|
102
|
+
buttons = []
|
|
103
|
+
for i in range(1, 6):
|
|
104
|
+
if i == self.current_page:
|
|
105
|
+
text = self._PAGINATION_SYMBOLS["current"].format(i)
|
|
106
|
+
elif i == 4:
|
|
107
|
+
text = self._PAGINATION_SYMBOLS["next"].format(i)
|
|
108
|
+
elif i == 5:
|
|
109
|
+
text = self._PAGINATION_SYMBOLS["last"].format(self.count_pages)
|
|
110
|
+
i = self.count_pages
|
|
111
|
+
else:
|
|
112
|
+
text = str(i)
|
|
113
|
+
buttons.append(self._create_button(text, i))
|
|
114
|
+
return buttons
|
|
115
|
+
|
|
116
|
+
def _build_middle_pagination(self) -> list[InlineKeyboardButton]:
|
|
117
|
+
return [
|
|
118
|
+
self._create_button(self._PAGINATION_SYMBOLS["first"].format(1), 1),
|
|
119
|
+
self._create_button(
|
|
120
|
+
self._PAGINATION_SYMBOLS["prev"].format(self.current_page - 1),
|
|
121
|
+
self.current_page - 1,
|
|
122
|
+
),
|
|
123
|
+
self._create_button(
|
|
124
|
+
self._PAGINATION_SYMBOLS["current"].format(self.current_page),
|
|
125
|
+
self.current_page,
|
|
126
|
+
),
|
|
127
|
+
self._create_button(
|
|
128
|
+
self._PAGINATION_SYMBOLS["next"].format(self.current_page + 1),
|
|
129
|
+
self.current_page + 1,
|
|
130
|
+
),
|
|
131
|
+
self._create_button(
|
|
132
|
+
self._PAGINATION_SYMBOLS["last"].format(self.count_pages),
|
|
133
|
+
self.count_pages,
|
|
134
|
+
),
|
|
135
|
+
]
|
|
136
|
+
|
|
137
|
+
def _build_right_pagination(self) -> list[InlineKeyboardButton]:
|
|
138
|
+
buttons = [
|
|
139
|
+
self._create_button(self._PAGINATION_SYMBOLS["first"].format(1), 1),
|
|
140
|
+
self._create_button(
|
|
141
|
+
self._PAGINATION_SYMBOLS["prev"].format(self.count_pages - 3),
|
|
142
|
+
self.count_pages - 3,
|
|
143
|
+
),
|
|
144
|
+
]
|
|
145
|
+
|
|
146
|
+
for i in range(self.count_pages - 2, self.count_pages + 1):
|
|
147
|
+
text = (
|
|
148
|
+
self._PAGINATION_SYMBOLS["current"].format(i)
|
|
149
|
+
if i == self.current_page
|
|
150
|
+
else str(i)
|
|
151
|
+
)
|
|
152
|
+
buttons.append(self._create_button(text, i))
|
|
153
|
+
|
|
154
|
+
return buttons
|
|
155
|
+
|
|
156
|
+
def languages(
|
|
157
|
+
self, callback_pattern: str, locales: str | list[str], row_width: int = 2
|
|
158
|
+
) -> None:
|
|
159
|
+
"""Optimized language selection keyboard.
|
|
160
|
+
|
|
161
|
+
Args:
|
|
162
|
+
callback_pattern (str): The pattern used for callback data.
|
|
163
|
+
locales (str | list[str]): One or more locales to be used in the keyboard.
|
|
164
|
+
row_width (int, optional): The number of buttons per row. Defaults to 2.
|
|
165
|
+
|
|
166
|
+
Example:
|
|
167
|
+
>>> keyboard = InlineKeyboard()
|
|
168
|
+
>>> keyboard.languages('lang_{locale}', ['en_US', 'ru_RU', 'uk_UA'])
|
|
169
|
+
>>> print(keyboard.keyboard)
|
|
170
|
+
[[InlineKeyboardButton(text='English', callback_data='lang_en_US'), InlineKeyboardButton(text='Русский', callback_data='lang_ru_RU')], [InlineKeyboardButton(text='Українська', callback_data='lang_uk_UA')]]
|
|
171
|
+
|
|
172
|
+
"""
|
|
173
|
+
if isinstance(locales, str):
|
|
174
|
+
locales = [locales]
|
|
175
|
+
|
|
176
|
+
buttons = [
|
|
177
|
+
InlineButton(
|
|
178
|
+
text=self._LOCALES.get(locale, "Invalid locale"),
|
|
179
|
+
callback_data=callback_pattern.format(locale=locale),
|
|
180
|
+
)
|
|
181
|
+
for locale in locales
|
|
182
|
+
if locale in self._LOCALES
|
|
183
|
+
]
|
|
184
|
+
|
|
185
|
+
self.keyboard = [
|
|
186
|
+
buttons[i : i + row_width] for i in range(0, len(buttons), row_width)
|
|
187
|
+
]
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
# Copyright (c) 2025 Johnnie
|
|
2
|
+
#
|
|
3
|
+
# This software is released under the MIT License.
|
|
4
|
+
# https://opensource.org/licenses/MIT
|
|
5
|
+
|
|
6
|
+
from dataclasses import dataclass, field
|
|
7
|
+
from pyrogram.types import InlineKeyboardButton, WebAppInfo, CallbackGame, LoginUrl
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
@dataclass
|
|
11
|
+
class KeyboardBase:
|
|
12
|
+
row_width: int = 3
|
|
13
|
+
keyboard: list[list] = field(default_factory=list)
|
|
14
|
+
|
|
15
|
+
def add(self, *args: object) -> None:
|
|
16
|
+
self.keyboard = [
|
|
17
|
+
list(args[i : i + self.row_width])
|
|
18
|
+
for i in range(0, len(args), self.row_width)
|
|
19
|
+
]
|
|
20
|
+
|
|
21
|
+
def row(self, *args: object) -> None:
|
|
22
|
+
self.keyboard.append(list(args))
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
@dataclass
|
|
26
|
+
class Button:
|
|
27
|
+
|
|
28
|
+
text: str
|
|
29
|
+
|
|
30
|
+
def __post_init__(self):
|
|
31
|
+
if not isinstance(self.text, str):
|
|
32
|
+
raise ValueError("Button text must be a string")
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
@dataclass
|
|
36
|
+
class InlineButton(InlineKeyboardButton, Button):
|
|
37
|
+
callback_data: str | bytes | None = None
|
|
38
|
+
url: str | None = None
|
|
39
|
+
web_app: WebAppInfo | None = None
|
|
40
|
+
login_url: LoginUrl | None = None
|
|
41
|
+
user_id: int | None = None
|
|
42
|
+
switch_inline_query: str | None = None
|
|
43
|
+
switch_inline_query_current_chat: str | None = None
|
|
44
|
+
callback_game: CallbackGame | None = None
|
|
45
|
+
requires_password: bool | None = None
|
|
46
|
+
pay: bool | None = None
|
|
47
|
+
copy_text: str | None = None
|
|
48
|
+
|
|
49
|
+
def __post_init__(self):
|
|
50
|
+
super().__post_init__()
|
|
51
|
+
super(InlineKeyboardButton, self).__init__(
|
|
52
|
+
text=self.text,
|
|
53
|
+
callback_data=self.callback_data,
|
|
54
|
+
url=self.url,
|
|
55
|
+
web_app=self.web_app,
|
|
56
|
+
login_url=self.login_url,
|
|
57
|
+
user_id=self.user_id,
|
|
58
|
+
switch_inline_query=self.switch_inline_query,
|
|
59
|
+
switch_inline_query_current_chat=self.switch_inline_query_current_chat,
|
|
60
|
+
callback_game=self.callback_game,
|
|
61
|
+
requires_password=self.requires_password,
|
|
62
|
+
pay=self.pay,
|
|
63
|
+
copy_text=self.copy_text,
|
|
64
|
+
)
|