🔖 Update to v1.1.0

This commit is contained in:
xtaodada 2022-06-20 21:55:14 +08:00
parent ba9da97b3c
commit 2a1b54802b
Signed by: xtaodada
GPG Key ID: 4CBB3F4FA8C85659
28 changed files with 545 additions and 355 deletions

View File

@ -245,14 +245,14 @@ coin_lost: I lost my coin
## lang ## lang
lang_des: Switch language. lang_des: Switch language.
lang_change_to: The language has been switched to lang_change_to: The language has been switched to
lang_reboot: Restarting. lang_reboot: Reloading.
lang_current_lang: The current language is lang_current_lang: The current language is
lang_all_lang: All available languages are lang_all_lang: All available languages are
## alias ## alias
alias_des: Redirect original command. alias_des: Redirect original command.
alias_list: 'The following is a list of redirect commands:' alias_list: 'The following is a list of redirect commands:'
alias_no: You have not redirected any original commands. alias_no: You have not redirected any original commands.
alias_success: Edit redirection command successPagerMaid-Pyro is restarting. alias_success: Edit redirection command successPagerMaid-Pyro is reloading.
alias_exist: Something went wrong, woooo~ The command that is redirected is already occupied. alias_exist: Something went wrong, woooo~ The command that is redirected is already occupied.
alias_no_exist: Something went wrong, woooo~ The original command is not redirected. alias_no_exist: Something went wrong, woooo~ The original command is not redirected.
#message #message
@ -309,7 +309,7 @@ apt_processing: Installing plugins...
apt_no_py: Something went wrong ~ Failed to get the plug-in file from the attachment. apt_no_py: Something went wrong ~ Failed to get the plug-in file from the attachment.
apt_plugin: plugin apt_plugin: plugin
apt_installed: installed apt_installed: installed
apt_reboot: PagerMaid-Pyro is restarting. apt_reboot: PagerMaid-Pyro is reloading.
apt_install_success: successful installation apt_install_success: successful installation
apt_not_found: not founded apt_not_found: not founded
apt_no_update: no need to update apt_no_update: no need to update
@ -553,3 +553,6 @@ sb_remove: The automatic banned list has been removed this group.
sb_exist: This group exists in the automatic banned list. sb_exist: This group exists in the automatic banned list.
sb_no_exist: This group does't exist in the automatic banned list. sb_no_exist: This group does't exist in the automatic banned list.
sb_channel: Successfully blocked this channel in this group. sb_channel: Successfully blocked this channel in this group.
#reload
reload_des: Reload the PagerMaid-Pyro instance.
reload_ok: Successfully reloaded.

View File

@ -245,14 +245,14 @@ coin_lost: I lost my coin
## lang ## lang
lang_des: switchlanguage. lang_des: switchlanguage.
lang_change_to: The language has been switchedto lang_change_to: The language has been switchedto
lang_reboot: Restarting. lang_reboot: リロード中
lang_current_lang: 拡張カードの pubage is lang_current_lang: 拡張カードの pubage is
lang_all_lang: All available languages are lang_all_lang: All available languages are
## alias ## alias
alias_des: Redirect original command。 alias_des: Redirect original command。
alias_list: 'The following is a list of redirect commands:' alias_list: 'The following is a list of redirect commands:'
alias_no: You have not redirected any original commands. alias_no: You have not redirected any original commands.
alias_success: Edit redirection command success,PagerMaid-Pyro is restarting. alias_success: リダイレクトコマンドの編集に成功しました。PagerMaid-Pyro がリロードされています。
alias_exist: Something went wrong, woo~ The commd that is redirected is already occupied。 alias_exist: Something went wrong, woo~ The commd that is redirected is already occupied。
alias_no_exist: Something went wrong, woo~ The original commd is not redirected. alias_no_exist: Something went wrong, woo~ The original commd is not redirected.
#message #message
@ -309,7 +309,7 @@ apt_processing: Installing plugins...
apt_no_py: Something went wrong ~ Failed to get the plug-in file from the attachment. apt_no_py: Something went wrong ~ Failed to get the plug-in file from the attachment.
apt_plugin: plugin apt_plugin: plugin
apt_installed: installed apt_installed: installed
apt_reboot: PagerMaid-Pyro is restarting apt_reboot: PagerMaid-Pyroはリロードされています
apt_install_success: successful installation apt_install_success: successful installation
apt_not_found: not founded apt_not_found: not founded
apt_no_update: no need to update apt_no_update: no need to update
@ -553,3 +553,6 @@ sb_remove: The automatic banned list has been removed this group.
sb_exist: This group exists in the automatic banned list. sb_exist: This group exists in the automatic banned list.
sb_no_exist: This group does't exist in the automatic banned list. sb_no_exist: This group does't exist in the automatic banned list.
sb_channel: Successfully blocked this channel in this group. sb_channel: Successfully blocked this channel in this group.
#reload
reload_des: PagerMaid-Pyroインスタンスをリロードします。
reload_ok: 再読み込みに成功しました。

View File

@ -245,14 +245,14 @@ coin_lost: 我丢了硬币
## lang ## lang
lang_des: 切换语言。 lang_des: 切换语言。
lang_change_to: 语言已切换到 lang_change_to: 语言已切换到
lang_reboot: 正在重新启动 lang_reboot: 正在重新加载
lang_current_lang: 当前语言是 lang_current_lang: 当前语言是
lang_all_lang: 所有可用的语言有: lang_all_lang: 所有可用的语言有:
## alias ## alias
alias_des: 重定向原始命令。 alias_des: 重定向原始命令。
alias_list: '以下是重定向命令列表:' alias_list: '以下是重定向命令列表:'
alias_no: 您还没有重定向任何原始命令。 alias_no: 您还没有重定向任何原始命令。
alias_success: 编辑重定向命令成功PagerMaid-Pyro 正在重新启动 alias_success: 编辑重定向命令成功PagerMaid-Pyro 正在重新加载
alias_exist: 出错了呜呜呜 ~ 重定向指向的命令已被占用。 alias_exist: 出错了呜呜呜 ~ 重定向指向的命令已被占用。
alias_no_exist: 出错了呜呜呜 ~ 原始命令没有被重定向。 alias_no_exist: 出错了呜呜呜 ~ 原始命令没有被重定向。
#message #message
@ -309,7 +309,7 @@ apt_processing: 安装插件中 . . .
apt_no_py: 出错了呜呜呜 ~ 无法从附件获取插件文件。 apt_no_py: 出错了呜呜呜 ~ 无法从附件获取插件文件。
apt_plugin: 插件 apt_plugin: 插件
apt_installed: 已安装 apt_installed: 已安装
apt_reboot: PagerMaid-Pyro 正在重新启动 apt_reboot: PagerMaid-Pyro 正在重新加载中
apt_install_success: 安装成功 apt_install_success: 安装成功
apt_not_found: 没有找到 apt_not_found: 没有找到
apt_no_update: 无需更新 apt_no_update: 无需更新
@ -553,3 +553,6 @@ sb_remove: 已被移除自动封禁列表。
sb_exist: 此群组存在于自动封禁列表中。 sb_exist: 此群组存在于自动封禁列表中。
sb_no_exist: 此群组不存在于自动封禁列表中。 sb_no_exist: 此群组不存在于自动封禁列表中。
sb_channel: 成功在本群封禁此频道。 sb_channel: 成功在本群封禁此频道。
#reload
reload_des: 重新加载内置模块和插件。
reload_ok: 重新加载内置模块和插件成功。

View File

@ -245,14 +245,14 @@ coin_lost: 我擲了硬幣
## lang ## lang
lang_des: 切換語言 lang_des: 切換語言
lang_change_to: 語言已切換到 lang_change_to: 語言已切換到
lang_reboot: 正在重新啟動 lang_reboot: 正在重新加載
lang_current_lang: 目前語言是 lang_current_lang: 目前語言是
lang_all_lang: 所有語言有這些: lang_all_lang: 所有語言有這些:
## alias ## alias
alias_des: 重定向原始命令。 alias_des: 重定向原始命令。
alias_list: '以下是重定向命令列表:' alias_list: '以下是重定向命令列表:'
alias_no: 您還沒有重定向任何原始命令。 alias_no: 您還沒有重定向任何原始命令。
alias_success: 編輯重定向命令成功PagerMaid-Pyro 正在重新啟動 alias_success: 編輯重定向命令成功PagerMaid-Pyro 正在重新加载
alias_exist: 出錯了嗚嗚嗚 ~ 重定向指向的命令已被佔用。 alias_exist: 出錯了嗚嗚嗚 ~ 重定向指向的命令已被佔用。
alias_no_exist: 出錯了嗚嗚嗚 ~ 原始命令沒有被重定向。 alias_no_exist: 出錯了嗚嗚嗚 ~ 原始命令沒有被重定向。
#message #message
@ -309,7 +309,7 @@ apt_processing: 安裝插件中…
apt_no_py: Error無法獲取插件文件。 apt_no_py: Error無法獲取插件文件。
apt_plugin: 插件 apt_plugin: 插件
apt_installed: 已安裝 apt_installed: 已安裝
apt_reboot: 正在重新啟動 PagerMaid-Pyro。 apt_reboot: PagerMaid-Pyro 正在重新加載
apt_install_success: 安裝成功 apt_install_success: 安裝成功
apt_not_found: Error沒有找到插件 apt_not_found: Error沒有找到插件
apt_no_update: 沒必要更新 apt_no_update: 沒必要更新
@ -553,3 +553,6 @@ sb_remove: 已被移除自動封禁列表。
sb_exist: 此群組存在於自動封禁列表中。 sb_exist: 此群組存在於自動封禁列表中。
sb_no_exist: 此群組不存在於自動封禁列表中。 sb_no_exist: 此群組不存在於自動封禁列表中。
sb_channel: 成功在本群封禁此頻道。 sb_channel: 成功在本群封禁此頻道。
#reload
reload_des: 重新加載內置模塊和插件。
reload_ok: 重新加載內置模塊和插件成功。

View File

@ -1,15 +1,16 @@
import contextlib
from coloredlogs import ColoredFormatter from coloredlogs import ColoredFormatter
from datetime import datetime, timezone
from logging import getLogger, StreamHandler, CRITICAL, INFO, basicConfig, DEBUG from logging import getLogger, StreamHandler, CRITICAL, INFO, basicConfig, DEBUG
from datetime import datetime
from os import getcwd from os import getcwd
from apscheduler.schedulers.asyncio import AsyncIOScheduler
from pagermaid.config import Config from pagermaid.config import Config
from pagermaid.scheduler import scheduler
import pyromod.listen import pyromod.listen
from pyrogram import Client from pyrogram import Client
import sys import sys
pgm_version = "1.0.9" pgm_version = "1.1.0"
CMD_LIST = {} CMD_LIST = {}
module_dir = __path__[0] module_dir = __path__[0]
working_dir = getcwd() working_dir = getcwd()
@ -17,9 +18,7 @@ working_dir = getcwd()
read_context = {} read_context = {}
help_messages = {} help_messages = {}
all_permissions = [] all_permissions = []
scheduler = AsyncIOScheduler(timezone="Asia/ShangHai")
if not scheduler.running:
scheduler.start()
logs = getLogger(__name__) logs = getLogger(__name__)
logging_format = "%(levelname)s [%(asctime)s] [%(name)s] %(message)s" logging_format = "%(levelname)s [%(asctime)s] [%(name)s] %(message)s"
logging_handler = StreamHandler() logging_handler = StreamHandler()
@ -27,6 +26,9 @@ logging_handler.setFormatter(ColoredFormatter(logging_format))
root_logger = getLogger() root_logger = getLogger()
root_logger.setLevel(DEBUG if Config.DEBUG else CRITICAL) root_logger.setLevel(DEBUG if Config.DEBUG else CRITICAL)
root_logger.addHandler(logging_handler) root_logger.addHandler(logging_handler)
pyro_logger = getLogger("pyrogram")
pyro_logger.setLevel(CRITICAL)
pyro_logger.addHandler(logging_handler)
basicConfig(level=DEBUG if Config.DEBUG else INFO) basicConfig(level=DEBUG if Config.DEBUG else INFO)
logs.setLevel(DEBUG if Config.DEBUG else INFO) logs.setLevel(DEBUG if Config.DEBUG else INFO)
@ -38,19 +40,21 @@ elif not Config.API_HASH:
logs.error("Api-Hash Not Found!") logs.error("Api-Hash Not Found!")
sys.exit(1) sys.exit(1)
start_time = datetime.utcnow() start_time = datetime.now(timezone.utc)
try: with contextlib.suppress(ImportError):
import uvloop import uvloop # noqa
uvloop.install() uvloop.install()
except ImportError:
pass if not scheduler.running:
scheduler.start()
bot = Client("pagermaid", bot = Client("pagermaid",
session_string=Config.STRING_SESSION, session_string=Config.STRING_SESSION,
api_id=Config.API_ID, api_id=Config.API_ID,
api_hash=Config.API_HASH, api_hash=Config.API_HASH,
ipv6=Config.IPV6, ipv6=Config.IPV6,
proxy=Config.PROXY) proxy=Config.PROXY)
bot.job = scheduler
async def log(message): async def log(message):

