pyrobale 0.2.9.4__py3-none-any.whl → 0.3.5__py3-none-any.whl
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.
- pyrobale/__init__.py +3 -0
- pyrobale/client/__init__.py +574 -0
- pyrobale/exceptions/__init__.py +0 -0
- pyrobale/exceptions/common.py +10 -0
- pyrobale/objects/__init__.py +86 -0
- pyrobale/objects/animation.py +33 -0
- pyrobale/objects/audio.py +24 -0
- pyrobale/objects/callbackquery.py +42 -0
- pyrobale/objects/chat.py +463 -0
- pyrobale/objects/chatmember.py +162 -0
- pyrobale/objects/chatphoto.py +18 -0
- pyrobale/objects/contact.py +16 -0
- pyrobale/objects/copytextbutton.py +5 -0
- pyrobale/objects/document.py +26 -0
- pyrobale/objects/enums.py +28 -0
- pyrobale/objects/file.py +15 -0
- pyrobale/objects/inlinekeyboardbutton.py +24 -0
- pyrobale/objects/inlinekeyboardmarkup.py +84 -0
- pyrobale/objects/inputfile.py +17 -0
- pyrobale/objects/inputmedias.py +166 -0
- pyrobale/objects/invoice.py +14 -0
- pyrobale/objects/keyboardbutton.py +19 -0
- pyrobale/objects/labeledprice.py +8 -0
- pyrobale/objects/location.py +4 -0
- pyrobale/objects/message.py +368 -0
- pyrobale/objects/messageid.py +3 -0
- pyrobale/objects/photosize.py +9 -0
- pyrobale/objects/precheckoutquery.py +21 -0
- pyrobale/objects/replykeyboardmarkup.py +54 -0
- pyrobale/objects/sticker.py +16 -0
- pyrobale/objects/stickerset.py +12 -0
- pyrobale/objects/successfulpayment.py +15 -0
- pyrobale/objects/update.py +23 -0
- pyrobale/objects/user.py +20 -0
- pyrobale/objects/utils.py +28 -0
- pyrobale/objects/video.py +20 -0
- pyrobale/objects/voice.py +4 -0
- pyrobale/objects/webappdata.py +3 -0
- pyrobale/objects/webappinfo.py +3 -0
- pyrobale-0.3.5.dist-info/METADATA +176 -0
- pyrobale-0.3.5.dist-info/RECORD +43 -0
- pyrobale-0.3.5.dist-info/licenses/LICENSE +21 -0
- pyrobale-0.2.9.4.dist-info/METADATA +0 -833
- pyrobale-0.2.9.4.dist-info/RECORD +0 -5
- pyrobale-0.2.9.4.dist-info/licenses/LICENSE +0 -678
- pyrobale.py +0 -2545
- {pyrobale-0.2.9.4.dist-info → pyrobale-0.3.5.dist-info}/WHEEL +0 -0
pyrobale/__init__.py
ADDED
@@ -0,0 +1,574 @@
|
|
1
|
+
from typing import Optional, Union, List, Dict, Any, Callable, Awaitable, TypeVar
|
2
|
+
from ..objects.animation import Animation
|
3
|
+
from ..objects.audio import Audio
|
4
|
+
from ..objects.callbackquery import CallbackQuery
|
5
|
+
from ..objects.chatmember import ChatMember
|
6
|
+
from ..objects.chatphoto import ChatPhoto
|
7
|
+
from ..objects.chat import Chat
|
8
|
+
from ..objects.contact import Contact
|
9
|
+
from ..objects.copytextbutton import CopyTextButton
|
10
|
+
from ..objects.document import Document
|
11
|
+
from ..objects.file import File
|
12
|
+
from ..objects.inlinekeyboardbutton import InlineKeyboardButton
|
13
|
+
from ..objects.inlinekeyboardmarkup import InlineKeyboardMarkup
|
14
|
+
from ..objects.inputfile import InputFile
|
15
|
+
from ..objects.inputmedias import (
|
16
|
+
InputMedia,
|
17
|
+
InputMediaAudio,
|
18
|
+
InputMediaDocument,
|
19
|
+
InputMediaPhoto,
|
20
|
+
InputMediaVideo,
|
21
|
+
)
|
22
|
+
from ..objects.invoice import Invoice
|
23
|
+
from ..objects.keyboardbutton import KeyboardButton
|
24
|
+
from ..objects.labeledprice import LabeledPrice
|
25
|
+
from ..objects.location import Location
|
26
|
+
from ..objects.messageid import MessageId
|
27
|
+
from ..objects.message import Message
|
28
|
+
from ..objects.photosize import PhotoSize
|
29
|
+
from ..objects.precheckoutquery import PreCheckoutQuery
|
30
|
+
from ..objects.replykeyboardmarkup import ReplyKeyboardMarkup
|
31
|
+
from ..objects.sticker import Sticker
|
32
|
+
from ..objects.stickerset import StickerSet
|
33
|
+
from ..objects.successfulpayment import SuccessfulPayment
|
34
|
+
from ..objects.user import User
|
35
|
+
from ..objects.video import Video
|
36
|
+
from ..objects.voice import Voice
|
37
|
+
from ..objects.webappdata import WebAppData
|
38
|
+
from ..objects.webappinfo import WebAppInfo
|
39
|
+
from ..objects.utils import *
|
40
|
+
import asyncio
|
41
|
+
import aiohttp
|
42
|
+
import bale
|
43
|
+
from enum import Enum
|
44
|
+
from ..objects.enums import UpdatesTypes, ChatAction, ChatType
|
45
|
+
|
46
|
+
|
47
|
+
class Client:
|
48
|
+
"""A client for interacting with the Bale messenger API.
|
49
|
+
|
50
|
+
token: The bot token to use for authentication.
|
51
|
+
"""
|
52
|
+
|
53
|
+
def __init__(self, token: str, base_url: str = "https://tapi.bale.ai/bot"):
|
54
|
+
self.token = token
|
55
|
+
self.base_url = base_url
|
56
|
+
self.requests_base = base_url + token
|
57
|
+
|
58
|
+
self.handlers = []
|
59
|
+
self.running = False
|
60
|
+
self.last_update_id = 0
|
61
|
+
|
62
|
+
async def get_updates(
|
63
|
+
self,
|
64
|
+
offset: Optional[int] = None,
|
65
|
+
limit: Optional[int] = None,
|
66
|
+
timeout: Optional[int] = None,
|
67
|
+
) -> List[Dict]:
|
68
|
+
data = await make_get(
|
69
|
+
self.requests_base
|
70
|
+
+ f"/getUpdates?offset={offset}&limit={limit}&timeout={timeout}"
|
71
|
+
)
|
72
|
+
return data["result"]
|
73
|
+
|
74
|
+
async def set_webhook(self, url: str) -> bool:
|
75
|
+
data = await make_post(self.requests_base + "/setWebhook", data={"url": url})
|
76
|
+
return data["result"]
|
77
|
+
|
78
|
+
async def get_webhook_info(self) -> Dict:
|
79
|
+
data = await make_get(self.requests_base + "/getWebhookInfo")
|
80
|
+
return data["result"]
|
81
|
+
|
82
|
+
async def get_me(self) -> User:
|
83
|
+
data = await make_get(self.requests_base + "/getMe")
|
84
|
+
return User(**data["result"])
|
85
|
+
|
86
|
+
async def logout(self) -> bool:
|
87
|
+
data = await make_get(self.requests_base + "/logOut")
|
88
|
+
return data["result"]
|
89
|
+
|
90
|
+
async def close(self) -> bool:
|
91
|
+
data = await make_get(self.requests_base + "/close")
|
92
|
+
return data["result"]
|
93
|
+
|
94
|
+
async def send_message(
|
95
|
+
self,
|
96
|
+
chat_id: int,
|
97
|
+
text: str,
|
98
|
+
reply_to_message_id: Optional[int] = None,
|
99
|
+
reply_markup: Optional[Union[InlineKeyboardMarkup, ReplyKeyboardMarkup]] = None,
|
100
|
+
) -> Message:
|
101
|
+
data = await make_post(
|
102
|
+
self.requests_base + "/sendMessage",
|
103
|
+
data={
|
104
|
+
"chat_id": chat_id,
|
105
|
+
"text": text,
|
106
|
+
"reply_to_message_id": reply_to_message_id,
|
107
|
+
"reply_markup": reply_markup.to_dict() if reply_markup else None,
|
108
|
+
},
|
109
|
+
)
|
110
|
+
return Message(**pythonize(data["result"]))
|
111
|
+
|
112
|
+
async def forward_message(
|
113
|
+
self, chat_id: int, from_chat_id: int, message_id: int
|
114
|
+
) -> Message:
|
115
|
+
data = await make_post(
|
116
|
+
self.requests_base + "/forwardMessage",
|
117
|
+
data={
|
118
|
+
"chat_id": chat_id,
|
119
|
+
"from_chat_id": from_chat_id,
|
120
|
+
"message_id": message_id,
|
121
|
+
},
|
122
|
+
)
|
123
|
+
return Message(**pythonize(data["result"]))
|
124
|
+
|
125
|
+
async def copy_message(
|
126
|
+
self, chat_id: int, from_chat_id: int, message_id: int
|
127
|
+
) -> Message:
|
128
|
+
data = await make_post(
|
129
|
+
self.requests_base + "/copyMessage",
|
130
|
+
data={
|
131
|
+
"chat_id": chat_id,
|
132
|
+
"from_chat_id": from_chat_id,
|
133
|
+
"message_id": message_id,
|
134
|
+
},
|
135
|
+
)
|
136
|
+
return Message(**pythonize(data["result"]))
|
137
|
+
|
138
|
+
async def send_photo(
|
139
|
+
self,
|
140
|
+
chat_id: Union[int, str],
|
141
|
+
photo: Union[InputFile, str],
|
142
|
+
caption: Optional[str] = None,
|
143
|
+
reply_to_message_id: Optional[int] = None,
|
144
|
+
reply_markup: Optional[Union[InlineKeyboardMarkup, ReplyKeyboardMarkup]] = None,
|
145
|
+
) -> Message:
|
146
|
+
data = await make_post(
|
147
|
+
self.requests_base + "/sendPhoto",
|
148
|
+
data={
|
149
|
+
"chat_id": chat_id,
|
150
|
+
"photo": photo,
|
151
|
+
"caption": caption,
|
152
|
+
"reply_to_message_id": reply_to_message_id,
|
153
|
+
"reply_markup": reply_markup.to_dict() if reply_markup else None,
|
154
|
+
},
|
155
|
+
)
|
156
|
+
return Message(**pythonize(data["result"]))
|
157
|
+
|
158
|
+
async def send_audio(
|
159
|
+
self,
|
160
|
+
chat_id: int,
|
161
|
+
audio: Union[InputFile, str],
|
162
|
+
caption: Optional[str] = None,
|
163
|
+
reply_to_message_id: Optional[int] = None,
|
164
|
+
reply_markup: Optional[Union[InlineKeyboardMarkup, ReplyKeyboardMarkup]] = None,
|
165
|
+
) -> Message:
|
166
|
+
data = await make_post(
|
167
|
+
self.requests_base + "/sendAudio",
|
168
|
+
data={
|
169
|
+
"chat_id": chat_id,
|
170
|
+
"audio": audio,
|
171
|
+
"caption": caption,
|
172
|
+
"reply_to_message_id": reply_to_message_id,
|
173
|
+
"reply_markup": reply_markup.to_dict() if reply_markup else None,
|
174
|
+
},
|
175
|
+
)
|
176
|
+
return Message(**pythonize(data["result"]))
|
177
|
+
|
178
|
+
async def send_document(
|
179
|
+
self,
|
180
|
+
chat_id: int,
|
181
|
+
document: Union[InputFile, str],
|
182
|
+
caption: Optional[str] = None,
|
183
|
+
reply_to_message_id: Optional[int] = None,
|
184
|
+
reply_markup: Optional[Union[InlineKeyboardMarkup, ReplyKeyboardMarkup]] = None,
|
185
|
+
) -> Message:
|
186
|
+
data = await make_post(
|
187
|
+
self.requests_base + "/sendDocument",
|
188
|
+
data={
|
189
|
+
"chat_id": chat_id,
|
190
|
+
"document": document,
|
191
|
+
"caption": caption,
|
192
|
+
"reply_to_message_id": reply_to_message_id,
|
193
|
+
"reply_markup": reply_markup.to_dict() if reply_markup else None,
|
194
|
+
},
|
195
|
+
)
|
196
|
+
return Message(**pythonize(data["result"]))
|
197
|
+
|
198
|
+
async def send_video(
|
199
|
+
self,
|
200
|
+
chat_id: int,
|
201
|
+
video: Union[InputFile, str],
|
202
|
+
caption: Optional[str] = None,
|
203
|
+
reply_to_message_id: Optional[int] = None,
|
204
|
+
reply_markup: Optional[Union[InlineKeyboardMarkup, ReplyKeyboardMarkup]] = None,
|
205
|
+
) -> Message:
|
206
|
+
data = await make_post(
|
207
|
+
self.requests_base + "/sendVideo",
|
208
|
+
data={
|
209
|
+
"chat_id": chat_id,
|
210
|
+
"video": video,
|
211
|
+
"caption": caption,
|
212
|
+
"reply_to_message_id": reply_to_message_id,
|
213
|
+
"reply_markup": reply_markup.to_dict() if reply_markup else None,
|
214
|
+
},
|
215
|
+
)
|
216
|
+
return Message(**pythonize(data["result"]))
|
217
|
+
|
218
|
+
async def send_animation(
|
219
|
+
self,
|
220
|
+
chat_id: int,
|
221
|
+
animation: Union[InputFile, str],
|
222
|
+
caption: Optional[str] = None,
|
223
|
+
reply_to_message_id: Optional[int] = None,
|
224
|
+
reply_markup: Optional[Union[InlineKeyboardMarkup, ReplyKeyboardMarkup]] = None,
|
225
|
+
) -> Message:
|
226
|
+
data = await make_post(
|
227
|
+
self.requests_base + "/sendAnimation",
|
228
|
+
data={
|
229
|
+
"chat_id": chat_id,
|
230
|
+
"animation": animation,
|
231
|
+
"caption": caption,
|
232
|
+
"reply_to_message_id": reply_to_message_id,
|
233
|
+
"reply_markup": reply_markup.to_dict() if reply_markup else None,
|
234
|
+
},
|
235
|
+
)
|
236
|
+
return Message(**pythonize(data["result"]))
|
237
|
+
|
238
|
+
async def send_voice(
|
239
|
+
self,
|
240
|
+
chat_id: int,
|
241
|
+
voice: Union[InputFile, str],
|
242
|
+
caption: Optional[str] = None,
|
243
|
+
reply_to_message_id: Optional[int] = None,
|
244
|
+
reply_markup: Optional[Union[InlineKeyboardMarkup, ReplyKeyboardMarkup]] = None,
|
245
|
+
) -> Message:
|
246
|
+
data = await make_post(
|
247
|
+
self.requests_base + "/sendVoice",
|
248
|
+
data={
|
249
|
+
"chat_id": chat_id,
|
250
|
+
"voice": voice,
|
251
|
+
"caption": caption,
|
252
|
+
"reply_to_message_id": reply_to_message_id,
|
253
|
+
"reply_markup": reply_markup.to_dict() if reply_markup else None,
|
254
|
+
},
|
255
|
+
)
|
256
|
+
return Message(**pythonize(data["result"]))
|
257
|
+
|
258
|
+
async def send_media_group(
|
259
|
+
self,
|
260
|
+
chat_id: int,
|
261
|
+
media: List[Union[InputMediaPhoto, InputMediaVideo, InputMediaAudio]],
|
262
|
+
reply_to_message_id: Optional[int] = None,
|
263
|
+
reply_markup: Optional[Union[InlineKeyboardMarkup, ReplyKeyboardMarkup]] = None,
|
264
|
+
) -> List[Message]:
|
265
|
+
data = await make_post(
|
266
|
+
self.requests_base + "/sendMediaGroup",
|
267
|
+
data={
|
268
|
+
"chat_id": chat_id,
|
269
|
+
"media": media,
|
270
|
+
"reply_to_message_id": reply_to_message_id,
|
271
|
+
"reply_markup": reply_markup.to_dict() if reply_markup else None,
|
272
|
+
},
|
273
|
+
)
|
274
|
+
return Message(**pythonize(data["result"]))
|
275
|
+
|
276
|
+
async def send_location(
|
277
|
+
self,
|
278
|
+
chat_id: int,
|
279
|
+
latitude: float,
|
280
|
+
longitude: float,
|
281
|
+
reply_to_message_id: Optional[int] = None,
|
282
|
+
reply_markup: Optional[Union[InlineKeyboardMarkup, ReplyKeyboardMarkup]] = None,
|
283
|
+
) -> Message:
|
284
|
+
data = await make_post(
|
285
|
+
self.requests_base + "/sendLocation",
|
286
|
+
data={
|
287
|
+
"chat_id": chat_id,
|
288
|
+
"latitude": latitude,
|
289
|
+
"longitude": longitude,
|
290
|
+
"reply_to_message_id": reply_to_message_id,
|
291
|
+
"reply_markup": reply_markup.to_dict() if reply_markup else None,
|
292
|
+
},
|
293
|
+
)
|
294
|
+
return Message(**pythonize(data["result"]))
|
295
|
+
|
296
|
+
async def send_contact(
|
297
|
+
self,
|
298
|
+
chat_id: int,
|
299
|
+
phone_number: str,
|
300
|
+
first_name: str,
|
301
|
+
last_name: Optional[str] = None,
|
302
|
+
reply_to_message_id: Optional[int] = None,
|
303
|
+
reply_markup: Optional[Union[InlineKeyboardMarkup, ReplyKeyboardMarkup]] = None,
|
304
|
+
) -> Message:
|
305
|
+
data = await make_post(
|
306
|
+
self.requests_base + "/sendContact",
|
307
|
+
data={
|
308
|
+
"chat_id": chat_id,
|
309
|
+
"phone_number": phone_number,
|
310
|
+
"first_name": first_name,
|
311
|
+
"last_name": last_name,
|
312
|
+
"reply_to_message_id": reply_to_message_id,
|
313
|
+
"reply_markup": reply_markup.to_dict() if reply_markup else None,
|
314
|
+
},
|
315
|
+
)
|
316
|
+
return Message(**pythonize(data["result"]))
|
317
|
+
|
318
|
+
async def get_file(self, file_id: str) -> File:
|
319
|
+
data = await make_post(
|
320
|
+
self.requests_base + "/getFile", data={"file_id": file_id}
|
321
|
+
)
|
322
|
+
return File(**pythonize(data["result"]))
|
323
|
+
|
324
|
+
async def answer_callback_query(
|
325
|
+
self,
|
326
|
+
callback_query_id: str,
|
327
|
+
text: Optional[str] = None,
|
328
|
+
show_alert: Optional[bool] = None,
|
329
|
+
):
|
330
|
+
data = await make_post(
|
331
|
+
self.requests_base + "/answerCallbackQuery",
|
332
|
+
data={
|
333
|
+
"callback_query_id": callback_query_id,
|
334
|
+
"text": text,
|
335
|
+
"show_alert": show_alert,
|
336
|
+
},
|
337
|
+
)
|
338
|
+
return data.get("ok", False)
|
339
|
+
|
340
|
+
async def ban_chat_member(self, chat_id: int, user_id: int) -> bool:
|
341
|
+
data = await make_post(
|
342
|
+
self.requests_base + "/banChatMember",
|
343
|
+
data={"chat_id": chat_id, "user_id": user_id},
|
344
|
+
)
|
345
|
+
return data.get("ok", False)
|
346
|
+
|
347
|
+
async def unban_chat_member(self, chat_id: int, user_id: int) -> bool:
|
348
|
+
data = await make_post(
|
349
|
+
self.requests_base + "/unbanChatMember",
|
350
|
+
data={"chat_id": chat_id, "user_id": user_id},
|
351
|
+
)
|
352
|
+
return data.get("ok", False)
|
353
|
+
|
354
|
+
async def get_chat_member(self, chat_id: int, user_id: int) -> ChatMember:
|
355
|
+
data = await make_post(
|
356
|
+
self.requests_base + "/getChatMember",
|
357
|
+
data={"chat_id": chat_id, "user_id": user_id},
|
358
|
+
)
|
359
|
+
return ChatMember(
|
360
|
+
kwargs={"client": self, "chat": chat_id}, **pythonize(data["result"])
|
361
|
+
)
|
362
|
+
|
363
|
+
async def promote_chat_member(
|
364
|
+
self,
|
365
|
+
chat_id: int,
|
366
|
+
user_id: int,
|
367
|
+
can_change_info: Optional[bool] = None,
|
368
|
+
can_post_messages: Optional[bool] = None,
|
369
|
+
can_edit_messages: Optional[bool] = None,
|
370
|
+
can_delete_messages: Optional[bool] = None,
|
371
|
+
can_invite_users: Optional[bool] = None,
|
372
|
+
can_restrict_members: Optional[bool] = None,
|
373
|
+
can_pin_messages: Optional[bool] = None,
|
374
|
+
can_promote_members: Optional[bool] = None,
|
375
|
+
):
|
376
|
+
data = await make_post(
|
377
|
+
self.requests_base + "/promoteChatMember",
|
378
|
+
data={
|
379
|
+
"chat_id": chat_id,
|
380
|
+
"user_id": user_id,
|
381
|
+
"can_change_info": can_change_info,
|
382
|
+
"can_post_messages": can_post_messages,
|
383
|
+
"can_edit_messages": can_edit_messages,
|
384
|
+
"can_delete_messages": can_delete_messages,
|
385
|
+
"can_invite_users": can_invite_users,
|
386
|
+
"can_restrict_members": can_restrict_members,
|
387
|
+
"can_pin_messages": can_pin_messages,
|
388
|
+
"can_promote_members": can_promote_members,
|
389
|
+
},
|
390
|
+
)
|
391
|
+
return data.get("ok", False)
|
392
|
+
|
393
|
+
async def set_chat_photo(self, chat_id: int, photo: InputFile) -> bool:
|
394
|
+
data = await make_post(
|
395
|
+
self.requests_base + "/setChatPhoto",
|
396
|
+
data={"chat_id": chat_id, "photo": photo},
|
397
|
+
)
|
398
|
+
return data.get("ok", False)
|
399
|
+
|
400
|
+
async def leave_chat(self, chat_id: int) -> bool:
|
401
|
+
data = await make_post(
|
402
|
+
self.requests_base + "/leaveChat", data={"chat_id": chat_id}
|
403
|
+
)
|
404
|
+
return data.get("ok", False)
|
405
|
+
|
406
|
+
async def get_chat(self, chat_id: int) -> Chat:
|
407
|
+
data = await make_post(
|
408
|
+
self.requests_base + "/getChat", data={"chat_id": chat_id}
|
409
|
+
)
|
410
|
+
return Chat(**pythonize(data["result"]))
|
411
|
+
|
412
|
+
async def get_chat_members_count(self, chat_id: int) -> int:
|
413
|
+
data = await make_post(
|
414
|
+
self.requests_base + "/getChatMembersCount", data={"chat_id": chat_id}
|
415
|
+
)
|
416
|
+
return data.get("result", 0)
|
417
|
+
|
418
|
+
async def pin_chat_message(self, chat_id: int, message_id: int) -> bool:
|
419
|
+
data = await make_post(
|
420
|
+
self.requests_base + "/pinChatMessage",
|
421
|
+
data={"chat_id": chat_id, "message_id": message_id},
|
422
|
+
)
|
423
|
+
return data.get("ok", False)
|
424
|
+
|
425
|
+
async def unpin_chat_message(self, chat_id: int) -> bool:
|
426
|
+
data = await make_post(
|
427
|
+
self.requests_base + "/unpinChatMessage", data={"chat_id": chat_id}
|
428
|
+
)
|
429
|
+
return data.get("ok", False)
|
430
|
+
|
431
|
+
async def unpin_all_chat_messages(self, chat_id: int) -> bool:
|
432
|
+
data = await make_post(
|
433
|
+
self.requests_base + "/unpinAllChatMessages", data={"chat_id": chat_id}
|
434
|
+
)
|
435
|
+
return data.get("ok", False)
|
436
|
+
|
437
|
+
async def set_chat_title(self, chat_id: int, title: str) -> bool:
|
438
|
+
data = await make_post(
|
439
|
+
self.requests_base + "/setChatTitle",
|
440
|
+
data={"chat_id": chat_id, "title": title},
|
441
|
+
)
|
442
|
+
return data.get("ok", False)
|
443
|
+
|
444
|
+
async def set_chat_description(self, chat_id: int, description: str) -> bool:
|
445
|
+
data = await make_post(
|
446
|
+
self.requests_base + "/setChatDescription",
|
447
|
+
data={"chat_id": chat_id, "description": description},
|
448
|
+
)
|
449
|
+
return data.get("ok", False)
|
450
|
+
|
451
|
+
async def delete_chat_photo(self, chat_id: int) -> bool:
|
452
|
+
data = await make_post(
|
453
|
+
self.requests_base + "/deleteChatPhoto", data={"chat_id": chat_id}
|
454
|
+
)
|
455
|
+
return data.get("ok", False)
|
456
|
+
|
457
|
+
async def create_chat_invite_link(self, chat_id: int) -> str:
|
458
|
+
data = await make_post(
|
459
|
+
self.requests_base + "/createChatInviteLink", data={"chat_id": chat_id}
|
460
|
+
)
|
461
|
+
return data.get("result", "")
|
462
|
+
|
463
|
+
async def revoke_chat_invite_link(self, chat_id: int, invite_link: str) -> str:
|
464
|
+
data = await make_post(
|
465
|
+
self.requests_base + "/revokeChatInviteLink",
|
466
|
+
data={"chat_id": chat_id, "invite_link": invite_link},
|
467
|
+
)
|
468
|
+
return data.get("result", "")
|
469
|
+
|
470
|
+
async def export_chat_invite_link(self, chat_id: int) -> str:
|
471
|
+
data = await make_post(
|
472
|
+
self.requests_base + "/exportChatInviteLink", data={"chat_id": chat_id}
|
473
|
+
)
|
474
|
+
return data.get("result", "")
|
475
|
+
|
476
|
+
async def send_chat_action(self, chat_id: int, action: ChatAction) -> bool:
|
477
|
+
data = await make_post(
|
478
|
+
self.requests_base + "/sendChatAction",
|
479
|
+
data={"chat_id": str(chat_id), "action": action.value},
|
480
|
+
)
|
481
|
+
return data.get("ok", False)
|
482
|
+
|
483
|
+
async def process_update(self, update: Dict[str, Any]) -> None:
|
484
|
+
"""Process a single update and call registered handlers."""
|
485
|
+
update_id = update.get("update_id")
|
486
|
+
if update_id:
|
487
|
+
self.last_update_id = update_id + 1
|
488
|
+
|
489
|
+
for handler in self.handlers:
|
490
|
+
update_type = handler["type"].value
|
491
|
+
if update_type in update:
|
492
|
+
event = update[update_type]
|
493
|
+
|
494
|
+
event = self._convert_event(handler["type"], event)
|
495
|
+
|
496
|
+
if asyncio.iscoroutinefunction(handler["callback"]):
|
497
|
+
asyncio.create_task(handler["callback"](event))
|
498
|
+
else:
|
499
|
+
handler["callback"](event)
|
500
|
+
|
501
|
+
def _convert_event(self, handler_type: UpdatesTypes, event: Dict[str, Any]) -> Any:
|
502
|
+
"""Convert raw event data to appropriate object type."""
|
503
|
+
if handler_type in (UpdatesTypes.MESSAGE, UpdatesTypes.MESSAGE_EDITED):
|
504
|
+
return Message(**pythonize(event), kwargs={"client": self})
|
505
|
+
elif handler_type == UpdatesTypes.CALLBACK_QUERY:
|
506
|
+
return CallbackQuery(kwargs={"client": self}, **pythonize(event))
|
507
|
+
elif handler_type == UpdatesTypes.PRE_CHECKOUT_QUERY:
|
508
|
+
return PreCheckoutQuery(kwargs={"client": self}, **pythonize(event))
|
509
|
+
elif handler_type == UpdatesTypes.MEMBER_JOINED:
|
510
|
+
return ChatMember(
|
511
|
+
kwargs={"client": self}, **pythonize(event.get("new_chat_member", {}))
|
512
|
+
)
|
513
|
+
elif handler_type == UpdatesTypes.MEMBER_LEFT:
|
514
|
+
return ChatMember(
|
515
|
+
kwargs={"client": self}, **pythonize(event.get("left_chat_member", {}))
|
516
|
+
)
|
517
|
+
return event
|
518
|
+
|
519
|
+
def add_handler(
|
520
|
+
self,
|
521
|
+
update_type: UpdatesTypes,
|
522
|
+
callback: Callable[[Any], Union[None, Awaitable[None]]],
|
523
|
+
) -> None:
|
524
|
+
"""Register a handler for specific update type."""
|
525
|
+
self.handlers.append({"type": update_type, "callback": callback})
|
526
|
+
|
527
|
+
def remove_handler(
|
528
|
+
self, callback: Callable[[Any], Union[None, Awaitable[None]]]
|
529
|
+
) -> None:
|
530
|
+
"""Remove a handler from the list of handlers."""
|
531
|
+
self.handlers = [
|
532
|
+
handler for handler in self.handlers if handler["callback"] != callback
|
533
|
+
]
|
534
|
+
|
535
|
+
def remove_all_handlers(self) -> None:
|
536
|
+
"""Remove all handlers from the list of handlers."""
|
537
|
+
self.handlers = []
|
538
|
+
|
539
|
+
async def start_polling(self, timeout: int = 30, limit: int = 100) -> None:
|
540
|
+
"""Start polling updates from the server."""
|
541
|
+
if self.running:
|
542
|
+
raise RuntimeError("Client is already running")
|
543
|
+
|
544
|
+
self.running = True
|
545
|
+
while self.running:
|
546
|
+
if 1:
|
547
|
+
updates = await self.get_updates(
|
548
|
+
offset=self.last_update_id, limit=limit, timeout=timeout
|
549
|
+
)
|
550
|
+
|
551
|
+
for update in updates:
|
552
|
+
await self.process_update(update)
|
553
|
+
|
554
|
+
else: # except Exception as e:
|
555
|
+
# print(f"Error while polling updates: {e}")
|
556
|
+
await asyncio.sleep(5)
|
557
|
+
|
558
|
+
async def stop_polling(self) -> None:
|
559
|
+
"""Stop polling updates."""
|
560
|
+
self.running = False
|
561
|
+
|
562
|
+
def run(self, timeout: int = 30, limit: int = 100) -> None:
|
563
|
+
"""Run the client."""
|
564
|
+
loop = asyncio.get_event_loop()
|
565
|
+
loop.run_until_complete(self.start_polling(timeout, limit))
|
566
|
+
|
567
|
+
def stop(self) -> None:
|
568
|
+
"""Stop the client."""
|
569
|
+
loop = asyncio.get_event_loop()
|
570
|
+
loop.run_until_complete(self.stop_polling())
|
571
|
+
|
572
|
+
async def handle_webhook_update(self, update_data: Dict[str, Any]) -> None:
|
573
|
+
"""Process an update received via webhook."""
|
574
|
+
await self.process_update(update_data)
|
File without changes
|
@@ -0,0 +1,86 @@
|
|
1
|
+
from .voice import Voice
|
2
|
+
from .replykeyboardmarkup import ReplyKeyboardMarkup
|
3
|
+
from .inputmedias import (
|
4
|
+
InputMedia,
|
5
|
+
InputMediaPhoto,
|
6
|
+
InputMediaVideo,
|
7
|
+
InputMediaAnimation,
|
8
|
+
InputMediaAudio,
|
9
|
+
InputMediaDocument,
|
10
|
+
)
|
11
|
+
from .message import Message
|
12
|
+
from .invoice import Invoice
|
13
|
+
from .audio import Audio
|
14
|
+
from .inputmedias import InputMedia
|
15
|
+
from .inlinekeyboardbutton import InlineKeyboardButton
|
16
|
+
from .photosize import PhotoSize
|
17
|
+
from .chat import Chat
|
18
|
+
from .sticker import Sticker
|
19
|
+
from .contact import Contact
|
20
|
+
from .animation import Animation
|
21
|
+
from .user import User
|
22
|
+
from .chatphoto import ChatPhoto
|
23
|
+
from .webappinfo import WebAppInfo
|
24
|
+
from .keyboardbutton import KeyboardButton
|
25
|
+
from .callbackquery import CallbackQuery
|
26
|
+
from .inputfile import InputFile
|
27
|
+
from .webappdata import WebAppData
|
28
|
+
from .precheckoutquery import PreCheckoutQuery
|
29
|
+
from .location import Location
|
30
|
+
from .document import Document
|
31
|
+
from .inlinekeyboardmarkup import InlineKeyboardMarkup
|
32
|
+
from .file import File
|
33
|
+
from .copytextbutton import CopyTextButton
|
34
|
+
from ..client import Client
|
35
|
+
from .chatmember import ChatMember
|
36
|
+
from .video import Video
|
37
|
+
from .stickerset import StickerSet
|
38
|
+
from .successfulpayment import SuccessfulPayment
|
39
|
+
from .messageid import MessageId
|
40
|
+
from .labeledprice import LabeledPrice
|
41
|
+
from .update import Update
|
42
|
+
from .enums import UpdatesTypes, ChatAction, ChatType
|
43
|
+
|
44
|
+
__all__ = [
|
45
|
+
"UpdatesTypes",
|
46
|
+
"ChatAction",
|
47
|
+
"ChatType",
|
48
|
+
"Voice",
|
49
|
+
"ReplyKeyboardMarkup",
|
50
|
+
"InputMediaPhoto",
|
51
|
+
"Message",
|
52
|
+
"Invoice",
|
53
|
+
"Audio",
|
54
|
+
"InputMedia",
|
55
|
+
"InlineKeyboardButton",
|
56
|
+
"PhotoSize",
|
57
|
+
"InputMediaDocument",
|
58
|
+
"Chat",
|
59
|
+
"Sticker",
|
60
|
+
"InputMediaAudio",
|
61
|
+
"Contact",
|
62
|
+
"Animation",
|
63
|
+
"InputMediaVideo",
|
64
|
+
"User",
|
65
|
+
"ChatPhoto",
|
66
|
+
"WebAppInfo",
|
67
|
+
"KeyboardButton",
|
68
|
+
"InputMediaAnimation",
|
69
|
+
"CallbackQuery",
|
70
|
+
"InputFile",
|
71
|
+
"WebAppData",
|
72
|
+
"PreCheckoutQuery",
|
73
|
+
"Location",
|
74
|
+
"Document",
|
75
|
+
"InlineKeyboardMarkup",
|
76
|
+
"File",
|
77
|
+
"CopyTextButton",
|
78
|
+
"Client",
|
79
|
+
"ChatMember",
|
80
|
+
"Video",
|
81
|
+
"StickerSet",
|
82
|
+
"SuccessfulPayment",
|
83
|
+
"MessageId",
|
84
|
+
"LabeledPrice",
|
85
|
+
"Update",
|
86
|
+
]
|