Rubka 6.6.2__py3-none-any.whl → 7.1.17__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.
- rubka/__init__.py +70 -0
- rubka/api.py +6 -17
- rubka/asynco.py +1058 -255
- rubka/button.py +1 -1
- rubka/context.py +560 -25
- rubka/exceptions.py +35 -1
- rubka/filters.py +16 -0
- rubka/helpers.py +1461 -0
- rubka/metadata.py +117 -0
- rubka/rubino.py +227 -96
- rubka/tv.py +145 -0
- rubka/update.py +560 -25
- {rubka-6.6.2.dist-info → rubka-7.1.17.dist-info}/METADATA +29 -11
- {rubka-6.6.2.dist-info → rubka-7.1.17.dist-info}/RECORD +17 -13
- rubka-7.1.17.dist-info/entry_points.txt +2 -0
- {rubka-6.6.2.dist-info → rubka-7.1.17.dist-info}/WHEEL +0 -0
- {rubka-6.6.2.dist-info → rubka-7.1.17.dist-info}/top_level.txt +0 -0
rubka/button.py
CHANGED
rubka/context.py
CHANGED
|
@@ -1,5 +1,68 @@
|
|
|
1
|
-
from typing import
|
|
2
|
-
|
|
1
|
+
from typing import Union
|
|
2
|
+
from pathlib import Path
|
|
3
|
+
from typing import List, Optional, Dict, Any, Literal, Callable, Union,Set
|
|
4
|
+
import re,inspect
|
|
5
|
+
import asyncio
|
|
6
|
+
_EMOJI_PATTERN = re.compile(
|
|
7
|
+
"["
|
|
8
|
+
"\U0001F300-\U0001F5FF"
|
|
9
|
+
"\U0001F600-\U0001F64F"
|
|
10
|
+
"\U0001F680-\U0001F6FF"
|
|
11
|
+
"\U0001F700-\U0001F77F"
|
|
12
|
+
"\U0001F780-\U0001F7FF"
|
|
13
|
+
"\U0001F800-\U0001F8FF"
|
|
14
|
+
"\U0001F900-\U0001F9FF"
|
|
15
|
+
"\U0001FA00-\U0001FA6F"
|
|
16
|
+
"\U0001FA70-\U0001FAFF"
|
|
17
|
+
"\U00002700-\U000027BF"
|
|
18
|
+
"\U00002600-\U000026FF"
|
|
19
|
+
"\U00002000-\U000023FF"
|
|
20
|
+
"]+",
|
|
21
|
+
flags=re.UNICODE
|
|
22
|
+
)
|
|
23
|
+
|
|
24
|
+
def contains_emoji(text: str) -> bool:
|
|
25
|
+
if not text:return False
|
|
26
|
+
return bool(_EMOJI_PATTERN.search(text))
|
|
27
|
+
|
|
28
|
+
def count_emojis(text: str) -> int:
|
|
29
|
+
if not text:return 0
|
|
30
|
+
return len(_EMOJI_PATTERN.findall(text))
|
|
31
|
+
def contains_link_or_mention(text: str) -> bool:
|
|
32
|
+
if not text:return False
|
|
33
|
+
pattern = re.compile(
|
|
34
|
+
r"(?i)\b("
|
|
35
|
+
r"https?://[^\s]+"
|
|
36
|
+
r"|www\.[^\s]+"
|
|
37
|
+
r"|[a-zA-Z0-9.-]+\.(com|net|org|ir|edu|gov|info|biz|io|me|co|xyz|in|us|uk|ru|tv|cc|app|dev|site|store|cloud|shop)"
|
|
38
|
+
r"|t\.me/[^\s]+"
|
|
39
|
+
r"|telegram\.me/[^\s]+"
|
|
40
|
+
r"|rubika\.(ir|app)/[^\s]+"
|
|
41
|
+
r"|whatsapp\.com/[^\s]+"
|
|
42
|
+
r"|wa\.me/[^\s]+"
|
|
43
|
+
r"|instagram\.com/[^\s]+"
|
|
44
|
+
r"|instagr\.am/[^\s]+"
|
|
45
|
+
r"|youtube\.com/[^\s]+"
|
|
46
|
+
r"|youtu\.be/[^\s]+"
|
|
47
|
+
r"|aparat\.com/[^\s]+"
|
|
48
|
+
r"|discord\.gg/[^\s]+"
|
|
49
|
+
r"|discord\.com/[^\s]+"
|
|
50
|
+
r"|splus\.ir/[^\s]+"
|
|
51
|
+
r"|eitaa\.com/[^\s]+"
|
|
52
|
+
r"|ble\.ir/[^\s]+"
|
|
53
|
+
r"|gap\.im/[^\s]+"
|
|
54
|
+
r"|rubino\.ir/[^\s]+"
|
|
55
|
+
r"|pin\.it/[^\s]+"
|
|
56
|
+
r"|twitter\.com/[^\s]+"
|
|
57
|
+
r"|x\.com/[^\s]+"
|
|
58
|
+
r"|facebook\.com/[^\s]+"
|
|
59
|
+
r"|threads\.net/[^\s]+"
|
|
60
|
+
r"|@\w+"
|
|
61
|
+
r"|\b\d{1,3}(?:\.\d{1,3}){3}\b"
|
|
62
|
+
r"|\[?[A-F0-9:]{2,39}\]?"
|
|
63
|
+
r")\b"
|
|
64
|
+
)
|
|
65
|
+
return bool(pattern.search(text))
|
|
3
66
|
class File:
|
|
4
67
|
def __init__(self, data: dict):
|
|
5
68
|
self.file_id: str = data.get("file_id")
|
|
@@ -184,9 +247,25 @@ class Bot:
|
|
|
184
247
|
self.username: str = data.get("username")
|
|
185
248
|
self.start_message: str = data.get("start_message")
|
|
186
249
|
self.share_url: str = data.get("share_url")
|
|
187
|
-
from typing import Union
|
|
188
|
-
from pathlib import Path
|
|
189
250
|
|
|
251
|
+
class hybrid_property:
|
|
252
|
+
def __init__(self, func):
|
|
253
|
+
self.func = func
|
|
254
|
+
|
|
255
|
+
def __get__(self, instance, owner):
|
|
256
|
+
if instance is None:
|
|
257
|
+
return self
|
|
258
|
+
coro = self.func(instance)
|
|
259
|
+
try:
|
|
260
|
+
loop = asyncio.get_running_loop()
|
|
261
|
+
return coro
|
|
262
|
+
except RuntimeError:
|
|
263
|
+
try:
|
|
264
|
+
loop = asyncio.get_event_loop()
|
|
265
|
+
except RuntimeError:
|
|
266
|
+
loop = asyncio.new_event_loop()
|
|
267
|
+
asyncio.set_event_loop(loop)
|
|
268
|
+
return loop.run_until_complete(coro)
|
|
190
269
|
class Message:
|
|
191
270
|
def __init__(self, bot, chat_id, message_id, sender_id, text=None, raw_data=None):
|
|
192
271
|
self.bot = bot
|
|
@@ -196,6 +275,52 @@ class Message:
|
|
|
196
275
|
self.author_guid = self.raw_data.get("sender_id", sender_id)
|
|
197
276
|
self.message_id: str = self.raw_data.get("message_id", message_id)
|
|
198
277
|
self.text: str = self.raw_data.get("text", text)
|
|
278
|
+
self.has_link = contains_link_or_mention(self.raw_data.get("text", text))
|
|
279
|
+
self.is_link = self.has_link
|
|
280
|
+
self.is_mention = bool(re.search(r"@\w+", self.raw_data.get("text", text) or ""))
|
|
281
|
+
self.is_hashtag = bool(re.search(r"#\w+", text or ""))
|
|
282
|
+
self.is_number = bool(re.search(r"\d+", text or ""))
|
|
283
|
+
self.is_emoji = contains_emoji(self.raw_data.get("text", text))
|
|
284
|
+
self.emoji_count = count_emojis(self.raw_data.get("text", text))
|
|
285
|
+
self.is_pure_emoji = bool(self.is_emoji and self.emoji_count == len(self.text))
|
|
286
|
+
self.is_photo = None
|
|
287
|
+
self.is_video = None
|
|
288
|
+
self.is_audio = None
|
|
289
|
+
self.is_voice = None
|
|
290
|
+
self.is_document = None
|
|
291
|
+
self.is_archive = None
|
|
292
|
+
self.is_executable = None
|
|
293
|
+
self.is_font = None
|
|
294
|
+
self.metadata = self.raw_data.get("metadata", {})
|
|
295
|
+
self.is_metadata = self.metadata
|
|
296
|
+
self.meta_parts = self.metadata.get("meta_data_parts", [])
|
|
297
|
+
self.has_metadata = bool(self.meta_parts)
|
|
298
|
+
self.meta_types = [part.get("type") for part in self.meta_parts] if self.has_metadata else []
|
|
299
|
+
self.is_bold = "Bold" in self.meta_types
|
|
300
|
+
self.is_italic = "Italic" in self.meta_types
|
|
301
|
+
self.is_strike = "Strike" in self.meta_types
|
|
302
|
+
self.is_underline = "Underline" in self.meta_types
|
|
303
|
+
self.is_quote = "Quote" in self.meta_types
|
|
304
|
+
self.is_spoiler = "Spoiler" in self.meta_types
|
|
305
|
+
self.is_pre = "Pre" in self.meta_types
|
|
306
|
+
self.is_mono = "Mono" in self.meta_types
|
|
307
|
+
self.is_link_meta = "Link" in self.meta_types
|
|
308
|
+
self.meta_links = [part.get("link_url") for part in self.meta_parts if part.get("type") == "Link"]
|
|
309
|
+
self.meta_link_positions = [
|
|
310
|
+
{"from": part.get("from_index"), "length": part.get("length"), "url": part.get("link_url")}
|
|
311
|
+
for part in self.meta_parts if part.get("type") == "Link"
|
|
312
|
+
]
|
|
313
|
+
self.has_link = contains_link_or_mention(self.text) or self.is_link_meta
|
|
314
|
+
self.is_formatted = any([
|
|
315
|
+
self.is_bold,
|
|
316
|
+
self.is_italic,
|
|
317
|
+
self.is_strike,
|
|
318
|
+
self.is_underline,
|
|
319
|
+
self.is_quote,
|
|
320
|
+
self.is_spoiler,
|
|
321
|
+
self.is_pre,
|
|
322
|
+
self.is_mono
|
|
323
|
+
])
|
|
199
324
|
self.sender_id: str = self.raw_data.get("sender_id", sender_id)
|
|
200
325
|
self.time: str = self.raw_data.get("time")
|
|
201
326
|
self.is_edited: bool = self.raw_data.get("is_edited", False)
|
|
@@ -226,19 +351,85 @@ class Message:
|
|
|
226
351
|
self.is_contact = self.contact_message is not None
|
|
227
352
|
self.has_any_media = any([self.file, self.sticker, self.poll, self.location, self.live_location])
|
|
228
353
|
self.edited_text = self.raw_data.get("edited_text") if self.is_edited else None
|
|
229
|
-
self.
|
|
354
|
+
if self.file and self.file.file_name:
|
|
355
|
+
name = self.file.file_name.lower()
|
|
356
|
+
self.is_photo = name.endswith((".jpg", ".jpeg", ".png", ".gif", ".webp"))
|
|
357
|
+
self.is_video = name.endswith((".mp4", ".mov", ".avi", ".mkv", ".webm"))
|
|
358
|
+
self.is_audio = name.endswith((".mp3", ".wav", ".ogg", ".m4a", ".flac"))
|
|
359
|
+
self.is_voice = name.endswith((".ogg", ".m4a"))
|
|
360
|
+
self.is_document = name.endswith((".pdf", ".doc", ".docx", ".txt", ".xls", ".xlsx", ".ppt", ".pptx"))
|
|
361
|
+
self.is_archive = name.endswith((".zip", ".rar", ".7z", ".tar", ".gz"))
|
|
362
|
+
self.is_executable = name.endswith((".exe", ".msi", ".bat", ".sh"))
|
|
363
|
+
self.is_font = name.endswith((".ttf", ".otf", ".woff", ".woff2"))
|
|
230
364
|
@property
|
|
231
365
|
def session(self):
|
|
232
366
|
if self.chat_id not in self.bot.sessions:
|
|
233
367
|
self.bot.sessions[self.chat_id] = {}
|
|
234
368
|
return self.bot.sessions[self.chat_id]
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
369
|
+
|
|
370
|
+
def reply(self, text: str, delete_after: int = None,parse_mode : Optional[Literal["HTML", "Markdown"]] = None , **kwargs):
|
|
371
|
+
async def _reply_async():
|
|
372
|
+
send_func = self.bot.send_message
|
|
373
|
+
if inspect.iscoroutinefunction(send_func):
|
|
374
|
+
msg = await send_func(
|
|
375
|
+
self.chat_id,
|
|
376
|
+
text,
|
|
377
|
+
reply_to_message_id=self.message_id,
|
|
378
|
+
delete_after=delete_after,
|
|
379
|
+
parse_mode=parse_mode,
|
|
380
|
+
**kwargs
|
|
381
|
+
)
|
|
382
|
+
else:
|
|
383
|
+
msg = send_func(
|
|
384
|
+
self.chat_id,
|
|
385
|
+
text,
|
|
386
|
+
reply_to_message_id=self.message_id,
|
|
387
|
+
delete_after=delete_after,
|
|
388
|
+
**kwargs
|
|
389
|
+
)
|
|
390
|
+
class Pick:
|
|
391
|
+
def __init__(self, bot, chat_id, message_id):
|
|
392
|
+
self.bot = bot
|
|
393
|
+
self.chat_id = chat_id
|
|
394
|
+
self.message_id = message_id
|
|
395
|
+
|
|
396
|
+
def edit(self, new_text):
|
|
397
|
+
async def _edit():
|
|
398
|
+
func = self.bot.edit_message_text
|
|
399
|
+
if inspect.iscoroutinefunction(func):
|
|
400
|
+
await func(self.chat_id, self.message_id, new_text)
|
|
401
|
+
else:
|
|
402
|
+
func(self.chat_id, self.message_id, new_text)
|
|
403
|
+
|
|
404
|
+
try:
|
|
405
|
+
loop = asyncio.get_running_loop()
|
|
406
|
+
if loop.is_running():
|
|
407
|
+
return asyncio.create_task(_edit())
|
|
408
|
+
except RuntimeError:
|
|
409
|
+
return asyncio.run(_edit())
|
|
410
|
+
|
|
411
|
+
def delete(self):
|
|
412
|
+
async def _delete():
|
|
413
|
+
func = self.bot.delete_message
|
|
414
|
+
if inspect.iscoroutinefunction(func):
|
|
415
|
+
await func(self.chat_id, self.message_id)
|
|
416
|
+
else:
|
|
417
|
+
func(self.chat_id, self.message_id)
|
|
418
|
+
try:
|
|
419
|
+
loop = asyncio.get_running_loop()
|
|
420
|
+
if loop.is_running():
|
|
421
|
+
return asyncio.create_task(_delete())
|
|
422
|
+
except RuntimeError:
|
|
423
|
+
return asyncio.run(_delete())
|
|
424
|
+
chat_id = msg.get("chat_id") if isinstance(msg, dict) else getattr(msg, "chat_id", self.chat_id)
|
|
425
|
+
message_id = msg.get("message_id") if isinstance(msg, dict) else getattr(msg, "message_id", self.message_id)
|
|
426
|
+
return Pick(self.bot, chat_id, message_id)
|
|
427
|
+
try:
|
|
428
|
+
loop = asyncio.get_running_loop()
|
|
429
|
+
if loop.is_running():
|
|
430
|
+
return asyncio.create_task(_reply_async())
|
|
431
|
+
except RuntimeError:
|
|
432
|
+
return asyncio.run(_reply_async())
|
|
242
433
|
def answer(self, text: str, **kwargs):
|
|
243
434
|
return self.bot.send_message(
|
|
244
435
|
self.chat_id,
|
|
@@ -246,15 +437,42 @@ class Message:
|
|
|
246
437
|
reply_to_message_id=self.message_id,
|
|
247
438
|
**kwargs
|
|
248
439
|
)
|
|
440
|
+
|
|
249
441
|
|
|
250
|
-
def reply_poll(
|
|
251
|
-
|
|
442
|
+
def reply_poll(
|
|
443
|
+
self,
|
|
444
|
+
question: str,
|
|
445
|
+
options: List[str],
|
|
446
|
+
type: Literal['Regular', 'Quiz'] = "Regular",
|
|
447
|
+
allows_multiple_answers: bool = False,
|
|
448
|
+
is_anonymous: bool = True,
|
|
449
|
+
correct_option_index: Optional[int] = None,
|
|
450
|
+
hint: Optional[str] = None,
|
|
451
|
+
reply_to_message_id: Optional[str] = None,
|
|
452
|
+
disable_notification: bool = False,
|
|
453
|
+
show_results: bool = False,
|
|
454
|
+
inline_keypad: Optional[Dict[str, Any]] = None,
|
|
455
|
+
chat_keypad: Optional[Dict[str, Any]] = None,
|
|
456
|
+
chat_keypad_type: Optional[Literal['New', 'Remove', 'None']] = None,
|
|
457
|
+
**kwargs
|
|
458
|
+
) -> dict:
|
|
459
|
+
payload = {
|
|
252
460
|
"chat_id": self.chat_id,
|
|
253
461
|
"question": question,
|
|
254
462
|
"options": options,
|
|
255
|
-
"
|
|
256
|
-
|
|
257
|
-
|
|
463
|
+
"type": type,
|
|
464
|
+
"allows_multiple_answers": allows_multiple_answers,
|
|
465
|
+
"is_anonymous": is_anonymous,
|
|
466
|
+
"correct_option_index": correct_option_index,
|
|
467
|
+
"hint": hint,
|
|
468
|
+
"reply_to_message_id": self.message_id if not reply_to_message_id else reply_to_message_id,
|
|
469
|
+
"disable_notification": disable_notification,
|
|
470
|
+
"show_results": show_results,
|
|
471
|
+
"inline_keypad": inline_keypad,
|
|
472
|
+
"chat_keypad": chat_keypad,
|
|
473
|
+
"chat_keypad_type": chat_keypad_type,
|
|
474
|
+
}
|
|
475
|
+
return self.bot._post("sendPoll", {key: value for key, value in payload.items() if value is not None}, **kwargs)
|
|
258
476
|
|
|
259
477
|
|
|
260
478
|
def reply_document(
|
|
@@ -457,6 +675,14 @@ class Message:
|
|
|
457
675
|
chat_id=self.chat_id,
|
|
458
676
|
message_id=self.message_id
|
|
459
677
|
)
|
|
678
|
+
@hybrid_property
|
|
679
|
+
async def author_name(self):return await self.bot.get_name(self.chat_id)
|
|
680
|
+
@hybrid_property
|
|
681
|
+
async def name(self):return await self.bot.get_name(self.chat_id)
|
|
682
|
+
@hybrid_property
|
|
683
|
+
async def username(self):return await self.bot.get_username(self.chat_id)
|
|
684
|
+
@hybrid_property
|
|
685
|
+
async def author_info(self):return await self.bot.get_chat(self.chat_id)
|
|
460
686
|
class AuxData:
|
|
461
687
|
def __init__(self, data: dict):
|
|
462
688
|
self.start_id = data.get("start_id")
|
|
@@ -467,37 +693,346 @@ class InlineMessage:
|
|
|
467
693
|
def __init__(self, bot, raw_data: dict):
|
|
468
694
|
self.bot = bot
|
|
469
695
|
self.raw_data = raw_data
|
|
470
|
-
|
|
696
|
+
chat_id : str = raw_data.get("chat_id")
|
|
697
|
+
sender_id : str = raw_data.get("sender_id")
|
|
471
698
|
self.chat_id: str = raw_data.get("chat_id")
|
|
472
699
|
self.message_id: str = raw_data.get("message_id")
|
|
473
700
|
self.sender_id: str = raw_data.get("sender_id")
|
|
474
701
|
self.text: str = raw_data.get("text")
|
|
475
702
|
self.aux_data = AuxData(raw_data.get("aux_data", {})) if "aux_data" in raw_data else None
|
|
703
|
+
self.bot = bot
|
|
704
|
+
self.raw_data = raw_data or {}
|
|
705
|
+
self.object_guid = chat_id
|
|
706
|
+
self.author_guid = self.raw_data.get("sender_id", sender_id)
|
|
707
|
+
self.has_link = bool(re.search(r"(https?://[^\s]+ | www\.[^\s]+ | [a-zA-Z0-9.-]+\.(com|net|org|ir|edu|gov|info|biz|io|me|co) | t\.me/[^\s]+ | telegram\.me/[^\s]+ | @\w+ | \b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\b)", self.text))
|
|
708
|
+
self.sender_id: str = self.raw_data.get("sender_id", sender_id)
|
|
709
|
+
self.time: str = self.raw_data.get("time")
|
|
710
|
+
self.is_edited: bool = self.raw_data.get("is_edited", False)
|
|
711
|
+
self.sender_type: str = self.raw_data.get("sender_type")
|
|
712
|
+
self.args = []
|
|
713
|
+
self.is_command = bool(self.text and self.text.startswith("/"))
|
|
714
|
+
self.is_user = self.chat_id.startswith("b")
|
|
715
|
+
self.is_private = self.chat_id.startswith("b")
|
|
716
|
+
self.is_group = self.chat_id.startswith("g")
|
|
717
|
+
self.is_channel = self.chat_id.startswith("c")
|
|
718
|
+
self.reply_to_message_id: Optional[str] = self.raw_data.get("reply_to_message_id")
|
|
719
|
+
self.forwarded_from = ForwardedFrom(self.raw_data["forwarded_from"]) if "forwarded_from" in self.raw_data else None
|
|
720
|
+
self.file = File(self.raw_data["file"]) if "file" in self.raw_data else None
|
|
721
|
+
self.sticker = Sticker(self.raw_data["sticker"]) if "sticker" in self.raw_data else None
|
|
722
|
+
self.contact_message = ContactMessage(self.raw_data["contact_message"]) if "contact_message" in self.raw_data else None
|
|
723
|
+
self.aux_data = AuxData(self.raw_data["aux_data"]) if "aux_data" in self.raw_data else None
|
|
724
|
+
self.is_reply = self.reply_to_message_id is not None
|
|
725
|
+
self.has_media = any([self.file, self.sticker])
|
|
726
|
+
self.is_forwarded = self.forwarded_from is not None
|
|
727
|
+
self.is_text = bool(self.text and not self.has_media)
|
|
728
|
+
self.is_media = self.has_media
|
|
729
|
+
self.is_contact = self.contact_message is not None
|
|
730
|
+
self.has_any_media = any([self.file, self.sticker,])
|
|
731
|
+
self.edited_text = self.raw_data.get("edited_text") if self.is_edited else None
|
|
732
|
+
if self.file and self.file.file_name:
|
|
733
|
+
name = self.file.file_name.lower()
|
|
734
|
+
self.is_photo = name.endswith((".jpg", ".jpeg", ".png", ".gif", ".webp"))
|
|
735
|
+
self.is_video = name.endswith((".mp4", ".mov", ".avi", ".mkv", ".webm"))
|
|
736
|
+
self.is_audio = name.endswith((".mp3", ".wav", ".ogg", ".m4a", ".flac"))
|
|
737
|
+
self.is_voice = name.endswith((".ogg", ".m4a"))
|
|
738
|
+
self.is_document = name.endswith((".pdf", ".doc", ".docx", ".txt", ".xls", ".xlsx", ".ppt", ".pptx"))
|
|
739
|
+
self.is_archive = name.endswith((".zip", ".rar", ".7z", ".tar", ".gz"))
|
|
740
|
+
self.is_executable = name.endswith((".exe", ".msi", ".bat", ".sh"))
|
|
741
|
+
self.is_font = name.endswith((".ttf", ".otf", ".woff", ".woff2"))
|
|
742
|
+
|
|
476
743
|
|
|
477
|
-
|
|
744
|
+
@property
|
|
745
|
+
def session(self):
|
|
746
|
+
if self.chat_id not in self.bot.sessions:
|
|
747
|
+
self.bot.sessions[self.chat_id] = {}
|
|
748
|
+
return self.bot.sessions[self.chat_id]
|
|
749
|
+
|
|
750
|
+
def reply(self, text: str, delete_after: int = None, **kwargs):
|
|
751
|
+
async def _reply_async():
|
|
752
|
+
send_func = self.bot.send_message
|
|
753
|
+
if inspect.iscoroutinefunction(send_func):
|
|
754
|
+
msg = await send_func(
|
|
755
|
+
self.chat_id,
|
|
756
|
+
text,
|
|
757
|
+
reply_to_message_id=self.message_id,
|
|
758
|
+
delete_after=delete_after,
|
|
759
|
+
**kwargs
|
|
760
|
+
)
|
|
761
|
+
else:
|
|
762
|
+
msg = send_func(
|
|
763
|
+
self.chat_id,
|
|
764
|
+
text,
|
|
765
|
+
reply_to_message_id=self.message_id,
|
|
766
|
+
delete_after=delete_after,
|
|
767
|
+
**kwargs
|
|
768
|
+
)
|
|
769
|
+
class Pick:
|
|
770
|
+
def __init__(self, bot, chat_id, message_id):
|
|
771
|
+
self.bot = bot
|
|
772
|
+
self.chat_id = chat_id
|
|
773
|
+
self.message_id = message_id
|
|
774
|
+
|
|
775
|
+
def edit(self, new_text):
|
|
776
|
+
async def _edit():
|
|
777
|
+
func = self.bot.edit_message_text
|
|
778
|
+
if inspect.iscoroutinefunction(func):
|
|
779
|
+
await func(self.chat_id, self.message_id, new_text)
|
|
780
|
+
else:
|
|
781
|
+
func(self.chat_id, self.message_id, new_text)
|
|
782
|
+
|
|
783
|
+
try:
|
|
784
|
+
loop = asyncio.get_running_loop()
|
|
785
|
+
if loop.is_running():
|
|
786
|
+
return asyncio.create_task(_edit())
|
|
787
|
+
except RuntimeError:
|
|
788
|
+
return asyncio.run(_edit())
|
|
789
|
+
|
|
790
|
+
def delete(self):
|
|
791
|
+
async def _delete():
|
|
792
|
+
func = self.bot.delete_message
|
|
793
|
+
if inspect.iscoroutinefunction(func):
|
|
794
|
+
await func(self.chat_id, self.message_id)
|
|
795
|
+
else:
|
|
796
|
+
func(self.chat_id, self.message_id)
|
|
797
|
+
try:
|
|
798
|
+
loop = asyncio.get_running_loop()
|
|
799
|
+
if loop.is_running():
|
|
800
|
+
return asyncio.create_task(_delete())
|
|
801
|
+
except RuntimeError:
|
|
802
|
+
return asyncio.run(_delete())
|
|
803
|
+
chat_id = msg.get("chat_id") if isinstance(msg, dict) else getattr(msg, "chat_id", self.chat_id)
|
|
804
|
+
message_id = msg.get("message_id") if isinstance(msg, dict) else getattr(msg, "message_id", self.message_id)
|
|
805
|
+
return Pick(self.bot, chat_id, message_id)
|
|
806
|
+
try:
|
|
807
|
+
loop = asyncio.get_running_loop()
|
|
808
|
+
if loop.is_running():
|
|
809
|
+
return asyncio.create_task(_reply_async())
|
|
810
|
+
except RuntimeError:
|
|
811
|
+
return asyncio.run(_reply_async())
|
|
812
|
+
def answer(self, text: str, **kwargs):
|
|
478
813
|
return self.bot.send_message(
|
|
814
|
+
self.chat_id,
|
|
815
|
+
text,
|
|
816
|
+
reply_to_message_id=self.message_id,
|
|
817
|
+
**kwargs
|
|
818
|
+
)
|
|
819
|
+
|
|
820
|
+
|
|
821
|
+
def reply_poll(self, question: str, options: List[str], **kwargs) -> Dict[str, Any]:
|
|
822
|
+
return self.bot._post("sendPoll", {
|
|
823
|
+
"chat_id": self.chat_id,
|
|
824
|
+
"question": question,
|
|
825
|
+
"options": options,
|
|
826
|
+
"reply_to_message_id": self.message_id,
|
|
827
|
+
**kwargs
|
|
828
|
+
})
|
|
829
|
+
|
|
830
|
+
|
|
831
|
+
def reply_document(
|
|
832
|
+
self,
|
|
833
|
+
path: Optional[Union[str, Path]] = None,
|
|
834
|
+
file_id: Optional[str] = None,
|
|
835
|
+
text: Optional[str] = None,
|
|
836
|
+
chat_keypad: Optional[Dict[str, Any]] = None,
|
|
837
|
+
inline_keypad: Optional[Dict[str, Any]] = None,
|
|
838
|
+
chat_keypad_type: Optional[str] = "None",
|
|
839
|
+
disable_notification: bool = False
|
|
840
|
+
):
|
|
841
|
+
if chat_keypad and chat_keypad_type == "none":chat_keypad_type == "New"
|
|
842
|
+
return self.bot.send_document(
|
|
843
|
+
chat_id=self.chat_id,
|
|
844
|
+
path=path,
|
|
845
|
+
file_id=file_id,
|
|
846
|
+
text=text,
|
|
847
|
+
chat_keypad=chat_keypad,
|
|
848
|
+
inline_keypad=inline_keypad,
|
|
849
|
+
chat_keypad_type=chat_keypad_type,
|
|
850
|
+
disable_notification=disable_notification,
|
|
851
|
+
reply_to_message_id=self.message_id
|
|
852
|
+
)
|
|
853
|
+
def reply_file(
|
|
854
|
+
self,
|
|
855
|
+
path: Optional[Union[str, Path]] = None,
|
|
856
|
+
file_id: Optional[str] = None,
|
|
857
|
+
text: Optional[str] = None,
|
|
858
|
+
chat_keypad: Optional[Dict[str, Any]] = None,
|
|
859
|
+
inline_keypad: Optional[Dict[str, Any]] = None,
|
|
860
|
+
chat_keypad_type: Optional[str] = "None",
|
|
861
|
+
disable_notification: bool = False
|
|
862
|
+
):
|
|
863
|
+
if chat_keypad and chat_keypad_type == "none":
|
|
864
|
+
chat_keypad_type == "New"
|
|
865
|
+
|
|
866
|
+
return self.bot.send_document(
|
|
479
867
|
chat_id=self.chat_id,
|
|
868
|
+
path=path,
|
|
869
|
+
file_id=file_id,
|
|
480
870
|
text=text,
|
|
871
|
+
chat_keypad=chat_keypad,
|
|
872
|
+
inline_keypad=inline_keypad,
|
|
873
|
+
chat_keypad_type=chat_keypad_type,
|
|
874
|
+
disable_notification=disable_notification,
|
|
875
|
+
reply_to_message_id=self.message_id
|
|
876
|
+
)
|
|
877
|
+
|
|
878
|
+
def reply_image(
|
|
879
|
+
self,
|
|
880
|
+
path: Optional[Union[str, Path]] = None,
|
|
881
|
+
file_id: Optional[str] = None,
|
|
882
|
+
text: Optional[str] = None,
|
|
883
|
+
chat_keypad: Optional[Dict[str, Any]] = None,
|
|
884
|
+
inline_keypad: Optional[Dict[str, Any]] = None,
|
|
885
|
+
chat_keypad_type: Optional[str] = "None",
|
|
886
|
+
disable_notification: bool = False
|
|
887
|
+
):
|
|
888
|
+
if chat_keypad and chat_keypad_type == "none":
|
|
889
|
+
chat_keypad_type == "New"
|
|
890
|
+
return self.bot.send_image(
|
|
891
|
+
chat_id=self.chat_id,
|
|
892
|
+
path=path,
|
|
893
|
+
file_id=file_id,
|
|
894
|
+
text=text,
|
|
895
|
+
chat_keypad=chat_keypad,
|
|
896
|
+
inline_keypad=inline_keypad,
|
|
897
|
+
chat_keypad_type=chat_keypad_type,
|
|
898
|
+
disable_notification=disable_notification,
|
|
899
|
+
reply_to_message_id=self.message_id
|
|
900
|
+
)
|
|
901
|
+
|
|
902
|
+
def reply_music(
|
|
903
|
+
self,
|
|
904
|
+
path: Optional[Union[str, Path]] = None,
|
|
905
|
+
file_id: Optional[str] = None,
|
|
906
|
+
text: Optional[str] = None,
|
|
907
|
+
chat_keypad: Optional[Dict[str, Any]] = None,
|
|
908
|
+
inline_keypad: Optional[Dict[str, Any]] = None,
|
|
909
|
+
chat_keypad_type: Optional[str] = "None",
|
|
910
|
+
disable_notification: bool = False
|
|
911
|
+
):
|
|
912
|
+
if chat_keypad and chat_keypad_type == "none":
|
|
913
|
+
chat_keypad_type == "New"
|
|
914
|
+
return self.bot.send_music(
|
|
915
|
+
chat_id=self.chat_id,
|
|
916
|
+
path=path,
|
|
917
|
+
file_id=file_id,
|
|
918
|
+
text=text,
|
|
919
|
+
chat_keypad=chat_keypad,
|
|
920
|
+
inline_keypad=inline_keypad,
|
|
921
|
+
chat_keypad_type=chat_keypad_type,
|
|
922
|
+
disable_notification=disable_notification,
|
|
923
|
+
reply_to_message_id=self.message_id
|
|
924
|
+
)
|
|
925
|
+
|
|
926
|
+
def reply_voice(
|
|
927
|
+
self,
|
|
928
|
+
path: Optional[Union[str, Path]] = None,
|
|
929
|
+
file_id: Optional[str] = None,
|
|
930
|
+
text: Optional[str] = None,
|
|
931
|
+
chat_keypad: Optional[Dict[str, Any]] = None,
|
|
932
|
+
inline_keypad: Optional[Dict[str, Any]] = None,
|
|
933
|
+
chat_keypad_type: Optional[str] = "None",
|
|
934
|
+
disable_notification: bool = False
|
|
935
|
+
):
|
|
936
|
+
if chat_keypad and chat_keypad_type == "none":
|
|
937
|
+
chat_keypad_type == "New"
|
|
938
|
+
return self.bot.send_voice(
|
|
939
|
+
chat_id=self.chat_id,
|
|
940
|
+
path=path,
|
|
941
|
+
file_id=file_id,
|
|
942
|
+
text=text,
|
|
943
|
+
chat_keypad=chat_keypad,
|
|
944
|
+
inline_keypad=inline_keypad,
|
|
945
|
+
chat_keypad_type=chat_keypad_type,
|
|
946
|
+
disable_notification=disable_notification,
|
|
947
|
+
reply_to_message_id=self.message_id
|
|
948
|
+
)
|
|
949
|
+
|
|
950
|
+
def reply_gif(
|
|
951
|
+
self,
|
|
952
|
+
path: Optional[Union[str, Path]] = None,
|
|
953
|
+
file_id: Optional[str] = None,
|
|
954
|
+
text: Optional[str] = None,
|
|
955
|
+
chat_keypad: Optional[Dict[str, Any]] = None,
|
|
956
|
+
inline_keypad: Optional[Dict[str, Any]] = None,
|
|
957
|
+
chat_keypad_type: Optional[str] = "None",
|
|
958
|
+
disable_notification: bool = False
|
|
959
|
+
):
|
|
960
|
+
if chat_keypad and chat_keypad_type == "none":chat_keypad_type == "New"
|
|
961
|
+
return self.bot.send_gif(
|
|
962
|
+
chat_id=self.chat_id,
|
|
963
|
+
path=path,
|
|
964
|
+
file_id=file_id,
|
|
965
|
+
text=text,
|
|
966
|
+
chat_keypad=chat_keypad,
|
|
967
|
+
inline_keypad=inline_keypad,
|
|
968
|
+
chat_keypad_type=chat_keypad_type,
|
|
969
|
+
disable_notification=disable_notification,
|
|
970
|
+
reply_to_message_id=self.message_id
|
|
971
|
+
)
|
|
972
|
+
|
|
973
|
+
def reply_location(self, latitude: str, longitude: str, **kwargs) -> Dict[str, Any]:
|
|
974
|
+
return self.bot.send_location(
|
|
975
|
+
chat_id=self.chat_id,
|
|
976
|
+
latitude=latitude,
|
|
977
|
+
longitude=longitude,
|
|
481
978
|
reply_to_message_id=self.message_id,
|
|
482
979
|
**kwargs
|
|
483
980
|
)
|
|
484
|
-
|
|
981
|
+
|
|
982
|
+
def reply_contact(self, first_name: str, last_name: str, phone_number: str, **kwargs) -> Dict[str, Any]:
|
|
983
|
+
return self.bot.send_contact(
|
|
984
|
+
chat_id=self.chat_id,
|
|
985
|
+
first_name=first_name,
|
|
986
|
+
last_name=last_name,
|
|
987
|
+
phone_number=phone_number,
|
|
988
|
+
reply_to_message_id=self.message_id,
|
|
989
|
+
**kwargs
|
|
990
|
+
)
|
|
991
|
+
|
|
992
|
+
def reply_keypad(self, text: str, keypad: Dict[str, Any], **kwargs) -> Dict[str, Any]:
|
|
485
993
|
return self.bot.send_message(
|
|
486
|
-
self.chat_id,
|
|
487
|
-
text,
|
|
994
|
+
chat_id=self.chat_id,
|
|
995
|
+
text=text,
|
|
996
|
+
chat_keypad_type="New",
|
|
997
|
+
chat_keypad=keypad,
|
|
998
|
+
reply_to_message_id=self.message_id,
|
|
999
|
+
**kwargs
|
|
1000
|
+
)
|
|
1001
|
+
|
|
1002
|
+
def reply_inline(self, text: str, inline_keypad: Dict[str, Any], **kwargs) -> Dict[str, Any]:
|
|
1003
|
+
return self.bot.send_message(
|
|
1004
|
+
chat_id=self.chat_id,
|
|
1005
|
+
text=text,
|
|
1006
|
+
inline_keypad=inline_keypad,
|
|
488
1007
|
reply_to_message_id=self.message_id,
|
|
489
1008
|
**kwargs
|
|
490
1009
|
)
|
|
491
1010
|
|
|
492
|
-
def
|
|
1011
|
+
def reply_sticker(self, sticker_id: str, **kwargs) -> Dict[str, Any]:
|
|
1012
|
+
return self.bot._post("sendSticker", {
|
|
1013
|
+
"chat_id": self.chat_id,
|
|
1014
|
+
"sticker_id": sticker_id,
|
|
1015
|
+
"reply_to_message_id": self.message_id,
|
|
1016
|
+
**kwargs
|
|
1017
|
+
})
|
|
1018
|
+
|
|
1019
|
+
def edit(self, new_text: str) -> Dict[str, Any]:
|
|
493
1020
|
return self.bot.edit_message_text(
|
|
494
1021
|
chat_id=self.chat_id,
|
|
495
1022
|
message_id=self.message_id,
|
|
496
1023
|
text=new_text
|
|
497
1024
|
)
|
|
498
1025
|
|
|
499
|
-
def delete(self):
|
|
1026
|
+
def delete(self) -> Dict[str, Any]:
|
|
500
1027
|
return self.bot.delete_message(
|
|
501
1028
|
chat_id=self.chat_id,
|
|
502
1029
|
message_id=self.message_id
|
|
503
|
-
)
|
|
1030
|
+
)
|
|
1031
|
+
@hybrid_property
|
|
1032
|
+
async def author_name(self):return await self.bot.get_name(self.chat_id)
|
|
1033
|
+
@hybrid_property
|
|
1034
|
+
async def name(self):return await self.bot.get_name(self.chat_id)
|
|
1035
|
+
@hybrid_property
|
|
1036
|
+
async def username(self):return await self.bot.get_username(self.chat_id)
|
|
1037
|
+
@hybrid_property
|
|
1038
|
+
async def author_info(self):return await self.bot.get_chat(self.chat_id)
|