View File

@ -18,12 +18,12 @@ async def main():
for module_name in module_list: for module_name in module_list:
try: try:
import_module("pagermaid.modules." + module_name) import_module(f"pagermaid.modules.{module_name}")
except BaseException as exception: except BaseException as exception:
logs.info(f"{lang('module')} {module_name} {lang('error')}: {type(exception)}: {exception}") logs.info(f"{lang('module')} {module_name} {lang('error')}: {type(exception)}: {exception}")
for plugin_name in plugin_list: for plugin_name in plugin_list:
try: try:
import_module("plugins." + plugin_name) import_module(f"plugins.{plugin_name}")
except BaseException as exception: except BaseException as exception:
logs.info(f"{lang('module')} {plugin_name} {lang('error')}: {exception}") logs.info(f"{lang('module')} {plugin_name} {lang('error')}: {exception}")
plugin_list.remove(plugin_name) plugin_list.remove(plugin_name)

View File

@ -17,7 +17,7 @@ class Permission:
self.name = name[1:] if name.startswith("-") else name self.name = name[1:] if name.startswith("-") else name
self.root = self.name.split(".")[0] self.root = self.name.split(".")[0]
self.sub = self.name.split(".")[1] if len(self.name.split(".")) > 1 else "" self.sub = self.name.split(".")[1] if len(self.name.split(".")) > 1 else ""
self.enable: bool = False if name.startswith("-") else True self.enable: bool = not name.startswith("-")
self.act: str = "access" if self.enable else "ejection" self.act: str = "access" if self.enable else "ejection"
@ -25,11 +25,13 @@ def enforce_permission(user: int, permission: str):
data = permission.split(".") data = permission.split(".")
if len(data) != 2: if len(data) != 2:
raise ValueError("Invalid permission format") raise ValueError("Invalid permission format")
if permissions.enforce(str(user), data[0], "access"): if permissions.enforce(
if not permissions.enforce(str(user), permission, "ejection"): str(user), data[0], "access"
) and not permissions.enforce(str(user), permission, "ejection"):
return True return True
if permissions.enforce(str(user), permission, "access"): if permissions.enforce(
if not permissions.enforce(str(user), permission, "ejection"): str(user), permission, "access"
) and not permissions.enforce(str(user), permission, "ejection"):
return True return True
return False return False
@ -43,7 +45,7 @@ def parse_pen(pen: Permission) -> List[Permission]:
for i in all_permissions: for i in all_permissions:
if pen.root == i.root and len(findall(pen.sub.replace("*", r"([\s\S]*)"), i.sub)) > 0 and i not in datas: if pen.root == i.root and len(findall(pen.sub.replace("*", r"([\s\S]*)"), i.sub)) > 0 and i not in datas:
datas.append(i) datas.append(i)
if len(datas) == 0: if not datas:
raise ValueError("No permission found") raise ValueError("No permission found")
return datas return datas
@ -61,40 +63,28 @@ def remove_user_from_group(user: str, group: str):
def add_permission_for_group(group: str, permission: Permission): def add_permission_for_group(group: str, permission: Permission):
if "*" in permission.name: data = parse_pen(permission) if "*" in permission.name else [permission]
data = parse_pen(permission)
else:
data = [permission]
for i in data: for i in data:
permissions.add_policy(group, i.name, permission.act, "allow") permissions.add_policy(group, i.name, permission.act, "allow")
permissions.save_policy() permissions.save_policy()
def remove_permission_for_group(group: str, permission: Permission): def remove_permission_for_group(group: str, permission: Permission):
if "*" in permission.name: data = parse_pen(permission) if "*" in permission.name else [permission]
data = parse_pen(permission)
else:
data = [permission]
for i in data: for i in data:
permissions.remove_policy(group, i.name, permission.act, "allow") permissions.remove_policy(group, i.name, permission.act, "allow")
permissions.save_policy() permissions.save_policy()
def add_permission_for_user(user: str, permission: Permission): def add_permission_for_user(user: str, permission: Permission):
if "*" in permission.name: data = parse_pen(permission) if "*" in permission.name else [permission]
data = parse_pen(permission)
else:
data = [permission]
for i in data: for i in data:
permissions.add_permission_for_user(user, i.name, permission.act, "allow") permissions.add_permission_for_user(user, i.name, permission.act, "allow")
permissions.save_policy() permissions.save_policy()
def remove_permission_for_user(user: str, permission: Permission): def remove_permission_for_user(user: str, permission: Permission):
if "*" in permission.name: data = parse_pen(permission) if "*" in permission.name else [permission]
data = parse_pen(permission)
else:
data = [permission]
for i in data: for i in data:
permissions.delete_permission_for_user(user, i.name, permission.act, "allow") permissions.delete_permission_for_user(user, i.name, permission.act, "allow")
permissions.save_policy() permissions.save_policy()

View File

@ -1,3 +1,4 @@
import contextlib
import sys import sys
import secrets import secrets
from asyncio import sleep from asyncio import sleep
@ -5,7 +6,6 @@ from time import strftime, gmtime, time
from traceback import format_exc from traceback import format_exc
from pyrogram import ContinuePropagation, StopPropagation, filters, Client from pyrogram import ContinuePropagation, StopPropagation, filters, Client
from pagermaid.single_utils import Message
from pyrogram.errors.exceptions.bad_request_400 import ( from pyrogram.errors.exceptions.bad_request_400 import (
MessageIdInvalid, MessageIdInvalid,
MessageNotModified, MessageNotModified,
@ -16,7 +16,9 @@ from pyrogram.handlers import MessageHandler, EditedMessageHandler
from pagermaid import help_messages, logs, Config, bot, read_context, all_permissions from pagermaid import help_messages, logs, Config, bot, read_context, all_permissions
from pagermaid.group_manager import Permission from pagermaid.group_manager import Permission
from pagermaid.single_utils import Message
from pagermaid.utils import lang, attach_report, sudo_filter, alias_command, get_permission_name, process_exit from pagermaid.utils import lang, attach_report, sudo_filter, alias_command, get_permission_name, process_exit
from pagermaid.utils import client as httpx_client
secret_generator = secrets.SystemRandom() secret_generator = secrets.SystemRandom()
@ -97,7 +99,8 @@ def listener(**args):
def decorator(function): def decorator(function):
async def handler(client: Client, message: Message): async def handler(client: Client, message: Message):
message.client = client message.bot = client
message.request = httpx_client
try: try:
try: try:
@ -116,11 +119,14 @@ def listener(**args):
raise ContinuePropagation raise ContinuePropagation
read_context[(message.chat.id, message.id)] = True read_context[(message.chat.id, message.id)] = True
if function.__code__.co_argcount == 1:
await function(message)
elif function.__code__.co_argcount == 2:
await function(client, message) await function(client, message)
except StopPropagation: except StopPropagation as e:
raise StopPropagation raise StopPropagation from e
except KeyboardInterrupt: except KeyboardInterrupt as e:
raise KeyboardInterrupt raise KeyboardInterrupt from e
except MessageNotModified: except MessageNotModified:
pass pass
except MessageIdInvalid: except MessageIdInvalid:
@ -129,29 +135,21 @@ def listener(**args):
) )
except UserNotParticipant: except UserNotParticipant:
pass pass
except ContinuePropagation: except ContinuePropagation as e:
raise ContinuePropagation raise ContinuePropagation from e
except SystemExit: except SystemExit:
await process_exit(start=False, _client=client, message=message) await process_exit(start=False, _client=client, message=message)
sys.exit(0) sys.exit(0)
except BaseException: except BaseException:
exc_info = sys.exc_info()[1] exc_info = sys.exc_info()[1]
exc_format = format_exc() exc_format = format_exc()
try: with contextlib.suppress(BaseException):
await message.edit(lang("run_error"), no_reply=True) # noqa await message.edit(lang("run_error"), no_reply=True) # noqa
except BaseException:
pass
if not diagnostics: if not diagnostics:
return return
if Config.ERROR_REPORT: if Config.ERROR_REPORT:
report = f"# Generated: {strftime('%H:%M %d/%m/%Y', gmtime())}. \n" \ report = f"""# Generated: {strftime('%H:%M %d/%m/%Y', gmtime())}. \n# ChatID: {message.chat.id}. \n# UserID: {message.from_user.id if message.from_user else message.sender_chat.id}. \n# Message: \n-----BEGIN TARGET MESSAGE-----\n{message.text or message.caption}\n-----END TARGET MESSAGE-----\n# Traceback: \n-----BEGIN TRACEBACK-----\n{str(exc_format)}\n-----END TRACEBACK-----\n# Error: "{str(exc_info)}". \n"""
f"# ChatID: {message.chat.id}. \n" \
f"# UserID: {message.from_user.id if message.from_user else message.sender_chat.id}. \n" \
f"# Message: \n-----BEGIN TARGET MESSAGE-----\n" \
f"{message.text if message.text else message.caption}\n-----END TARGET MESSAGE-----\n" \
f"# Traceback: \n-----BEGIN TRACEBACK-----\n" \
f"{str(exc_format)}\n-----END TRACEBACK-----\n" \
f"# Error: \"{str(exc_info)}\". \n"
await attach_report(report, f"exception.{time()}.pagermaid", None, await attach_report(report, f"exception.{time()}.pagermaid", None,
"Error report generated.") "Error report generated.")
if (message.chat.id, message.id) in read_context: if (message.chat.id, message.id) in read_context:
@ -185,12 +183,18 @@ def raw_listener(filter_s):
def decorator(function): def decorator(function):
async def handler(client, message): async def handler(client, message):
message.bot = client
message.request = httpx_client
try: try:
if function.__code__.co_argcount == 1:
await function(message)
elif function.__code__.co_argcount == 2:
await function(client, message) await function(client, message)
except StopPropagation: except StopPropagation as e:
raise StopPropagation raise StopPropagation from e
except ContinuePropagation: except ContinuePropagation as e:
raise ContinuePropagation raise ContinuePropagation from e
except SystemExit: except SystemExit:
await process_exit(start=False, _client=client, message=message) await process_exit(start=False, _client=client, message=message)
sys.exit(0) sys.exit(0)
@ -201,10 +205,8 @@ def raw_listener(filter_s):
except BaseException: except BaseException:
exc_info = sys.exc_info()[1] exc_info = sys.exc_info()[1]
exc_format = format_exc() exc_format = format_exc()
try: with contextlib.suppress(BaseException):
await message.edit(lang('run_error'), no_reply=True) await message.edit(lang('run_error'), no_reply=True)
except BaseException:
pass
if Config.ERROR_REPORT: if Config.ERROR_REPORT:
report = f"# Generated: {strftime('%H:%M %d/%m/%Y', gmtime())}. \n" \ report = f"# Generated: {strftime('%H:%M %d/%m/%Y', gmtime())}. \n" \
f"# ChatID: {message.chat.id}. \n" \ f"# ChatID: {message.chat.id}. \n" \

