diff --git a/pagermaid/__init__.py b/pagermaid/__init__.py index 6553f30..59f5345 100644 --- a/pagermaid/__init__.py +++ b/pagermaid/__init__.py @@ -22,8 +22,8 @@ from pagermaid.scheduler import scheduler import pyromod.listen from pyrogram import Client -pgm_version = "1.4.10" -pgm_version_code = 1410 +pgm_version = "1.4.11" +pgm_version_code = 1411 CMD_LIST = {} module_dir = __path__[0] working_dir = getcwd() diff --git a/pagermaid/common/plugin.py b/pagermaid/common/plugin.py index d338ddc..341f525 100644 --- a/pagermaid/common/plugin.py +++ b/pagermaid/common/plugin.py @@ -6,10 +6,10 @@ from typing import Optional, List, Tuple, Dict from pydantic import BaseModel, ValidationError +import pagermaid.modules from pagermaid import Config, logs from pagermaid.enums import Message from pagermaid.common.cache import cache -from pagermaid.modules import plugin_list as active_plugins from pagermaid.utils import client from pagermaid.services import sqlite @@ -33,6 +33,7 @@ class LocalPlugin(BaseModel): @property def load_status(self) -> bool: """插件加载状态""" + active_plugins = pagermaid.modules.plugin_list return self.name in active_plugins def remove(self): @@ -307,6 +308,7 @@ class PluginManager: ) -> Tuple[List[str], List[LocalPlugin], List[LocalPlugin]]: """Get plugins status""" all_local_plugins = self.plugins + active_plugins = pagermaid.modules.plugin_list disabled_plugins = [] inactive_plugins = [] for plugin in all_local_plugins: diff --git a/pagermaid/enums/command.py b/pagermaid/enums/command.py new file mode 100644 index 0000000..fa3b86e --- /dev/null +++ b/pagermaid/enums/command.py @@ -0,0 +1,52 @@ +from typing import NewType, Callable, Any, Awaitable, Union, TYPE_CHECKING, Optional + +from ..inject import inject + +if TYPE_CHECKING: + from . import Client, Message + +CommandHandlerFunc = NewType("CommandHandlerFunc", Callable[[Any, Any], Awaitable[Any]]) +CommandHandlerDecorator = NewType( + "CommandHandlerDecorator", + Callable[[Union["CommandHandler", CommandHandlerFunc]], "CommandHandler"], +) + + +class CommandHandler: + def __init__(self, func: CommandHandlerFunc, command: Optional[str]) -> None: + self._pgp_func__: CommandHandlerFunc = func + self._pgp_command__: Optional[str] = command + self._pgp_raw_handler = None + + def func(self) -> CommandHandlerFunc: + return self._pgp_func__ + + def set_handler(self, handler): + self._pgp_raw_handler = handler + + def get_handler(self): + return self._pgp_raw_handler + + async def handler(self, client: "Client", message: "Message"): + func = self.func() + if data := inject(message, func): + await func(**data) + else: + if func.__code__.co_argcount == 0: + await func() + if func.__code__.co_argcount == 1: + await func(message) + elif func.__code__.co_argcount == 2: + await func(client, message) + + def sub_command(self, **kwargs) -> CommandHandlerDecorator: + if self._pgp_command__ is None: + raise ValueError("Cannot add subcommand to a handler without a command") + if self._pgp_raw_handler is None: + raise ValueError("Cannot add subcommand to a handler without init") + from pagermaid.listener import listener + + def decorator(func: CommandHandlerFunc) -> CommandHandlerFunc: + return listener(__parent_command=self._pgp_command__, **kwargs)(func) + + return decorator diff --git a/pagermaid/hook.py b/pagermaid/hook.py index 3189ce5..0f84a3e 100644 --- a/pagermaid/hook.py +++ b/pagermaid/hook.py @@ -103,12 +103,14 @@ class Hook: logs.info(f"[shutdown]: {type(exception)}: {exception}") @staticmethod - async def command_pre(message: Message, command): + async def command_pre(message: Message, command, sub_command): cors = [] try: for pre in hook_functions["command_pre"]: try: - data = inject(message, pre, command=command) + data = inject( + message, pre, command=command, sub_command=sub_command + ) except Exception as exception: logs.info(f"[process_error]: {type(exception)}: {exception}") continue @@ -124,12 +126,14 @@ class Hook: logs.info(f"[command_pre]: {type(exception)}: {exception}") @staticmethod - async def command_post(message: Message, command): + async def command_post(message: Message, command, sub_command): cors = [] try: for post in hook_functions["command_post"]: try: - data = inject(message, post, command=command) + data = inject( + message, post, command=command, sub_command=sub_command + ) except Exception as exception: logs.info(f"[process_error]: {type(exception)}: {exception}") continue diff --git a/pagermaid/listener.py b/pagermaid/listener.py index 0321cbd..a1abc08 100644 --- a/pagermaid/listener.py +++ b/pagermaid/listener.py @@ -17,8 +17,8 @@ from pyrogram.handlers import MessageHandler, EditedMessageHandler from pagermaid import help_messages, logs, Config, bot, read_context, all_permissions from pagermaid.common.ignore import ignore_groups_manager +from pagermaid.enums.command import CommandHandler, CommandHandlerDecorator from pagermaid.group_manager import Permission -from pagermaid.inject import inject from pagermaid.single_utils import ( Message, AlreadyInConversationError, @@ -41,9 +41,11 @@ from pyromod.utils import mod_filters _lock = asyncio.Lock() -def listener(**args): +def listener(**args) -> CommandHandlerDecorator: """Register an event listener.""" + parent_command = args.get("__parent_command") command = args.get("command") + allow_parent = args.get("allow_parent", False) disallow_alias = args.get("disallow_alias", False) need_admin = args.get("need_admin", False) description = args.get("description") @@ -70,15 +72,20 @@ def listener(**args): priority = 0 if command is not None: - if command in help_messages: + if parent_command is None and command in help_messages: if help_messages[alias_command(command)]["priority"] <= priority: raise ValueError( f"{lang('error_prefix')} {lang('command')} \"{command}\" {lang('has_reg')}" ) else: block_process = True - pattern = rf"^(,|,){alias_command(command, disallow_alias)}(?: |$)([\s\S]*)" - sudo_pattern = rf"^(/){alias_command(command, disallow_alias)}(?: |$)([\s\S]*)" + real_command = ( + alias_command(command, disallow_alias) + if parent_command is None + else f"{parent_command} {command}" + ) + pattern = rf"^(,|,){real_command}(?: |$)([\s\S]*)" + sudo_pattern = rf"^(/){real_command}(?: |$)([\s\S]*)" if pattern is not None and not pattern.startswith("(?i)"): args["pattern"] = f"(?i){pattern}" else: @@ -137,7 +144,14 @@ def listener(**args): if "block_process" in args: del args["block_process"] - def decorator(function): + def decorator(function) -> CommandHandler: + func = CommandHandler( + function, + alias_command(command, disallow_alias) + if command and parent_command is None + else None, + ) + async def handler(client: Client, message: Message): try: # ignore @@ -149,11 +163,15 @@ def listener(**args): except BaseException: pass try: - parameter = message.matches[0].group(2).split(" ") + arguments = message.matches[0].group(2) + parameter = arguments.split(" ") if parameter == [""]: parameter = [] + if parent_command is not None and command is not None: + parameter.insert(0, command) + arguments = f"{command} {arguments}".strip() message.parameter = parameter - message.arguments = message.matches[0].group(2) + message.arguments = arguments except BaseException: message.parameter = None message.arguments = None @@ -164,18 +182,18 @@ def listener(**args): read_context[(message.chat.id, message.id)] = True if command: - await Hook.command_pre(message, command) - if data := inject(message, function): - await function(**data) - else: - if function.__code__.co_argcount == 0: - await function() - if function.__code__.co_argcount == 1: - await function(message) - elif function.__code__.co_argcount == 2: - await function(client, message) + await Hook.command_pre( + message, + parent_command or command, + command if parent_command else None, + ) + await func.handler(client, message) if command: - await Hook.command_post(message, command) + await Hook.command_post( + message, + parent_command or command, + command if parent_command else None, + ) except StopPropagation as e: raise StopPropagation from e except KeyboardInterrupt as e: @@ -235,30 +253,38 @@ def listener(**args): await Hook.process_error_exec(message, command, exc_info, exc_format) if (message.chat.id, message.id) in read_context: del read_context[(message.chat.id, message.id)] - if block_process: + if block_process or (parent_command and not allow_parent): message.stop_propagation() message.continue_propagation() - bot.add_handler( - MessageHandler(handler, filters=base_filters), group=0 + priority + bot.dispatcher.add_handler( + MessageHandler(handler, filters=base_filters), + group=0 + priority, + first=parent_command and not allow_parent, ) if command: - bot.add_handler( - MessageHandler(handler, filters=sudo_filters), group=50 + priority + bot.dispatcher.add_handler( + MessageHandler(handler, filters=sudo_filters), + group=50 + priority, + first=parent_command and not allow_parent, ) if not ignore_edited: - bot.add_handler( - EditedMessageHandler(handler, filters=base_filters), group=1 + priority + bot.dispatcher.add_handler( + EditedMessageHandler(handler, filters=base_filters), + group=1 + priority, + first=parent_command and not allow_parent, ) if command: - bot.add_handler( + bot.dispatcher.add_handler( EditedMessageHandler(handler, filters=sudo_filters), group=51 + priority, + first=parent_command and not allow_parent, ) - return handler + func.set_handler(handler) + return func - if description is not None and command is not None: + if description is not None and command is not None and parent_command is None: if parameters is None: parameters = "" help_messages.update( diff --git a/pagermaid/modules/avoid.py b/pagermaid/modules/avoid.py index dfacaf4..9df6c77 100644 --- a/pagermaid/modules/avoid.py +++ b/pagermaid/modules/avoid.py @@ -1,6 +1,7 @@ """ PagerMaid module for different ways to avoid users. """ from pagermaid import log +from pagermaid.enums.command import CommandHandler from pagermaid.single_utils import sqlite from pagermaid.utils import lang from pagermaid.enums import Client, Message @@ -14,40 +15,65 @@ from pagermaid.listener import listener description=lang("ghost_des"), parameters="", ) -async def ghost(client: Client, message: Message): +async def ghost(message: Message): """Toggles ghosting of a user.""" if len(message.parameter) != 1: await message.edit(f"{lang('error_prefix')}{lang('arg_error')}") return + await message.edit(f"{lang('error_prefix')}{lang('arg_error')}") + + +ghost: "CommandHandler" + + +@ghost.sub_command( + is_plugin=False, + outgoing=True, + command="true", +) +async def ghost_true(client: Client, message: Message): myself = await client.get_me() self_user_id = myself.id - if message.parameter[0] == "true": - if message.chat.id == self_user_id: - return await message.edit(lang("ghost_e_mark")) - sqlite[f"ghosted.chat_id.{str(message.chat.id)}"] = True - await message.safe_delete() - await log( - f"{lang('ghost_set_f')} ChatID {str(message.chat.id)} {lang('ghost_set_l')}" - ) - elif message.parameter[0] == "false": - if message.chat.id == self_user_id: - await message.edit(lang("ghost_e_mark")) - return - try: - del sqlite[f"ghosted.chat_id.{str(message.chat.id)}"] - except KeyError: - return await message.edit(lang("ghost_e_noexist")) - await message.safe_delete() - await log( - f"{lang('ghost_set_f')} ChatID {str(message.chat.id)} {lang('ghost_cancel')}" - ) - elif message.parameter[0] == "status": - if sqlite.get(f"ghosted.chat_id.{str(message.chat.id)}", None): - await message.edit(lang("ghost_e_exist")) - else: - await message.edit(lang("ghost_e_noexist")) + if message.chat.id == self_user_id: + return await message.edit(lang("ghost_e_mark")) + sqlite[f"ghosted.chat_id.{str(message.chat.id)}"] = True + await message.safe_delete() + await log( + f"{lang('ghost_set_f')} ChatID {str(message.chat.id)} {lang('ghost_set_l')}" + ) + + +@ghost.sub_command( + is_plugin=False, + outgoing=True, + command="false", +) +async def ghost_false(client: Client, message: Message): + myself = await client.get_me() + self_user_id = myself.id + if message.chat.id == self_user_id: + await message.edit(lang("ghost_e_mark")) + return + try: + del sqlite[f"ghosted.chat_id.{str(message.chat.id)}"] + except KeyError: + return await message.edit(lang("ghost_e_noexist")) + await message.safe_delete() + await log( + f"{lang('ghost_set_f')} ChatID {str(message.chat.id)} {lang('ghost_cancel')}" + ) + + +@ghost.sub_command( + is_plugin=False, + outgoing=True, + command="status", +) +async def ghost_status(message: Message): + if sqlite.get(f"ghosted.chat_id.{str(message.chat.id)}", None): + await message.edit(lang("ghost_e_exist")) else: - await message.edit(f"{lang('error_prefix')}{lang('arg_error')}") + await message.edit(lang("ghost_e_noexist")) @listener( @@ -58,36 +84,64 @@ async def ghost(client: Client, message: Message): description=lang("deny_des"), parameters="", ) -async def deny(client: Client, message: Message): +async def deny(message: Message): """Toggles denying of a user.""" if len(message.parameter) != 1: await message.edit(f"{lang('error_prefix')}{lang('arg_error')}") return + await message.edit(f"{lang('error_prefix')}{lang('arg_error')}") + + +deny: "CommandHandler" + + +@deny.sub_command( + is_plugin=False, + outgoing=True, + need_admin=True, + command="true", +) +async def deny_true(client: Client, message: Message): myself = await client.get_me() self_user_id = myself.id - if message.parameter[0] == "true": - if message.chat.id == self_user_id: - return await message.edit(lang("ghost_e_mark")) - sqlite[f"denied.chat_id.{str(message.chat.id)}"] = True - await message.safe_delete() - await log(f"ChatID {str(message.chat.id)} {lang('deny_set')}") - elif message.parameter[0] == "false": - if message.chat.id == self_user_id: - await message.edit(lang("ghost_e_mark")) - return - try: - del sqlite[f"denied.chat_id.{str(message.chat.id)}"] - except KeyError: - return await message.edit(lang("deny_e_noexist")) - await message.safe_delete() - await log(f"ChatID {str(message.chat.id)} {lang('deny_cancel')}") - elif message.parameter[0] == "status": - if sqlite.get(f"denied.chat_id.{str(message.chat.id)}", None): - await message.edit(lang("deny_e_exist")) - else: - await message.edit(lang("deny_e_noexist")) + if message.chat.id == self_user_id: + return await message.edit(lang("ghost_e_mark")) + sqlite[f"denied.chat_id.{str(message.chat.id)}"] = True + await message.safe_delete() + await log(f"ChatID {str(message.chat.id)} {lang('deny_set')}") + + +@deny.sub_command( + is_plugin=False, + outgoing=True, + need_admin=True, + command="false", +) +async def deny_false(client: Client, message: Message): + myself = await client.get_me() + self_user_id = myself.id + if message.chat.id == self_user_id: + await message.edit(lang("ghost_e_mark")) + return + try: + del sqlite[f"denied.chat_id.{str(message.chat.id)}"] + except KeyError: + return await message.edit(lang("deny_e_noexist")) + await message.safe_delete() + await log(f"ChatID {str(message.chat.id)} {lang('deny_cancel')}") + + +@deny.sub_command( + is_plugin=False, + outgoing=True, + need_admin=True, + command="status", +) +async def deny_status(message: Message): + if sqlite.get(f"denied.chat_id.{str(message.chat.id)}", None): + await message.edit(lang("deny_e_exist")) else: - await message.edit(f"{lang('error_prefix')}{lang('arg_error')}") + await message.edit(lang("deny_e_noexist")) @listener(is_plugin=False, incoming=True, outgoing=False, ignore_edited=True) diff --git a/pagermaid/modules/mixpanel.py b/pagermaid/modules/mixpanel.py index 40a99d3..8bfb39a 100644 --- a/pagermaid/modules/mixpanel.py +++ b/pagermaid/modules/mixpanel.py @@ -134,7 +134,7 @@ async def mixpanel_init_id(bot: Client): @Hook.command_postprocessor() -async def mixpanel_report(bot: Client, message: Message, command): +async def mixpanel_report(bot: Client, message: Message, command, sub_command): if not Config.ALLOW_ANALYTIC: return await set_people(bot) @@ -144,11 +144,14 @@ async def mixpanel_report(bot: Client, message: Message, command): sender_id = message.sender_chat.id if message.sender_chat else sender_id if sender_id < 0 and message.outgoing: sender_id = bot.me.id + properties = {"command": command, "bot_id": bot.me.id} + if sub_command: + properties["sub_command"] = sub_command bot.loop.create_task( mp.track( str(sender_id), f"Function {command}", - {"command": command, "bot_id": bot.me.id}, + properties, ) ) diff --git a/pagermaid/modules/sudo.py b/pagermaid/modules/sudo.py index def609e..a48cb57 100644 --- a/pagermaid/modules/sudo.py +++ b/pagermaid/modules/sudo.py @@ -1,3 +1,4 @@ +from pagermaid.enums.command import CommandHandler from pagermaid.single_utils import sqlite from pagermaid.listener import listener from pagermaid.group_manager import ( @@ -29,15 +30,45 @@ def from_msg_get_sudo_id(message: Message) -> int: parameters="{on|off|add|remove|gaddp|gaddu|gdelp|gdelu|glist|uaddp|udelp|list}", description=lang("sudo_des"), ) -async def sudo_change(client: Client, message: Message): +async def sudo_change(message: Message): """To enable or disable sudo of your userbot.""" - input_str = message.arguments + await edit_delete(message, lang("arg_error")) + + +sudo_change: "CommandHandler" + + +@sudo_change.sub_command( + is_plugin=False, + command="on", + need_admin=True, +) +async def sudo_on(message: Message): sudo = get_sudo_list() - if input_str == "on": - if _status_sudo(): - return await edit_delete(message, lang("sudo_has_enabled")) - sqlite["sudo_enable"] = True - text = f"__{lang('sudo_enable')}__\n" + if _status_sudo(): + return await edit_delete(message, lang("sudo_has_enabled")) + sqlite["sudo_enable"] = True + text = f"__{lang('sudo_enable')}__\n" + if len(sudo) != 0: + return await message.edit( + text, + ) + text += f"**{lang('sudo_no_sudo')}**" + return await message.edit( + text, + ) + + +@sudo_change.sub_command( + is_plugin=False, + command="off", + need_admin=True, +) +async def sudo_off(message: Message): + sudo = get_sudo_list() + if _status_sudo(): + del sqlite["sudo_enable"] + text = f"__{lang('sudo_disable')}__\n" if len(sudo) != 0: return await message.edit( text, @@ -46,109 +77,173 @@ async def sudo_change(client: Client, message: Message): return await message.edit( text, ) - elif input_str == "off": - if _status_sudo(): - del sqlite["sudo_enable"] - text = f"__{lang('sudo_disable')}__\n" - if len(sudo) != 0: - return await message.edit( - text, - ) - text += f"**{lang('sudo_no_sudo')}**" - return await message.edit( - text, - ) - await edit_delete(message, lang("sudo_has_disabled")) - elif input_str == "add": - from_id = from_msg_get_sudo_id(message) - if from_id in sudo: - return await edit_delete(message, f"__{lang('sudo_add')}__") - sudo.append(from_id) - sqlite["sudo_list"] = sudo - add_user_to_group(str(from_id), "default") # 添加到默认组 - if from_id > 0: - await message.edit(f"__{lang('sudo_add')}__") - else: - await message.edit(f"__{lang('sudo_add_chat')}__") - elif input_str == "remove": - from_id = from_msg_get_sudo_id(message) - if from_id not in sudo: - return await edit_delete(message, f"__{lang('sudo_no')}__") - sudo.remove(from_id) - sqlite["sudo_list"] = sudo - if from_id > 0: - await message.edit(f"__{lang('sudo_remove')}__") - else: - await message.edit(f"__{lang('sudo_remove_chat')}__") - elif input_str == "list": - if len(sudo) == 0: - return await edit_delete(message, f"__{lang('sudo_no_one')}__") - text = f"**{lang('sudo_list')}**\n\n" - for i in sudo.copy(): - try: - if i > 0: - user = await client.get_users(i) - if user.is_deleted: - sudo.remove(i) - sqlite["sudo_list"] = sudo - continue - text += f"• {user.mention()} - {' '.join(permissions.get_roles_for_user(str(i)))}\n" - else: - chat = await client.get_chat(i) - text += f"• {chat.title} - {' '.join(permissions.get_roles_for_user(str(i)))}\n" - for j in permissions.get_permissions_for_user(str(i)): - text += f" • {'-' if j[2] == 'ejection' else ''}{j[1]}\n" - except Exception: - text += ( - f"• `{i}` - {' '.join(permissions.get_roles_for_user(str(i)))}\n" - ) - await message.edit(text) - elif len(message.parameter) > 0: - if len(message.parameter) == 2: - from_id = from_msg_get_sudo_id(message) - if message.parameter[0] == "glist": - if not ( - data := permissions.get_permissions_for_user( - str(message.parameter[1]) - ) - ): - return await edit_delete(message, f"__{lang('sudo_group_list')}__") - text = f"**{message.parameter[1]} {lang('sudo_group_list')}**\n\n" - for i in data: - text += f" • `{'-' if i[2] == 'ejection' else ''}{i[1]}`\n" - return await message.edit(text) - if from_id not in sudo: - return await edit_delete(message, f"__{lang('sudo_no')}__") - elif message.parameter[0] == "gaddu": - add_user_to_group(str(from_id), message.parameter[1]) - return await message.edit(lang("sudo_group_add_user")) - elif message.parameter[0] == "gdelu": - remove_user_from_group(str(from_id), message.parameter[1]) - return await message.edit(lang("sudo_group_del_user")) - elif message.parameter[0] == "uaddp": - add_permission_for_user(str(from_id), Permission(message.parameter[1])) - return await message.edit(lang("sudo_user_add_per")) - elif message.parameter[0] == "udelp": - remove_permission_for_user( - str(from_id), Permission(message.parameter[1]) - ) - return await message.edit(lang("sudo_user_del_per")) - else: - return await edit_delete(message, lang("arg_error")) - if len(message.parameter) == 3: - if message.parameter[0] == "gaddp": - add_permission_for_group( - message.parameter[1], Permission(message.parameter[2]) - ) - return await message.edit(lang("sudo_group_add_per")) - elif message.parameter[0] == "gdelp": - remove_permission_for_group( - message.parameter[1], Permission(message.parameter[2]) - ) - return await message.edit(lang("sudo_group_del_per")) - else: - return await edit_delete(message, lang("arg_error")) - else: - await edit_delete(message, lang("arg_error")) + await edit_delete(message, lang("sudo_has_disabled")) + + +@sudo_change.sub_command( + is_plugin=False, + command="add", + need_admin=True, +) +async def sudo_add(message: Message): + sudo = get_sudo_list() + from_id = from_msg_get_sudo_id(message) + if from_id in sudo: + return await edit_delete(message, f"__{lang('sudo_add')}__") + sudo.append(from_id) + sqlite["sudo_list"] = sudo + add_user_to_group(str(from_id), "default") # 添加到默认组 + if from_id > 0: + await message.edit(f"__{lang('sudo_add')}__") else: - await edit_delete(message, lang("arg_error")) + await message.edit(f"__{lang('sudo_add_chat')}__") + + +@sudo_change.sub_command( + is_plugin=False, + command="remove", + need_admin=True, +) +async def sudo_remove(message: Message): + sudo = get_sudo_list() + from_id = from_msg_get_sudo_id(message) + if from_id not in sudo: + return await edit_delete(message, f"__{lang('sudo_no')}__") + sudo.remove(from_id) + sqlite["sudo_list"] = sudo + if from_id > 0: + await message.edit(f"__{lang('sudo_remove')}__") + else: + await message.edit(f"__{lang('sudo_remove_chat')}__") + + +@sudo_change.sub_command( + is_plugin=False, + command="list", + need_admin=True, +) +async def sudo_list(client: Client, message: Message): + sudo = get_sudo_list() + if len(sudo) == 0: + return await edit_delete(message, f"__{lang('sudo_no_one')}__") + text = f"**{lang('sudo_list')}**\n\n" + for i in sudo.copy(): + try: + if i > 0: + user = await client.get_users(i) + if user.is_deleted: + sudo.remove(i) + sqlite["sudo_list"] = sudo + continue + text += f"• {user.mention()} - {' '.join(permissions.get_roles_for_user(str(i)))}\n" + else: + chat = await client.get_chat(i) + text += f"• {chat.title} - {' '.join(permissions.get_roles_for_user(str(i)))}\n" + for j in permissions.get_permissions_for_user(str(i)): + text += f" • {'-' if j[2] == 'ejection' else ''}{j[1]}\n" + except Exception: + text += f"• `{i}` - {' '.join(permissions.get_roles_for_user(str(i)))}\n" + await message.edit(text) + + +def check_parameter_length(length: int, check_permission: bool): + def decorator(func): + async def wrapper(message: Message): + if len(message.parameter) != length: + return await edit_delete(message, lang("arg_error")) + if check_permission: + sudo = get_sudo_list() + from_id = from_msg_get_sudo_id(message) + if from_id not in sudo: + return await edit_delete(message, f"__{lang('sudo_no')}__") + + return await func(message) + + return wrapper + + return decorator + + +@sudo_change.sub_command( + is_plugin=False, + command="glist", + need_admin=True, +) +@check_parameter_length(2, False) +async def sudo_glist(message: Message): + if not (data := permissions.get_permissions_for_user(str(message.parameter[1]))): + return await edit_delete(message, f"__{lang('sudo_group_list')}__") + text = f"**{message.parameter[1]} {lang('sudo_group_list')}**\n\n" + for i in data: + text += f" • `{'-' if i[2] == 'ejection' else ''}{i[1]}`\n" + return await message.edit(text) + + +@sudo_change.sub_command( + is_plugin=False, + command="gaddu", + need_admin=True, +) +@check_parameter_length(2, True) +async def sudo_gaddu(message: Message): + from_id = from_msg_get_sudo_id(message) + add_user_to_group(str(from_id), message.parameter[1]) + return await message.edit(lang("sudo_group_add_user")) + + +@sudo_change.sub_command( + is_plugin=False, + command="gdelu", + need_admin=True, +) +@check_parameter_length(2, True) +async def sudo_gdelu(message: Message): + from_id = from_msg_get_sudo_id(message) + remove_user_from_group(str(from_id), message.parameter[1]) + return await message.edit(lang("sudo_group_del_user")) + + +@sudo_change.sub_command( + is_plugin=False, + command="uaddp", + need_admin=True, +) +@check_parameter_length(2, True) +async def sudo_uaddp(message: Message): + from_id = from_msg_get_sudo_id(message) + add_permission_for_user(str(from_id), Permission(message.parameter[1])) + return await message.edit(lang("sudo_user_add_per")) + + +@sudo_change.sub_command( + is_plugin=False, + command="udelp", + need_admin=True, +) +@check_parameter_length(2, True) +async def sudo_udelp(message: Message): + from_id = from_msg_get_sudo_id(message) + remove_permission_for_user(str(from_id), Permission(message.parameter[1])) + return await message.edit(lang("sudo_user_del_per")) + + +@sudo_change.sub_command( + is_plugin=False, + command="gaddp", + need_admin=True, +) +@check_parameter_length(3, False) +async def sudo_gaddp(message: Message): + add_permission_for_group(message.parameter[1], Permission(message.parameter[2])) + return await message.edit(lang("sudo_group_add_per")) + + +@sudo_change.sub_command( + is_plugin=False, + command="gdelp", + need_admin=True, +) +@check_parameter_length(3, False) +async def sudo_gdelp(message: Message): + remove_permission_for_group(message.parameter[1], Permission(message.parameter[2])) + return await message.edit(lang("sudo_group_del_per")) diff --git a/pyromod/listen/listen.py b/pyromod/listen/listen.py index e90e842..2976ee8 100644 --- a/pyromod/listen/listen.py +++ b/pyromod/listen/listen.py @@ -21,6 +21,7 @@ along with pyromod. If not, see . import asyncio import contextlib import functools +from collections import OrderedDict from datetime import datetime from typing import Optional, List, Union @@ -425,3 +426,24 @@ class Dispatcher(pyrogram.dispatcher.Dispatcher): # noqa lock.release() self.loop.create_task(fn()) + + @patchable + def add_handler(self, handler, group: int, first: bool): + if not first: + return self.oldadd_handler(handler, group) + + async def fn(): + for lock in self.locks_list: + await lock.acquire() + + try: + if group not in self.groups: + self.groups[group] = [] + self.groups = OrderedDict(sorted(self.groups.items())) + + self.groups[group].insert(0, handler) + finally: + for lock in self.locks_list: + lock.release() + + self.loop.create_task(fn())