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.
Files changed (47) hide show
  1. pyrobale/__init__.py +3 -0
  2. pyrobale/client/__init__.py +574 -0
  3. pyrobale/exceptions/__init__.py +0 -0
  4. pyrobale/exceptions/common.py +10 -0
  5. pyrobale/objects/__init__.py +86 -0
  6. pyrobale/objects/animation.py +33 -0
  7. pyrobale/objects/audio.py +24 -0
  8. pyrobale/objects/callbackquery.py +42 -0
  9. pyrobale/objects/chat.py +463 -0
  10. pyrobale/objects/chatmember.py +162 -0
  11. pyrobale/objects/chatphoto.py +18 -0
  12. pyrobale/objects/contact.py +16 -0
  13. pyrobale/objects/copytextbutton.py +5 -0
  14. pyrobale/objects/document.py +26 -0
  15. pyrobale/objects/enums.py +28 -0
  16. pyrobale/objects/file.py +15 -0
  17. pyrobale/objects/inlinekeyboardbutton.py +24 -0
  18. pyrobale/objects/inlinekeyboardmarkup.py +84 -0
  19. pyrobale/objects/inputfile.py +17 -0
  20. pyrobale/objects/inputmedias.py +166 -0
  21. pyrobale/objects/invoice.py +14 -0
  22. pyrobale/objects/keyboardbutton.py +19 -0
  23. pyrobale/objects/labeledprice.py +8 -0
  24. pyrobale/objects/location.py +4 -0
  25. pyrobale/objects/message.py +368 -0
  26. pyrobale/objects/messageid.py +3 -0
  27. pyrobale/objects/photosize.py +9 -0
  28. pyrobale/objects/precheckoutquery.py +21 -0
  29. pyrobale/objects/replykeyboardmarkup.py +54 -0
  30. pyrobale/objects/sticker.py +16 -0
  31. pyrobale/objects/stickerset.py +12 -0
  32. pyrobale/objects/successfulpayment.py +15 -0
  33. pyrobale/objects/update.py +23 -0
  34. pyrobale/objects/user.py +20 -0
  35. pyrobale/objects/utils.py +28 -0
  36. pyrobale/objects/video.py +20 -0
  37. pyrobale/objects/voice.py +4 -0
  38. pyrobale/objects/webappdata.py +3 -0
  39. pyrobale/objects/webappinfo.py +3 -0
  40. pyrobale-0.3.5.dist-info/METADATA +176 -0
  41. pyrobale-0.3.5.dist-info/RECORD +43 -0
  42. pyrobale-0.3.5.dist-info/licenses/LICENSE +21 -0
  43. pyrobale-0.2.9.4.dist-info/METADATA +0 -833
  44. pyrobale-0.2.9.4.dist-info/RECORD +0 -5
  45. pyrobale-0.2.9.4.dist-info/licenses/LICENSE +0 -678
  46. pyrobale.py +0 -2545
  47. {pyrobale-0.2.9.4.dist-info → pyrobale-0.3.5.dist-info}/WHEEL +0 -0
pyrobale/__init__.py ADDED
@@ -0,0 +1,3 @@
1
+ from .objects.utils import *
2
+ from .exceptions import *
3
+ from .objects import *
@@ -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,10 @@
1
+ class PyroBaleException(Exception):
2
+ pass
3
+
4
+
5
+ class InvalidTokenException(PyroBaleException):
6
+ pass
7
+
8
+
9
+ class NotFoundException(PyroBaleException):
10
+ pass
@@ -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
+ ]