Rubka 7.1.9__py3-none-any.whl → 7.1.10__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/context.py +30 -0
- rubka/update.py +210 -18
- {rubka-7.1.9.dist-info → rubka-7.1.10.dist-info}/METADATA +1 -1
- {rubka-7.1.9.dist-info → rubka-7.1.10.dist-info}/RECORD +7 -7
- {rubka-7.1.9.dist-info → rubka-7.1.10.dist-info}/WHEEL +0 -0
- {rubka-7.1.9.dist-info → rubka-7.1.10.dist-info}/entry_points.txt +0 -0
- {rubka-7.1.9.dist-info → rubka-7.1.10.dist-info}/top_level.txt +0 -0
rubka/context.py
CHANGED
|
@@ -291,6 +291,36 @@ class Message:
|
|
|
291
291
|
self.is_archive = None
|
|
292
292
|
self.is_executable = None
|
|
293
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
|
+
])
|
|
294
324
|
self.sender_id: str = self.raw_data.get("sender_id", sender_id)
|
|
295
325
|
self.time: str = self.raw_data.get("time")
|
|
296
326
|
self.is_edited: bool = self.raw_data.get("is_edited", False)
|
rubka/update.py
CHANGED
|
@@ -1,8 +1,68 @@
|
|
|
1
|
-
from typing import Any, Dict, List,Optional
|
|
2
1
|
from typing import Union
|
|
3
2
|
from pathlib import Path
|
|
3
|
+
from typing import List, Optional, Dict, Any, Literal, Callable, Union,Set
|
|
4
4
|
import re,inspect
|
|
5
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))
|
|
6
66
|
class File:
|
|
7
67
|
def __init__(self, data: dict):
|
|
8
68
|
self.file_id: str = data.get("file_id")
|
|
@@ -215,10 +275,51 @@ class Message:
|
|
|
215
275
|
self.author_guid = self.raw_data.get("sender_id", sender_id)
|
|
216
276
|
self.message_id: str = self.raw_data.get("message_id", message_id)
|
|
217
277
|
self.text: str = self.raw_data.get("text", text)
|
|
218
|
-
self.has_link =
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
))
|
|
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.meta_parts = self.metadata.get("meta_data_parts", [])
|
|
296
|
+
self.has_metadata = bool(self.meta_parts)
|
|
297
|
+
self.meta_types = [part.get("type") for part in self.meta_parts] if self.has_metadata else []
|
|
298
|
+
self.is_bold = "Bold" in self.meta_types
|
|
299
|
+
self.is_italic = "Italic" in self.meta_types
|
|
300
|
+
self.is_strike = "Strike" in self.meta_types
|
|
301
|
+
self.is_underline = "Underline" in self.meta_types
|
|
302
|
+
self.is_quote = "Quote" in self.meta_types
|
|
303
|
+
self.is_spoiler = "Spoiler" in self.meta_types
|
|
304
|
+
self.is_pre = "Pre" in self.meta_types
|
|
305
|
+
self.is_mono = "Mono" in self.meta_types
|
|
306
|
+
self.is_link_meta = "Link" in self.meta_types
|
|
307
|
+
self.meta_links = [part.get("link_url") for part in self.meta_parts if part.get("type") == "Link"]
|
|
308
|
+
self.meta_link_positions = [
|
|
309
|
+
{"from": part.get("from_index"), "length": part.get("length"), "url": part.get("link_url")}
|
|
310
|
+
for part in self.meta_parts if part.get("type") == "Link"
|
|
311
|
+
]
|
|
312
|
+
self.has_link = contains_link_or_mention(self.text) or self.is_link_meta
|
|
313
|
+
self.is_formatted = any([
|
|
314
|
+
self.is_bold,
|
|
315
|
+
self.is_italic,
|
|
316
|
+
self.is_strike,
|
|
317
|
+
self.is_underline,
|
|
318
|
+
self.is_quote,
|
|
319
|
+
self.is_spoiler,
|
|
320
|
+
self.is_pre,
|
|
321
|
+
self.is_mono
|
|
322
|
+
])
|
|
222
323
|
self.sender_id: str = self.raw_data.get("sender_id", sender_id)
|
|
223
324
|
self.time: str = self.raw_data.get("time")
|
|
224
325
|
self.is_edited: bool = self.raw_data.get("is_edited", False)
|
|
@@ -336,14 +437,40 @@ class Message:
|
|
|
336
437
|
)
|
|
337
438
|
|
|
338
439
|
|
|
339
|
-
def reply_poll(
|
|
340
|
-
|
|
440
|
+
def reply_poll(
|
|
441
|
+
self,
|
|
442
|
+
question: str,
|
|
443
|
+
options: List[str],
|
|
444
|
+
type: Literal['Regular', 'Quiz'] = "Regular",
|
|
445
|
+
allows_multiple_answers: bool = False,
|
|
446
|
+
is_anonymous: bool = True,
|
|
447
|
+
correct_option_index: Optional[int] = None,
|
|
448
|
+
hint: Optional[str] = None,
|
|
449
|
+
reply_to_message_id: Optional[str] = None,
|
|
450
|
+
disable_notification: bool = False,
|
|
451
|
+
show_results: bool = False,
|
|
452
|
+
inline_keypad: Optional[Dict[str, Any]] = None,
|
|
453
|
+
chat_keypad: Optional[Dict[str, Any]] = None,
|
|
454
|
+
chat_keypad_type: Optional[Literal['New', 'Remove', 'None']] = None,
|
|
455
|
+
**kwargs
|
|
456
|
+
) -> dict:
|
|
457
|
+
payload = {
|
|
341
458
|
"chat_id": self.chat_id,
|
|
342
459
|
"question": question,
|
|
343
460
|
"options": options,
|
|
344
|
-
"
|
|
345
|
-
|
|
346
|
-
|
|
461
|
+
"type": type,
|
|
462
|
+
"allows_multiple_answers": allows_multiple_answers,
|
|
463
|
+
"is_anonymous": is_anonymous,
|
|
464
|
+
"correct_option_index": correct_option_index,
|
|
465
|
+
"hint": hint,
|
|
466
|
+
"reply_to_message_id": self.message_id if not reply_to_message_id else reply_to_message_id,
|
|
467
|
+
"disable_notification": disable_notification,
|
|
468
|
+
"show_results": show_results,
|
|
469
|
+
"inline_keypad": inline_keypad,
|
|
470
|
+
"chat_keypad": chat_keypad,
|
|
471
|
+
"chat_keypad_type": chat_keypad_type,
|
|
472
|
+
}
|
|
473
|
+
return self.bot._post("sendPoll", {key: value for key, value in payload.items() if value is not None}, **kwargs)
|
|
347
474
|
|
|
348
475
|
|
|
349
476
|
def reply_document(
|
|
@@ -617,13 +744,69 @@ class InlineMessage:
|
|
|
617
744
|
if self.chat_id not in self.bot.sessions:
|
|
618
745
|
self.bot.sessions[self.chat_id] = {}
|
|
619
746
|
return self.bot.sessions[self.chat_id]
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
747
|
+
|
|
748
|
+
def reply(self, text: str, delete_after: int = None, **kwargs):
|
|
749
|
+
async def _reply_async():
|
|
750
|
+
send_func = self.bot.send_message
|
|
751
|
+
if inspect.iscoroutinefunction(send_func):
|
|
752
|
+
msg = await send_func(
|
|
753
|
+
self.chat_id,
|
|
754
|
+
text,
|
|
755
|
+
reply_to_message_id=self.message_id,
|
|
756
|
+
delete_after=delete_after,
|
|
757
|
+
**kwargs
|
|
758
|
+
)
|
|
759
|
+
else:
|
|
760
|
+
msg = send_func(
|
|
761
|
+
self.chat_id,
|
|
762
|
+
text,
|
|
763
|
+
reply_to_message_id=self.message_id,
|
|
764
|
+
delete_after=delete_after,
|
|
765
|
+
**kwargs
|
|
766
|
+
)
|
|
767
|
+
class Pick:
|
|
768
|
+
def __init__(self, bot, chat_id, message_id):
|
|
769
|
+
self.bot = bot
|
|
770
|
+
self.chat_id = chat_id
|
|
771
|
+
self.message_id = message_id
|
|
772
|
+
|
|
773
|
+
def edit(self, new_text):
|
|
774
|
+
async def _edit():
|
|
775
|
+
func = self.bot.edit_message_text
|
|
776
|
+
if inspect.iscoroutinefunction(func):
|
|
777
|
+
await func(self.chat_id, self.message_id, new_text)
|
|
778
|
+
else:
|
|
779
|
+
func(self.chat_id, self.message_id, new_text)
|
|
780
|
+
|
|
781
|
+
try:
|
|
782
|
+
loop = asyncio.get_running_loop()
|
|
783
|
+
if loop.is_running():
|
|
784
|
+
return asyncio.create_task(_edit())
|
|
785
|
+
except RuntimeError:
|
|
786
|
+
return asyncio.run(_edit())
|
|
787
|
+
|
|
788
|
+
def delete(self):
|
|
789
|
+
async def _delete():
|
|
790
|
+
func = self.bot.delete_message
|
|
791
|
+
if inspect.iscoroutinefunction(func):
|
|
792
|
+
await func(self.chat_id, self.message_id)
|
|
793
|
+
else:
|
|
794
|
+
func(self.chat_id, self.message_id)
|
|
795
|
+
try:
|
|
796
|
+
loop = asyncio.get_running_loop()
|
|
797
|
+
if loop.is_running():
|
|
798
|
+
return asyncio.create_task(_delete())
|
|
799
|
+
except RuntimeError:
|
|
800
|
+
return asyncio.run(_delete())
|
|
801
|
+
chat_id = msg.get("chat_id") if isinstance(msg, dict) else getattr(msg, "chat_id", self.chat_id)
|
|
802
|
+
message_id = msg.get("message_id") if isinstance(msg, dict) else getattr(msg, "message_id", self.message_id)
|
|
803
|
+
return Pick(self.bot, chat_id, message_id)
|
|
804
|
+
try:
|
|
805
|
+
loop = asyncio.get_running_loop()
|
|
806
|
+
if loop.is_running():
|
|
807
|
+
return asyncio.create_task(_reply_async())
|
|
808
|
+
except RuntimeError:
|
|
809
|
+
return asyncio.run(_reply_async())
|
|
627
810
|
def answer(self, text: str, **kwargs):
|
|
628
811
|
return self.bot.send_message(
|
|
629
812
|
self.chat_id,
|
|
@@ -631,6 +814,7 @@ class InlineMessage:
|
|
|
631
814
|
reply_to_message_id=self.message_id,
|
|
632
815
|
**kwargs
|
|
633
816
|
)
|
|
817
|
+
|
|
634
818
|
|
|
635
819
|
def reply_poll(self, question: str, options: List[str], **kwargs) -> Dict[str, Any]:
|
|
636
820
|
return self.bot._post("sendPoll", {
|
|
@@ -841,4 +1025,12 @@ class InlineMessage:
|
|
|
841
1025
|
return self.bot.delete_message(
|
|
842
1026
|
chat_id=self.chat_id,
|
|
843
1027
|
message_id=self.message_id
|
|
844
|
-
)
|
|
1028
|
+
)
|
|
1029
|
+
@hybrid_property
|
|
1030
|
+
async def author_name(self):return await self.bot.get_name(self.chat_id)
|
|
1031
|
+
@hybrid_property
|
|
1032
|
+
async def name(self):return await self.bot.get_name(self.chat_id)
|
|
1033
|
+
@hybrid_property
|
|
1034
|
+
async def username(self):return await self.bot.get_username(self.chat_id)
|
|
1035
|
+
@hybrid_property
|
|
1036
|
+
async def author_info(self):return await self.bot.get_chat(self.chat_id)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: Rubka
|
|
3
|
-
Version: 7.1.
|
|
3
|
+
Version: 7.1.10
|
|
4
4
|
Summary: Rubika: A Python library for interacting with the Rubika Bot API. This library provides an easy-to-use interface to send messages, polls, stickers, media files, manage groups and channels, handle inline keyboards, and implement advanced bot features like subscription management, user authentication, and message handling. Ideal for developers looking to automate and extend their Rubika bots with Python.
|
|
5
5
|
Home-page: https://github.com/Mahdy-Ahmadi/Rubka
|
|
6
6
|
Download-URL: https://github.com/Mahdy-Ahmadi/rubka/archive/refs/tags/v6.6.4.zip
|
|
@@ -3,7 +3,7 @@ rubka/api.py,sha256=wa1gQj7NDc7QEbmNNRz-TIOdVqfMWFC362tndRKdqig,68449
|
|
|
3
3
|
rubka/asynco.py,sha256=uuqhWLPrhPVIlb4l7umwryYFD_x2tDFfcYxo-Yb49Uc,112784
|
|
4
4
|
rubka/button.py,sha256=woSzZVd5MtTqOrP-YgkH5b0GS9y4DuKBsFSc9-KuLnk,13320
|
|
5
5
|
rubka/config.py,sha256=Bck59xkOiqioLv0GkQ1qPGnBXVctz1hKk6LT4h2EPx0,78
|
|
6
|
-
rubka/context.py,sha256=
|
|
6
|
+
rubka/context.py,sha256=mYyYybwe_vqhp5ublxByYTmFUbsemXWiK3huRBO8V98,42389
|
|
7
7
|
rubka/decorators.py,sha256=hGwUoE4q2ImrunJIGJ_kzGYYxQf1ueE0isadqraKEts,1157
|
|
8
8
|
rubka/exceptions.py,sha256=DDOGIHEMoliHNW5E7C_s38WZgqqMBv9812fcJGvj7TY,1173
|
|
9
9
|
rubka/filters.py,sha256=DY1bdkpRKIiLtVcy6X3hOnlGPcVOK4HFb3QgmaPx6Oo,12116
|
|
@@ -14,7 +14,7 @@ rubka/keypad.py,sha256=yGsNt8W5HtUFBzVF1m_p7GySlu1hwIcSvXZ4BTdrlvg,9558
|
|
|
14
14
|
rubka/logger.py,sha256=J2I6NiK1z32lrAzC4H1Et6WPMBXxXGCVUsW4jgcAofs,289
|
|
15
15
|
rubka/rubino.py,sha256=HOILsm2zOIRe9EW1hxhLinhjwE_TvFrOAxBsg9T_L5E,61701
|
|
16
16
|
rubka/tv.py,sha256=rBoyCadCH3I3YqQGrQYv_dLtTg1I63AzVf1orn-hbko,5724
|
|
17
|
-
rubka/update.py,sha256
|
|
17
|
+
rubka/update.py,sha256=ky4FvHMAnAX6VAZCQ1xsjwlvCVTHubmaoWsTOrIefEM,42347
|
|
18
18
|
rubka/utils.py,sha256=XUQUZxQt9J2f0X5hmAH_MH1kibTAfdT1T4AaBkBhBBs,148
|
|
19
19
|
rubka/adaptorrubka/__init__.py,sha256=6o2tCXnVeES7nx-LjnzsuMqjKcWIm9qwKficLE54s-U,83
|
|
20
20
|
rubka/adaptorrubka/enums.py,sha256=cyiakExmZi-QQpYuf_A93HQvfZVmyG_0uVuvTTNT5To,1053
|
|
@@ -37,8 +37,8 @@ rubka/adaptorrubka/types/socket/message.py,sha256=0WgLMZh4eow8Zn7AiSX4C3GZjQTkIg
|
|
|
37
37
|
rubka/adaptorrubka/utils/__init__.py,sha256=OgCFkXdNFh379quNwIVOAWY2NP5cIOxU5gDRRALTk4o,54
|
|
38
38
|
rubka/adaptorrubka/utils/configs.py,sha256=nMUEOJh1NqDJsf9W9PurkN_DLYjO6kKPMm923i4Jj_A,492
|
|
39
39
|
rubka/adaptorrubka/utils/utils.py,sha256=5-LioLNYX_TIbQGDeT50j7Sg9nAWH2LJUUs-iEXpsUY,8816
|
|
40
|
-
rubka-7.1.
|
|
41
|
-
rubka-7.1.
|
|
42
|
-
rubka-7.1.
|
|
43
|
-
rubka-7.1.
|
|
44
|
-
rubka-7.1.
|
|
40
|
+
rubka-7.1.10.dist-info/METADATA,sha256=iNaufLcqGhGb6uLiUsOD4dGUQUtd9VusDZgJDLjK8BI,34645
|
|
41
|
+
rubka-7.1.10.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
42
|
+
rubka-7.1.10.dist-info/entry_points.txt,sha256=4aESuUmuUOALMUy7Kucv_Gb5YlqhsJmTmdXLlZU9sJ0,46
|
|
43
|
+
rubka-7.1.10.dist-info/top_level.txt,sha256=vy2A4lot11cRMdQS-F4HDCIXL3JK8RKfu7HMDkezJW4,6
|
|
44
|
+
rubka-7.1.10.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|