View File

@ -8,37 +8,38 @@ from pagermaid.utils import lang
def __list_modules(): def __list_modules():
module_paths = glob(dirname(__file__) + f"{sep}*.py") module_paths = glob(f"{dirname(__file__)}{sep}*.py")
result = [ return [
basename(file)[:-3] basename(file)[:-3]
for file in module_paths for file in module_paths
if isfile(file) and file.endswith(".py") and not file.endswith("__init__.py") if isfile(file)
and file.endswith(".py")
and not file.endswith("__init__.py")
] ]
return result
def __list_plugins(): def __list_plugins():
plugin_paths = glob(f"{getcwd()}{sep}plugins" + f"{sep}*.py") plugin_paths = glob(f"{getcwd()}{sep}plugins" + f"{sep}*.py")
if not exists(f"{getcwd()}{sep}plugins"): if not exists(f"{getcwd()}{sep}plugins"):
makedirs(f"{getcwd()}{sep}plugins") makedirs(f"{getcwd()}{sep}plugins")
result = [ return [
basename(file)[:-3] basename(file)[:-3]
for file in plugin_paths for file in plugin_paths
if isfile(file) and file.endswith(".py") and not file.endswith("__init__.py") if isfile(file)
and file.endswith(".py")
and not file.endswith("__init__.py")
] ]
return result
module_list_string = "" module_list_string = "".join(
plugin_list_string = "" f"{module}, " for module in sorted(__list_modules())
)
for module in sorted(__list_modules()):
module_list_string += f"{module}, "
module_list_string = module_list_string[:-2] module_list_string = module_list_string[:-2]
for plugin in sorted(__list_plugins()): plugin_list_string = "".join(
plugin_list_string += f"{plugin}, " f"{plugin}, " for plugin in sorted(__list_plugins())
)
plugin_list_string = plugin_list_string[:-2] plugin_list_string = plugin_list_string[:-2]

View File

@ -1,6 +1,5 @@
from os import remove from os import remove
from pyrogram import Client
from pyrogram.errors import UsernameNotOccupied, PeerIdInvalid from pyrogram.errors import UsernameNotOccupied, PeerIdInvalid
from pyrogram.types import User from pyrogram.types import User
@ -8,11 +7,13 @@ from pagermaid import Config
from pagermaid.listener import listener from pagermaid.listener import listener
from pagermaid.utils import lang, Message from pagermaid.utils import lang, Message
import contextlib
@listener(is_plugin=False, outgoing=True, command="profile",
@listener(is_plugin=False, command="profile",
description=lang('profile_des'), description=lang('profile_des'),
parameters="<username>") parameters="<username>")
async def profile(client: Client, message: Message): async def profile(message: Message):
""" Queries profile of a user. """ """ Queries profile of a user. """
if len(message.parameter) > 1: if len(message.parameter) > 1:
await message.edit(f"{lang('error_prefix')}{lang('arg_error')}") await message.edit(f"{lang('error_prefix')}{lang('arg_error')}")
@ -29,7 +30,7 @@ async def profile(client: Client, message: Message):
if user.isdigit(): if user.isdigit():
user = int(user) user = int(user)
else: else:
user = await client.get_me() user = await message.bot.get_me()
if message.entities is not None: if message.entities is not None:
if message.entities[0].type == "text_mention": if message.entities[0].type == "text_mention":
user = message.entities[0].user user = message.entities[0].user
@ -39,7 +40,7 @@ async def profile(client: Client, message: Message):
return await message.edit(f"{lang('error_prefix')}{lang('arg_error')}") return await message.edit(f"{lang('error_prefix')}{lang('arg_error')}")
if not isinstance(user, User): if not isinstance(user, User):
try: try:
user = await client.get_users(user) user = await message.bot.get_users(user)
except PeerIdInvalid: except PeerIdInvalid:
return await message.edit(f"{lang('error_prefix')}{lang('profile_e_nof')}") return await message.edit(f"{lang('error_prefix')}{lang('profile_e_nof')}")
except UsernameNotOccupied: except UsernameNotOccupied:
@ -66,10 +67,10 @@ async def profile(client: Client, message: Message):
f"{lang('profile_restricted')}: {restricted} \n" \ f"{lang('profile_restricted')}: {restricted} \n" \
f"{lang('profile_type')}: {user_type} \n" \ f"{lang('profile_type')}: {user_type} \n" \
f"[{first_name}](tg://user?id={user.id})" f"[{first_name}](tg://user?id={user.id})"
photo = await client.download_media(user.photo.big_file_id) photo = await message.bot.download_media(user.photo.big_file_id)
reply_to = message.reply_to_message reply_to = message.reply_to_message
try: try:
await client.send_photo( await message.bot.send_photo(
message.chat.id, message.chat.id,
photo, photo,
caption=caption, caption=caption,
@ -85,7 +86,7 @@ async def profile(client: Client, message: Message):
need_admin=True, need_admin=True,
description=lang('block_des'), description=lang('block_des'),
parameters="(username/uid/reply)") parameters="(username/uid/reply)")
async def block_user(client: Client, message: Message): async def block_user(message: Message):
""" Block a user. """ """ Block a user. """
if len(message.parameter) > 1: if len(message.parameter) > 1:
await message.edit(f"{lang('error_prefix')}{lang('arg_error')}") await message.edit(f"{lang('error_prefix')}{lang('arg_error')}")
@ -95,11 +96,9 @@ async def block_user(client: Client, message: Message):
user = message.obtain_user() user = message.obtain_user()
if not user: if not user:
return await message.edit(f"{lang('error_prefix')}{lang('arg_error')}") return await message.edit(f"{lang('error_prefix')}{lang('arg_error')}")
try: with contextlib.suppress(Exception):
if await client.block_user(user): if await message.bot.block_user(user):
return await message.edit(f"{lang('block_success')} `{user}`") return await message.edit(f"{lang('block_success')} `{user}`")
except Exception: # noqa
pass
await message.edit(f"`{user}` {lang('block_exist')}") await message.edit(f"`{user}` {lang('block_exist')}")
@ -107,7 +106,7 @@ async def block_user(client: Client, message: Message):
need_admin=True, need_admin=True,
description=lang('unblock_des'), description=lang('unblock_des'),
parameters="<username/uid/reply>") parameters="<username/uid/reply>")
async def unblock_user(client: Client, message: Message): async def unblock_user(message: Message):
""" Unblock a user. """ """ Unblock a user. """
if len(message.parameter) > 1: if len(message.parameter) > 1:
await message.edit(f"{lang('error_prefix')}{lang('arg_error')}") await message.edit(f"{lang('error_prefix')}{lang('arg_error')}")
@ -117,9 +116,7 @@ async def unblock_user(client: Client, message: Message):
user = message.obtain_user() user = message.obtain_user()
if not user: if not user:
return await message.edit(f"{lang('error_prefix')}{lang('arg_error')}") return await message.edit(f"{lang('error_prefix')}{lang('arg_error')}")
try: with contextlib.suppress(Exception):
if await client.unblock_user(user): if await message.bot.unblock_user(user):
return await message.edit(f"{lang('unblock_success')} `{user}`") return await message.edit(f"{lang('unblock_success')} `{user}`")
except Exception: # noqa
pass
await message.edit(f"`{user}` {lang('unblock_exist')}") await message.edit(f"`{user}` {lang('unblock_exist')}")

View File

