diff --git a/misskaty/__main__.py b/misskaty/__main__.py index af5628a4..5853d980 100644 --- a/misskaty/__main__.py +++ b/misskaty/__main__.py @@ -27,6 +27,7 @@ from misskaty import ( user, ) from misskaty.core.message_utils import * +from misskaty.core.decorator.ratelimiter import ratelimiter from misskaty.helper import bot_sys_stats, paginate_modules from misskaty.plugins import ALL_MODULES from misskaty.vars import COMMAND_HANDLER, LOG_CHANNEL, SUDO @@ -127,6 +128,7 @@ keyboard = InlineKeyboardMarkup( @app.on_message(filters.command("start", COMMAND_HANDLER)) +@ratelimiter async def start(_, message): if not message.from_user: return if message.chat.type.value != "private": @@ -180,6 +182,7 @@ async def start(_, message): @app.on_callback_query(filters.regex("bot_commands")) +@ratelimiter async def commands_callbacc(_, CallbackQuery): text, keyboard = await help_parser(CallbackQuery.from_user.mention) await app.send_message( @@ -191,12 +194,14 @@ async def commands_callbacc(_, CallbackQuery): @app.on_callback_query(filters.regex("stats_callback")) +@ratelimiter async def stats_callbacc(_, CallbackQuery): text = await bot_sys_stats() await app.answer_callback_query(CallbackQuery.id, text, show_alert=True) @app.on_message(filters.command("help", COMMAND_HANDLER)) +@ratelimiter async def help_command(_, message): if not message.from_user: return if message.chat.type.value != "private": @@ -280,6 +285,7 @@ If you want give coffee to my owner you can send /donate command for more info. @app.on_callback_query(filters.regex(r"help_(.*?)")) +@ratelimiter async def help_button(client, query): home_match = re.match(r"help_home\((.+?)\)", query.data) mod_match = re.match(r"help_module\((.+?)\)", query.data) diff --git a/misskaty/core/decorator/ratelimiter.py b/misskaty/core/decorator/ratelimiter.py new file mode 100644 index 00000000..cd9a411d --- /dev/null +++ b/misskaty/core/decorator/ratelimiter.py @@ -0,0 +1,41 @@ +from cachetools import TTLCache +from functools import wraps +from ..ratelimiter_func import RateLimiter +from typing import Callable, Union +from pyrogram import Client +from pyrogram.types import CallbackQuery, Message + +ratelimit = RateLimiter() +# storing spammy user in cache for 1minute before allowing them to use commands again. +warned_users = TTLCache(maxsize=128, ttl=60) +warning_message = "Spam detected! ignoring your all requests for few minutes." + +def ratelimiter(func: Callable) -> Callable: + """ + Restricts user's from spamming commands or pressing buttons multiple times + using leaky bucket algorithm and pyrate_limiter. + """ + + @wraps(func) + async def decorator(client: Client, update: Union[Message, CallbackQuery]): + userid = update.from_user.id if update.from_user else update.sender_chat.id + is_limited = await ratelimit.acquire(userid) + + if is_limited and userid not in warned_users: + + if isinstance(update, Message): + await update.reply_text(warning_message) + warned_users[userid] = 1 + return + + elif isinstance(update, CallbackQuery): + await update.answer(warning_message, show_alert=True) + warned_users[userid] = 1 + return + + elif is_limited and userid in warned_users: + pass + else: + return await func(client, update) + + return decorator \ No newline at end of file diff --git a/misskaty/core/ratelimiter_func.py b/misskaty/core/ratelimiter_func.py new file mode 100644 index 00000000..97a26141 --- /dev/null +++ b/misskaty/core/ratelimiter_func.py @@ -0,0 +1,45 @@ +from typing import Union + +from pyrate_limiter import (BucketFullException, Duration, Limiter, + MemoryListBucket, RequestRate) + + +class RateLimiter: + """ + Implement rate limit logic using leaky bucket + algorithm, via pyrate_limiter. + (https://pypi.org/project/pyrate-limiter/) + """ + + def __init__(self) -> None: + + # 3 requests per seconds + self.second_rate = RequestRate(3, Duration.SECOND) + + # 20 requests per minute. + self.minute_rate = RequestRate(20, Duration.MINUTE) + + # 1000 requests per hour + self.hourly_rate = RequestRate(1000, Duration.HOUR) + + # 10000 requests per day + self.daily_rate = RequestRate(10000, Duration.DAY) + + self.limiter = Limiter( + self.minute_rate, + self.hourly_rate, + self.daily_rate, + bucket_class=MemoryListBucket, + ) + + async def acquire(self, userid: Union[int, str]) -> bool: + """ + Acquire rate limit per userid and return True / False + based on userid ratelimit status. + """ + + try: + self.limiter.try_acquire(userid) + return False + except BucketFullException: + return True \ No newline at end of file diff --git a/misskaty/plugins/admin.py b/misskaty/plugins/admin.py index 5dc3b1db..e0aa80f4 100644 --- a/misskaty/plugins/admin.py +++ b/misskaty/plugins/admin.py @@ -16,6 +16,7 @@ from misskaty.core.decorator.permissions import ( list_admins, member_permissions, ) +from misskaty.core.decorator.ratelimiter import ratelimiter from misskaty.core.keyboard import ikb from misskaty.core.message_utils import kirimPesan from misskaty.helper.functions import ( @@ -74,6 +75,7 @@ async def admin_cache_func(_, cmu): # Purge CMD @app.on_message(filters.command("purge", COMMAND_HANDLER) & filters.group) @adminsOnly("can_delete_messages") +@ratelimiter async def purge(_, message): if not message.from_user: return @@ -128,6 +130,7 @@ async def purge(_, message): # Kick members @app.on_message(filters.command(["kick", "dkick"], COMMAND_HANDLER) & filters.group) @adminsOnly("can_restrict_members") +@ratelimiter async def kickFunc(client, message): if not message.from_user: return @@ -159,6 +162,7 @@ async def kickFunc(client, message): # Ban/DBan/TBan User @app.on_message(filters.command(["ban", "dban", "tban"], COMMAND_HANDLER) & filters.group) @adminsOnly("can_restrict_members") +@ratelimiter async def banFunc(client, message): if not message.from_user: return @@ -211,6 +215,7 @@ async def banFunc(client, message): # Unban members @app.on_message(filters.command("unban", COMMAND_HANDLER) & filters.group) @adminsOnly("can_restrict_members") +@ratelimiter async def unban_func(_, message): if not message.from_user: return @@ -236,6 +241,7 @@ async def unban_func(_, message): # Ban users listed in a message @app.on_message(filters.user(SUDO) & filters.command("listban", COMMAND_HANDLER) & filters.group) +@ratelimiter async def list_ban_(c, message): if not message.from_user: return @@ -287,6 +293,7 @@ async def list_ban_(c, message): # Unban users listed in a message @app.on_message(filters.user(SUDO) & filters.command("listunban", COMMAND_HANDLER) & filters.group) +@ratelimiter async def list_unban_(c, message): if not message.from_user: return @@ -331,6 +338,7 @@ async def list_unban_(c, message): # Delete messages @app.on_message(filters.command("del", COMMAND_HANDLER) & filters.group) @adminsOnly("can_delete_messages") +@ratelimiter async def deleteFunc(_, message): if not message.from_user: return @@ -346,6 +354,7 @@ async def deleteFunc(_, message): # Promote Members @app.on_message(filters.command(["promote", "fullpromote"], COMMAND_HANDLER) & filters.group) @adminsOnly("can_promote_members") +@ratelimiter async def promoteFunc(client, message): if not message.from_user: return @@ -392,6 +401,7 @@ async def promoteFunc(client, message): # Demote Member @app.on_message(filters.command("demote", COMMAND_HANDLER) & filters.group) @adminsOnly("can_promote_members") +@ratelimiter async def demote(client, message): if not message.from_user: return @@ -420,6 +430,7 @@ async def demote(client, message): # Pin Messages @app.on_message(filters.command(["pin", "unpin"], COMMAND_HANDLER) & filters.group) @adminsOnly("can_pin_messages") +@ratelimiter async def pin(_, message): if not message.from_user: return @@ -448,6 +459,7 @@ async def pin(_, message): # Mute members @app.on_message(filters.command(["mute", "tmute"], COMMAND_HANDLER) & filters.group) @adminsOnly("can_restrict_members") +@ratelimiter async def mute(client, message): if not message.from_user: return @@ -496,6 +508,7 @@ async def mute(client, message): # Unmute members @app.on_message(filters.command("unmute", COMMAND_HANDLER) & filters.group) @adminsOnly("can_restrict_members") +@ratelimiter async def unmute(_, message): if not message.from_user: return @@ -509,6 +522,7 @@ async def unmute(_, message): @app.on_message(filters.command(["warn", "dwarn"], COMMAND_HANDLER) & filters.group) @adminsOnly("can_restrict_members") +@ratelimiter async def warn_user(client, message): if not message.from_user: return @@ -547,6 +561,7 @@ async def warn_user(client, message): @app.on_callback_query(filters.regex("unwarn_")) +@ratelimiter async def remove_warning(_, cq): from_user = cq.from_user chat_id = cq.message.chat.id @@ -572,6 +587,7 @@ async def remove_warning(_, cq): @app.on_callback_query(filters.regex("unmute_")) +@ratelimiter async def unmute_user(_, cq): from_user = cq.from_user chat_id = cq.message.chat.id @@ -591,6 +607,7 @@ async def unmute_user(_, cq): @app.on_callback_query(filters.regex("unban_")) +@ratelimiter async def unban_user(_, cq): from_user = cq.from_user chat_id = cq.message.chat.id @@ -613,6 +630,7 @@ async def unban_user(_, cq): # Remove Warn @app.on_message(filters.command("rmwarn", COMMAND_HANDLER) & filters.group) @adminsOnly("can_restrict_members") +@ratelimiter async def remove_warnings(_, message): if not message.from_user: return @@ -634,6 +652,7 @@ async def remove_warnings(_, message): # Warns @app.on_message(filters.command("warns", COMMAND_HANDLER) & filters.group) @capture_err +@ratelimiter async def check_warns(_, message): if not message.from_user: return @@ -652,6 +671,7 @@ async def check_warns(_, message): # Report User in Group @app.on_message((filters.command("report", COMMAND_HANDLER) | filters.command(["admins", "admin"], prefixes="@")) & filters.group) @capture_err +@ratelimiter async def report_user(_, message): if not message.reply_to_message: return await message.reply_text("Reply to a message to report that user.") diff --git a/misskaty/plugins/afk.py b/misskaty/plugins/afk.py index a7db83b7..dafb5fe2 100644 --- a/misskaty/plugins/afk.py +++ b/misskaty/plugins/afk.py @@ -17,6 +17,7 @@ from database.afk_db import add_afk, cleanmode_off, cleanmode_on, is_afk, remove from misskaty import app from misskaty.core.decorator.errors import capture_err from misskaty.core.decorator.permissions import adminsOnly +from misskaty.core.decorator.ratelimiter import ratelimiter from misskaty.core.message_utils import kirimPesan from misskaty.helper import get_readable_time2 from misskaty.vars import COMMAND_HANDLER @@ -32,6 +33,7 @@ Just type something in group to remove AFK Status.""" # Handle set AFK Command @capture_err @app.on_message(filters.command(["afk"], COMMAND_HANDLER)) +@ratelimiter async def active_afk(_, message): if message.sender_chat: return await kirimPesan(message, "This feature not supported for channel.") @@ -182,6 +184,7 @@ async def active_afk(_, message): @app.on_message(filters.command("afkdel", COMMAND_HANDLER) & filters.group) +@ratelimiter @adminsOnly("can_change_info") async def afk_state(_, message): if not message.from_user: diff --git a/misskaty/plugins/auto_approve.py b/misskaty/plugins/auto_approve.py index c01096d8..c3364244 100644 --- a/misskaty/plugins/auto_approve.py +++ b/misskaty/plugins/auto_approve.py @@ -10,6 +10,7 @@ from pyrogram.errors import UserAlreadyParticipant, UserIsBlocked from pyrogram.types import InlineKeyboardButton, InlineKeyboardMarkup from misskaty import app +from misskaty.core.decorator.ratelimiter import ratelimiter from misskaty.core.decorator.errors import capture_err @@ -37,6 +38,7 @@ async def approve_join_chat(c, m): @app.on_callback_query(filters.regex(r"^approve")) +@ratelimiter async def approve_chat(c, q): i, chat = q.data.split("_") try: @@ -49,6 +51,7 @@ async def approve_chat(c, q): @app.on_callback_query(filters.regex(r"^declined")) +@ratelimiter async def decline_chat(c, q): i, chat = q.data.split("_") try: diff --git a/misskaty/plugins/bypass.py b/misskaty/plugins/bypass.py index 62c07d65..ed03538e 100644 --- a/misskaty/plugins/bypass.py +++ b/misskaty/plugins/bypass.py @@ -17,6 +17,7 @@ from pyrogram.types import InlineKeyboardButton, InlineKeyboardMarkup from misskaty import app from misskaty.core.message_utils import * from misskaty.core.decorator.errors import capture_err +from misskaty.core.decorator.ratelimiter import ratelimiter from misskaty.helper import http, get_readable_file_size, rentry from misskaty.vars import COMMAND_HANDLER @@ -87,6 +88,7 @@ def wetransfer_bypass(url: str) -> str: @app.on_message(filters.command(["directurl"], COMMAND_HANDLER)) @capture_err +@ratelimiter async def bypass(_, message): if len(message.command) == 1: return await kirimPesan(message, f"Gunakan perintah /{message.command[0]} untuk bypass url") @@ -114,6 +116,8 @@ async def bypass(_, message): reply_markup=markup, disable_web_page_preview=True, ) - else: + elif "we.tl" or "wetransfer.com" in message.command[1]: data = wetransfer_bypass(url) await editPesan(msg, f"{data}\n\n{mention}") + else: + await kirimPesan(message, "Unsupported url..") \ No newline at end of file diff --git a/misskaty/plugins/chatbot_ai.py b/misskaty/plugins/chatbot_ai.py index 8d4a5db8..88ef935a 100644 --- a/misskaty/plugins/chatbot_ai.py +++ b/misskaty/plugins/chatbot_ai.py @@ -4,10 +4,12 @@ from pyrogram.errors import MessageNotModified from misskaty import app from misskaty.helper.http import http from misskaty.core.message_utils import * +from misskaty.core.decorator.ratelimiter import ratelimiter from misskaty.vars import COMMAND_HANDLER, OPENAI_API @app.on_message(filters.command("ask", COMMAND_HANDLER)) +@ratelimiter async def chatbot(c, m): if len(m.command) == 1: return await kirimPesan(m, f"Gunakan perintah /{m.command[0]} [pertanyaan] untuk menanyakan pertanyaan menggunakan AI.") diff --git a/misskaty/plugins/code_tester.py b/misskaty/plugins/code_tester.py index 53a845c9..d2eeb967 100644 --- a/misskaty/plugins/code_tester.py +++ b/misskaty/plugins/code_tester.py @@ -4,6 +4,7 @@ from pyrogram.errors import MessageTooLong from misskaty import app from misskaty.helper.tools import rentry +from misskaty.core.decorator.ratelimiter import ratelimiter from misskaty.vars import COMMAND_HANDLER __MODULE__ = "CodeTester" @@ -72,6 +73,7 @@ async def glot(lang, langcode, code): @app.on_message(filters.command(["codelist"], COMMAND_HANDLER)) +@ratelimiter async def list_lang(client, message): daftarlang = await listcode() list_ = "".join(f"~> {i['name']}\n" for i in daftarlang) @@ -80,6 +82,7 @@ async def list_lang(client, message): @app.on_message(filters.command(["assembly"], "!")) @app.on_edited_message(filters.command(["assembly"], "!")) +@ratelimiter async def assembly(client, message): if len(message.command) < 2: return await message.reply("Please enter the code you want to run.") @@ -97,6 +100,7 @@ async def assembly(client, message): @app.on_message(filters.command(["ats"], "!")) @app.on_edited_message(filters.command(["ats"], "!")) +@ratelimiter async def ats(client, message): if len(message.command) < 2: return await message.reply("Please enter the code you want to run.") @@ -114,6 +118,7 @@ async def ats(client, message): @app.on_message(filters.command(["bash"], "!")) @app.on_edited_message(filters.command(["bash"], "!")) +@ratelimiter async def bash(client, message): if len(message.command) < 2: return await message.reply("Please enter the code you want to run.") @@ -131,6 +136,7 @@ async def bash(client, message): @app.on_message(filters.command(["c"], "!")) @app.on_edited_message(filters.command(["c"], "!")) +@ratelimiter async def c(client, message): if len(message.command) < 2: return await message.reply("Please enter the code you want to run.") @@ -148,6 +154,7 @@ async def c(client, message): @app.on_message(filters.command(["clojure"], "!")) @app.on_edited_message(filters.command(["clojure"], "!")) +@ratelimiter async def clojure(client, message): if len(message.command) < 2: return await message.reply("Please enter the code you want to run.") @@ -165,6 +172,7 @@ async def clojure(client, message): @app.on_message(filters.command(["cobol"], "!")) @app.on_edited_message(filters.command(["cobol"], "!")) +@ratelimiter async def cobol(client, message): if len(message.command) < 2: return await message.reply("Please enter the code you want to run.") @@ -182,6 +190,7 @@ async def cobol(client, message): @app.on_message(filters.command(["coffeescript"], "!")) @app.on_edited_message(filters.command(["coffeescript"], "!")) +@ratelimiter async def coffeescript(client, message): if len(message.command) < 2: return await message.reply("Please enter the code you want to run.") @@ -199,6 +208,7 @@ async def coffeescript(client, message): @app.on_message(filters.command(["cpp"], "!")) @app.on_edited_message(filters.command(["cpp"], "!")) +@ratelimiter async def cpp(client, message): if len(message.command) < 2: return await message.reply("Please enter the code you want to run.") @@ -216,6 +226,7 @@ async def cpp(client, message): @app.on_message(filters.command(["crystal"], "!")) @app.on_edited_message(filters.command(["crystal"], "!")) +@ratelimiter async def crystal(client, message): if len(message.command) < 2: return await message.reply("Please enter the code you want to run.") @@ -233,6 +244,7 @@ async def crystal(client, message): @app.on_message(filters.command(["csharp"], "!")) @app.on_edited_message(filters.command(["csharp"], "!")) +@ratelimiter async def csharp(client, message): if len(message.command) < 2: return await message.reply("Please enter the code you want to run.") @@ -250,6 +262,7 @@ async def csharp(client, message): @app.on_message(filters.command(["d"], "!")) @app.on_edited_message(filters.command(["d"], "!")) +@ratelimiter async def d(client, message): if len(message.command) < 2: return await message.reply("Please enter the code you want to run.") @@ -267,6 +280,7 @@ async def d(client, message): @app.on_message(filters.command(["elixir"], "!")) @app.on_edited_message(filters.command(["elixir"], "!")) +@ratelimiter async def elixir(client, message): if len(message.command) < 2: return await message.reply("Please enter the code you want to run.") @@ -301,6 +315,7 @@ async def elm(client, message): @app.on_message(filters.command(["erlang"], "!")) @app.on_edited_message(filters.command(["erlang"], "!")) +@ratelimiter async def erlang(client, message): if len(message.command) < 2: return await message.reply("Please enter the code you want to run.") @@ -318,6 +333,7 @@ async def erlang(client, message): @app.on_message(filters.command(["fsharp"], "!")) @app.on_edited_message(filters.command(["fsharp"], "!")) +@ratelimiter async def fsharp(client, message): if len(message.command) < 2: return await message.reply("Please enter the code you want to run.") @@ -335,6 +351,7 @@ async def fsharp(client, message): @app.on_message(filters.command(["go"], "!")) @app.on_edited_message(filters.command(["go"], "!")) +@ratelimiter async def go(client, message): if len(message.command) < 2: return await message.reply("Please enter the code you want to run.") @@ -352,6 +369,7 @@ async def go(client, message): @app.on_message(filters.command(["groovy"], "!")) @app.on_edited_message(filters.command(["groovy"], "!")) +@ratelimiter async def groovy(client, message): if len(message.command) < 2: return await message.reply("Please enter the code you want to run.") @@ -369,6 +387,7 @@ async def groovy(client, message): @app.on_message(filters.command(["haskell"], "!")) @app.on_edited_message(filters.command(["haskell"], "!")) +@ratelimiter async def haskell(client, message): if len(message.command) < 2: return await message.reply("Please enter the code you want to run.") @@ -386,6 +405,7 @@ async def haskell(client, message): @app.on_message(filters.command(["idris"], "!")) @app.on_edited_message(filters.command(["idris"], "!")) +@ratelimiter async def idris(client, message): if len(message.command) < 2: return await message.reply("Please enter the code you want to run.") @@ -403,6 +423,7 @@ async def idris(client, message): @app.on_message(filters.command(["java"], "!")) @app.on_edited_message(filters.command(["java"], "!")) +@ratelimiter async def java(client, message): if len(message.command) < 2: return await message.reply("Please enter the code you want to run.") @@ -420,6 +441,7 @@ async def java(client, message): @app.on_message(filters.command(["javascript"], "!")) @app.on_edited_message(filters.command(["javascript"], "!")) +@ratelimiter async def javascript(client, message): if len(message.command) < 2: return await message.reply("Please enter the code you want to run.") @@ -437,6 +459,7 @@ async def javascript(client, message): @app.on_message(filters.command(["julia"], "!")) @app.on_edited_message(filters.command(["julia"], "!")) +@ratelimiter async def julia(client, message): if len(message.command) < 2: return await message.reply("Please enter the code you want to run.") @@ -454,6 +477,7 @@ async def julia(client, message): @app.on_message(filters.command(["kotlin"], "!")) @app.on_edited_message(filters.command(["kotlin"], "!")) +@ratelimiter async def kotlin(client, message): if len(message.command) < 2: return await message.reply("Please enter the code you want to run.") @@ -471,6 +495,7 @@ async def kotlin(client, message): @app.on_message(filters.command(["lua"], "!")) @app.on_edited_message(filters.command(["lua"], "!")) +@ratelimiter async def lua(client, message): if len(message.command) < 2: return await message.reply("Please enter the code you want to run.") @@ -488,6 +513,7 @@ async def lua(client, message): @app.on_message(filters.command(["mercury"], "!")) @app.on_edited_message(filters.command(["mercury"], "!")) +@ratelimiter async def mercury(client, message): if len(message.command) < 2: return await message.reply("Please enter the code you want to run.") @@ -505,6 +531,7 @@ async def mercury(client, message): @app.on_message(filters.command(["nim"], "!")) @app.on_edited_message(filters.command(["nim"], "!")) +@ratelimiter async def nim(client, message): if len(message.command) < 2: return await message.reply("Please enter the code you want to run.") @@ -522,6 +549,7 @@ async def nim(client, message): @app.on_message(filters.command(["nix"], "!")) @app.on_edited_message(filters.command(["nix"], "!")) +@ratelimiter async def nix(client, message): if len(message.command) < 2: return await message.reply("Please enter the code you want to run.") @@ -539,6 +567,7 @@ async def nix(client, message): @app.on_message(filters.command(["ocaml"], "!")) @app.on_edited_message(filters.command(["ocaml"], "!")) +@ratelimiter async def ocaml(client, message): if len(message.command) < 2: return await message.reply("Please enter the code you want to run.") @@ -556,6 +585,7 @@ async def ocaml(client, message): @app.on_message(filters.command(["perl"], "!")) @app.on_edited_message(filters.command(["perl"], "!")) +@ratelimiter async def perl(client, message): if len(message.command) < 2: return await message.reply("Please enter the code you want to run.") @@ -590,6 +620,7 @@ async def php(client, message): @app.on_message(filters.command(["python"], "!")) @app.on_edited_message(filters.command(["python"], "!")) +@ratelimiter async def python(client, message): if len(message.command) < 2: return await message.reply("Please enter the code you want to run.") @@ -607,6 +638,7 @@ async def python(client, message): @app.on_message(filters.command(["raku"], "!")) @app.on_edited_message(filters.command(["raku"], "!")) +@ratelimiter async def raku(client, message): if len(message.command) < 2: return await message.reply("Please enter the code you want to run.") @@ -624,6 +656,7 @@ async def raku(client, message): @app.on_message(filters.command(["ruby"], "!")) @app.on_edited_message(filters.command(["ruby"], "!")) +@ratelimiter async def ruby(client, message): if len(message.command) < 2: return await message.reply("Please enter the code you want to run.") @@ -641,6 +674,7 @@ async def ruby(client, message): @app.on_message(filters.command(["rust"], "!")) @app.on_edited_message(filters.command(["rust"], "!")) +@ratelimiter async def rust(client, message): if len(message.command) < 2: return await message.reply("Please enter the code you want to run.") @@ -658,6 +692,7 @@ async def rust(client, message): @app.on_message(filters.command(["scala"], "!")) @app.on_edited_message(filters.command(["scala"], "!")) +@ratelimiter async def scala(client, message): if len(message.command) < 2: return await message.reply("Please enter the code you want to run.") @@ -692,6 +727,7 @@ async def swift(client, message): @app.on_message(filters.command(["typescript"], "!")) @app.on_edited_message(filters.command(["typescript"], "!")) +@ratelimiter async def typescript(client, message): if len(message.command) < 2: return await message.reply("Please enter the code you want to run.") diff --git a/misskaty/plugins/copy_forward.py b/misskaty/plugins/copy_forward.py index 16c5981d..69e5cff8 100644 --- a/misskaty/plugins/copy_forward.py +++ b/misskaty/plugins/copy_forward.py @@ -3,11 +3,13 @@ from pyrogram.errors import UserIsBlocked, UserNotParticipant from pyrogram.types import InlineKeyboardButton, InlineKeyboardMarkup from misskaty import BOT_USERNAME, app +from misskaty.core.decorator.ratelimiter import ratelimiter from misskaty.core.decorator.errors import capture_err from misskaty.vars import COMMAND_HANDLER @app.on_message(filters.command(["copy"], COMMAND_HANDLER)) +@ratelimiter async def copy(client, message): if len(message.command) == 1: if not message.reply_to_message: diff --git a/misskaty/plugins/download_upload.py b/misskaty/plugins/download_upload.py index 8194884c..f2e839f8 100644 --- a/misskaty/plugins/download_upload.py +++ b/misskaty/plugins/download_upload.py @@ -11,6 +11,7 @@ from pySmartDL import SmartDL from misskaty import app from misskaty.core.decorator.errors import capture_err +from misskaty.core.decorator.ratelimiter import ratelimiter from misskaty.helper.http import http from misskaty.helper.pyro_progress import humanbytes, progress_for_pyrogram from misskaty.vars import COMMAND_HANDLER, SUDO @@ -30,6 +31,7 @@ __HELP__ = """ @app.on_message(filters.command(["anon"], COMMAND_HANDLER)) +@ratelimiter async def upload(bot, message): if not message.reply_to_message: return await message.reply("Please reply to media file.") @@ -103,7 +105,7 @@ async def download(client, message): estimated_total_time = downloader.get_eta(human=True) try: - current_message = "trying to download...\n" + current_message = "Trying to download...\n" current_message += f"URL: {url}\n" current_message += f"File Name: {custom_file_name}\n" current_message += f"Speed: {speed}\n" @@ -126,6 +128,7 @@ async def download(client, message): @app.on_message(filters.command(["tiktokdl"], COMMAND_HANDLER)) @capture_err +@ratelimiter async def tiktokdl(client, message): if len(message.command) == 1: return await message.reply(f"Use command /{message.command[0]} [link] to download tiktok video.") @@ -162,6 +165,7 @@ async def fbdl(client, message): await message.reply_video( path, caption=f"{os.path.basename(path)}\n\nUploaded for {message.from_user.mention} [{message.from_user.id}]", + thumb="img/thumb.jpg" ) await msg.delete() try: diff --git a/misskaty/plugins/filter_request.py b/misskaty/plugins/filter_request.py index efc1693f..aca36014 100644 --- a/misskaty/plugins/filter_request.py +++ b/misskaty/plugins/filter_request.py @@ -9,6 +9,7 @@ from pyrogram.types import InlineKeyboardButton, InlineKeyboardMarkup from misskaty import app from .web_scraper import SCRAP_DICT, data_kuso from .pypi_search import PYPI_DICT +from misskaty.core.decorator.ratelimiter import ratelimiter from misskaty.core.decorator.errors import capture_err from misskaty.helper.time_gap import check_time_gap @@ -131,7 +132,8 @@ async def start(_, message): @app.on_callback_query(filters.regex(r"^donereq")) -async def _callbackreq(c, q): +@ratelimiter +async def callbackreq(c, q): try: user = await c.get_chat_member(-1001201566570, q.from_user.id) if user.status in [ @@ -169,7 +171,8 @@ async def _callbackreq(c, q): @app.on_callback_query(filters.regex(r"^dahada")) -async def _callbackreqada(c, q): +@ratelimiter +async def callbackreqada(c, q): try: user = await c.get_chat_member(-1001201566570, q.from_user.id) if user.status in [ @@ -225,7 +228,8 @@ async def _callbackreqada(c, q): @app.on_callback_query(filters.regex(r"^rejectreq")) -async def _callbackreject(c, q): +@ratelimiter +async def callbackreject(c, q): try: user = await c.get_chat_member(-1001201566570, q.from_user.id) if user.status in [ @@ -263,7 +267,8 @@ async def _callbackreject(c, q): @app.on_callback_query(filters.regex(r"^unavailablereq")) -async def _callbackunav(c, q): +@ratelimiter +async def callbackunav(c, q): try: user = await c.get_chat_member(-1001201566570, q.from_user.id) if user.status in [ @@ -323,7 +328,8 @@ async def _callbackunav(c, q): @app.on_callback_query(filters.regex(r"^reqcompl$")) -async def _callbackaft_done(c, q): +@ratelimiter +async def callbackaft_done(c, q): await q.answer( "Request ini sudah terselesaikan 🥳, silahkan cek di channel atau grup yaa..", show_alert=True, @@ -332,7 +338,8 @@ async def _callbackaft_done(c, q): @app.on_callback_query(filters.regex(r"^reqreject$")) -async def _callbackaft_rej(c, q): +@ratelimiter +async def callbackaft_rej(c, q): await q.answer( "Request ini ditolak 💔, silahkan cek rules grup yaa.", show_alert=True, @@ -341,7 +348,8 @@ async def _callbackaft_rej(c, q): @app.on_callback_query(filters.regex(r"^requnav$")) -async def _callbackaft_unav(c, q): +@ratelimiter +async def callbackaft_unav(c, q): await q.answer( "Request ini tidak tersedia ☹️, mungkin filmnya belum rilis atau memang tidak tersedia versi digital.", show_alert=True, @@ -350,7 +358,8 @@ async def _callbackaft_unav(c, q): @app.on_callback_query(filters.regex(r"^reqavailable$")) -async def _callbackaft_dahada(c, q): +@ratelimiter +async def callbackaft_dahada(c, q): await q.answer("Request ini sudah ada, silahkan cari 🔍 di channelnya yaa 😉..", show_alert=True) diff --git a/misskaty/plugins/filters.py b/misskaty/plugins/filters.py index b176c675..10e7ac9e 100644 --- a/misskaty/plugins/filters.py +++ b/misskaty/plugins/filters.py @@ -28,6 +28,7 @@ from pyrogram import filters from database.filters_db import delete_filter, get_filter, get_filters_names, save_filter from misskaty import app from misskaty.core.decorator.errors import capture_err +from misskaty.core.decorator.ratelimiter import ratelimiter from misskaty.core.decorator.permissions import adminsOnly from misskaty.core.keyboard import ikb from misskaty.core.message_utils import * @@ -44,14 +45,15 @@ You can use markdown or html to save text too. @app.on_message(filters.command("addfilter") & ~filters.private) @adminsOnly("can_change_info") +@ratelimiter async def save_filters(_, m): if len(m.command) == 1 or not m.reply_to_message: - return await kirimPesan(m, "**Usage:**\nReply to a text or sticker with /filter [FILTER_NAME] to save it.") + return await kirimPesan(m, "**Usage:**\nReply to a text or sticker with /addfilter [FILTER_NAME] to save it.") if not m.reply_to_message.text and not m.reply_to_message.sticker: return await kirimPesan(m, "__**You can only save text or stickers in filters for now.**__") name = m.text.split(None, 1)[1].strip() if not name: - return await kirimPesan(m, "**Usage:**\n__/filter [FILTER_NAME]__") + return await kirimPesan(m, "**Usage:**\n__/addfilter [FILTER_NAME]__") chat_id = m.chat.id _type = "text" if m.reply_to_message.text else "sticker" _filter = { @@ -64,6 +66,7 @@ async def save_filters(_, m): @app.on_message(filters.command("filters") & ~filters.private) @capture_err +@ratelimiter async def get_filterss(_, m): _filters = await get_filters_names(m.chat.id) if not _filters: @@ -77,12 +80,13 @@ async def get_filterss(_, m): @app.on_message(filters.command("stopfilter") & ~filters.private) @adminsOnly("can_change_info") +@ratelimiter async def del_filter(_, m): if len(m.command) < 2: - return await kirimPesan(m, "**Usage:**\n__/stop [FILTER_NAME]__") + return await kirimPesan(m, "**Usage:**\n__/stopfilter [FILTER_NAME]__") name = m.text.split(None, 1)[1].strip() if not name: - return await kirimPesan(m, "**Usage:**\n__/stop [FILTER_NAME]__") + return await kirimPesan(m, "**Usage:**\n__/stopfilter [FILTER_NAME]__") chat_id = m.chat.id deleted = await delete_filter(chat_id, name) if deleted: @@ -95,7 +99,6 @@ async def del_filter(_, m): filters.text & ~filters.private & ~filters.via_bot & ~filters.forwarded, group=2, ) -@capture_err async def filters_re(_, message): text = message.text.lower().strip() if not text: diff --git a/misskaty/plugins/genss.py b/misskaty/plugins/genss.py index 6e27c9d8..b9e20221 100644 --- a/misskaty/plugins/genss.py +++ b/misskaty/plugins/genss.py @@ -18,7 +18,7 @@ from pyrogram.types import InlineKeyboardMarkup from misskaty import BOT_USERNAME, app from misskaty.core.decorator.errors import capture_err -from misskaty.core.decorator.pyro_cooldown import wait +from misskaty.core.decorator.ratelimiter import ratelimiter from misskaty.core.message_utils import * from misskaty.helper import gen_ik_buttons, get_duration, is_url, progress_for_pyrogram, screenshot_flink, take_ss from misskaty.vars import COMMAND_HANDLER @@ -32,8 +32,9 @@ __HELP__ = """" """ -@app.on_message(filters.command(["genss"], COMMAND_HANDLER) & wait(30)) +@app.on_message(filters.command(["genss"], COMMAND_HANDLER)) @capture_err +@ratelimiter async def genss(client, m): if not m.from_user: return @@ -105,5 +106,6 @@ async def genss(client, m): @app.on_callback_query(filters.regex(r"^scht")) +@ratelimiter async def _(c, m): asyncio.create_task(screenshot_flink(c, m)) diff --git a/misskaty/plugins/grup_tools.py b/misskaty/plugins/grup_tools.py index 41033c26..4d243919 100644 --- a/misskaty/plugins/grup_tools.py +++ b/misskaty/plugins/grup_tools.py @@ -11,6 +11,7 @@ from pyrogram.types import ChatMemberUpdated, InlineKeyboardButton, InlineKeyboa from database.users_chats_db import db from misskaty import BOT_USERNAME, app +from misskaty.core.decorator.ratelimiter import ratelimiter from misskaty.core.decorator.errors import asyncify, capture_err from misskaty.helper.http import http from misskaty.vars import COMMAND_HANDLER, LOG_CHANNEL, SUDO, SUPPORT_CHAT @@ -320,6 +321,7 @@ async def gen_invite(bot, message): @app.on_message(filters.command(["adminlist"], COMMAND_HANDLER)) @capture_err +@ratelimiter async def adminlist(_, message): if message.chat.type == enums.ChatType.PRIVATE: return await message.reply("Perintah ini hanya untuk grup") @@ -336,6 +338,7 @@ async def adminlist(_, message): @app.on_message(filters.command(["kickme"], COMMAND_HANDLER)) @capture_err +@ratelimiter async def kickme(_, message): reason = None if len(message.text.split()) >= 2: diff --git a/misskaty/plugins/imdb_search.py b/misskaty/plugins/imdb_search.py index 5ba9220d..8614eab0 100644 --- a/misskaty/plugins/imdb_search.py +++ b/misskaty/plugins/imdb_search.py @@ -20,8 +20,8 @@ from database.imdb_db import * from misskaty import BOT_USERNAME, app from misskaty.core.message_utils import * from misskaty.core.decorator.errors import capture_err -from misskaty.helper.http import http -from misskaty.helper.tools import get_random_string, search_jw, GENRES_EMOJI +from misskaty.core.decorator.ratelimiter import ratelimiter +from misskaty.helper import http, get_random_string, search_jw, GENRES_EMOJI from misskaty.vars import COMMAND_HANDLER LOGGER = logging.getLogger(__name__) @@ -32,6 +32,7 @@ headers = {"User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_5) AppleWe # IMDB Choose Language @app.on_message(filters.command(["imdb"], COMMAND_HANDLER)) @capture_err +@ratelimiter async def imdb_choose(_, m): if len(m.command) == 1: return await kirimPesan(m, f"ℹ️ Please add query after CMD!\nEx: /{m.command[0]} Jurassic World") @@ -62,6 +63,7 @@ async def imdb_choose(_, m): @app.on_callback_query(filters.regex("^imdbset")) +@ratelimiter async def imdbsetlang(client, query): i, uid = query.data.split("#") if query.from_user.id != int(uid): @@ -79,6 +81,7 @@ async def imdbsetlang(client, query): @app.on_callback_query(filters.regex("^setimdb")) +@ratelimiter async def imdbsetlang(client, query): i, lang, uid = query.data.split("#") if query.from_user.id != int(uid): @@ -195,6 +198,7 @@ async def imdb_search_en(kueri, message): @app.on_callback_query(filters.regex("^imdbcari")) +@ratelimiter async def imdbcari(client, query): BTN = [] i, lang, msg, uid = query.data.split("#") @@ -279,6 +283,7 @@ async def imdbcari(client, query): @app.on_callback_query(filters.regex("^imdbres_id")) +@ratelimiter async def imdb_id_callback(_, query): i, userid, movie = query.data.split("#") if query.from_user.id != int(userid): @@ -399,6 +404,7 @@ async def imdb_id_callback(_, query): @app.on_callback_query(filters.regex("^imdbres_en")) +@ratelimiter async def imdb_en_callback(bot, query): i, userid, movie = query.data.split("#") if query.from_user.id != int(userid): diff --git a/misskaty/plugins/inkick_user.py b/misskaty/plugins/inkick_user.py index 237ac2d7..ed49ee0b 100644 --- a/misskaty/plugins/inkick_user.py +++ b/misskaty/plugins/inkick_user.py @@ -10,17 +10,19 @@ from pyrogram.errors.exceptions.bad_request_400 import ( from pyrogram.errors.exceptions.forbidden_403 import ChatWriteForbidden from misskaty import app +from misskaty.core.decorator.ratelimiter import ratelimiter from misskaty.core.message_utils import editPesan, kirimPesan from misskaty.vars import COMMAND_HANDLER __MODULE__ = "Inkick" __HELP__ = """" /instatus - View member status in group. -/dkick - Remove deleted account from group. +/ban_ghosts - Remove deleted account from group. """ @app.on_message(filters.incoming & ~filters.private & filters.command(["inkick"], COMMAND_HANDLER)) +@ratelimiter async def inkick(_, message): if message.sender_chat: return await message.reply("This feature not available for channel.") @@ -60,6 +62,7 @@ async def inkick(_, message): # Kick User Without Username @app.on_message(filters.incoming & ~filters.private & filters.command(["uname"], COMMAND_HANDLER)) +@ratelimiter async def uname(_, message): if message.sender_chat: return await message.reply("This feature not available for channel.") @@ -95,7 +98,8 @@ async def uname(_, message): @app.on_message(filters.incoming & ~filters.private & filters.command(["ban_ghosts"], COMMAND_HANDLER)) -async def dkick(client, message): +@ratelimiter +async def rm_delacc(client, message): if message.sender_chat: return await message.reply("This feature not available for channel.") user = await app.get_chat_member(message.chat.id, message.from_user.id) @@ -127,6 +131,7 @@ async def dkick(client, message): @app.on_message(filters.incoming & ~filters.private & filters.command(["instatus"], COMMAND_HANDLER)) +@ratelimiter async def instatus(client, message): if message.sender_chat: return await kirimPesan(message, "Not supported channel.") diff --git a/misskaty/plugins/inline_search.py b/misskaty/plugins/inline_search.py index c2f79b18..c33b5334 100644 --- a/misskaty/plugins/inline_search.py +++ b/misskaty/plugins/inline_search.py @@ -21,6 +21,7 @@ from pyrogram.types import ( ) from misskaty import BOT_USERNAME, app, user +from misskaty.core.decorator.ratelimiter import ratelimiter from misskaty.helper import post_to_telegraph, http, GENRES_EMOJI, search_jw from misskaty.plugins.misc_tools import get_content from utils import demoji @@ -98,7 +99,7 @@ async def inline_menu(_, inline_query: InlineQuery): kueri = inline_query.query.split(None, 1)[1].strip() headers = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) " "Chrome/61.0.3163.100 Safari/537.36"} jsonapi = await http.get( - "https://github.com/yasirarism/telegram-bot-api-spec/raw/main/api.json", + "https://github.com/PaulSonOfLars/telegram-bot-api-spec/raw/main/api.json", headers=headers, follow_redirects=True, ) @@ -500,6 +501,7 @@ async def inline_menu(_, inline_query: InlineQuery): @app.on_callback_query(filters.regex(r"prvtmsg\((.+)\)")) +@ratelimiter async def prvt_msg(_, c_q): msg_id = str(c_q.matches[0].group(1)) @@ -516,6 +518,7 @@ async def prvt_msg(_, c_q): @app.on_callback_query(filters.regex(r"destroy\((.+)\)")) +@ratelimiter async def destroy_msg(_, c_q): msg_id = str(c_q.matches[0].group(1)) @@ -534,6 +537,7 @@ async def destroy_msg(_, c_q): @app.on_callback_query(filters.regex("^imdbinl#")) +@ratelimiter async def imdb_inl(_, query): i, user, movie = query.data.split("#") if user == f"{query.from_user.id}": diff --git a/misskaty/plugins/json.py b/misskaty/plugins/json.py index 519d663a..f626d4a8 100644 --- a/misskaty/plugins/json.py +++ b/misskaty/plugins/json.py @@ -12,11 +12,13 @@ from pyrogram import filters from pyrogram.types import InlineKeyboardButton, InlineKeyboardMarkup from misskaty import app +from misskaty.core.decorator.ratelimiter import ratelimiter from misskaty.vars import COMMAND_HANDLER # View Structure Telegram Message As JSON @app.on_message(filters.command(["json"], COMMAND_HANDLER)) +@ratelimiter async def jsonify(_, message): the_real_message = None reply_to_id = None diff --git a/misskaty/plugins/karma.py b/misskaty/plugins/karma.py index 8ec92683..939405fb 100644 --- a/misskaty/plugins/karma.py +++ b/misskaty/plugins/karma.py @@ -13,6 +13,7 @@ from database.karma_db import ( from misskaty import app from misskaty.core.decorator.errors import capture_err from misskaty.core.decorator.permissions import adminsOnly +from misskaty.core.decorator.ratelimiter import ratelimiter from misskaty.helper.functions import alpha_to_int, int_to_alpha __MODULE__ = "Karma" @@ -116,6 +117,7 @@ async def downvote(_, message): @app.on_message(filters.command("karma") & filters.group) @capture_err +@ratelimiter async def command_karma(_, message): chat_id = message.chat.id if not message.reply_to_message: @@ -162,6 +164,7 @@ async def command_karma(_, message): @app.on_message(filters.command("karma_toggle") & ~filters.private) @adminsOnly +@ratelimiter async def captcha_state(_, message): usage = "**Usage:**\n/karma_toggle [ENABLE|DISABLE]" if len(message.command) != 2: diff --git a/misskaty/plugins/mediainfo.py b/misskaty/plugins/mediainfo.py index 7afb6c98..330d8425 100644 --- a/misskaty/plugins/mediainfo.py +++ b/misskaty/plugins/mediainfo.py @@ -15,36 +15,37 @@ from pyrogram.types import InlineKeyboardButton, InlineKeyboardMarkup from misskaty import app from misskaty.core.message_utils import * -from misskaty.core.decorator.pyro_cooldown import wait +from misskaty.core.decorator.ratelimiter import ratelimiter from misskaty.helper import http, progress_for_pyrogram, runcmd, post_to_telegraph from misskaty.vars import COMMAND_HANDLER from utils import get_file_id -@app.on_message(filters.command(["mediainfo"], COMMAND_HANDLER) & wait(30)) +@app.on_message(filters.command(["mediainfo"], COMMAND_HANDLER)) +@ratelimiter async def mediainfo(client, message): if not message.from_user: return if message.reply_to_message and message.reply_to_message.media: - process = await kirimPesan(message, "`Sedang memproses, lama waktu tergantung ukuran file kamu...`", quote=True) + process = await kirimPesan(message, "`Processing, total time is based size of your files...`", quote=True) file_info = get_file_id(message.reply_to_message) if file_info is None: - return await editPesan(process, "Balas ke format media yang valid") + return await editPesan(process, "Please reply to valid media.") c_time = time.time() file_path = await message.reply_to_message.download( progress=progress_for_pyrogram, - progress_args=("trying to download, sabar yakk..", process, c_time), + progress_args=("Trying to download..", process, c_time), ) output_ = await runcmd(f'mediainfo "{file_path}"') out = output_[0] if len(output_) != 0 else None body_text = f""" - MissKatyBot MediaInfo - JSON - {file_info}.type +MissKatyBot MediaInfo +JSON +{file_info}.type - DETAILS - {out or 'Not Supported'} +DETAILS +{out or 'Not Supported'} """ text_ = file_info.message_type try: diff --git a/misskaty/plugins/memify.py b/misskaty/plugins/memify.py index 21534698..becad598 100644 --- a/misskaty/plugins/memify.py +++ b/misskaty/plugins/memify.py @@ -5,6 +5,7 @@ from PIL import Image, ImageDraw, ImageFont from pyrogram import filters from misskaty import app +from misskaty.core.decorator.ratelimiter import ratelimiter from misskaty.core.decorator.errors import capture_err from misskaty.vars import COMMAND_HANDLER @@ -134,6 +135,7 @@ async def draw_meme_text(image_path, text): @app.on_message(filters.command(["mmf"], COMMAND_HANDLER)) @capture_err +@ratelimiter async def memify(client, message): if message.reply_to_message and (message.reply_to_message.sticker or message.reply_to_message.photo): try: diff --git a/misskaty/plugins/misc_tools.py b/misskaty/plugins/misc_tools.py index e91c46fa..69ef4126 100644 --- a/misskaty/plugins/misc_tools.py +++ b/misskaty/plugins/misc_tools.py @@ -25,6 +25,7 @@ from pyrogram.types import CallbackQuery, InlineKeyboardButton, InlineKeyboardMa from misskaty import BOT_USERNAME, app from misskaty.core.decorator.errors import capture_err +from misskaty.core.decorator.ratelimiter import ratelimiter from misskaty.core.message_utils import hapusPesan, kirimPesan from misskaty.helper.http import http from misskaty.helper.tools import rentry @@ -54,6 +55,7 @@ def remove_html_tags(text): @app.on_message(filters.command("readqr", COMMAND_HANDLER)) +@ratelimiter async def readqr(c, m): if not m.reply and not m.reply.media and not m.reply.photo: return await m.reply("Please reply photo that contain valid QR Code.") @@ -68,6 +70,7 @@ async def readqr(c, m): @app.on_message(filters.command("createqr", COMMAND_HANDLER)) +@ratelimiter async def makeqr(c, m): if m.reply_to_message and m.reply_to_message.text: teks = m.reply_to_message.text @@ -103,6 +106,7 @@ async def stackoverflow(client, message): @app.on_message(filters.command(["google"], COMMAND_HANDLER)) @capture_err +@ratelimiter async def gsearch(client, message): if len(message.command) == 1: return await message.reply("Give a query to search in Google!") @@ -150,6 +154,7 @@ async def gsearch(client, message): @app.on_message(filters.command(["tr", "trans", "translate"], COMMAND_HANDLER)) @capture_err +@ratelimiter async def translate(client, message): if message.reply_to_message and (message.reply_to_message.text or message.reply_to_message.caption): target_lang = "id" if len(message.command) == 1 else message.text.split()[1] @@ -175,6 +180,7 @@ async def translate(client, message): @app.on_message(filters.command(["tts"], COMMAND_HANDLER)) @capture_err +@ratelimiter async def tts(_, message): if message.reply_to_message and (message.reply_to_message.text or message.reply_to_message.caption): if len(message.text.split()) == 1: @@ -207,6 +213,7 @@ async def tts(_, message): @app.on_message(filters.command(["tosticker"], COMMAND_HANDLER)) @capture_err +@ratelimiter async def tostick(client, message): try: if not message.reply_to_message or not message.reply_to_message.photo: @@ -223,6 +230,7 @@ async def tostick(client, message): @app.on_message(filters.command(["toimage"], COMMAND_HANDLER)) @capture_err +@ratelimiter async def topho(client, message): try: if not message.reply_to_message or not message.reply_to_message.sticker: @@ -241,6 +249,7 @@ async def topho(client, message): @app.on_message(filters.command(["id"], COMMAND_HANDLER)) +@ratelimiter async def showid(client, message): chat_type = message.chat.type if chat_type == "private": @@ -274,6 +283,7 @@ async def showid(client, message): @app.on_message(filters.command(["info"], COMMAND_HANDLER)) +@ratelimiter async def who_is(client, message): # https://github.com/SpEcHiDe/PyroGramBot/blob/master/pyrobot/plugins/admemes/whois.py#L19 if message.sender_chat: @@ -295,11 +305,11 @@ async def who_is(client, message): message_out_str += f"➲Last Name: {last_name}\n" message_out_str += f"➲Telegram ID: {from_user.id}\n" username = from_user.username or "None" - dc_id = from_user.dc_id or "[User Doesnt Have A Valid DP]" + dc_id = from_user.dc_id or "[User Doesn't Have Profile Pic]" message_out_str += f"➲Data Centre: {dc_id}\n" message_out_str += f"➲User Name: @{username}\n" - message_out_str += f"➲User 𝖫𝗂𝗇𝗄: Click Here\n" - if message.chat.type in (("supergroup", "channel")): + message_out_str += f"➲User Link: Click Here\n" + if message.chat.type.value in (("supergroup", "channel")): try: chat_member_p = await message.chat.get_member(from_user.id) joined_date = datetime.fromtimestamp(chat_member_p.joined_date or time.time()).strftime("%Y.%m.%d %H:%M:%S") @@ -331,6 +341,7 @@ async def who_is(client, message): @app.on_callback_query(filters.regex("^close")) +@ratelimiter async def close_callback(bot: Client, query: CallbackQuery): i, userid = query.data.split("#") if query.from_user.id != int(userid): @@ -359,6 +370,7 @@ async def mdlapi(title): @app.on_message(filters.command(["mdl"], COMMAND_HANDLER)) @capture_err +@ratelimiter async def mdlsearch(client, message): if " " in message.text: r, title = message.text.split(None, 1) @@ -385,6 +397,7 @@ async def mdlsearch(client, message): @app.on_callback_query(filters.regex("^mdls")) +@ratelimiter async def mdl_callback(bot: Client, query: CallbackQuery): i, user, msg_id, slug = query.data.split("#") if user == f"{query.from_user.id}": diff --git a/misskaty/plugins/nightmode.py b/misskaty/plugins/nightmode.py index 00ac2e15..f34f803e 100644 --- a/misskaty/plugins/nightmode.py +++ b/misskaty/plugins/nightmode.py @@ -13,6 +13,7 @@ from pyrogram.types import ( ) from misskaty import BOT_USERNAME, app +from misskaty.core.decorator.ratelimiter import ratelimiter from misskaty.vars import LOG_CHANNEL, NIGHTMODE @@ -190,6 +191,7 @@ async def job_open_ymoviez(): @app.on_callback_query(filters.regex(r"^nightmd$")) +@ratelimiter async def callbackanightmd(c: Client, q: CallbackQuery): await q.answer( f"🔖 Hai, Aku {BOT_USERNAME} dibuat menggunakan Framework Pyrogram v{__version__} dan Python 3.10.\n\nMau buat bot seperti ini? Yuuk belajar di @botindonesia\nOwner: @YasirArisM", diff --git a/misskaty/plugins/notes.py b/misskaty/plugins/notes.py index 9b87aeed..b825d531 100644 --- a/misskaty/plugins/notes.py +++ b/misskaty/plugins/notes.py @@ -28,6 +28,7 @@ from pyrogram import filters from database.notes_db import delete_note, get_note, get_note_names, save_note from misskaty import app from misskaty.core.decorator.errors import capture_err +from misskaty.core.decorator.ratelimiter import ratelimiter from misskaty.core.decorator.permissions import adminsOnly from misskaty.core.keyboard import ikb from misskaty.helper.functions import extract_text_and_keyb @@ -45,6 +46,7 @@ __HELP__ = """/notes To Get All The Notes In The Chat. @app.on_message(filters.command("addnote") & ~filters.private) @adminsOnly("can_change_info") +@ratelimiter async def save_notee(_, message): if len(message.command) < 2 or not message.reply_to_message: await message.reply( @@ -70,6 +72,7 @@ async def save_notee(_, message): @app.on_message(filters.command("notes") & ~filters.private) @capture_err +@ratelimiter async def get_notes(_, message): message.text.split()[0][0] chat_id = message.chat.id @@ -87,6 +90,7 @@ async def get_notes(_, message): @app.on_message(filters.regex(r"^#.+") & filters.text & ~filters.private) @capture_err +@ratelimiter async def get_one_note(_, message): name = message.text.replace("#", "", 1) if not name: @@ -111,6 +115,7 @@ async def get_one_note(_, message): @app.on_message(filters.command("delnote") & ~filters.private) @adminsOnly("can_change_info") +@ratelimiter async def del_note(_, message): if len(message.command) == 1: return await message.reply("**Usage**\n__/delnote [NOTE_NAME]__") diff --git a/misskaty/plugins/ocr.py b/misskaty/plugins/ocr.py index 87336620..05ead49b 100644 --- a/misskaty/plugins/ocr.py +++ b/misskaty/plugins/ocr.py @@ -8,10 +8,11 @@ import os from pyrogram import filters -from telegraph import upload_file +from telegraph.aio import Telegraph from misskaty import app from misskaty.core.message_utils import * +from misskaty.core.decorator.ratelimiter import ratelimiter from misskaty.core.decorator.errors import capture_err from misskaty.helper.http import http from misskaty.vars import COMMAND_HANDLER @@ -22,6 +23,7 @@ __HELP__ = "/ocr [reply to photo] - Read Text From Image" @app.on_message(filters.command(["ocr"], COMMAND_HANDLER)) @capture_err +@ratelimiter async def ocr(_, m): reply = m.reply_to_message if not reply or not reply.photo and not reply.sticker: @@ -31,8 +33,8 @@ async def ocr(_, m): file_path = await reply.download() if reply.sticker: file_path = await reply.download(f"ocr_{m.from_user.id}.jpg") - response = upload_file(file_path) - url = f"https://telegra.ph{response[0]}" + response = await Telegraph().upload_file(file_path) + url = f"https://telegra.ph{response[0]['src']}" req = ( await http.get( f"https://script.google.com/macros/s/AKfycbwURISN0wjazeJTMHTPAtxkrZTWTpsWIef5kxqVGoXqnrzdLdIQIfLO7jsR5OQ5GO16/exec?url={url}", diff --git a/misskaty/plugins/paste.py b/misskaty/plugins/paste.py index 0b9019b2..a25b69c6 100644 --- a/misskaty/plugins/paste.py +++ b/misskaty/plugins/paste.py @@ -1,7 +1,6 @@ """ - * @author yasir - * @date 2022-12-01 09:12:27 - * @lastModified 2022-12-01 09:32:31 + * @author Yasir Aris M + * @created 2022-12-01 09:12:27 * @projectName MissKatyPyro * Copyright @YasirPedia All rights reserved """ @@ -13,6 +12,7 @@ from pyrogram import filters from pyrogram.types import InlineKeyboardButton, InlineKeyboardMarkup from misskaty import app +from misskaty.core.decorator.ratelimiter import ratelimiter from misskaty.core.message_utils import * from misskaty.helper import http, rentry, post_to_telegraph from misskaty.vars import COMMAND_HANDLER @@ -67,6 +67,7 @@ pattern = compiles(r"^text/|json$|yaml$|xml$|toml$|x-sh$|x-shellscript$|x-subrip @app.on_message(filters.command(["tgraph"], COMMAND_HANDLER)) +@ratelimiter async def telegraph_paste(_, message): reply = message.reply_to_message if not reply and len(message.command) < 2: @@ -139,6 +140,7 @@ async def telegraph_paste(_, message): # Default Paste to Wastebin using Deta @app.on_message(filters.command(["paste"], COMMAND_HANDLER)) +@ratelimiter async def wastepaste(_, message): reply = message.reply_to_message target = str(message.command[0]).split("@", maxsplit=1)[0] @@ -203,6 +205,7 @@ async def wastepaste(_, message): # Nekobin Paste @app.on_message(filters.command(["neko"], COMMAND_HANDLER)) +@ratelimiter async def nekopaste(_, message): reply = message.reply_to_message target = str(message.command[0]).split("@", maxsplit=1)[0] @@ -260,6 +263,7 @@ async def nekopaste(_, message): # Paste as spacebin @app.on_message(filters.command(["sbin"], COMMAND_HANDLER)) +@ratelimiter async def spacebinn(_, message): reply = message.reply_to_message target = str(message.command[0]).split("@", maxsplit=1)[0] @@ -319,6 +323,7 @@ async def spacebinn(_, message): # Rentry paste @app.on_message(filters.command(["rentry"], COMMAND_HANDLER)) +@ratelimiter async def rentrypaste(_, message): reply = message.reply_to_message target = str(message.command[0]).split("@", maxsplit=1)[0] @@ -375,6 +380,7 @@ async def rentrypaste(_, message): # Tempaste pastebin @app.on_message(filters.command(["temp_paste"], COMMAND_HANDLER)) +@ratelimiter async def tempaste(_, message): reply = message.reply_to_message target = str(message.command[0]).split("@", maxsplit=1)[0] diff --git a/misskaty/plugins/ping.py b/misskaty/plugins/ping.py index 08acd06b..550463e4 100644 --- a/misskaty/plugins/ping.py +++ b/misskaty/plugins/ping.py @@ -13,11 +13,13 @@ from subprocess import run as srun from pyrogram import filters from misskaty import app, botStartTime +from misskaty.core.decorator.ratelimiter import ratelimiter from misskaty.helper.human_read import get_readable_time from misskaty.vars import COMMAND_HANDLER @app.on_message(filters.command(["ping"], COMMAND_HANDLER)) +@ratelimiter async def ping(_, message): currentTime = get_readable_time(time.time() - botStartTime) start_t = time.time() @@ -31,6 +33,7 @@ async def ping(_, message): @app.on_message(filters.command(["ping_dc"], COMMAND_HANDLER)) +@ratelimiter async def ping_handler(_, message): m = await message.reply("Pinging datacenters...") async with Lock(): diff --git a/misskaty/plugins/pypi_search.py b/misskaty/plugins/pypi_search.py index 6a692776..42e9bdff 100644 --- a/misskaty/plugins/pypi_search.py +++ b/misskaty/plugins/pypi_search.py @@ -9,6 +9,7 @@ from pykeyboard import InlineButton, InlineKeyboard from pyrogram import filters from misskaty import app +from misskaty.core.decorator.ratelimiter import ratelimiter from misskaty.core.message_utils import * from misskaty.helper.http import http from misskaty.plugins.web_scraper import split_arr, headers @@ -40,6 +41,7 @@ async def getDataPypi(msg, kueri, CurrentPage, user): @app.on_message(filters.command(["pypi"], COMMAND_HANDLER)) +@ratelimiter async def pypi_s(client, message): kueri = " ".join(message.command[1:]) if not kueri: @@ -58,6 +60,7 @@ async def pypi_s(client, message): @app.on_callback_query(filters.create(lambda _, __, query: "page_pypi#" in query.data)) +@ratelimiter async def pypipage_callback(client, callback_query): if callback_query.from_user.id != int(callback_query.data.split("#")[3]): return await callback_query.answer("Not yours..", True) @@ -82,6 +85,7 @@ async def pypipage_callback(client, callback_query): @app.on_callback_query(filters.create(lambda _, __, query: "pypidata#" in query.data)) +@ratelimiter async def pypi_getdata(_, callback_query): if callback_query.from_user.id != int(callback_query.data.split("#")[3]): return await callback_query.answer("Not yours..", True) diff --git a/misskaty/plugins/quotly.py b/misskaty/plugins/quotly.py index 5cca75e4..f7e82d55 100644 --- a/misskaty/plugins/quotly.py +++ b/misskaty/plugins/quotly.py @@ -5,6 +5,7 @@ from pyrogram.types import Message from misskaty import app from misskaty.helper.http import http +from misskaty.core.decorator.ratelimiter import ratelimiter __MODULE__ = "Fun" __HELP__ = """ @@ -197,6 +198,7 @@ def isArgInt(txt) -> list: @app.on_message(filters.command(["q"]) & filters.reply) +@ratelimiter async def msg_quotly_cmd(c: Client, m: Message): if len(m.text.split()) > 1: check_arg = isArgInt(m.command[1]) diff --git a/misskaty/plugins/sangmata.py b/misskaty/plugins/sangmata.py index 06863ec5..172a0419 100644 --- a/misskaty/plugins/sangmata.py +++ b/misskaty/plugins/sangmata.py @@ -3,6 +3,7 @@ from pyrogram import filters from database.sangmata_db import * from misskaty import app from misskaty.core.decorator.permissions import adminsOnly +from misskaty.core.decorator.ratelimiter import ratelimiter from misskaty.core.message_utils import kirimPesan from misskaty.vars import COMMAND_HANDLER @@ -42,6 +43,7 @@ async def cek_mataa(_, m): @app.on_message(filters.group & filters.command("sangmata_set", COMMAND_HANDLER) & ~filters.bot & ~filters.via_bot) @adminsOnly("can_change_info") +@ratelimiter async def set_mataa(_, m): if len(m.command) == 1: return await kirimPesan(m, f"Use /{m.command[0]} on, to enable sangmata. If you want disable, you can use off parameter.") diff --git a/misskaty/plugins/sed.py b/misskaty/plugins/sed.py index 1b1cd01b..5ccd86c9 100644 --- a/misskaty/plugins/sed.py +++ b/misskaty/plugins/sed.py @@ -8,9 +8,11 @@ from pyrogram import filters from pyrogram.errors import MessageEmpty from misskaty import app +from misskaty.core.decorator.ratelimiter import ratelimiter @app.on_message(filters.regex(r"^s/(.+)?/(.+)?(/.+)?") & filters.reply) +@ratelimiter async def sed(c, m): exp = regex.split(r"(?{stickerid}".format(stickerid=m.reply_to_message.sticker.file_id)) @app.on_message(filters.command("unkang", COMMAND_HANDLER) & filters.reply) +@ratelimiter async def getstickerid(c, m): if m.reply_to_message.sticker: pp = await m.reply_text("Trying to remove from pack..") @@ -87,6 +91,7 @@ async def getstickerid(c, m): @app.on_message(filters.command(["curi", "kang"], COMMAND_HANDLER)) +@ratelimiter async def kang_sticker(c, m): if not m.from_user: return await m.reply_text("You are anon admin, kang stickers in my pm.") diff --git a/misskaty/plugins/sub_extractor.py b/misskaty/plugins/sub_extractor.py index 50b1849c..41056c47 100644 --- a/misskaty/plugins/sub_extractor.py +++ b/misskaty/plugins/sub_extractor.py @@ -1,6 +1,6 @@ """ * @author yasir - * @date 2022-12-01 09:12:27 + * @created 2022-12-01 09:12:27 * @projectName MissKatyPyro * Copyright @YasirPedia All rights reserved """ @@ -17,6 +17,7 @@ from pyrogram.types import InlineKeyboardButton, InlineKeyboardMarkup from misskaty import app from misskaty.core.message_utils import * +from misskaty.core.decorator.ratelimiter import ratelimiter from misskaty.core.decorator.errors import capture_err from misskaty.helper.pyro_progress import progress_for_pyrogram from misskaty.helper.tools import get_random_string @@ -61,6 +62,7 @@ def get_subname(lang, url, format): @app.on_message(filters.command(["ceksub", "extractmedia"], COMMAND_HANDLER)) +@ratelimiter async def ceksub(_, m): cmd = m.text.split(" ", 1) if len(cmd) == 1: @@ -107,6 +109,7 @@ async def ceksub(_, m): @app.on_message(filters.command(["converttosrt"], COMMAND_HANDLER)) @capture_err +@ratelimiter async def convertsrt(c, m): reply = m.reply_to_message if not reply and reply.document and (reply.document.file_name.endswith(".vtt") or reply.document.file_name.endswith(".ass")): @@ -133,6 +136,7 @@ async def convertsrt(c, m): @app.on_callback_query(filters.regex(r"^streamextract#")) +@ratelimiter async def stream_extract(bot, update): cb_data = update.data usr = update.message.reply_to_message diff --git a/misskaty/plugins/ubot_plugin.py b/misskaty/plugins/ubot_plugin.py index b42dd6f5..51741532 100644 --- a/misskaty/plugins/ubot_plugin.py +++ b/misskaty/plugins/ubot_plugin.py @@ -1,7 +1,6 @@ """ * @author yasir * @date 2022-12-01 09:12:27 - * @lastModified 2022-12-01 09:32:31 * @projectName MissKatyPyro * Copyright @YasirPedia All rights reserved """ diff --git a/misskaty/plugins/urban_dict.py b/misskaty/plugins/urban_dict.py index 49199134..f93ee020 100644 --- a/misskaty/plugins/urban_dict.py +++ b/misskaty/plugins/urban_dict.py @@ -2,6 +2,7 @@ import asyncio from pykeyboard import InlineKeyboard from pyrogram import filters +from misskaty.core.decorator.ratelimiter import ratelimiter from misskaty.helper.http import http from misskaty import app from misskaty.vars import COMMAND_HANDLER @@ -32,6 +33,7 @@ async def getData(chat_id, message_id, GetWord, CurrentPage): @app.on_message(filters.command(["ud"], COMMAND_HANDLER)) +@ratelimiter async def urbanDictionary(client, message): if not message.from_user: return @@ -51,6 +53,7 @@ async def urbanDictionary(client, message): @app.on_callback_query(filters.create(lambda _, __, query: "pagination_urban#" in query.data)) +@ratelimiter async def ud_callback(client, callback_query): message_id = callback_query.message.id chat_id = callback_query.message.chat.id diff --git a/misskaty/plugins/web_scraper.py b/misskaty/plugins/web_scraper.py index 57169baa..3f4228b1 100644 --- a/misskaty/plugins/web_scraper.py +++ b/misskaty/plugins/web_scraper.py @@ -1,7 +1,6 @@ """ * @author yasir - * @date 2022-12-01 09:12:27 - * @lastModified 2023-01-11 12:23:31 + * @created 2022-12-01 09:12:27 * @projectName MissKatyPyro * Copyright @YasirPedia All rights reserved """ @@ -10,6 +9,7 @@ import logging from bs4 import BeautifulSoup from pykeyboard import InlineKeyboard, InlineButton from pyrogram import filters +from misskaty.core.decorator.ratelimiter import ratelimiter from misskaty.helper.http import http from misskaty.helper.kuso_utils import Kusonime from misskaty import app @@ -336,6 +336,7 @@ async def getDataGomov(msg, kueri, CurrentPage, user): # Terbit21 CMD @app.on_message(filters.command(["terbit21"], COMMAND_HANDLER)) +@ratelimiter async def terbit21_s(client, message): kueri = " ".join(message.command[1:]) if not kueri: @@ -353,6 +354,7 @@ async def terbit21_s(client, message): # LK21 CMD @app.on_message(filters.command(["lk21"], COMMAND_HANDLER)) +@ratelimiter async def lk21_s(client, message): message.chat.id kueri = " ".join(message.command[1:]) @@ -371,6 +373,7 @@ async def lk21_s(client, message): # Pahe CMD @app.on_message(filters.command(["pahe"], COMMAND_HANDLER)) +@ratelimiter async def pahe_s(client, message): message.chat.id kueri = " ".join(message.command[1:]) @@ -389,6 +392,7 @@ async def pahe_s(client, message): # Gomov CMD @app.on_message(filters.command(["gomov"], COMMAND_HANDLER)) +@ratelimiter async def gomov_s(client, message): kueri = " ".join(message.command[1:]) if not kueri: @@ -408,6 +412,7 @@ async def gomov_s(client, message): # MelongMovie CMD @app.on_message(filters.command(["melongmovie"], COMMAND_HANDLER)) +@ratelimiter async def melong_s(client, message): kueri = " ".join(message.command[1:]) if not kueri: @@ -427,6 +432,7 @@ async def melong_s(client, message): # Savefilm21 CMD @app.on_message(filters.command(["savefilm21"], COMMAND_HANDLER)) +@ratelimiter async def savefilm_s(client, message): kueri = " ".join(message.command[1:]) if not kueri: @@ -446,6 +452,7 @@ async def savefilm_s(client, message): # Kusonime CMD @app.on_message(filters.command(["kusonime"], COMMAND_HANDLER)) +@ratelimiter async def kusonime_s(client, message): kueri = " ".join(message.command[1:]) if not kueri: @@ -467,6 +474,7 @@ async def kusonime_s(client, message): # Lendrive CMD @app.on_message(filters.command(["lendrive"], COMMAND_HANDLER)) +@ratelimiter async def lendrive_s(client, message): kueri = " ".join(message.command[1:]) if not kueri: @@ -486,6 +494,7 @@ async def lendrive_s(client, message): # Movieku CMD @app.on_message(filters.command(["movieku"], COMMAND_HANDLER)) +@ratelimiter async def movieku_s(client, message): kueri = " ".join(message.command[1:]) if not kueri: @@ -503,6 +512,7 @@ async def movieku_s(client, message): # Savefillm21 Page Callback @app.on_callback_query(filters.create(lambda _, __, query: "page_savefilm#" in query.data)) +@ratelimiter async def savefilmpage_callback(client, callback_query): if callback_query.from_user.id != int(callback_query.data.split("#")[3]): return await callback_query.answer("Not yours..", True) @@ -528,6 +538,7 @@ async def savefilmpage_callback(client, callback_query): # Kuso Page Callback @app.on_callback_query(filters.create(lambda _, __, query: "page_kuso#" in query.data)) +@ratelimiter async def kusopage_callback(client, callback_query): if callback_query.from_user.id != int(callback_query.data.split("#")[3]): return await callback_query.answer("Not yours..", True) @@ -555,6 +566,7 @@ async def kusopage_callback(client, callback_query): # Lendrive Page Callback @app.on_callback_query(filters.create(lambda _, __, query: "page_lendrive#" in query.data)) +@ratelimiter async def moviekupage_callback(client, callback_query): if callback_query.from_user.id != int(callback_query.data.split("#")[3]): return await callback_query.answer("Not yours..", True) @@ -580,6 +592,7 @@ async def moviekupage_callback(client, callback_query): # Movieku Page Callback @app.on_callback_query(filters.create(lambda _, __, query: "page_movieku#" in query.data)) +@ratelimiter async def moviekupage_callback(client, callback_query): if callback_query.from_user.id != int(callback_query.data.split("#")[3]): return await callback_query.answer("Not yours..", True) @@ -603,6 +616,7 @@ async def moviekupage_callback(client, callback_query): # Terbit21 Page Callback @app.on_callback_query(filters.create(lambda _, __, query: "page_terbit21#" in query.data)) +@ratelimiter async def terbit21page_callback(client, callback_query): if callback_query.from_user.id != int(callback_query.data.split("#")[3]): return await callback_query.answer("Not yours..", True) @@ -626,6 +640,7 @@ async def terbit21page_callback(client, callback_query): # Page Callback Melong @app.on_callback_query(filters.create(lambda _, __, query: "page_melong#" in query.data)) +@ratelimiter async def melongpage_callback(client, callback_query): if callback_query.from_user.id != int(callback_query.data.split("#")[3]): return await callback_query.answer("Not yours..", True) @@ -651,6 +666,7 @@ async def melongpage_callback(client, callback_query): # Lk21 Page Callback @app.on_callback_query(filters.create(lambda _, __, query: "page_lk21#" in query.data)) +@ratelimiter async def lk21page_callback(client, callback_query): if callback_query.from_user.id != int(callback_query.data.split("#")[3]): return await callback_query.answer("Not yours..", True) @@ -674,6 +690,7 @@ async def lk21page_callback(client, callback_query): # Pahe Page Callback @app.on_callback_query(filters.create(lambda _, __, query: "page_pahe#" in query.data)) +@ratelimiter async def pahepage_callback(client, callback_query): if callback_query.from_user.id != int(callback_query.data.split("#")[3]): return await callback_query.answer("Not yours..", True) @@ -697,6 +714,7 @@ async def pahepage_callback(client, callback_query): # Gomov Page Callback @app.on_callback_query(filters.create(lambda _, __, query: "page_gomov#" in query.data)) +@ratelimiter async def gomovpage_callback(client, callback_query): if callback_query.from_user.id != int(callback_query.data.split("#")[3]): return await callback_query.answer("Not yours..", True) @@ -723,6 +741,7 @@ async def gomovpage_callback(client, callback_query): ### Scrape DDL Link From Web ### # Kusonime DDL @app.on_callback_query(filters.create(lambda _, __, query: "kusoextract#" in query.data)) +@ratelimiter async def kusonime_scrap(_, callback_query): if callback_query.from_user.id != int(callback_query.data.split("#")[3]): return await callback_query.answer("Not yours..", True) @@ -755,6 +774,7 @@ async def kusonime_scrap(_, callback_query): # Savefilm21 DDL @app.on_callback_query(filters.create(lambda _, __, query: "sf21extract#" in query.data)) +@ratelimiter async def savefilm21_scrap(_, callback_query): if callback_query.from_user.id != int(callback_query.data.split("#")[3]): return await callback_query.answer("Not yours..", True) @@ -781,6 +801,7 @@ async def savefilm21_scrap(_, callback_query): # Scrape Link Download Movieku.CC @app.on_message(filters.command(["movieku_scrap"], COMMAND_HANDLER)) +@ratelimiter async def muviku_scrap(_, message): try: link = message.text.split(" ", maxsplit=1)[1] @@ -806,6 +827,7 @@ async def muviku_scrap(_, message): # Scrape DDL Link Melongmovie @app.on_callback_query(filters.create(lambda _, __, query: "melongextract#" in query.data)) +@ratelimiter async def melong_scrap(_, callback_query): if callback_query.from_user.id != int(callback_query.data.split("#")[3]): return await callback_query.answer("Not yours..", True) @@ -835,6 +857,7 @@ async def melong_scrap(_, callback_query): # Scrape DDL Link Gomov @app.on_callback_query(filters.create(lambda _, __, query: "gomovextract#" in query.data)) +@ratelimiter async def gomov_dl(_, callback_query): if callback_query.from_user.id != int(callback_query.data.split("#")[3]): return await callback_query.answer("Not yours..", True) @@ -864,6 +887,7 @@ async def gomov_dl(_, callback_query): @app.on_callback_query(filters.create(lambda _, __, query: "lendriveextract#" in query.data)) +@ratelimiter async def lendrive_dl(_, callback_query): if callback_query.from_user.id != int(callback_query.data.split("#")[3]): return await callback_query.answer("Not yours..", True) diff --git a/misskaty/plugins/webss.py b/misskaty/plugins/webss.py index c1b05b0e..1a4cbe15 100644 --- a/misskaty/plugins/webss.py +++ b/misskaty/plugins/webss.py @@ -1,14 +1,12 @@ -import base64 import os from asyncio import gather -from io import BytesIO -from PIL import Image from pyrogram import filters from misskaty import app from misskaty.core.message_utils import * from misskaty.core.decorator.errors import capture_err +from misskaty.core.decorator.ratelimiter import ratelimiter from misskaty.helper.http import http from misskaty.vars import COMMAND_HANDLER @@ -20,18 +18,16 @@ __HELP__ = """ @app.on_message(filters.command(["webss"], COMMAND_HANDLER)) @capture_err +@ratelimiter async def take_ss(_, m): if len(m.command) == 1: return await kirimPesan(m, "Give A Url To Fetch Screenshot.") url = m.command[1] if m.command[1].startswith("http") else f"https://{m.command[1]}" - filename = f"webSS_{m.from_user.id}.jpg" + filename = f"webSS_{m.from_user.id}.png" msg = await m.reply("Capturing screenshot...") try: - photo = (await http.get(f"https://yasirapi.eu.org/webss?url={url}")).json() - img = Image.open(BytesIO(base64.decodebytes(bytes(photo["result"], "utf-8")))) - img.save(filename) - await editPesan(msg, "Uploading...") - await gather(*[m.reply_document(filename), m.reply_photo(filename)]) + url = f"https://webss.yasirapi.eu.org/api?url={url}&width=1280&height=720" + await gather(*[m.reply_document(url, file_name=filename), m.reply_photo(url, file_name=filename)]) await hapusPesan(m) os.remove(filename) except Exception as e: diff --git a/misskaty/plugins/ytdl_download_new.py b/misskaty/plugins/ytdl_download_new.py index 27718afb..5845684b 100644 --- a/misskaty/plugins/ytdl_download_new.py +++ b/misskaty/plugins/ytdl_download_new.py @@ -9,7 +9,7 @@ from pyrogram.types import CallbackQuery, InlineKeyboardButton, InlineKeyboardMa from misskaty import app from misskaty.core.message_utils import * from misskaty.core.decorator.errors import capture_err -from misskaty.core.decorator.pyro_cooldown import wait +from misskaty.core.decorator.ratelimiter import ratelimiter from misskaty.helper.http import http from misskaty.vars import COMMAND_HANDLER, LOG_CHANNEL @@ -22,8 +22,9 @@ def rand_key(): return str(uuid4())[:8] -@app.on_message(filters.command(["ytsearch"], COMMAND_HANDLER) & ~filters.channel & wait(30)) +@app.on_message(filters.command(["ytsearch"], COMMAND_HANDLER) & ~filters.channel) @capture_err +@ratelimiter async def ytsearch(_, message): if message.sender_chat: return await kirimPesan(message, "This feature not supported for channel.") @@ -60,6 +61,7 @@ async def ytsearch(_, message): @app.on_message(filters.command(["ytdown"], COMMAND_HANDLER)) @capture_err +@ratelimiter async def ytdownv2(_, message): if not message.from_user: return @@ -77,6 +79,7 @@ async def ytdownv2(_, message): @app.on_callback_query(filters.regex(r"^yt_listall")) +@ratelimiter async def ytdl_listall_callback(_, cq: CallbackQuery): if cq.from_user.id != cq.message.reply_to_message.from_user.id: return await cq.answer("Not your task", True) @@ -87,6 +90,7 @@ async def ytdl_listall_callback(_, cq: CallbackQuery): @app.on_callback_query(filters.regex(r"^yt_extract_info")) +@ratelimiter async def ytdl_extractinfo_callback(_, cq: CallbackQuery): if cq.from_user.id != cq.message.reply_to_message.from_user.id: return await cq.answer("Not your task", True) @@ -112,6 +116,7 @@ async def ytdl_extractinfo_callback(_, cq: CallbackQuery): @app.on_callback_query(filters.regex(r"^yt_(gen|dl)")) +@ratelimiter async def ytdl_gendl_callback(_, cq: CallbackQuery): if cq.from_user.id != cq.message.reply_to_message.from_user.id: return await cq.answer("Not your task", True) @@ -155,6 +160,7 @@ async def ytdl_gendl_callback(_, cq: CallbackQuery): @app.on_callback_query(filters.regex(r"^ytdl_scroll")) +@ratelimiter async def ytdl_scroll_callback(_, cq: CallbackQuery): if cq.from_user.id != cq.message.reply_to_message.from_user.id: return await cq.answer("Not your task", True)