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/update.py CHANGED
@@ -1,5 +1,68 @@
1
- from typing import Any, Dict, List,Optional
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.info = {attr: value for attr, value in vars(self).items()}
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
- def reply(self, text: str, **kwargs):
236
- return self.bot.send_message(
237
- self.chat_id,
238
- text,
239
- reply_to_message_id=self.message_id,
240
- **kwargs
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(self, question: str, options: List[str], **kwargs) -> Dict[str, Any]:
251
- return self.bot._post("sendPoll", {
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
- "reply_to_message_id": self.message_id,
256
- **kwargs
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
- def reply(self, text: str, **kwargs):
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
- def answer(self, text: str, **kwargs):
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 edit(self, new_text: str):
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)