@ -1 +1,91 @@
""" PagerMaid module for different ways to avoid users. """ from pyrogram import Client from pagermaid import log from pagermaid.single_utils import sqlite from pagermaid.utils import lang, Message from pagermaid.listener import listener @listener(is_plugin=False, outgoing=True, command="ghost", description=lang('ghost_des'), parameters="<true|false|status>") async def ghost(client: Client, message: Message): """ Toggles ghosting of a user. """ if len(message.parameter) != 1: await message.edit(f"{lang('error_prefix')}{lang('arg_error')}") return 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["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["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("ghosted.chat_id." + str(message.chat_id), None): await message.edit(lang('ghost_e_exist')) else: await message.edit(lang('ghost_e_noexist')) else: await message.edit(f"{lang('error_prefix')}{lang('arg_error')}") @listener(is_plugin=False, outgoing=True, command="deny", need_admin=True, description=lang('deny_des'), parameters="<true|false|status>") async def deny(client: Client, message: Message): """ Toggles denying of a user. """ if len(message.parameter) != 1: await message.edit(f"{lang('error_prefix')}{lang('arg_error')}") return 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["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["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("denied.chat_id." + str(message.chat_id), None): await message.edit(lang('deny_e_exist')) else: await message.edit(lang('deny_e_noexist')) else: await message.edit(f"{lang('error_prefix')}{lang('arg_error')}") @listener(is_plugin=False, incoming=True, outgoing=False, ignore_edited=True) async def set_read_acknowledgement(client: Client, message: Message): """ Event handler to infinitely read ghosted messages. """ if sqlite.get("ghosted.chat_id." + str(message.chat.id), None): await client.read_chat_history(message.chat.id) @listener(is_plugin=False, incoming=True, outgoing=False, ignore_edited=True) async def message_removal(_: Client, message: Message): """ Event handler to infinitely delete denied messages. """ if sqlite.get("denied.chat_id." + str(message.chat.id), None): await message.safe_delete() """ PagerMaid module for different ways to avoid users. """
from pagermaid import log
from pagermaid.single_utils import sqlite
from pagermaid.utils import lang, Message
from pagermaid.listener import listener
@listener(is_plugin=False, outgoing=True, command="ghost",
description=lang('ghost_des'),
parameters="<true|false|status>")
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
myself = await message.bot.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'))
else:
await message.edit(f"{lang('error_prefix')}{lang('arg_error')}")
@listener(is_plugin=False, outgoing=True, command="deny",
need_admin=True,
description=lang('deny_des'),
parameters="<true|false|status>")
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
myself = await message.bot.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'))
else:
await message.edit(f"{lang('error_prefix')}{lang('arg_error')}")
@listener(is_plugin=False, incoming=True, outgoing=False, ignore_edited=True)
async def set_read_acknowledgement(message: Message):
""" Event handler to infinitely read ghosted messages. """
if sqlite.get(f"ghosted.chat_id.{str(message.chat.id)}", None):
await message.bot.read_chat_history(message.chat.id)
@listener(is_plugin=False, incoming=True, outgoing=False, ignore_edited=True)
async def message_removal(message: Message):
""" Event handler to infinitely delete denied messages. """
if sqlite.get(f"denied.chat_id.{str(message.chat.id)}", None):
await message.safe_delete()

View File

@ -1,10 +1,9 @@
""" Pagermaid backup and recovery plugin. """ """ Pagermaid backup and recovery plugin. """
import os import os
import sys
import tarfile import tarfile
from traceback import format_exc from traceback import format_exc
from pyrogram import Client
from pagermaid.config import Config from pagermaid.config import Config
from pagermaid.listener import listener from pagermaid.listener import listener
from pagermaid.utils import upload_attachment, lang, Message from pagermaid.utils import upload_attachment, lang, Message
@ -42,7 +41,7 @@ def un_tar_gz(filename, dirs):
@listener(is_plugin=False, outgoing=True, command="backup", @listener(is_plugin=False, outgoing=True, command="backup",
description=lang('back_des')) description=lang('back_des'))
async def backup(_: Client, message: Message): async def backup(message: Message):
await message.edit(lang('backup_process')) await message.edit(lang('backup_process'))
# Remove old backup # Remove old backup
@ -66,23 +65,21 @@ async def backup(_: Client, message: Message):
@listener(is_plugin=False, outgoing=True, command="recovery", @listener(is_plugin=False, outgoing=True, command="recovery",
need_admin=True, need_admin=True,
description=lang('recovery_des')) description=lang('recovery_des'))
async def recovery(_: Client, message: Message): async def recovery(message: Message):
reply = message.reply_to_message reply = message.reply_to_message
if reply.document: # Overwrite local backup if not reply.document:
return await message.edit(lang('recovery_file_error'))
try: try:
if ".tar.gz" in reply.document.file_name: # Verify filename if ".tar.gz" not in reply.document.file_name:
return await message.edit(lang('recovery_file_error'))
await message.edit(lang('recovery_down')) await message.edit(lang('recovery_down'))
# Start download process # Start download process
pgm_backup_zip_name = await reply.download() # noqa pgm_backup_zip_name = await reply.download() # noqa
else:
return await message.edit(lang('recovery_file_error'))
except Exception as e: # noqa except Exception as e: # noqa
print(e, format_exc()) print(e, format_exc())
return await message.edit(lang('recovery_file_error')) return await message.edit(lang('recovery_file_error'))
else:
return await message.edit(lang('recovery_file_error'))
# Extract backup files # Extract backup files
await message.edit(lang('recovery_process')) await message.edit(lang('recovery_process'))
if not os.path.exists(pgm_backup_zip_name): if not os.path.exists(pgm_backup_zip_name):
@ -96,4 +93,4 @@ async def recovery(_: Client, message: Message):
os.remove(pgm_backup_zip_name) os.remove(pgm_backup_zip_name)
await message.edit(lang('recovery_success') + " " + lang('apt_reboot')) await message.edit(lang('recovery_success') + " " + lang('apt_reboot'))
exit(1) sys.exit(1)

View File

@ -2,7 +2,6 @@
from datetime import datetime from datetime import datetime
from pyrogram import Client
from pytz import country_names, country_timezones, timezone from pytz import country_names, country_timezones, timezone
from pagermaid.config import Config from pagermaid.config import Config
from pagermaid.listener import listener from pagermaid.listener import listener
@ -12,7 +11,7 @@ from pagermaid.utils import lang, Message
@listener(is_plugin=False, outgoing=True, command="time", @listener(is_plugin=False, outgoing=True, command="time",
description=lang('time_des'), description=lang('time_des'),
parameters=lang('time_parameters')) parameters=lang('time_parameters'))
async def time(_: Client, message: Message): async def time(message: Message):
""" For querying time. """ """ For querying time. """
if len(message.parameter) == 1: if len(message.parameter) == 1:
country = message.parameter[0].title() country = message.parameter[0].title()

View File

@ -1,19 +1,32 @@
""" The help module. """ """ The help module. """
from pyrogram import Client
from json import dump as json_dump from json import dump as json_dump
from os import listdir, sep from os import listdir, sep
from pagermaid import help_messages, Config from pagermaid import help_messages, Config
from pagermaid.group_manager import enforce_permission from pagermaid.group_manager import enforce_permission
from pagermaid.modules.reload import reload_all
from pagermaid.utils import lang, Message, from_self, from_msg_get_sudo_uid from pagermaid.utils import lang, Message, from_self, from_msg_get_sudo_uid
from pagermaid.listener import listener from pagermaid.listener import listener
import pathlib
@listener(is_plugin=False, command="help", @listener(is_plugin=False, command="help",
description=lang('help_des'), description=lang('help_des'),
parameters=f"<{lang('command')}>") parameters=f"<{lang('command')}>")
async def help_command(_: Client, message: Message): async def help_command(message: Message):
""" The help new command,""" """ The help new command,"""
if message.arguments:
if message.arguments in help_messages:
if from_self(message) or \
enforce_permission(from_msg_get_sudo_uid(message), help_messages[message.arguments]["permission"]):
await message.edit(f"{help_messages[message.arguments]['use']}")
else:
await message.edit(lang('help_no_permission'))
else:
await message.edit(lang('arg_error'))
else:
result = f"**{lang('help_list')}: \n**"
support_commands = ['username', 'name', 'pfp', 'bio', 'rmpfp', support_commands = ['username', 'name', 'pfp', 'bio', 'rmpfp',
'profile', 'block', 'unblock', 'ghost', 'deny', 'convert', 'profile', 'block', 'unblock', 'ghost', 'deny', 'convert',
'caption', 'ocr', 'highlight', 'time', 'translate', 'caption', 'ocr', 'highlight', 'time', 'translate',
@ -28,17 +41,6 @@ async def help_command(_: Client, message: Message):
'pingdc', 'ping', 'topcloud', 'pingdc', 'ping', 'topcloud',
's', 'sticker', 'sh', 'restart', 's', 'sticker', 'sh', 'restart',
'trace', 'chat', 'update'] 'trace', 'chat', 'update']
if message.arguments:
if message.arguments in help_messages:
if from_self(message) or \
enforce_permission(from_msg_get_sudo_uid(message), help_messages[message.arguments]["permission"]):
await message.edit(f"{help_messages[message.arguments]['use']}")
else:
await message.edit(lang('help_no_permission'))
else:
await message.edit(lang('arg_error'))
else:
result = f"**{lang('help_list')}: \n**"
for command in sorted(help_messages, reverse=False): for command in sorted(help_messages, reverse=False):
if str(command) in support_commands: if str(command) in support_commands:
continue continue
@ -62,7 +64,7 @@ async def help_command(_: Client, message: Message):
@listener(is_plugin=False, command="help_raw", @listener(is_plugin=False, command="help_raw",
description=lang('help_des'), description=lang('help_des'),
parameters=f"<{lang('command')}>") parameters=f"<{lang('command')}>")
async def help_raw_command(_: Client, message: Message): async def help_raw_command(message: Message):
""" The help raw command,""" """ The help raw command,"""
if message.arguments: if message.arguments:
if message.arguments in help_messages: if message.arguments in help_messages:
@ -79,29 +81,29 @@ async def help_raw_command(_: Client, message: Message):
if from_self(message) or \ if from_self(message) or \
enforce_permission(from_msg_get_sudo_uid(message), help_messages[command]["permission"]): enforce_permission(from_msg_get_sudo_uid(message), help_messages[command]["permission"]):
result += f"`{command}`, " result += f"`{command}`, "
await message.edit(result[:-2] + f"\n**{lang('help_send')} \",help <{lang('command')}>\" {lang('help_see')}** " await message.edit(
f"[{lang('help_source')}](https://t.me/PagerMaid_Modify)", f"""{result[:-2]}\n**{lang('help_send')} ",help <{lang('command')}>" {lang('help_see')}** [{lang('help_source')}](https://t.me/PagerMaid_Modify)""",
disable_web_page_preview=True) disable_web_page_preview=True,
)
@listener(is_plugin=False, command="lang", @listener(is_plugin=False, command="lang",
need_admin=True, need_admin=True,
description=lang('lang_des')) description=lang('lang_des'))
async def lang_change(_: Client, message: Message): async def lang_change(message: Message):
to_lang = message.arguments to_lang = message.arguments
from_lang = Config.LANGUAGE from_lang = Config.LANGUAGE
dir_, dir__ = listdir('languages/built-in'), [] dir_, dir__ = listdir('languages/built-in'), []
for i in dir_: for i in dir_:
if not i.find('yml') == -1: if i.find('yml') != -1:
dir__.append(i[:-4]) dir__.append(i[:-4])
with open('config.yml') as f: file = pathlib.Path('config.yml').read_text()
file = f.read()
if to_lang in dir__: if to_lang in dir__:
file = file.replace(f'application_language: "{from_lang}"', f'application_language: "{to_lang}"') file = file.replace(f'application_language: "{from_lang}"', f'application_language: "{to_lang}"')
with open('config.yml', 'w') as f: with open('config.yml', 'w') as f:
f.write(file) f.write(file)
await message.edit(f"{lang('lang_change_to')} {to_lang}, {lang('lang_reboot')}") await message.edit(f"{lang('lang_change_to')} {to_lang}, {lang('lang_reboot')}")
exit(1) reload_all()
else: else:
await message.edit(f'{lang("lang_current_lang")} {Config.LANGUAGE}\n\n' await message.edit(f'{lang("lang_current_lang")} {Config.LANGUAGE}\n\n'
f'{lang("lang_all_lang")}{"".join(dir__)}') f'{lang("lang_all_lang")}{"".join(dir__)}')
@ -112,7 +114,7 @@ async def lang_change(_: Client, message: Message):
need_admin=True, need_admin=True,
description=lang('alias_des'), description=lang('alias_des'),
parameters='{list|del|set} <source> <to>') parameters='{list|del|set} <source> <to>')
async def alias_commands(_: Client, message: Message): async def alias_commands(message: Message):
source_commands = [] source_commands = []
to_commands = [] to_commands = []
texts = [] texts = []
@ -123,9 +125,12 @@ async def alias_commands(_: Client, message: Message):
await message.edit(lang('arg_error')) await message.edit(lang('arg_error'))
return return
elif len(message.parameter) == 1: elif len(message.parameter) == 1:
if not len(source_commands) == 0: if source_commands:
for i in range(0, len(source_commands)): texts.extend(
texts.append(f'`{source_commands[i]}` --> `{to_commands[i]}`') f'`{source_commands[i]}` --> `{to_commands[i]}`'
for i in range(len(source_commands))
)
await message.edit(lang('alias_list') + '\n\n' + '\n'.join(texts)) await message.edit(lang('alias_list') + '\n\n' + '\n'.join(texts))
else: else:
await message.edit(lang('alias_no')) await message.edit(lang('alias_no'))
@ -136,7 +141,7 @@ async def alias_commands(_: Client, message: Message):
with open(f"data{sep}alias.json", 'w') as f: with open(f"data{sep}alias.json", 'w') as f:
json_dump(Config.alias_dict, f) json_dump(Config.alias_dict, f)
await message.edit(lang('alias_success')) await message.edit(lang('alias_success'))
exit(1) reload_all()
except KeyError: except KeyError:
await message.edit(lang('alias_no_exist')) await message.edit(lang('alias_no_exist'))
return return
@ -150,4 +155,4 @@ async def alias_commands(_: Client, message: Message):
with open(f"data{sep}alias.json", 'w') as f: with open(f"data{sep}alias.json", 'w') as f:
json_dump(Config.alias_dict, f) json_dump(Config.alias_dict, f)
await message.edit(lang('alias_success')) await message.edit(lang('alias_success'))
exit(1) reload_all()

View File

