Rubka 6.8.5__tar.gz → 7.1.1__tar.gz
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.
Potentially problematic release.
This version of Rubka might be problematic. Click here for more details.
- {rubka-6.8.5 → rubka-7.1.1}/PKG-INFO +2 -1
- {rubka-6.8.5 → rubka-7.1.1}/Rubka.egg-info/PKG-INFO +2 -1
- {rubka-6.8.5 → rubka-7.1.1}/Rubka.egg-info/requires.txt +1 -0
- {rubka-6.8.5 → rubka-7.1.1}/rubka/api.py +2 -1
- {rubka-6.8.5 → rubka-7.1.1}/rubka/asynco.py +152 -12
- {rubka-6.8.5 → rubka-7.1.1}/rubka/context.py +63 -19
- {rubka-6.8.5 → rubka-7.1.1}/rubka/update.py +64 -10
- {rubka-6.8.5 → rubka-7.1.1}/setup.py +2 -1
- {rubka-6.8.5 → rubka-7.1.1}/README.md +0 -0
- {rubka-6.8.5 → rubka-7.1.1}/Rubka.egg-info/SOURCES.txt +0 -0
- {rubka-6.8.5 → rubka-7.1.1}/Rubka.egg-info/dependency_links.txt +0 -0
- {rubka-6.8.5 → rubka-7.1.1}/Rubka.egg-info/entry_points.txt +0 -0
- {rubka-6.8.5 → rubka-7.1.1}/Rubka.egg-info/not-zip-safe +0 -0
- {rubka-6.8.5 → rubka-7.1.1}/Rubka.egg-info/top_level.txt +0 -0
- {rubka-6.8.5 → rubka-7.1.1}/rubka/__init__.py +0 -0
- {rubka-6.8.5 → rubka-7.1.1}/rubka/adaptorrubka/__init__.py +0 -0
- {rubka-6.8.5 → rubka-7.1.1}/rubka/adaptorrubka/client/__init__.py +0 -0
- {rubka-6.8.5 → rubka-7.1.1}/rubka/adaptorrubka/client/client.py +0 -0
- {rubka-6.8.5 → rubka-7.1.1}/rubka/adaptorrubka/crypto/__init__.py +0 -0
- {rubka-6.8.5 → rubka-7.1.1}/rubka/adaptorrubka/crypto/crypto.py +0 -0
- {rubka-6.8.5 → rubka-7.1.1}/rubka/adaptorrubka/enums.py +0 -0
- {rubka-6.8.5 → rubka-7.1.1}/rubka/adaptorrubka/exceptions.py +0 -0
- {rubka-6.8.5 → rubka-7.1.1}/rubka/adaptorrubka/methods/__init__.py +0 -0
- {rubka-6.8.5 → rubka-7.1.1}/rubka/adaptorrubka/methods/methods.py +0 -0
- {rubka-6.8.5 → rubka-7.1.1}/rubka/adaptorrubka/network/__init__.py +0 -0
- {rubka-6.8.5 → rubka-7.1.1}/rubka/adaptorrubka/network/helper.py +0 -0
- {rubka-6.8.5 → rubka-7.1.1}/rubka/adaptorrubka/network/network.py +0 -0
- {rubka-6.8.5 → rubka-7.1.1}/rubka/adaptorrubka/network/socket.py +0 -0
- {rubka-6.8.5 → rubka-7.1.1}/rubka/adaptorrubka/sessions/__init__.py +0 -0
- {rubka-6.8.5 → rubka-7.1.1}/rubka/adaptorrubka/sessions/sessions.py +0 -0
- {rubka-6.8.5 → rubka-7.1.1}/rubka/adaptorrubka/types/__init__.py +0 -0
- {rubka-6.8.5 → rubka-7.1.1}/rubka/adaptorrubka/types/socket/__init__.py +0 -0
- {rubka-6.8.5 → rubka-7.1.1}/rubka/adaptorrubka/types/socket/message.py +0 -0
- {rubka-6.8.5 → rubka-7.1.1}/rubka/adaptorrubka/utils/__init__.py +0 -0
- {rubka-6.8.5 → rubka-7.1.1}/rubka/adaptorrubka/utils/configs.py +0 -0
- {rubka-6.8.5 → rubka-7.1.1}/rubka/adaptorrubka/utils/utils.py +0 -0
- {rubka-6.8.5 → rubka-7.1.1}/rubka/button.py +0 -0
- {rubka-6.8.5 → rubka-7.1.1}/rubka/config.py +0 -0
- {rubka-6.8.5 → rubka-7.1.1}/rubka/decorators.py +0 -0
- {rubka-6.8.5 → rubka-7.1.1}/rubka/exceptions.py +0 -0
- {rubka-6.8.5 → rubka-7.1.1}/rubka/filters.py +0 -0
- {rubka-6.8.5 → rubka-7.1.1}/rubka/helpers.py +0 -0
- {rubka-6.8.5 → rubka-7.1.1}/rubka/jobs.py +0 -0
- {rubka-6.8.5 → rubka-7.1.1}/rubka/keyboards.py +0 -0
- {rubka-6.8.5 → rubka-7.1.1}/rubka/keypad.py +0 -0
- {rubka-6.8.5 → rubka-7.1.1}/rubka/logger.py +0 -0
- {rubka-6.8.5 → rubka-7.1.1}/rubka/rubino.py +0 -0
- {rubka-6.8.5 → rubka-7.1.1}/rubka/tv.py +0 -0
- {rubka-6.8.5 → rubka-7.1.1}/rubka/utils.py +0 -0
- {rubka-6.8.5 → rubka-7.1.1}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: Rubka
|
|
3
|
-
Version:
|
|
3
|
+
Version: 7.1.1
|
|
4
4
|
Summary: rubika A Python library for interacting with Rubika Bot API.
|
|
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
|
|
@@ -31,6 +31,7 @@ Requires-Dist: Pillow
|
|
|
31
31
|
Requires-Dist: websocket-client
|
|
32
32
|
Requires-Dist: pycryptodome
|
|
33
33
|
Requires-Dist: aiohttp
|
|
34
|
+
Requires-Dist: httpx
|
|
34
35
|
Requires-Dist: tqdm
|
|
35
36
|
Requires-Dist: mutagen
|
|
36
37
|
Requires-Dist: filetype
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: Rubka
|
|
3
|
-
Version:
|
|
3
|
+
Version: 7.1.1
|
|
4
4
|
Summary: rubika A Python library for interacting with Rubika Bot API.
|
|
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
|
|
@@ -31,6 +31,7 @@ Requires-Dist: Pillow
|
|
|
31
31
|
Requires-Dist: websocket-client
|
|
32
32
|
Requires-Dist: pycryptodome
|
|
33
33
|
Requires-Dist: aiohttp
|
|
34
|
+
Requires-Dist: httpx
|
|
34
35
|
Requires-Dist: tqdm
|
|
35
36
|
Requires-Dist: mutagen
|
|
36
37
|
Requires-Dist: filetype
|
|
@@ -1016,7 +1016,8 @@ class Robot:
|
|
|
1016
1016
|
inline_keypad: Optional[Dict[str, Any]] = None,
|
|
1017
1017
|
disable_notification: bool = False,
|
|
1018
1018
|
reply_to_message_id: Optional[str] = None,
|
|
1019
|
-
chat_keypad_type: Optional[Literal["New", "Removed"]] = None
|
|
1019
|
+
chat_keypad_type: Optional[Literal["New", "Removed"]] = None,
|
|
1020
|
+
delete_after = None
|
|
1020
1021
|
) -> Dict[str, Any]:
|
|
1021
1022
|
"""
|
|
1022
1023
|
Send a text message to a chat.
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import asyncio,aiohttp,aiofiles,time,datetime,json,tempfile,os,sys,subprocess,mimetypes,time, hashlib
|
|
1
|
+
import asyncio,aiohttp,aiofiles,time,datetime,json,tempfile,os,sys,subprocess,mimetypes,time, hashlib,sqlite3
|
|
2
2
|
from typing import List, Optional, Dict, Any, Literal, Callable, Union,Set
|
|
3
3
|
from collections import OrderedDict
|
|
4
4
|
from .exceptions import APIRequestError,raise_for_status,InvalidAccessError,InvalidInputError,TooRequestError,InvalidTokenError
|
|
@@ -19,7 +19,6 @@ from tqdm import tqdm
|
|
|
19
19
|
API_URL = "https://botapi.rubika.ir/v3"
|
|
20
20
|
|
|
21
21
|
def install_package(package_name: str) -> bool:
|
|
22
|
-
"""Installs a package using pip."""
|
|
23
22
|
try:
|
|
24
23
|
subprocess.check_call([sys.executable, "-m", "pip", "install", package_name], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
|
|
25
24
|
return True
|
|
@@ -27,7 +26,6 @@ def install_package(package_name: str) -> bool:
|
|
|
27
26
|
return False
|
|
28
27
|
|
|
29
28
|
def get_importlib_metadata():
|
|
30
|
-
"""Dynamically imports and returns metadata functions from importlib."""
|
|
31
29
|
try:
|
|
32
30
|
from importlib.metadata import version, PackageNotFoundError
|
|
33
31
|
return version, PackageNotFoundError
|
|
@@ -43,7 +41,6 @@ def get_importlib_metadata():
|
|
|
43
41
|
version, PackageNotFoundError = get_importlib_metadata()
|
|
44
42
|
|
|
45
43
|
def get_installed_version(package_name: str) -> Optional[str]:
|
|
46
|
-
"""Gets the installed version of a package."""
|
|
47
44
|
if version is None:
|
|
48
45
|
return "unknown"
|
|
49
46
|
try:
|
|
@@ -52,7 +49,6 @@ def get_installed_version(package_name: str) -> Optional[str]:
|
|
|
52
49
|
return None
|
|
53
50
|
|
|
54
51
|
async def get_latest_version(package_name: str) -> Optional[str]:
|
|
55
|
-
"""Fetches the latest version of a package from PyPI asynchronously."""
|
|
56
52
|
url = f"https://pypi.org/pypi/{package_name}/json"
|
|
57
53
|
try:
|
|
58
54
|
async with aiohttp.ClientSession() as session:
|
|
@@ -64,7 +60,6 @@ async def get_latest_version(package_name: str) -> Optional[str]:
|
|
|
64
60
|
return None
|
|
65
61
|
|
|
66
62
|
async def check_rubka_version():
|
|
67
|
-
"""Checks for outdated 'rubka' package and warns the user."""
|
|
68
63
|
package_name = "rubka"
|
|
69
64
|
installed_version = get_installed_version(package_name)
|
|
70
65
|
if installed_version is None:
|
|
@@ -87,7 +82,6 @@ async def check_rubka_version():
|
|
|
87
82
|
|
|
88
83
|
|
|
89
84
|
def show_last_six_words(text: str) -> str:
|
|
90
|
-
"""Returns the last 6 characters of a stripped string."""
|
|
91
85
|
text = text.strip()
|
|
92
86
|
return text[-6:]
|
|
93
87
|
class AttrDict(dict):
|
|
@@ -170,12 +164,16 @@ max_cache_size and max_msg_age help manage duplicate message processing efficien
|
|
|
170
164
|
self._max_cache_size = max_cache_size
|
|
171
165
|
self._callback_handlers: List[dict] = []
|
|
172
166
|
self._edited_message_handlers = []
|
|
167
|
+
self._message_saver_enabled = False
|
|
168
|
+
self._max_messages = None
|
|
169
|
+
self._db_path = os.path.join(os.getcwd(), "RubkaSaveMessage.db")
|
|
170
|
+
self._ensure_db()
|
|
173
171
|
self._message_handlers: List[dict] = []
|
|
174
172
|
|
|
175
173
|
logger.info(f"Initialized RubikaBot with token: {token[:8]}***")
|
|
176
174
|
async def _get_session(self) -> aiohttp.ClientSession:
|
|
177
175
|
if self._aiohttp_session is None or self._aiohttp_session.closed:
|
|
178
|
-
connector = aiohttp.TCPConnector(limit=100, ssl=False)
|
|
176
|
+
connector = aiohttp.TCPConnector(limit=100, ssl=False)
|
|
179
177
|
timeout = aiohttp.ClientTimeout(total=self.timeout)
|
|
180
178
|
self._aiohttp_session = aiohttp.ClientSession(connector=connector, timeout=timeout)
|
|
181
179
|
return self._aiohttp_session
|
|
@@ -251,15 +249,157 @@ max_cache_size and max_msg_age help manage duplicate message processing efficien
|
|
|
251
249
|
raw = f"{message_id}:{update_type}:{msg_data.get('text','')}:{msg_data.get('author_guid','')}"
|
|
252
250
|
return hashlib.sha1(raw.encode()).hexdigest()
|
|
253
251
|
async def get_me(self) -> Dict[str, Any]:
|
|
254
|
-
"""Get info about the bot itself."""
|
|
255
252
|
return await self._post("getMe", {})
|
|
256
253
|
async def geteToken(self):
|
|
257
|
-
"""Check if the bot token is valid."""
|
|
258
254
|
if (await self.get_me())['status'] != "OK":
|
|
259
255
|
raise InvalidTokenError("The provided bot token is invalid or expired.")
|
|
260
256
|
from typing import Callable, Any, Optional, List
|
|
261
257
|
|
|
262
258
|
|
|
259
|
+
#save message database __________________________
|
|
260
|
+
|
|
261
|
+
def _ensure_db(self):
|
|
262
|
+
conn = sqlite3.connect(self._db_path)
|
|
263
|
+
cur = conn.cursor()
|
|
264
|
+
cur.execute("""
|
|
265
|
+
CREATE TABLE IF NOT EXISTS messages (
|
|
266
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
267
|
+
chat_id TEXT NOT NULL,
|
|
268
|
+
message_id TEXT NOT NULL,
|
|
269
|
+
sender_id TEXT,
|
|
270
|
+
text TEXT,
|
|
271
|
+
raw_data TEXT,
|
|
272
|
+
time TEXT,
|
|
273
|
+
saved_at INTEGER
|
|
274
|
+
);
|
|
275
|
+
""")
|
|
276
|
+
cur.execute("CREATE UNIQUE INDEX IF NOT EXISTS idx_chat_message ON messages(chat_id, message_id);")
|
|
277
|
+
conn.commit()
|
|
278
|
+
conn.close()
|
|
279
|
+
|
|
280
|
+
def _insert_message(self, record: dict):
|
|
281
|
+
conn = sqlite3.connect(self._db_path)
|
|
282
|
+
cur = conn.cursor()
|
|
283
|
+
cur.execute("""
|
|
284
|
+
INSERT OR IGNORE INTO messages
|
|
285
|
+
(chat_id, message_id, sender_id, text, raw_data, time, saved_at)
|
|
286
|
+
VALUES (?, ?, ?, ?, ?, ?, ?)
|
|
287
|
+
""", (
|
|
288
|
+
record.get("chat_id"),
|
|
289
|
+
record.get("message_id"),
|
|
290
|
+
record.get("sender_id"),
|
|
291
|
+
record.get("text"),
|
|
292
|
+
json.dumps(record.get("raw_data") or {}, ensure_ascii=False),
|
|
293
|
+
record.get("time"),
|
|
294
|
+
int(time.time())
|
|
295
|
+
))
|
|
296
|
+
conn.commit()
|
|
297
|
+
if getattr(self, "_max_messages", None) is not None:
|
|
298
|
+
cur.execute("SELECT COUNT(*) FROM messages")
|
|
299
|
+
total = cur.fetchone()[0]
|
|
300
|
+
if total > self._max_messages:
|
|
301
|
+
remove_count = total - self._max_messages
|
|
302
|
+
cur.execute(
|
|
303
|
+
"DELETE FROM messages WHERE id IN (SELECT id FROM messages ORDER BY saved_at ASC LIMIT ?)",
|
|
304
|
+
(remove_count,)
|
|
305
|
+
)
|
|
306
|
+
conn.commit()
|
|
307
|
+
|
|
308
|
+
conn.close()
|
|
309
|
+
|
|
310
|
+
def _fetch_message(self, chat_id: str, message_id: str):
|
|
311
|
+
conn = sqlite3.connect(self._db_path)
|
|
312
|
+
cur = conn.cursor()
|
|
313
|
+
cur.execute(
|
|
314
|
+
"SELECT chat_id, message_id, sender_id, text, raw_data, time, saved_at FROM messages WHERE chat_id=? AND message_id=?",
|
|
315
|
+
(chat_id, message_id)
|
|
316
|
+
)
|
|
317
|
+
row = cur.fetchone()
|
|
318
|
+
conn.close()
|
|
319
|
+
if not row:
|
|
320
|
+
return None
|
|
321
|
+
chat_id, message_id, sender_id, text, raw_data_json, time_val, saved_at = row
|
|
322
|
+
try:
|
|
323
|
+
raw = json.loads(raw_data_json)
|
|
324
|
+
except:
|
|
325
|
+
raw = {}
|
|
326
|
+
return {
|
|
327
|
+
"chat_id": chat_id,
|
|
328
|
+
"message_id": message_id,
|
|
329
|
+
"sender_id": sender_id,
|
|
330
|
+
"text": text,
|
|
331
|
+
"raw_data": raw,
|
|
332
|
+
"time": time_val,
|
|
333
|
+
"saved_at": saved_at
|
|
334
|
+
}
|
|
335
|
+
async def save_message(self, message: Message):
|
|
336
|
+
try:
|
|
337
|
+
record = {
|
|
338
|
+
"chat_id": getattr(message, "chat_id", None),
|
|
339
|
+
"message_id": getattr(message, "message_id", None),
|
|
340
|
+
"sender_id": getattr(message, "author_guid", None),
|
|
341
|
+
"text": getattr(message, "text", None),
|
|
342
|
+
"raw_data": getattr(message, "raw_data", {}),
|
|
343
|
+
"time": getattr(message, "time", None),
|
|
344
|
+
}
|
|
345
|
+
await asyncio.to_thread(self._insert_message, record)
|
|
346
|
+
except Exception as e:
|
|
347
|
+
print(f"[DB] Error saving message: {e}")
|
|
348
|
+
|
|
349
|
+
async def get_message(self, chat_id: str, message_id: str):
|
|
350
|
+
return await asyncio.to_thread(self._fetch_message, chat_id, message_id)
|
|
351
|
+
|
|
352
|
+
def start_save_message(self, max_messages: int = 1000):
|
|
353
|
+
if self._message_saver_enabled:
|
|
354
|
+
return
|
|
355
|
+
self._message_saver_enabled = True
|
|
356
|
+
self._max_messages = max_messages
|
|
357
|
+
decorators = [
|
|
358
|
+
"on_message", "on_edited_message", "on_message_file", "on_message_forwarded",
|
|
359
|
+
"on_message_reply", "on_message_text", "on_update", "on_callback",
|
|
360
|
+
"on_callback_query", "callback_query_handler", "callback_query",
|
|
361
|
+
"on_inline_query", "on_inline_query_prefix", "on_message_private", "on_message_group"
|
|
362
|
+
]
|
|
363
|
+
|
|
364
|
+
for decorator_name in decorators:
|
|
365
|
+
if hasattr(self, decorator_name):
|
|
366
|
+
original_decorator = getattr(self, decorator_name)
|
|
367
|
+
|
|
368
|
+
def make_wrapper(orig_decorator):
|
|
369
|
+
def wrapper(*args, **kwargs):
|
|
370
|
+
decorator = orig_decorator(*args, **kwargs)
|
|
371
|
+
def inner_wrapper(func):
|
|
372
|
+
async def inner(bot, message, *a, **kw):
|
|
373
|
+
try:
|
|
374
|
+
await bot.save_message(message)
|
|
375
|
+
if getattr(self, "_max_messages", None) is not None:
|
|
376
|
+
await asyncio.to_thread(self._prune_old_messages)
|
|
377
|
+
except Exception as e:
|
|
378
|
+
print(f"[DB] Save error: {e}")
|
|
379
|
+
return await func(bot, message, *a, **kw)
|
|
380
|
+
return decorator(inner)
|
|
381
|
+
return inner_wrapper
|
|
382
|
+
return wrapper
|
|
383
|
+
|
|
384
|
+
setattr(self, decorator_name, make_wrapper(original_decorator))
|
|
385
|
+
def _prune_old_messages(self):
|
|
386
|
+
if not hasattr(self, "_max_messages") or self._max_messages is None:
|
|
387
|
+
return
|
|
388
|
+
conn = sqlite3.connect(self._db_path)
|
|
389
|
+
cur = conn.cursor()
|
|
390
|
+
cur.execute("SELECT COUNT(*) FROM messages")
|
|
391
|
+
total = cur.fetchone()[0]
|
|
392
|
+
if total > self._max_messages:
|
|
393
|
+
remove_count = total - self._max_messages
|
|
394
|
+
cur.execute(
|
|
395
|
+
"DELETE FROM messages WHERE id IN (SELECT id FROM messages ORDER BY saved_at ASC LIMIT ?)",
|
|
396
|
+
(remove_count,)
|
|
397
|
+
)
|
|
398
|
+
conn.commit()
|
|
399
|
+
conn.close()
|
|
400
|
+
|
|
401
|
+
#save message database __________________________ end
|
|
402
|
+
|
|
263
403
|
#decorator#
|
|
264
404
|
|
|
265
405
|
def on_message_private(
|
|
@@ -852,7 +992,7 @@ max_cache_size and max_msg_age help manage duplicate message processing efficien
|
|
|
852
992
|
asyncio.create_task(handler_info["func"](self, context))
|
|
853
993
|
continue
|
|
854
994
|
if handler_info["commands"] or handler_info["filters"]:
|
|
855
|
-
asyncio.create_task(handler_info["func"](self, context))#
|
|
995
|
+
asyncio.create_task(handler_info["func"](self, context))#kir baba kir
|
|
856
996
|
continue
|
|
857
997
|
elif update.get("type") == "UpdatedMessage":
|
|
858
998
|
msg = update.get("updated_message", {})
|
|
@@ -912,7 +1052,7 @@ max_cache_size and max_msg_age help manage duplicate message processing efficien
|
|
|
912
1052
|
async def run(
|
|
913
1053
|
self,
|
|
914
1054
|
debug: bool = False,
|
|
915
|
-
sleep_time: float = 0.
|
|
1055
|
+
sleep_time: float = 0.1,
|
|
916
1056
|
webhook_timeout: int = 20,
|
|
917
1057
|
update_limit: int = 100,
|
|
918
1058
|
retry_delay: float = 5.0,
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
from typing import Any, Dict, List,Optional
|
|
2
2
|
from typing import Union
|
|
3
3
|
from pathlib import Path
|
|
4
|
-
import re
|
|
4
|
+
import re,inspect
|
|
5
5
|
import asyncio
|
|
6
6
|
class File:
|
|
7
7
|
def __init__(self, data: dict):
|
|
@@ -265,24 +265,68 @@ class Message:
|
|
|
265
265
|
self.bot.sessions[self.chat_id] = {}
|
|
266
266
|
return self.bot.sessions[self.chat_id]
|
|
267
267
|
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
self.
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
268
|
+
def reply(self, text: str, delete_after: int = None, **kwargs):
|
|
269
|
+
async def _reply_async():
|
|
270
|
+
send_func = self.bot.send_message
|
|
271
|
+
if inspect.iscoroutinefunction(send_func):
|
|
272
|
+
msg = await send_func(
|
|
273
|
+
self.chat_id,
|
|
274
|
+
text,
|
|
275
|
+
reply_to_message_id=self.message_id,
|
|
276
|
+
delete_after=delete_after,
|
|
277
|
+
**kwargs
|
|
278
|
+
)
|
|
279
|
+
else:
|
|
280
|
+
msg = send_func(
|
|
281
|
+
self.chat_id,
|
|
282
|
+
text,
|
|
283
|
+
reply_to_message_id=self.message_id,
|
|
284
|
+
delete_after=delete_after,
|
|
285
|
+
**kwargs
|
|
286
|
+
)
|
|
287
|
+
class Pick:
|
|
288
|
+
def __init__(self, bot, chat_id, message_id):
|
|
289
|
+
self.bot = bot
|
|
290
|
+
self.chat_id = chat_id
|
|
291
|
+
self.message_id = message_id
|
|
292
|
+
|
|
293
|
+
def edit(self, new_text):
|
|
294
|
+
async def _edit():
|
|
295
|
+
func = self.bot.edit_message_text
|
|
296
|
+
if inspect.iscoroutinefunction(func):
|
|
297
|
+
await func(self.chat_id, self.message_id, new_text)
|
|
298
|
+
else:
|
|
299
|
+
func(self.chat_id, self.message_id, new_text)
|
|
300
|
+
|
|
301
|
+
try:
|
|
302
|
+
loop = asyncio.get_running_loop()
|
|
303
|
+
if loop.is_running():
|
|
304
|
+
return asyncio.create_task(_edit())
|
|
305
|
+
except RuntimeError:
|
|
306
|
+
return asyncio.run(_edit())
|
|
307
|
+
|
|
308
|
+
def delete(self):
|
|
309
|
+
async def _delete():
|
|
310
|
+
func = self.bot.delete_message
|
|
311
|
+
if inspect.iscoroutinefunction(func):
|
|
312
|
+
await func(self.chat_id, self.message_id)
|
|
313
|
+
else:
|
|
314
|
+
func(self.chat_id, self.message_id)
|
|
315
|
+
try:
|
|
316
|
+
loop = asyncio.get_running_loop()
|
|
317
|
+
if loop.is_running():
|
|
318
|
+
return asyncio.create_task(_delete())
|
|
319
|
+
except RuntimeError:
|
|
320
|
+
return asyncio.run(_delete())
|
|
321
|
+
chat_id = msg.get("chat_id") if isinstance(msg, dict) else getattr(msg, "chat_id", self.chat_id)
|
|
322
|
+
message_id = msg.get("message_id") if isinstance(msg, dict) else getattr(msg, "message_id", self.message_id)
|
|
323
|
+
return Pick(self.bot, chat_id, message_id)
|
|
324
|
+
try:
|
|
325
|
+
loop = asyncio.get_running_loop()
|
|
326
|
+
if loop.is_running():
|
|
327
|
+
return asyncio.create_task(_reply_async())
|
|
328
|
+
except RuntimeError:
|
|
329
|
+
return asyncio.run(_reply_async())
|
|
286
330
|
def answer(self, text: str, **kwargs):
|
|
287
331
|
return self.bot.send_message(
|
|
288
332
|
self.chat_id,
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
from typing import Any, Dict, List,Optional
|
|
2
2
|
from typing import Union
|
|
3
3
|
from pathlib import Path
|
|
4
|
-
import re
|
|
4
|
+
import re,inspect
|
|
5
5
|
import asyncio
|
|
6
6
|
class File:
|
|
7
7
|
def __init__(self, data: dict):
|
|
@@ -259,20 +259,74 @@ class Message:
|
|
|
259
259
|
self.is_archive = name.endswith((".zip", ".rar", ".7z", ".tar", ".gz"))
|
|
260
260
|
self.is_executable = name.endswith((".exe", ".msi", ".bat", ".sh"))
|
|
261
261
|
self.is_font = name.endswith((".ttf", ".otf", ".woff", ".woff2"))
|
|
262
|
-
self.info = {attr: value for attr, value in vars(self).items()}
|
|
263
262
|
@property
|
|
264
263
|
def session(self):
|
|
265
264
|
if self.chat_id not in self.bot.sessions:
|
|
266
265
|
self.bot.sessions[self.chat_id] = {}
|
|
267
266
|
return self.bot.sessions[self.chat_id]
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
267
|
+
|
|
268
|
+
def reply(self, text: str, delete_after: int = None, **kwargs):
|
|
269
|
+
async def _reply_async():
|
|
270
|
+
send_func = self.bot.send_message
|
|
271
|
+
if inspect.iscoroutinefunction(send_func):
|
|
272
|
+
msg = await send_func(
|
|
273
|
+
self.chat_id,
|
|
274
|
+
text,
|
|
275
|
+
reply_to_message_id=self.message_id,
|
|
276
|
+
delete_after=delete_after,
|
|
277
|
+
**kwargs
|
|
278
|
+
)
|
|
279
|
+
else:
|
|
280
|
+
msg = send_func(
|
|
281
|
+
self.chat_id,
|
|
282
|
+
text,
|
|
283
|
+
reply_to_message_id=self.message_id,
|
|
284
|
+
delete_after=delete_after,
|
|
285
|
+
**kwargs
|
|
286
|
+
)
|
|
287
|
+
class Pick:
|
|
288
|
+
def __init__(self, bot, chat_id, message_id):
|
|
289
|
+
self.bot = bot
|
|
290
|
+
self.chat_id = chat_id
|
|
291
|
+
self.message_id = message_id
|
|
292
|
+
|
|
293
|
+
def edit(self, new_text):
|
|
294
|
+
async def _edit():
|
|
295
|
+
func = self.bot.edit_message_text
|
|
296
|
+
if inspect.iscoroutinefunction(func):
|
|
297
|
+
await func(self.chat_id, self.message_id, new_text)
|
|
298
|
+
else:
|
|
299
|
+
func(self.chat_id, self.message_id, new_text)
|
|
300
|
+
|
|
301
|
+
try:
|
|
302
|
+
loop = asyncio.get_running_loop()
|
|
303
|
+
if loop.is_running():
|
|
304
|
+
return asyncio.create_task(_edit())
|
|
305
|
+
except RuntimeError:
|
|
306
|
+
return asyncio.run(_edit())
|
|
307
|
+
|
|
308
|
+
def delete(self):
|
|
309
|
+
async def _delete():
|
|
310
|
+
func = self.bot.delete_message
|
|
311
|
+
if inspect.iscoroutinefunction(func):
|
|
312
|
+
await func(self.chat_id, self.message_id)
|
|
313
|
+
else:
|
|
314
|
+
func(self.chat_id, self.message_id)
|
|
315
|
+
try:
|
|
316
|
+
loop = asyncio.get_running_loop()
|
|
317
|
+
if loop.is_running():
|
|
318
|
+
return asyncio.create_task(_delete())
|
|
319
|
+
except RuntimeError:
|
|
320
|
+
return asyncio.run(_delete())
|
|
321
|
+
chat_id = msg.get("chat_id") if isinstance(msg, dict) else getattr(msg, "chat_id", self.chat_id)
|
|
322
|
+
message_id = msg.get("message_id") if isinstance(msg, dict) else getattr(msg, "message_id", self.message_id)
|
|
323
|
+
return Pick(self.bot, chat_id, message_id)
|
|
324
|
+
try:
|
|
325
|
+
loop = asyncio.get_running_loop()
|
|
326
|
+
if loop.is_running():
|
|
327
|
+
return asyncio.create_task(_reply_async())
|
|
328
|
+
except RuntimeError:
|
|
329
|
+
return asyncio.run(_reply_async())
|
|
276
330
|
def answer(self, text: str, **kwargs):
|
|
277
331
|
return self.bot.send_message(
|
|
278
332
|
self.chat_id,
|
|
@@ -13,7 +13,7 @@ with open("README.md", "r", encoding="utf-8") as f:
|
|
|
13
13
|
|
|
14
14
|
setup(
|
|
15
15
|
name='Rubka',
|
|
16
|
-
version='
|
|
16
|
+
version='7.1.1',
|
|
17
17
|
description='rubika A Python library for interacting with Rubika Bot API.',
|
|
18
18
|
long_description=long_description,
|
|
19
19
|
long_description_content_type='text/markdown',
|
|
@@ -45,6 +45,7 @@ setup(
|
|
|
45
45
|
"websocket-client",
|
|
46
46
|
'pycryptodome',
|
|
47
47
|
'aiohttp',
|
|
48
|
+
'httpx',
|
|
48
49
|
'tqdm',
|
|
49
50
|
'mutagen',
|
|
50
51
|
'filetype',
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|