@ -1,5 +1,5 @@
""" Pagermaid message plugin. """ """ Pagermaid message plugin. """
from pyrogram import Client
from pyrogram.errors import Forbidden, FloodWait from pyrogram.errors import Forbidden, FloodWait
from pagermaid import log from pagermaid import log
@ -10,29 +10,29 @@ from pagermaid.utils import lang, Message
@listener(is_plugin=False, outgoing=True, command="id", @listener(is_plugin=False, outgoing=True, command="id",
description=lang("id_des")) description=lang("id_des"))
async def userid(_: Client, message: Message): async def userid(message: Message):
""" Query the UserID of the sender of the message you replied to. """ """ Query the UserID of the sender of the message you replied to. """
reply = message.reply_to_message reply = message.reply_to_message
text = "Message ID: `" + str(message.id) + "`\n\n" text = f"Message ID: `{str(message.id)}" + "`\n\n"
text += "**Chat**\nid:`" + str(message.chat.id) + "`\n" text += "**Chat**\nid:`" + str(message.chat.id) + "`\n"
msg_from = message.chat msg_from = message.chat
if msg_from.type == "private": if msg_from.type == "private":
try: try:
text += "first_name: `" + msg_from.first_name + "`\n" text += f"first_name: `{msg_from.first_name}" + "`\n"
except TypeError: except TypeError:
text += "**死号**\n" text += "**死号**\n"
if msg_from.last_name: if msg_from.last_name:
text += "last_name: `" + msg_from.last_name + "`\n" text += f"last_name: `{msg_from.last_name}" + "`\n"
if msg_from.username: if msg_from.username:
text += "username: @" + msg_from.username + "\n" text += f"username: @{msg_from.username}" + "\n"
if msg_from.type in ["supergroup", "channel"]: if msg_from.type in ["supergroup", "channel"]:
text += "title: `" + msg_from.title + "`\n" text += f"title: `{msg_from.title}" + "`\n"
try: try:
if msg_from.username: if msg_from.username:
text += "username: @" + msg_from.username + "\n" text += f"username: @{msg_from.username}" + "\n"
except AttributeError: except AttributeError:
return await message.edit(lang("leave_not_group")) return await message.edit(lang("leave_not_group"))
text += "protected: `" + str(msg_from.has_protected_content) + "`\n" text += f"protected: `{str(msg_from.has_protected_content)}" + "`\n"
if reply: if reply:
text += "\n" + lang('id_hint') + "\nMessage ID: `" + str(reply.id) + \ text += "\n" + lang('id_hint') + "\nMessage ID: `" + str(reply.id) + \
"`\n\n**User**\nid: `" + str(reply.from_user.id) + "`" "`\n\n**User**\nid: `" + str(reply.from_user.id) + "`"
@ -83,7 +83,7 @@ async def userid(_: Client, message: Message):
@listener(is_plugin=False, outgoing=True, command="uslog", @listener(is_plugin=False, outgoing=True, command="uslog",
description=lang('uslog_des'), description=lang('uslog_des'),
parameters="<string>") parameters="<string>")
async def uslog(_: Client, message: Message): async def uslog(message: Message):
""" Forwards a message into log group """ """ Forwards a message into log group """
if Config.LOG: if Config.LOG:
if message.reply_to_message: if message.reply_to_message:
@ -101,7 +101,7 @@ async def uslog(_: Client, message: Message):
@listener(is_plugin=False, outgoing=True, command="log", @listener(is_plugin=False, outgoing=True, command="log",
description=lang('log_des'), description=lang('log_des'),
parameters="<string>") parameters="<string>")
async def logging(_: Client, message: Message): async def logging(message: Message):
""" Forwards a message into log group """ """ Forwards a message into log group """
if Config.LOG: if Config.LOG:
if message.reply_to_message: if message.reply_to_message:
@ -119,10 +119,9 @@ async def logging(_: Client, message: Message):
@listener(is_plugin=False, outgoing=True, command="re", @listener(is_plugin=False, outgoing=True, command="re",
description=lang('re_des'), description=lang('re_des'),
parameters=lang('re_parameters')) parameters=lang('re_parameters'))
async def re(_: Client, message: Message): async def re(message: Message):
""" Forwards a message into this group """ """ Forwards a message into this group """
reply = message.reply_to_message if reply := message.reply_to_message:
if reply:
if message.arguments == '': if message.arguments == '':
num = 1 num = 1
else: else:
@ -130,10 +129,10 @@ async def re(_: Client, message: Message):
num = int(message.arguments) num = int(message.arguments)
if num > 100: if num > 100:
await message.edit(lang('re_too_big')) await message.edit(lang('re_too_big'))
except: # noqa except Exception:
return await message.edit(lang('re_arg_error')) return await message.edit(lang('re_arg_error'))
await message.safe_delete() await message.safe_delete()
for nums in range(0, num): for _ in range(num):
try: try:
if not message.chat.has_protected_content: if not message.chat.has_protected_content:
await reply.forward(reply.chat.id) await reply.forward(reply.chat.id)

View File

@ -1,30 +1,29 @@
""" PagerMaid module to manage plugins. """ """ PagerMaid module to manage plugins. """
import contextlib
import json import json
import importlib
from re import search, I from re import search, I
from os import remove, rename, chdir, path, sep from os import remove, rename, chdir, path, sep
from os.path import exists from os.path import exists
from shutil import copyfile, move from shutil import copyfile, move
from glob import glob from glob import glob
from pyrogram import Client from pagermaid import log, working_dir, Config, scheduler
from pagermaid import log, working_dir, Config
from pagermaid.listener import listener from pagermaid.listener import listener
from pagermaid.single_utils import safe_remove from pagermaid.single_utils import safe_remove
from pagermaid.utils import upload_attachment, lang, Message, client from pagermaid.utils import upload_attachment, lang, Message, client
from pagermaid.modules import plugin_list as active_plugins, __list_plugins from pagermaid.modules import plugin_list as active_plugins, __list_plugins
from pagermaid.modules.reload import reload_all
def remove_plugin(name): def remove_plugin(name):
plugin_directory = f"{working_dir}{sep}plugins{sep}" plugin_directory = f"{working_dir}{sep}plugins{sep}"
try: with contextlib.suppress(FileNotFoundError):
remove(f"{plugin_directory}{name}.py") remove(f"{plugin_directory}{name}.py")
except FileNotFoundError: with contextlib.suppress(FileNotFoundError):
pass
try:
remove(f"{plugin_directory}{name}.py.disabled") remove(f"{plugin_directory}{name}.py.disabled")
except FileNotFoundError:
pass
def move_plugin(file_path): def move_plugin(file_path):
@ -55,7 +54,7 @@ def update_version(plugin_name, version):
diagnostics=False, diagnostics=False,
description=lang('apt_des'), description=lang('apt_des'),
parameters=lang('apt_parameters')) parameters=lang('apt_parameters'))
async def plugin(__: Client, message: Message): async def plugin(message: Message):
if len(message.parameter) == 0: if len(message.parameter) == 0:
await message.edit(lang('arg_error')) await message.edit(lang('arg_error'))
return return
@ -81,7 +80,7 @@ async def plugin(__: Client, message: Message):
f"{path.basename(file_path)[:-3]} {lang('apt_installed')}," f"{path.basename(file_path)[:-3]} {lang('apt_installed')},"
f"{lang('apt_reboot')}") f"{lang('apt_reboot')}")
await log(f"{lang('apt_install_success')} {path.basename(file_path)[:-3]}.") await log(f"{lang('apt_install_success')} {path.basename(file_path)[:-3]}.")
exit(0) reload_all()
elif len(message.parameter) >= 2: elif len(message.parameter) >= 2:
process_list = message.parameter process_list = message.parameter
message = await message.edit(lang('apt_processing')) message = await message.edit(lang('apt_processing'))
@ -133,15 +132,15 @@ async def plugin(__: Client, message: Message):
text += lang('apt_reboot') text += lang('apt_reboot')
await message.edit(text) await message.edit(text)
if restart: if restart:
exit(0) reload_all()
else: else:
await message.edit(lang('arg_error')) await message.edit(lang('arg_error'))
elif message.parameter[0] == "remove": elif message.parameter[0] == "remove":
if len(message.parameter) == 2: if len(message.parameter) == 2:
if exists(f"{plugin_directory}{message.parameter[1]}.py") or \ if exists(f"{plugin_directory}{message.parameter[1]}.py") or \
exists(f"{plugin_directory}{message.parameter[1]}.py.disabled"): exists(f"{plugin_directory}{message.parameter[1]}.py.disabled"):
safe_remove(f"{plugin_directory}{message.parameter[1]}.py") remove_plugin(message.parameter[1])
safe_remove(f"{plugin_directory}{message.parameter[1]}.py.disabled") if exists(f"{plugin_directory}version.json"):
with open(f"{plugin_directory}version.json", 'r', encoding="utf-8") as f: with open(f"{plugin_directory}version.json", 'r', encoding="utf-8") as f:
version_json = json.load(f) version_json = json.load(f)
version_json[message.parameter[1]] = "0.0" version_json[message.parameter[1]] = "0.0"
@ -150,7 +149,7 @@ async def plugin(__: Client, message: Message):
await message.edit(f"{lang('apt_remove_success')} {message.parameter[1]}, " await message.edit(f"{lang('apt_remove_success')} {message.parameter[1]}, "
f"{lang('apt_reboot')} ") f"{lang('apt_reboot')} ")
await log(f"{lang('apt_remove')} {message.parameter[1]}.") await log(f"{lang('apt_remove')} {message.parameter[1]}.")
exit(0) reload_all()
elif "/" in message.parameter[1]: elif "/" in message.parameter[1]:
await message.edit(lang('arg_error')) await message.edit(lang('arg_error'))
else: else:
@ -201,7 +200,7 @@ async def plugin(__: Client, message: Message):
await message.edit(f"{lang('apt_plugin')} {message.parameter[1]} " await message.edit(f"{lang('apt_plugin')} {message.parameter[1]} "
f"{lang('apt_enable')},{lang('apt_reboot')}") f"{lang('apt_enable')},{lang('apt_reboot')}")
await log(f"{lang('apt_enable')} {message.parameter[1]}.") await log(f"{lang('apt_enable')} {message.parameter[1]}.")
exit(0) reload_all()
else: else:
await message.edit(lang('apt_not_exist')) await message.edit(lang('apt_not_exist'))
else: else:
@ -214,7 +213,7 @@ async def plugin(__: Client, message: Message):
await message.edit(f"{lang('apt_plugin')} {message.parameter[1]} " await message.edit(f"{lang('apt_plugin')} {message.parameter[1]} "
f"{lang('apt_disable')},{lang('apt_reboot')}") f"{lang('apt_disable')},{lang('apt_reboot')}")
await log(f"{lang('apt_disable')} {message.parameter[1]}.") await log(f"{lang('apt_disable')} {message.parameter[1]}.")
exit(0) reload_all()
else: else:
await message.edit(lang('apt_not_exist')) await message.edit(lang('apt_not_exist'))
else: else:
@ -262,7 +261,7 @@ async def plugin(__: Client, message: Message):
un_need_update += "\n`" + key + "`:Ver " + value un_need_update += "\n`" + key + "`:Ver " + value
else: else:
need_update_list.extend([key]) need_update_list.extend([key])
need_update += "\n`" + key + "`:Ver " + value + " --> Ver " + i['version'] need_update += "\n<code>" + key + "</code>:Ver " + value + " > Ver " + i['version']
continue continue
if un_need_update == f"{lang('apt_no_update')}:": if un_need_update == f"{lang('apt_no_update')}:":
un_need_update = "" un_need_update = ""
@ -288,7 +287,7 @@ async def plugin(__: Client, message: Message):
with open(f"{plugin_directory}version.json", "w") as f: with open(f"{plugin_directory}version.json", "w") as f:
json.dump(version_json, f) json.dump(version_json, f)
await message.edit(f"<b>{lang('apt_name')}</b>\n\n" + lang("apt_reading_list") + need_update) await message.edit(f"<b>{lang('apt_name')}</b>\n\n" + lang("apt_reading_list") + need_update)
exit(0) reload_all()
elif message.parameter[0] == "search": elif message.parameter[0] == "search":
if len(message.parameter) == 1: if len(message.parameter) == 1:
await message.edit(lang("apt_search_no_name")) await message.edit(lang("apt_search_no_name"))
@ -354,5 +353,9 @@ async def plugin(__: Client, message: Message):
await message.edit(lang("apt_why_not_install_a_plugin")) await message.edit(lang("apt_why_not_install_a_plugin"))
else: else:
await message.edit(",apt install " + " ".join(list_plugin)) await message.edit(",apt install " + " ".join(list_plugin))
elif message.parameter[0] == "reload":
# bot.dispatcher.remove_all_handlers() # noqa
scheduler.remove_all_jobs()
importlib.reload(importlib.import_module("plugins.sign"))
else: else:
await message.edit(lang("arg_error")) await message.edit(lang("arg_error"))

View File

@ -2,17 +2,17 @@
from asyncio import sleep from asyncio import sleep
from pyrogram import Client
from pagermaid import log from pagermaid import log
from pagermaid.listener import listener from pagermaid.listener import listener
from pagermaid.utils import lang, Message from pagermaid.utils import lang, Message
import contextlib
@listener(is_plugin=False, outgoing=True, command="prune", @listener(is_plugin=False, outgoing=True, command="prune",
need_admin=True, need_admin=True,
description=lang('prune_des')) description=lang('prune_des'))
async def prune(client: Client, message: Message): async def prune(message: Message):
""" Purge every single message after the message you replied to. """ """ Purge every single message after the message you replied to. """
if not message.reply_to_message: if not message.reply_to_message:
await message.edit(lang('not_reply')) await message.edit(lang('not_reply'))
@ -20,7 +20,7 @@ async def prune(client: Client, message: Message):
input_chat = message.chat.id input_chat = message.chat.id
messages = [] messages = []
count = 0 count = 0
async for msg in client.get_chat_history(input_chat, async for msg in message.bot.get_chat_history(input_chat,
limit=message.id - message.reply_to_message.id + 1): limit=message.id - message.reply_to_message.id + 1):
if msg.id < message.reply_to_message.id: if msg.id < message.reply_to_message.id:
break break
@ -29,13 +29,13 @@ async def prune(client: Client, message: Message):
if msg.reply_to_message: if msg.reply_to_message:
messages.append(msg.reply_to_message.id) messages.append(msg.reply_to_message.id)
if len(messages) == 100: if len(messages) == 100:
await client.delete_messages(input_chat, messages) await message.bot.delete_messages(input_chat, messages)
messages = [] messages = []
if messages: if messages:
await client.delete_messages(input_chat, messages) await message.bot.delete_messages(input_chat, messages)
await log(f"{lang('prune_hint1')} {str(count)} {lang('prune_hint2')}") await log(f"{lang('prune_hint1')} {str(count)} {lang('prune_hint2')}")
notification = await send_prune_notify(client, message, count, count) notification = await send_prune_notify(message, count, count)
await sleep(1) await sleep(1)
await notification.delete() await notification.delete()
@ -44,14 +44,14 @@ async def prune(client: Client, message: Message):
need_admin=True, need_admin=True,
description=lang('sp_des'), description=lang('sp_des'),
parameters=lang('sp_parameters')) parameters=lang('sp_parameters'))
async def self_prune(client: Client, message: Message): async def self_prune(message: Message):
""" Deletes specific amount of messages you sent. """ """ Deletes specific amount of messages you sent. """
msgs = [] msgs = []
count_buffer = 0 count_buffer = 0
if not len(message.parameter) == 1: if len(message.parameter) != 1:
if not message.reply_to_message: if not message.reply_to_message:
return await message.edit(lang('arg_error')) return await message.edit(lang('arg_error'))
async for msg in client.search_messages( async for msg in message.bot.search_messages(
message.chat.id, message.chat.id,
from_user="me", from_user="me",
offset=message.reply_to_message.id, offset=message.reply_to_message.id,
@ -59,15 +59,15 @@ async def self_prune(client: Client, message: Message):
msgs.append(msg.id) msgs.append(msg.id)
count_buffer += 1 count_buffer += 1
if len(msgs) == 100: if len(msgs) == 100:
await client.delete_messages(message.chat.id, msgs) await message.bot.delete_messages(message.chat.id, msgs)
msgs = [] msgs = []
if msgs: if msgs:
await client.delete_messages(message.chat.id, msgs) await message.bot.delete_messages(message.chat.id, msgs)
if count_buffer == 0: if count_buffer == 0:
await message.delete() await message.delete()
count_buffer += 1 count_buffer += 1
await log(f"{lang('prune_hint1')}{lang('sp_hint')} {str(count_buffer)} {lang('prune_hint2')}") await log(f"{lang('prune_hint1')}{lang('sp_hint')} {str(count_buffer)} {lang('prune_hint2')}")
notification = await send_prune_notify(client, message, count_buffer, count_buffer) notification = await send_prune_notify(message, count_buffer, count_buffer)
await sleep(1) await sleep(1)
await notification.delete() await notification.delete()
return return
@ -77,37 +77,38 @@ async def self_prune(client: Client, message: Message):
except ValueError: except ValueError:
await message.edit(lang('arg_error')) await message.edit(lang('arg_error'))
return return
async for msg in client.search_messages(message.chat.id, from_user="me"): async for msg in message.bot.search_messages(message.chat.id, from_user="me"):
if count_buffer == count: if count_buffer == count:
break break
msgs.append(msg.id) msgs.append(msg.id)
count_buffer += 1 count_buffer += 1
if len(msgs) == 100: if len(msgs) == 100:
await client.delete_messages(message.chat.id, msgs) await message.bot.delete_messages(message.chat.id, msgs)
msgs = [] msgs = []
if msgs: if msgs:
await client.delete_messages(message.chat.id, msgs) await message.bot.delete_messages(message.chat.id, msgs)
await log(f"{lang('prune_hint1')}{lang('sp_hint')} {str(count_buffer)} / {str(count)} {lang('prune_hint2')}") await log(
try: f"{lang('prune_hint1')}{lang('sp_hint')} {str(count_buffer)} / {count} {lang('prune_hint2')}"
notification = await send_prune_notify(client, message, count_buffer, count) )
with contextlib.suppress(ValueError):
notification = await send_prune_notify(message, count_buffer, count)
await sleep(1) await sleep(1)
await notification.delete() await notification.delete()
except ValueError:
pass
@listener(is_plugin=False, outgoing=True, command="yourprune", @listener(is_plugin=False, outgoing=True, command="yourprune",
need_admin=True, need_admin=True,
description=lang('yp_des'), description=lang('yp_des'),
parameters=lang('sp_parameters')) parameters=lang('sp_parameters'))
async def your_prune(client: Client, message: Message): async def your_prune(message: Message):
""" Deletes specific amount of messages someone sent. """ """ Deletes specific amount of messages someone sent. """
if not message.reply_to_message: if not message.reply_to_message:
return await message.edit(lang('not_reply')) return await message.edit(lang('not_reply'))
target = message.reply_to_message target = message.reply_to_message
if not target.from_user: if not target.from_user:
return await message.edit(lang('not_reply')) return await message.edit(lang('not_reply'))
if not len(message.parameter) == 1: if len(message.parameter) != 1:
return await message.edit(lang('arg_error')) return await message.edit(lang('arg_error'))
count = 0 count = 0
try: try:
@ -118,13 +119,16 @@ async def your_prune(client: Client, message: Message):
except Exception: # noqa except Exception: # noqa
pass pass
count_buffer = 0 count_buffer = 0
async for msg in client.search_messages(message.chat.id, from_user=target.from_user.id): async for msg in message.bot.search_messages(message.chat.id, from_user=target.from_user.id):
if count_buffer == count: if count_buffer == count:
break break
await msg.delete() await msg.delete()
count_buffer += 1 count_buffer += 1
await log(f"{lang('prune_hint1')}{lang('yp_hint')} {str(count_buffer)} / {str(count)} {lang('prune_hint2')}") await log(
notification = await send_prune_notify(client, message, count_buffer, count) f"{lang('prune_hint1')}{lang('yp_hint')} {str(count_buffer)} / {count} {lang('prune_hint2')}"
)
notification = await send_prune_notify(message, count_buffer, count)
await sleep(1) await sleep(1)
await notification.delete() await notification.delete()
@ -132,22 +136,19 @@ async def your_prune(client: Client, message: Message):
@listener(is_plugin=False, outgoing=True, command="del", @listener(is_plugin=False, outgoing=True, command="del",
need_admin=True, need_admin=True,
description=lang('del_des')) description=lang('del_des'))
async def delete(_: Client, message: Message): async def delete(message: Message):
""" Deletes the message you replied to. """ """ Deletes the message you replied to. """
target = message.reply_to_message if target := message.reply_to_message:
if target: with contextlib.suppress(Exception):
try:
await target.delete() await target.delete()
except Exception as e: # noqa
pass
await message.delete() await message.delete()
await log(lang('del_notification')) await log(lang('del_notification'))
else: else:
await message.delete() await message.delete()
async def send_prune_notify(client, message, count_buffer, count): async def send_prune_notify(message: Message, count_buffer, count):
return await client.send_message( return await message.bot.send_message(
message.chat.id, message.chat.id,
"%s %s / %s %s" % (lang('spn_deleted'), str(count_buffer), str(count), lang('prune_hint2')) f"{lang('spn_deleted')} {str(count_buffer)} / {str(count)} {lang('prune_hint2')}",
) )

View File

@ -0,0 +1,45 @@
import importlib
import pagermaid.config
import pagermaid.modules
from pagermaid import bot, logs, help_messages, all_permissions
from pagermaid.listener import listener
from pagermaid.utils import lang, Message
def reload_all():
bot.dispatcher.remove_all_handlers()
bot.job.remove_all_jobs()
loaded_plugins = list(pagermaid.modules.plugin_list)
loaded_plugins.extend(iter(pagermaid.modules.module_list))
# init
importlib.reload(pagermaid.modules)
importlib.reload(pagermaid.config)
help_messages.clear()
all_permissions.clear()
importlib.reload(pagermaid.modules)
for module_name in pagermaid.modules.module_list:
try:
module = importlib.import_module(f"pagermaid.modules.{module_name}")
if module_name in loaded_plugins:
importlib.reload(module)
except BaseException as exception:
logs.info(f"{lang('module')} {module_name} {lang('error')}: {type(exception)}: {exception}")
for plugin_name in pagermaid.modules.plugin_list:
try:
plugin = importlib.import_module(f"plugins.{plugin_name}")
if plugin_name in loaded_plugins:
importlib.reload(plugin)
except BaseException as exception:
logs.info(f"{lang('module')} {plugin_name} {lang('error')}: {exception}")
pagermaid.modules.plugin_list.remove(plugin_name)
@listener(is_plugin=False, command="reload",
need_admin=True,
description=lang('reload_des'))
async def reload_plugins(message: Message):
""" To reload plugins. """
reload_all()
await message.edit(lang("reload_ok"))

View File

@ -1,9 +1,9 @@
""" PagerMaid module that contains utilities related to system status. """ """ PagerMaid module that contains utilities related to system status. """
from datetime import datetime from datetime import datetime, timezone
from platform import uname, python_version from platform import uname, python_version
from sys import platform from sys import platform
from pyrogram import Client, __version__ from pyrogram import __version__
from pyrogram.raw.functions import Ping from pyrogram.raw.functions import Ping
from pyrogram.enums.parse_mode import ParseMode from pyrogram.enums.parse_mode import ParseMode
@ -21,7 +21,7 @@ from pagermaid.utils import lang, Message, execute
@listener(is_plugin=False, command="sysinfo", @listener(is_plugin=False, command="sysinfo",
description=lang('sysinfo_des')) description=lang('sysinfo_des'))
async def sysinfo(_: Client, message: Message): async def sysinfo(message: Message):
""" Retrieve system information via neofetch. """ """ Retrieve system information via neofetch. """
if not Config.SILENT: if not Config.SILENT:
message = await message.edit(lang("sysinfo_loading")) message = await message.edit(lang("sysinfo_loading"))
@ -33,7 +33,7 @@ async def sysinfo(_: Client, message: Message):
@listener(is_plugin=False, command="status", @listener(is_plugin=False, command="status",
description=lang('status_des')) description=lang('status_des'))
async def status(_: Client, message: Message): async def status(message: Message):
# database # database
# database = lang('status_online') if redis_status() else lang('status_offline') # database = lang('status_online') if redis_status() else lang('status_offline')
# uptime https://gist.github.com/borgstrom/936ca741e885a1438c374824efb038b3 # uptime https://gist.github.com/borgstrom/936ca741e885a1438c374824efb038b3
@ -55,7 +55,7 @@ async def status(_: Client, message: Message):
time_form = time_form.replace(key, value) time_form = time_form.replace(key, value)
return time_form return time_form
current_time = datetime.utcnow() current_time = datetime.now(timezone.utc)
uptime_sec = (current_time - start_time).total_seconds() uptime_sec = (current_time - start_time).total_seconds()
uptime = await human_time_duration(int(uptime_sec)) uptime = await human_time_duration(int(uptime_sec))
text = (f"**{lang('status_hint')}** \n" text = (f"**{lang('status_hint')}** \n"
@ -72,10 +72,10 @@ async def status(_: Client, message: Message):
@listener(is_plugin=False, command="ping", @listener(is_plugin=False, command="ping",
description=lang('ping_des')) description=lang('ping_des'))
async def ping(client: Client, message: Message): async def ping(message: Message):
""" Calculates latency between PagerMaid and Telegram. """ """ Calculates latency between PagerMaid and Telegram. """
start = datetime.now() start = datetime.now()
await client.invoke(Ping(ping_id=0)) await message.bot.invoke(Ping(ping_id=0))
end = datetime.now() end = datetime.now()
ping_duration = (end - start).microseconds / 1000 ping_duration = (end - start).microseconds / 1000
start = datetime.now() start = datetime.now()
@ -180,7 +180,8 @@ def neofetch_win():
gpu = [f' {g.strip()}' for g in gpu[1:]][0].strip() gpu = [f' {g.strip()}' for g in gpu[1:]][0].strip()
ram = get_ram() ram = get_ram()
disks = '\n'.join(partitions()) disks = '\n'.join(partitions())
text = f'<code>{user_name}@{host_name}\n---------\nOS: {os}\nUptime: {uptime}\n' \ return (
f'Motherboard: {mboard}\nCPU: {cpu}\nGPU: {gpu}\nMemory: {ram}\n' \ f'<code>{user_name}@{host_name}\n---------\nOS: {os}\nUptime: {uptime}\n'
f'Motherboard: {mboard}\nCPU: {cpu}\nGPU: {gpu}\nMemory: {ram}\n'
f'Disk:\n{disks}</code>' f'Disk:\n{disks}</code>'
return text )

View File

@ -1,5 +1,3 @@
from pyrogram import Client
from pagermaid.single_utils import sqlite from pagermaid.single_utils import sqlite
from pagermaid.listener import listener from pagermaid.listener import listener
from pagermaid.group_manager import add_permission_for_group, Permission, remove_permission_for_group, \ from pagermaid.group_manager import add_permission_for_group, Permission, remove_permission_for_group, \
@ -10,18 +8,17 @@ from pagermaid.single_utils import get_sudo_list
def from_msg_get_sudo_id(message: Message) -> int: def from_msg_get_sudo_id(message: Message) -> int:
reply = message.reply_to_message if reply := message.reply_to_message:
if reply:
return reply.from_user.id if reply.from_user else reply.sender_chat.id return reply.from_user.id if reply.from_user else reply.sender_chat.id
else: else:
return message.chat.id return message.chat.id
@listener(is_plugin=False, outgoing=True, command="sudo", @listener(is_plugin=False, command="sudo",
need_admin=True, need_admin=True,
parameters="{on|off|add|remove|gaddp|gaddu|gdelp|gdelu|glist|uaddp|udelp|list}", parameters="{on|off|add|remove|gaddp|gaddu|gdelp|gdelu|glist|uaddp|udelp|list}",
description=lang('sudo_des')) 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. """ """ To enable or disable sudo of your userbot. """
input_str = message.arguments input_str = message.arguments
sudo = get_sudo_list() sudo = get_sudo_list()
@ -79,28 +76,30 @@ async def sudo_change(client: Client, message: Message):
for i in sudo: for i in sudo:
try: try:
if i > 0: if i > 0:
user = await client.get_users(i) user = await message.bot.get_users(i)
text += f"{user.mention()} - {' '.join(permissions.get_roles_for_user(str(i)))}\n" text += f"{user.mention()} - {' '.join(permissions.get_roles_for_user(str(i)))}\n"
else: else:
chat = await client.get_chat(i) chat = await message.bot.get_chat(i)
text += f"{chat.title} - {' '.join(permissions.get_roles_for_user(str(i)))}\n" text += f"{chat.title} - {' '.join(permissions.get_roles_for_user(str(i)))}\n"
for j in permissions.get_permissions_for_user(str(i)): for j in permissions.get_permissions_for_user(str(i)):
text += f"{'-' if j[2] == 'ejection' else ''}{j[1]}\n" text += f"{'-' if j[2] == 'ejection' else ''}{j[1]}\n"
except: except Exception:
text += f"• `{i}` - {' '.join(permissions.get_roles_for_user(str(i)))}\n" text += f"• `{i}` - {' '.join(permissions.get_roles_for_user(str(i)))}\n"
await message.edit(text) await message.edit(text)
elif len(message.parameter) > 0: elif len(message.parameter) > 0:
if len(message.parameter) == 2: if len(message.parameter) == 2:
from_id = from_msg_get_sudo_id(message) from_id = from_msg_get_sudo_id(message)
if message.parameter[0] == "glist": if message.parameter[0] == "glist":
data = permissions.get_permissions_for_user(str(message.parameter[1])) if not (
if data: 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" text = f"**{message.parameter[1]} {lang('sudo_group_list')}**\n\n"
for i in data: for i in data:
text += f" • `{'-' if i[2] == 'ejection' else ''}{i[1]}`\n" text += f" • `{'-' if i[2] == 'ejection' else ''}{i[1]}`\n"
return await message.edit(text) return await message.edit(text)
else:
return await edit_delete(message, f"__{lang('sudo_group_list')}__")
if from_id not in sudo: if from_id not in sudo:
return await edit_delete(message, f"__{lang('sudo_no')}__") return await edit_delete(message, f"__{lang('sudo_no')}__")
elif message.parameter[0] == "gaddu": elif message.parameter[0] == "gaddu":

View File

@ -6,8 +6,6 @@ from sys import exit
from platform import node from platform import node
from getpass import getuser from getpass import getuser
from pyrogram import Client
from pagermaid import bot from pagermaid import bot
from pagermaid.listener import listener from pagermaid.listener import listener
from pagermaid.utils import attach_log, execute, Message, lang from pagermaid.utils import attach_log, execute, Message, lang
@ -17,7 +15,7 @@ from pagermaid.utils import attach_log, execute, Message, lang
need_admin=True, need_admin=True,
description=lang('sh_des'), description=lang('sh_des'),
parameters=lang('sh_parameters')) parameters=lang('sh_parameters'))
async def sh(_: Client, message: Message): async def sh(message: Message):
""" Use the command-line from Telegram. """ """ Use the command-line from Telegram. """
user = getuser() user = getuser()
command = message.arguments command = message.arguments
@ -51,7 +49,7 @@ async def sh(_: Client, message: Message):
@listener(is_plugin=False, command="restart", @listener(is_plugin=False, command="restart",
need_admin=True, need_admin=True,
description=lang('restart_des')) description=lang('restart_des'))
async def restart(_: Client, message: Message): async def restart(message: Message):
""" To re-execute PagerMaid. """ """ To re-execute PagerMaid. """
if not message.text[0].isalpha(): if not message.text[0].isalpha():
await message.edit(lang('restart_log')) await message.edit(lang('restart_log'))
@ -62,7 +60,7 @@ async def restart(_: Client, message: Message):
need_admin=True, need_admin=True,
description=lang('eval_des'), description=lang('eval_des'),
parameters=lang('eval_parameters')) parameters=lang('eval_parameters'))
async def sh_eval(_: Client, message: Message): async def sh_eval(message: Message):
""" Run python commands from Telegram. """ """ Run python commands from Telegram. """
try: try:
cmd = message.text.split(" ", maxsplit=1)[1] cmd = message.text.split(" ", maxsplit=1)[1]
@ -89,14 +87,9 @@ async def sh_eval(_: Client, message: Message):
evaluation = stdout evaluation = stdout
else: else:
evaluation = "Success" evaluation = "Success"
final_output = ( final_output = f"**>>>** ```{cmd}``` \n```{evaluation}```"
"**>>>** ```{}``` \n```{}```".format(
cmd,
evaluation,
)
)
if len(final_output) > 4096: if len(final_output) > 4096:
message = await message.edit("**>>>** ```{}```".format(cmd)) message = await message.edit(f"**>>>** ```{cmd}```")
await attach_log(bot, evaluation, message.chat.id, "output.log", message.id) await attach_log(bot, evaluation, message.chat.id, "output.log", message.id)
else: else:
await message.edit(final_output) await message.edit(final_output)
@ -104,11 +97,14 @@ async def sh_eval(_: Client, message: Message):
async def aexec(code, event, client): async def aexec(code, event, client):
exec( exec(
f"async def __aexec(e, client): " (
+ "\n msg = message = e" (
("async def __aexec(e, client): " + "\n msg = message = e")
+ "\n reply = message.reply_to_message" + "\n reply = message.reply_to_message"
)
+ "\n chat = e.chat" + "\n chat = e.chat"
+ "".join(f"\n {x}" for x in code.split("\n")), )
+ "".join(f"\n {x}" for x in code.split("\n"))
) )
return await locals()["__aexec"](event, client) return await locals()["__aexec"](event, client)

View File

@ -1,6 +1,4 @@
from sys import executable from sys import executable, exit
from pyrogram import Client
from pagermaid.listener import listener from pagermaid.listener import listener
from pagermaid.utils import lang, execute, Message, alias_command from pagermaid.utils import lang, execute, Message, alias_command
@ -10,7 +8,7 @@ from pagermaid.utils import lang, execute, Message, alias_command
need_admin=True, need_admin=True,
description=lang('update_des'), description=lang('update_des'),
parameters="<true/debug>") parameters="<true/debug>")
async def update(_: Client, message: Message): async def update(message: Message):
await execute('git fetch --all') await execute('git fetch --all')
if len(message.parameter) > 0: if len(message.parameter) > 0:
await execute('git reset --hard origin/master') await execute('git reset --hard origin/master')

25
pagermaid/scheduler.py Normal file
View File

@ -0,0 +1,25 @@
import contextlib
import datetime
import pytz
from apscheduler.schedulers.asyncio import AsyncIOScheduler
from pagermaid.single_utils import Message
scheduler = AsyncIOScheduler(timezone="Asia/ShangHai")
async def delete_message(message: Message) -> bool:
with contextlib.suppress(Exception):
await message.delete()
return True
return False
def add_delete_message_job(message: Message, delete_seconds: int = 60):
scheduler.add_job(
delete_message, "date",
id=f"{message.chat.id}|{message.id}|delete_message",
name=f"{message.chat.id}|{message.id}|delete_message",
args=[message],
run_date=datetime.datetime.now(pytz.timezone("Asia/Shanghai")) + datetime.timedelta(seconds=delete_seconds),
replace_existing=True)

View File

@ -1,6 +1,11 @@
import contextlib
from os import sep, remove, mkdir from os import sep, remove, mkdir
from os.path import exists from os.path import exists
from typing import List, Optional from typing import List, Optional
from apscheduler.schedulers.asyncio import AsyncIOScheduler
from httpx import AsyncClient
from pyrogram import Client
from pyrogram.types import Message from pyrogram.types import Message
from sqlitedict import SqliteDict from sqlitedict import SqliteDict
@ -19,15 +24,19 @@ def _status_sudo():
def safe_remove(name: str) -> None: def safe_remove(name: str) -> None:
try: with contextlib.suppress(FileNotFoundError):
remove(name) remove(name)
except FileNotFoundError:
pass
class Client(Client): # noqa
job: Optional[AsyncIOScheduler] = None
class Message(Message): # noqa class Message(Message): # noqa
arguments: str arguments: str
parameter: List parameter: List
bot: Client
request: Optional[AsyncClient] = None
def obtain_message(self) -> Optional[str]: def obtain_message(self) -> Optional[str]:
""" Obtains a message from either the reply message or command arguments. """ """ Obtains a message from either the reply message or command arguments. """
@ -37,5 +46,8 @@ class Message(Message): # noqa
""" Obtains a user from either the reply message or command arguments. """ """ Obtains a user from either the reply message or command arguments. """
return return
async def delay_delete(self, delete_seconds: int = 60) -> Optional[bool]:
return
async def safe_delete(self, revoke: bool = True) -> None: async def safe_delete(self, revoke: bool = True) -> None:
return return

View File

@ -1,3 +1,4 @@
import contextlib
import subprocess import subprocess
from importlib.util import find_spec from importlib.util import find_spec
from os.path import exists from os.path import exists
@ -18,22 +19,18 @@ from pagermaid.single_utils import _status_sudo, get_sudo_list, Message, sqlite
def lang(text: str) -> str: def lang(text: str) -> str:
""" i18n """ """ i18n """
result = Config.lang_dict.get(text, text) return Config.lang_dict.get(text, text)
return result
def alias_command(command: str, disallow_alias: bool = False) -> str: def alias_command(command: str, disallow_alias: bool = False) -> str:
""" alias """ """ alias """
if disallow_alias: return command if disallow_alias else Config.alias_dict.get(command, command)
return command
return Config.alias_dict.get(command, command)
async def attach_report(plaintext, file_name, reply_id=None, caption=None): async def attach_report(plaintext, file_name, reply_id=None, caption=None):
""" Attach plaintext as logs. """ """ Attach plaintext as logs. """
file = open(file_name, "w+") with open(file_name, "w+") as file:
file.write(plaintext) file.write(plaintext)
file.close()
try: try:
await bot.send_document( await bot.send_document(
"PagerMaid_Modify_bot", "PagerMaid_Modify_bot",
@ -48,9 +45,8 @@ async def attach_report(plaintext, file_name, reply_id=None, caption=None):
async def attach_log(plaintext, chat_id, file_name, reply_id=None, caption=None): async def attach_log(plaintext, chat_id, file_name, reply_id=None, caption=None):
""" Attach plaintext as logs. """ """ Attach plaintext as logs. """
file = open(file_name, "w+") with open(file_name, "w+") as file:
file.write(plaintext) file.write(plaintext)
file.close()
await bot.send_document( await bot.send_document(
chat_id, chat_id,
file_name, file_name,
@ -141,15 +137,9 @@ async def edit_delete(message: Message,
def get_permission_name(is_plugin: bool, need_admin: bool, command: str) -> str: def get_permission_name(is_plugin: bool, need_admin: bool, command: str) -> str:
""" Get permission name. """ """ Get permission name. """
if is_plugin: if is_plugin:
if need_admin: return f"plugins_root.{command}" if need_admin else f"plugins.{command}"
return f"plugins_root.{command}"
else: else:
return f"plugins.{command}" return f"system.{command}" if need_admin else f"modules.{command}"
else:
if need_admin:
return f"system.{command}"
else:
return f"modules.{command}"
def sudo_filter(permission: str): def sudo_filter(permission: str):
@ -196,11 +186,10 @@ async def process_exit(start: int, _client, message=None):
if start and data and cid and mid: if start and data and cid and mid:
msg: Message = await _client.get_messages(cid, mid) msg: Message = await _client.get_messages(cid, mid)
if msg: if msg:
try: with contextlib.suppress(Exception):
await msg.edit((msg.text if msg.from_user.is_self and msg.text else "") + await msg.edit(
((msg.text or msg.caption) if msg.from_user.is_self and (msg.text or msg.caption) else "") +
f'\n\n> {lang("restart_complete")}') f'\n\n> {lang("restart_complete")}')
except Exception as e: # noqa
pass
del sqlite["exit_msg"] del sqlite["exit_msg"]
if message: if message:
sqlite["exit_msg"] = {"cid": message.chat.id, "mid": message.id} sqlite["exit_msg"] = {"cid": message.chat.id, "mid": message.id}

View File

@ -25,11 +25,10 @@ from typing import Optional, List
import pyrogram import pyrogram
from pagermaid.single_utils import get_sudo_list, Message from pagermaid.single_utils import get_sudo_list, Message
from pagermaid.scheduler import add_delete_message_job
from ..utils import patch, patchable from ..utils import patch, patchable
loop = asyncio.get_event_loop()
class ListenerCanceled(Exception): class ListenerCanceled(Exception):
pass pass
@ -53,14 +52,14 @@ class Client:
chat = await self.get_chat(chat_id) chat = await self.get_chat(chat_id)
chat_id = chat.id chat_id = chat.id
future = loop.create_future() future = self.loop.create_future()
future.add_done_callback( future.add_done_callback(
functools.partial(self.clear_listener, chat_id) functools.partial(self.clear_listener, chat_id)
) )
self.listening.update({ self.listening.update({
chat_id: {"future": future, "filters": filters} chat_id: {"future": future, "filters": filters}
}) })
return await asyncio.wait_for(future, timeout) return await asyncio.wait_for(future, timeout, loop=self.loop)
@patchable @patchable
async def ask(self, chat_id, text, filters=None, timeout=None, *args, **kwargs): async def ask(self, chat_id, text, filters=None, timeout=None, *args, **kwargs):
@ -144,6 +143,7 @@ class User(pyrogram.types.User):
def cancel_listener(self): def cancel_listener(self):
return self._client.cancel_listener(self.id) return self._client.cancel_listener(self.id)
# pagermaid-pyro # pagermaid-pyro
@ -163,7 +163,9 @@ class Message(pyrogram.types.Message):
@patchable @patchable
def obtain_message(self) -> Optional[str]: def obtain_message(self) -> Optional[str]:
""" Obtains a message from either the reply message or command arguments. """ """ Obtains a message from either the reply message or command arguments. """
return self.arguments if self.arguments else (self.reply_to_message.text if self.reply_to_message else None) return self.arguments or (
self.reply_to_message.text if self.reply_to_message else None
)
@patchable @patchable
def obtain_user(self) -> Optional[int]: def obtain_user(self) -> Optional[int]:
@ -185,6 +187,10 @@ class Message(pyrogram.types.Message):
user = self.chat.id user = self.chat.id
return user return user
@patchable
async def delay_delete(self, delay: int = 60):
add_delete_message_job(self, delay)
@patchable @patchable
async def edit_text( async def edit_text(
self, self,
@ -219,8 +225,7 @@ class Message(pyrogram.types.Message):
disable_web_page_preview=disable_web_page_preview, disable_web_page_preview=disable_web_page_preview,
reply_markup=reply_markup reply_markup=reply_markup
) )
else: elif not no_reply:
if not no_reply:
msg = await self.reply( msg = await self.reply(
text=text, text=text,
parse_mode=parse_mode, parse_mode=parse_mode,
@ -238,9 +243,7 @@ class Message(pyrogram.types.Message):
reply_markup=reply_markup reply_markup=reply_markup
) )
except pyrogram.errors.exceptions.forbidden_403.MessageAuthorRequired: # noqa except pyrogram.errors.exceptions.forbidden_403.MessageAuthorRequired: # noqa
if no_reply: if not no_reply:
pass
else:
msg = await self.reply( msg = await self.reply(
text=text, text=text,
parse_mode=parse_mode, parse_mode=parse_mode,
@ -256,11 +259,26 @@ class Message(pyrogram.types.Message):
document="output.log", document="output.log",
reply_to_message_id=self.id reply_to_message_id=self.id
) )
if msg: if not msg:
return self
msg.parameter = self.parameter msg.parameter = self.parameter
msg.arguments = self.arguments msg.arguments = self.arguments
return msg return msg
else:
return self
edit = edit_text edit = edit_text
@patch(pyrogram.dispatcher.Dispatcher) # noqa
class Dispatcher(pyrogram.dispatcher.Dispatcher): # noqa
@patchable
def remove_all_handlers(self):
async def fn():
for lock in self.locks_list:
await lock.acquire()
self.groups.clear()
for lock in self.locks_list:
lock.release()
self.loop.create_task(fn())

View File

@ -57,27 +57,34 @@ class Pagination:
(f'{last_page} »' if last_page > 5 else last_page, self.page_data(last_page)) (f'{last_page} »' if last_page > 5 else last_page, self.page_data(last_page))
) )
elif page >= last_page-2: elif page >= last_page-2:
nav.extend([ nav.extend(
(f'« 1' if last_page-4 > 1 else 1, self.page_data(1)), [
(f' {last_page-3}' if last_page-4 > 1 else last_page-3, self.page_data(last_page-3)) ('« 1' if last_page > 5 else 1, self.page_data(1)),
]) (
f' {last_page-3}' if last_page > 5 else last_page - 3,
self.page_data(last_page - 3),
),
]
)
for n in range(last_page-2, last_page+1): for n in range(last_page-2, last_page+1):
text = f"· {n} ·" if n == page else n text = f"· {n} ·" if n == page else n
nav.append( (text, self.page_data(n)) ) nav.append( (text, self.page_data(n)) )
else: else:
nav = [ nav = [
(f'« 1', self.page_data(1)), ('« 1', self.page_data(1)),
(f' {page-1}', self.page_data(page - 1)), (f' {page-1}', self.page_data(page - 1)),
(f'· {page} ·', "noop"), (f'· {page} ·', "noop"),
(f'{page+1} ', self.page_data(page + 1)), (f'{page+1} ', self.page_data(page + 1)),
(f'{last_page} »', self.page_data(last_page)), (f'{last_page} »', self.page_data(last_page)),
] ]
buttons = []
for item in cutted: buttons = [
buttons.append(
(self.item_title(item, page), self.item_data(item, page)) (self.item_title(item, page), self.item_data(item, page))
) for item in cutted
]
kb_lines = array_chunk(buttons, columns) kb_lines = array_chunk(buttons, columns)
if last_page > 1: if last_page > 1:
kb_lines.append(nav) kb_lines.append(nav)

View File

@ -25,7 +25,7 @@ def patch(obj):
def wrapper(container): def wrapper(container):
for name,func in filter(is_patchable, container.__dict__.items()): for name,func in filter(is_patchable, container.__dict__.items()):
old = getattr(obj, name, None) old = getattr(obj, name, None)
setattr(obj, 'old'+name, old) setattr(obj, f'old{name}', old)
setattr(obj, name, func) setattr(obj, name, func)
return container return container
return wrapper return wrapper