mirror of
https://github.com/TeamPGM/PagerMaid-Pyro.git
synced 2024-11-21 13:38:21 +00:00
🔖 Update to v1.3.1
This commit is contained in:
parent
00a45fefc6
commit
2b37f95377
@ -4,7 +4,16 @@ from typing import Callable, Awaitable, Set, Dict
|
||||
|
||||
from coloredlogs import ColoredFormatter
|
||||
from datetime import datetime, timezone
|
||||
from logging import getLogger, StreamHandler, CRITICAL, INFO, basicConfig, DEBUG, Formatter, FileHandler
|
||||
from logging import (
|
||||
getLogger,
|
||||
StreamHandler,
|
||||
CRITICAL,
|
||||
INFO,
|
||||
basicConfig,
|
||||
DEBUG,
|
||||
Formatter,
|
||||
FileHandler,
|
||||
)
|
||||
from os import getcwd
|
||||
|
||||
from pagermaid.config import Config
|
||||
@ -12,8 +21,8 @@ from pagermaid.scheduler import scheduler
|
||||
import pyromod.listen
|
||||
from pyrogram import Client
|
||||
|
||||
pgm_version = "1.3.0"
|
||||
pgm_version_code = 1300
|
||||
pgm_version = "1.3.1"
|
||||
pgm_version_code = 1301
|
||||
CMD_LIST = {}
|
||||
module_dir = __path__[0]
|
||||
working_dir = getcwd()
|
||||
@ -21,7 +30,11 @@ working_dir = getcwd()
|
||||
read_context = {}
|
||||
help_messages = {}
|
||||
hook_functions: Dict[str, Set[Callable[[], Awaitable[None]]]] = {
|
||||
"startup": set(), "shutdown": set(), "command_pre": set(), "command_post": set(), "process_error": set(),
|
||||
"startup": set(),
|
||||
"shutdown": set(),
|
||||
"command_pre": set(),
|
||||
"command_post": set(),
|
||||
"process_error": set(),
|
||||
"load_plugins_finished": set(),
|
||||
}
|
||||
all_permissions = []
|
||||
@ -51,6 +64,7 @@ start_time = datetime.now(timezone.utc)
|
||||
|
||||
with contextlib.suppress(ImportError):
|
||||
import uvloop # noqa
|
||||
|
||||
uvloop.install()
|
||||
|
||||
if not scheduler.running:
|
||||
@ -68,16 +82,11 @@ bot.job = scheduler
|
||||
|
||||
|
||||
async def log(message):
|
||||
logs.info(
|
||||
message.replace('`', '\"')
|
||||
)
|
||||
logs.info(message.replace("`", '"'))
|
||||
if not Config.LOG:
|
||||
return
|
||||
try:
|
||||
await bot.send_message(
|
||||
Config.LOG_ID,
|
||||
message
|
||||
)
|
||||
await bot.send_message(Config.LOG_ID, message)
|
||||
except Exception:
|
||||
Config.LOG = False
|
||||
Config.LOG_ID = "me"
|
||||
|
@ -17,7 +17,7 @@ path.insert(1, f"{working_dir}{sep}plugins")
|
||||
|
||||
|
||||
async def main():
|
||||
logs.info(lang('platform') + platform + lang('platform_load'))
|
||||
logs.info(lang("platform") + platform + lang("platform_load"))
|
||||
|
||||
try:
|
||||
await start_client(bot)
|
||||
@ -35,7 +35,9 @@ async def main():
|
||||
try:
|
||||
import_module(f"pagermaid.modules.{module_name}")
|
||||
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.copy():
|
||||
try:
|
||||
import_module(f"plugins.{plugin_name}")
|
||||
@ -45,11 +47,12 @@ async def main():
|
||||
plugin_manager.load_local_plugins()
|
||||
|
||||
await process_exit(start=True, _client=bot)
|
||||
logs.info(lang('start'))
|
||||
logs.info(lang("start"))
|
||||
await Hook.load_success_exec()
|
||||
await Hook.startup()
|
||||
|
||||
await idle()
|
||||
await bot.stop()
|
||||
|
||||
|
||||
bot.run(main())
|
||||
|
@ -28,15 +28,12 @@ class AliasManager:
|
||||
|
||||
def get_all_alias_text(self) -> str:
|
||||
texts = []
|
||||
texts.extend(
|
||||
f'`{i.command}` > `{i.alias}`'
|
||||
for i in self.alias_list
|
||||
)
|
||||
return '\n'.join(texts)
|
||||
texts.extend(f"`{i.command}` > `{i.alias}`" for i in self.alias_list)
|
||||
return "\n".join(texts)
|
||||
|
||||
@staticmethod
|
||||
def save():
|
||||
with open(f"data{sep}alias.json", 'w', encoding="utf-8") as f:
|
||||
with open(f"data{sep}alias.json", "w", encoding="utf-8") as f:
|
||||
json_dump(Config.alias_dict, f)
|
||||
|
||||
@staticmethod
|
||||
|
@ -20,7 +20,7 @@ def cache(ttl=datetime.timedelta(minutes=15)):
|
||||
nonlocal cache_data
|
||||
bound = inspect.signature(func).bind(*args, **kw)
|
||||
bound.apply_defaults()
|
||||
ins_key = '|'.join([f'{k}_{v}' for k, v in bound.arguments.items()])
|
||||
ins_key = "|".join([f"{k}_{v}" for k, v in bound.arguments.items()])
|
||||
data: Cache = cache_data.get(ins_key, Cache(value=None, time=None))
|
||||
now = datetime.datetime.now()
|
||||
if (not data.time) or ((now - data.time) > ttl):
|
||||
@ -31,5 +31,7 @@ def cache(ttl=datetime.timedelta(minutes=15)):
|
||||
except Exception as e:
|
||||
raise e
|
||||
return data.value
|
||||
|
||||
return wrapped
|
||||
|
||||
return wrap
|
||||
|
@ -10,7 +10,7 @@ from pagermaid import Config
|
||||
from pagermaid.common.cache import cache
|
||||
from pagermaid.utils import client
|
||||
|
||||
plugins_path = Path('plugins')
|
||||
plugins_path = Path("plugins")
|
||||
|
||||
|
||||
class LocalPlugin(BaseModel):
|
||||
@ -57,11 +57,11 @@ class RemotePlugin(LocalPlugin):
|
||||
...
|
||||
|
||||
async def install(self) -> bool:
|
||||
html = await client.get(f'{Config.GIT_SOURCE}{self.name}/main.py')
|
||||
html = await client.get(f"{Config.GIT_SOURCE}{self.name}/main.py")
|
||||
if html.status_code == 200:
|
||||
self.remove()
|
||||
with open(plugins_path / f"{self.name}.py", mode="wb") as f:
|
||||
f.write(html.text.encode('utf-8'))
|
||||
f.write(html.text.encode("utf-8"))
|
||||
return True
|
||||
return False
|
||||
|
||||
@ -76,11 +76,11 @@ class PluginManager:
|
||||
def load_local_version_map(self):
|
||||
if not os.path.exists(plugins_path / "version.json"):
|
||||
return
|
||||
with open(plugins_path / "version.json", 'r', encoding="utf-8") as f:
|
||||
with open(plugins_path / "version.json", "r", encoding="utf-8") as f:
|
||||
self.version_map = json.load(f)
|
||||
|
||||
def save_local_version_map(self):
|
||||
with open(plugins_path / "version.json", 'w', encoding="utf-8") as f:
|
||||
with open(plugins_path / "version.json", "w", encoding="utf-8") as f:
|
||||
json.dump(self.version_map, f, indent=4)
|
||||
|
||||
def get_local_version(self, name: str) -> Optional[float]:
|
||||
@ -116,15 +116,17 @@ class PluginManager:
|
||||
def load_local_plugins(self) -> List[LocalPlugin]:
|
||||
self.load_local_version_map()
|
||||
self.plugins = []
|
||||
for plugin in os.listdir('plugins'):
|
||||
if plugin.endswith('.py') or plugin.endswith('.py.disabled'):
|
||||
plugin = plugin[:-12] if plugin.endswith('.py.disabled') else plugin[:-3]
|
||||
for plugin in os.listdir("plugins"):
|
||||
if plugin.endswith(".py") or plugin.endswith(".py.disabled"):
|
||||
plugin = (
|
||||
plugin[:-12] if plugin.endswith(".py.disabled") else plugin[:-3]
|
||||
)
|
||||
self.plugins.append(
|
||||
LocalPlugin(
|
||||
name=plugin,
|
||||
installed=self.get_plugin_install_status(plugin),
|
||||
status=self.get_plugin_load_status(plugin),
|
||||
version=self.get_local_version(plugin)
|
||||
version=self.get_local_version(plugin),
|
||||
)
|
||||
)
|
||||
return self.plugins
|
||||
@ -140,7 +142,8 @@ class PluginManager:
|
||||
RemotePlugin(
|
||||
**plugin,
|
||||
status=False,
|
||||
) for plugin in plugin_list
|
||||
)
|
||||
for plugin in plugin_list
|
||||
]
|
||||
self.remote_plugins = plugins
|
||||
self.remote_version_map = {}
|
||||
|
@ -4,7 +4,14 @@ import os
|
||||
|
||||
import pagermaid.config
|
||||
import pagermaid.modules
|
||||
from pagermaid import read_context, bot, help_messages, all_permissions, hook_functions, logs
|
||||
from pagermaid import (
|
||||
read_context,
|
||||
bot,
|
||||
help_messages,
|
||||
all_permissions,
|
||||
hook_functions,
|
||||
logs,
|
||||
)
|
||||
from pagermaid.common.plugin import plugin_manager
|
||||
from pagermaid.hook import Hook
|
||||
from pagermaid.utils import lang
|
||||
@ -32,7 +39,9 @@ async def reload_all():
|
||||
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}")
|
||||
logs.info(
|
||||
f"{lang('module')} {module_name} {lang('error')}: {type(exception)}: {exception}"
|
||||
)
|
||||
for plugin_name in pagermaid.modules.plugin_list.copy():
|
||||
try:
|
||||
plugin = importlib.import_module(f"plugins.{plugin_name}")
|
||||
|
@ -17,11 +17,11 @@ class Status(BaseModel):
|
||||
async def human_time_duration(seconds) -> str:
|
||||
parts = {}
|
||||
time_units = (
|
||||
('%m', 60 * 60 * 24 * 30),
|
||||
('%d', 60 * 60 * 24),
|
||||
('%H', 60 * 60),
|
||||
('%M', 60),
|
||||
('%S', 1)
|
||||
("%m", 60 * 60 * 24 * 30),
|
||||
("%d", 60 * 60 * 24),
|
||||
("%H", 60 * 60),
|
||||
("%M", 60),
|
||||
("%S", 1),
|
||||
)
|
||||
for unit, div in time_units:
|
||||
amount, seconds = divmod(int(seconds), div)
|
||||
@ -48,7 +48,7 @@ async def get_status() -> Status:
|
||||
return Status(
|
||||
version=pgm_version,
|
||||
run_time=uptime,
|
||||
cpu_percent=f'{cpu_percent}%',
|
||||
ram_percent=f'{ram_stat.percent}%',
|
||||
swap_percent=f'{swap_stat.percent}%',
|
||||
cpu_percent=f"{cpu_percent}%",
|
||||
ram_percent=f"{ram_stat.percent}%",
|
||||
swap_percent=f"{swap_stat.percent}%",
|
||||
)
|
||||
|
@ -33,11 +33,11 @@ async def run_eval(cmd: str, message=None, only_result: bool = False) -> str:
|
||||
async def aexec(code, event, client):
|
||||
exec(
|
||||
(
|
||||
(
|
||||
("async def __aexec(e, client): " + "\n msg = message = e")
|
||||
+ "\n reply = message.reply_to_message if message else None"
|
||||
)
|
||||
+ "\n chat = e.chat if e else None"
|
||||
(
|
||||
("async def __aexec(e, client): " + "\n msg = message = e")
|
||||
+ "\n reply = message.reply_to_message if message else None"
|
||||
)
|
||||
+ "\n chat = e.chat if e else None"
|
||||
)
|
||||
+ "".join(f"\n {x}" for x in code.split("\n"))
|
||||
)
|
||||
|
@ -4,9 +4,9 @@ from pagermaid.utils import execute
|
||||
|
||||
|
||||
async def update(force: bool = False):
|
||||
await execute('git fetch --all')
|
||||
await execute("git fetch --all")
|
||||
if force:
|
||||
await execute('git reset --hard origin/master')
|
||||
await execute('git pull --all')
|
||||
await execute("git reset --hard origin/master")
|
||||
await execute("git pull --all")
|
||||
await execute(f"{executable} -m pip install --upgrade -r requirements.txt")
|
||||
await execute(f"{executable} -m pip install -r requirements.txt")
|
||||
|
@ -15,9 +15,9 @@ def strtobool(val, default=False):
|
||||
'val' is anything else.
|
||||
"""
|
||||
val = val.lower()
|
||||
if val in ('y', 'yes', 't', 'true', 'on', '1'):
|
||||
if val in ("y", "yes", "t", "true", "on", "1"):
|
||||
return 1
|
||||
elif val in ('n', 'no', 'f', 'false', 'off', '0'):
|
||||
elif val in ("n", "no", "f", "false", "off", "0"):
|
||||
return 0
|
||||
else:
|
||||
print("[Degrade] invalid truth value %r" % (val,))
|
||||
@ -27,7 +27,9 @@ def strtobool(val, default=False):
|
||||
try:
|
||||
config: Dict = load(open(r"config.yml", encoding="utf-8"), Loader=FullLoader)
|
||||
except FileNotFoundError:
|
||||
print("The configuration file does not exist, and a new configuration file is being generated.")
|
||||
print(
|
||||
"The configuration file does not exist, and a new configuration file is being generated."
|
||||
)
|
||||
copyfile(f"{os.getcwd()}{os.sep}config.gen.yml", "config.yml")
|
||||
sys.exit(1)
|
||||
|
||||
@ -43,19 +45,29 @@ class Config:
|
||||
# TGX
|
||||
API_ID = DEFAULT_API_ID
|
||||
API_HASH = DEFAULT_API_HASH
|
||||
QRCODE_LOGIN = strtobool(os.environ.get("QRCODE_LOGIN", config.get("qrcode_login", "false")))
|
||||
QRCODE_LOGIN = strtobool(
|
||||
os.environ.get("QRCODE_LOGIN", config.get("qrcode_login", "false"))
|
||||
)
|
||||
STRING_SESSION = os.environ.get("STRING_SESSION")
|
||||
DEBUG = strtobool(os.environ.get("PGM_DEBUG", config["debug"]))
|
||||
ERROR_REPORT = strtobool(os.environ.get("PGM_ERROR_REPORT", config["error_report"]), True)
|
||||
ERROR_REPORT = strtobool(
|
||||
os.environ.get("PGM_ERROR_REPORT", config["error_report"]), True
|
||||
)
|
||||
LANGUAGE = os.environ.get("PGM_LANGUAGE", config["application_language"])
|
||||
REGION = os.environ.get("PGM_REGION", config["application_region"])
|
||||
TIME_ZONE = os.environ.get("PGM_TIME_ZONE", config.get("timezone", "Asia/Shanghai"))
|
||||
TIME_ZONE = os.environ.get(
|
||||
"PGM_TIME_ZONE", config.get("timezone", "Asia/Shanghai")
|
||||
)
|
||||
TTS = os.environ.get("PGM_TTS", config["application_tts"])
|
||||
LOG = strtobool(os.environ.get("PGM_LOG", config["log"]))
|
||||
LOG_ID = int(os.environ.get("PGM_LOG_ID", config["log_chatid"]))
|
||||
IPV6 = strtobool(os.environ.get("PGM_IPV6", config["ipv6"]))
|
||||
ALLOW_ANALYTIC = strtobool(os.environ.get("PGM_ALLOW_ANALYTIC", config["allow_analytic"]), True)
|
||||
SENTRY_API = "https://2e13a517aeb542e7a307cba8996b6d1a@o1342815.ingest.sentry.io/6617119"
|
||||
ALLOW_ANALYTIC = strtobool(
|
||||
os.environ.get("PGM_ALLOW_ANALYTIC", config["allow_analytic"]), True
|
||||
)
|
||||
SENTRY_API = (
|
||||
"https://2e13a517aeb542e7a307cba8996b6d1a@o1342815.ingest.sentry.io/6617119"
|
||||
)
|
||||
MIXPANEL_API = "c79162511383b0fa1e9c062a2a86c855"
|
||||
TIME_FORM = os.environ.get("PGM_TIME_FORM", config["time_form"])
|
||||
DATE_FORM = os.environ.get("PGM_DATE_FORM", config["date_form"])
|
||||
@ -63,31 +75,39 @@ class Config:
|
||||
SILENT = strtobool(os.environ.get("PGM_PGM_SILENT", config["silent"]), True)
|
||||
PROXY_ADDRESS = os.environ.get("PGM_PROXY_ADDRESS", config["proxy_addr"])
|
||||
PROXY_PORT = os.environ.get("PGM_PROXY_PORT", config["proxy_port"])
|
||||
PROXY_HTTP_ADDRESS = os.environ.get("PGM_PROXY_HTTP_ADDRESS", config["http_addr"])
|
||||
PROXY_HTTP_ADDRESS = os.environ.get(
|
||||
"PGM_PROXY_HTTP_ADDRESS", config["http_addr"]
|
||||
)
|
||||
PROXY_HTTP_PORT = os.environ.get("PGM_PROXY_HTTP_PORT", config["http_port"])
|
||||
PROXY = None
|
||||
if PROXY_ADDRESS and PROXY_PORT:
|
||||
PROXY = dict(
|
||||
scheme="socks5",
|
||||
hostname=PROXY_ADDRESS,
|
||||
port=int(PROXY_PORT)
|
||||
)
|
||||
PROXY = dict(scheme="socks5", hostname=PROXY_ADDRESS, port=int(PROXY_PORT))
|
||||
elif PROXY_HTTP_ADDRESS and PROXY_HTTP_PORT:
|
||||
PROXY = dict(
|
||||
scheme="http",
|
||||
hostname=PROXY_HTTP_ADDRESS,
|
||||
port=int(PROXY_HTTP_PORT)
|
||||
scheme="http", hostname=PROXY_HTTP_ADDRESS, port=int(PROXY_HTTP_PORT)
|
||||
)
|
||||
GIT_SOURCE = os.environ.get("PGM_GIT_SOURCE", config["git_source"])
|
||||
GIT_SOURCE = GIT_SOURCE.replace("TeamPGM/PagerMaid_Plugins/", "TeamPGM/PagerMaid_Plugins_Pyro/")
|
||||
GIT_SOURCE = GIT_SOURCE.replace(
|
||||
"TeamPGM/PagerMaid_Plugins/", "TeamPGM/PagerMaid_Plugins_Pyro/"
|
||||
)
|
||||
try:
|
||||
with open(f"languages{os.sep}built-in{os.sep}{LANGUAGE}.yml", "r", encoding="utf-8") as f:
|
||||
with open(
|
||||
f"languages{os.sep}built-in{os.sep}{LANGUAGE}.yml",
|
||||
"r",
|
||||
encoding="utf-8",
|
||||
) as f:
|
||||
lang_dict = safe_load(f)
|
||||
except Exception as e:
|
||||
print("[Degrade] Reading language YAML file failed, try to use the english language file.")
|
||||
print(
|
||||
"[Degrade] Reading language YAML file failed, try to use the english language file."
|
||||
)
|
||||
print(e)
|
||||
try:
|
||||
with open(f"languages{os.sep}built-in{os.sep}{LANGUAGE}.yml", "r", encoding="utf-8") as f:
|
||||
with open(
|
||||
f"languages{os.sep}built-in{os.sep}{LANGUAGE}.yml",
|
||||
"r",
|
||||
encoding="utf-8",
|
||||
) as f:
|
||||
lang_dict = safe_load(f)
|
||||
except Exception as e:
|
||||
print("[Error] Reading English language YAML file failed.")
|
||||
@ -99,8 +119,12 @@ class Config:
|
||||
except Exception as e:
|
||||
alias_dict = {}
|
||||
web_interface = config.get("web_interface", {})
|
||||
WEB_ENABLE = strtobool(os.environ.get("WEB_ENABLE", web_interface.get("enable", "False")))
|
||||
WEB_SECRET_KEY = os.environ.get("WEB_SECRET_KEY", web_interface.get("secret_key", "secret_key"))
|
||||
WEB_ENABLE = strtobool(
|
||||
os.environ.get("WEB_ENABLE", web_interface.get("enable", "False"))
|
||||
)
|
||||
WEB_SECRET_KEY = os.environ.get(
|
||||
"WEB_SECRET_KEY", web_interface.get("secret_key", "secret_key")
|
||||
)
|
||||
WEB_HOST = os.environ.get("WEB_HOST", web_interface.get("host", "127.0.0.1"))
|
||||
WEB_PORT = int(os.environ.get("WEB_PORT", web_interface.get("port", 3333)))
|
||||
WEB_ORIGINS = web_interface.get("origins", ["*"])
|
||||
|
@ -9,8 +9,13 @@ from pagermaid import all_permissions, module_dir
|
||||
|
||||
# init permissions
|
||||
if not os_path.exists(f"data{os_path.sep}gm_policy.csv"):
|
||||
copyfile(f"{module_dir}{os_path.sep}assets{os_path.sep}gm_policy.csv", f"data{os_path.sep}gm_policy.csv")
|
||||
permissions = casbin.Enforcer(f"pagermaid{sep}assets{sep}gm_model.conf", f"data{sep}gm_policy.csv")
|
||||
copyfile(
|
||||
f"{module_dir}{os_path.sep}assets{os_path.sep}gm_policy.csv",
|
||||
f"data{os_path.sep}gm_policy.csv",
|
||||
)
|
||||
permissions = casbin.Enforcer(
|
||||
f"pagermaid{sep}assets{sep}gm_model.conf", f"data{sep}gm_policy.csv"
|
||||
)
|
||||
permissions.logger.setLevel(CRITICAL)
|
||||
|
||||
|
||||
@ -27,15 +32,14 @@ def enforce_permission(user: int, permission: str):
|
||||
data = permission.split(".")
|
||||
if len(data) != 2:
|
||||
raise ValueError("Invalid permission format")
|
||||
if permissions.enforce(
|
||||
str(user), data[0], "access"
|
||||
) and not permissions.enforce(str(user), permission, "ejection"):
|
||||
if permissions.enforce(str(user), data[0], "access") and not permissions.enforce(
|
||||
str(user), permission, "ejection"
|
||||
):
|
||||
return True
|
||||
if permissions.enforce(
|
||||
str(user), permission, "access"
|
||||
) and not permissions.enforce(str(user), permission, "ejection"):
|
||||
return True
|
||||
return False
|
||||
return bool(
|
||||
permissions.enforce(str(user), permission, "access")
|
||||
and not permissions.enforce(str(user), permission, "ejection")
|
||||
)
|
||||
|
||||
|
||||
def parse_pen(pen: Permission) -> List[Permission]:
|
||||
@ -45,7 +49,11 @@ def parse_pen(pen: Permission) -> List[Permission]:
|
||||
raise ValueError("Wildcard not allowed in root name")
|
||||
datas = []
|
||||
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)
|
||||
if not datas:
|
||||
raise ValueError("No permission found")
|
||||
|
@ -14,9 +14,11 @@ class Hook:
|
||||
"""
|
||||
注册一个启动钩子
|
||||
"""
|
||||
|
||||
def decorator(function):
|
||||
hook_functions["startup"].add(function)
|
||||
return function
|
||||
|
||||
return decorator
|
||||
|
||||
@staticmethod
|
||||
@ -24,9 +26,11 @@ class Hook:
|
||||
"""
|
||||
注册一个关闭钩子
|
||||
"""
|
||||
|
||||
def decorator(function):
|
||||
hook_functions["shutdown"].add(function)
|
||||
return function
|
||||
|
||||
return decorator
|
||||
|
||||
@staticmethod
|
||||
@ -79,7 +83,9 @@ class Hook:
|
||||
|
||||
@staticmethod
|
||||
async def startup():
|
||||
if cors := [startup(**inject(None, startup)) for startup in hook_functions["startup"]]: # noqa
|
||||
if cors := [
|
||||
startup(**inject(None, startup)) for startup in hook_functions["startup"]
|
||||
]: # noqa
|
||||
try:
|
||||
await asyncio.gather(*cors)
|
||||
except Exception as exception:
|
||||
@ -87,7 +93,10 @@ class Hook:
|
||||
|
||||
@staticmethod
|
||||
async def shutdown():
|
||||
if cors := [shutdown(**inject(None, shutdown)) for shutdown in hook_functions["shutdown"]]: # noqa
|
||||
if cors := [
|
||||
shutdown(**inject(None, shutdown))
|
||||
for shutdown in hook_functions["shutdown"]
|
||||
]: # noqa
|
||||
try:
|
||||
await asyncio.gather(*cors)
|
||||
except Exception as exception:
|
||||
@ -136,12 +145,20 @@ class Hook:
|
||||
logs.info(f"[command_post]: {type(exception)}: {exception}")
|
||||
|
||||
@staticmethod
|
||||
async def process_error_exec(message: Message, command, exc_info: BaseException, exc_format: str):
|
||||
async def process_error_exec(
|
||||
message: Message, command, exc_info: BaseException, exc_format: str
|
||||
):
|
||||
cors = []
|
||||
try:
|
||||
for error in hook_functions["process_error"]:
|
||||
try:
|
||||
data = inject(message, error, command=command, exc_info=exc_info, exc_format=exc_format)
|
||||
data = inject(
|
||||
message,
|
||||
error,
|
||||
command=command,
|
||||
exc_info=exc_info,
|
||||
exc_format=exc_format,
|
||||
)
|
||||
except Exception as exception:
|
||||
logs.info(f"[process_error]: {type(exception)}: {exception}")
|
||||
continue
|
||||
@ -158,7 +175,10 @@ class Hook:
|
||||
|
||||
@staticmethod
|
||||
async def load_success_exec():
|
||||
if cors := [load(**inject(None, load)) for load in hook_functions["load_plugins_finished"]]: # noqa
|
||||
if cors := [
|
||||
load(**inject(None, load))
|
||||
for load in hook_functions["load_plugins_finished"]
|
||||
]: # noqa
|
||||
try:
|
||||
await asyncio.gather(*cors)
|
||||
except Exception as exception:
|
||||
|
@ -10,7 +10,8 @@ from pyrogram.errors.exceptions.bad_request_400 import (
|
||||
MessageIdInvalid,
|
||||
MessageNotModified,
|
||||
MessageEmpty,
|
||||
UserNotParticipant, PeerIdInvalid
|
||||
UserNotParticipant,
|
||||
PeerIdInvalid,
|
||||
)
|
||||
from pyrogram.handlers import MessageHandler, EditedMessageHandler
|
||||
|
||||
@ -18,15 +19,27 @@ from pagermaid import help_messages, logs, Config, bot, read_context, all_permis
|
||||
from pagermaid.common.ignore import ignore_groups_manager
|
||||
from pagermaid.group_manager import Permission
|
||||
from pagermaid.inject import inject
|
||||
from pagermaid.single_utils import Message, AlreadyInConversationError, TimeoutConversationError, ListenerCanceled
|
||||
from pagermaid.utils import lang, attach_report, sudo_filter, alias_command, get_permission_name, process_exit
|
||||
from pagermaid.single_utils import (
|
||||
Message,
|
||||
AlreadyInConversationError,
|
||||
TimeoutConversationError,
|
||||
ListenerCanceled,
|
||||
)
|
||||
from pagermaid.utils import (
|
||||
lang,
|
||||
attach_report,
|
||||
sudo_filter,
|
||||
alias_command,
|
||||
get_permission_name,
|
||||
process_exit,
|
||||
)
|
||||
from pagermaid.hook import Hook
|
||||
|
||||
_lock = asyncio.Lock()
|
||||
|
||||
|
||||
def listener(**args):
|
||||
""" Register an event listener. """
|
||||
"""Register an event listener."""
|
||||
command = args.get("command")
|
||||
disallow_alias = args.get("disallow_alias", False)
|
||||
need_admin = args.get("need_admin", False)
|
||||
@ -46,7 +59,7 @@ def listener(**args):
|
||||
if priority < 0 or priority > 100:
|
||||
raise ValueError("Priority must be between 0 and 100.")
|
||||
elif priority == 0 and is_plugin:
|
||||
""" Priority 0 is reserved for modules. """
|
||||
"""Priority 0 is reserved for modules."""
|
||||
priority = 1
|
||||
elif (not is_plugin) and need_admin:
|
||||
priority = 0
|
||||
@ -54,11 +67,13 @@ def listener(**args):
|
||||
if command is not None:
|
||||
if command in help_messages:
|
||||
if help_messages[alias_command(command)]["priority"] <= priority:
|
||||
raise ValueError(f"{lang('error_prefix')} {lang('command')} \"{command}\" {lang('has_reg')}")
|
||||
raise ValueError(
|
||||
f"{lang('error_prefix')} {lang('command')} \"{command}\" {lang('has_reg')}"
|
||||
)
|
||||
else:
|
||||
block_process = True
|
||||
pattern = fr"^(,|,){alias_command(command, disallow_alias)}(?: |$)([\s\S]*)"
|
||||
sudo_pattern = fr"^(/){alias_command(command, disallow_alias)}(?: |$)([\s\S]*)"
|
||||
pattern = rf"^(,|,){alias_command(command, disallow_alias)}(?: |$)([\s\S]*)"
|
||||
sudo_pattern = rf"^(/){alias_command(command, disallow_alias)}(?: |$)([\s\S]*)"
|
||||
if pattern is not None and not pattern.startswith("(?i)"):
|
||||
args["pattern"] = f"(?i){pattern}"
|
||||
else:
|
||||
@ -72,11 +87,7 @@ def listener(**args):
|
||||
else:
|
||||
base_filters = filters.all
|
||||
permission_name = get_permission_name(is_plugin, need_admin, command)
|
||||
sudo_filters = (
|
||||
sudo_filter(permission_name)
|
||||
& ~filters.via_bot
|
||||
& ~filters.forwarded
|
||||
)
|
||||
sudo_filters = sudo_filter(permission_name) & ~filters.via_bot & ~filters.forwarded
|
||||
if args["pattern"]:
|
||||
base_filters &= filters.regex(args["pattern"])
|
||||
sudo_filters &= filters.regex(sudo_pattern)
|
||||
@ -112,7 +123,6 @@ def listener(**args):
|
||||
del args["block_process"]
|
||||
|
||||
def decorator(function):
|
||||
|
||||
async def handler(client: Client, message: Message):
|
||||
try:
|
||||
# ignore
|
||||
@ -155,30 +165,29 @@ def listener(**args):
|
||||
raise StopPropagation from e
|
||||
except KeyboardInterrupt as e:
|
||||
raise KeyboardInterrupt from e
|
||||
except (UserNotParticipant, MessageNotModified, MessageEmpty, Flood, Forbidden, PeerIdInvalid):
|
||||
except (
|
||||
UserNotParticipant,
|
||||
MessageNotModified,
|
||||
MessageEmpty,
|
||||
Flood,
|
||||
Forbidden,
|
||||
PeerIdInvalid,
|
||||
):
|
||||
logs.warning(
|
||||
"An unknown chat error occurred while processing a command.",
|
||||
)
|
||||
except MessageIdInvalid:
|
||||
logs.warning(
|
||||
"Please Don't Delete Commands While it's Processing.."
|
||||
)
|
||||
logs.warning("Please Don't Delete Commands While it's Processing..")
|
||||
except AlreadyInConversationError:
|
||||
logs.warning(
|
||||
"Please Don't Send Commands In The Same Conversation.."
|
||||
)
|
||||
logs.warning("Please Don't Send Commands In The Same Conversation..")
|
||||
with contextlib.suppress(BaseException):
|
||||
await message.edit(lang("conversation_already_in_error"))
|
||||
except TimeoutConversationError:
|
||||
logs.warning(
|
||||
"Conversation Timed out while processing commands.."
|
||||
)
|
||||
logs.warning("Conversation Timed out while processing commands..")
|
||||
with contextlib.suppress(BaseException):
|
||||
await message.edit(lang("conversation_timed_out_error"))
|
||||
except ListenerCanceled:
|
||||
logs.warning(
|
||||
"Listener Canceled While Processing Commands.."
|
||||
)
|
||||
logs.warning("Listener Canceled While Processing Commands..")
|
||||
with contextlib.suppress(BaseException):
|
||||
await message.edit(lang("reload_des"))
|
||||
except ContinuePropagation as e:
|
||||
@ -199,35 +208,54 @@ def listener(**args):
|
||||
if Config.ERROR_REPORT:
|
||||
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"""
|
||||
|
||||
await attach_report(report, f"exception.{time()}.pgp.txt", None,
|
||||
"PGP Error report generated.")
|
||||
await Hook.process_error_exec(message, command, exc_info, exc_format)
|
||||
await attach_report(
|
||||
report,
|
||||
f"exception.{time()}.pgp.txt",
|
||||
None,
|
||||
"PGP Error report generated.",
|
||||
)
|
||||
await Hook.process_error_exec(
|
||||
message, command, exc_info, exc_format
|
||||
)
|
||||
if (message.chat.id, message.id) in read_context:
|
||||
del read_context[(message.chat.id, message.id)]
|
||||
if block_process:
|
||||
message.stop_propagation()
|
||||
message.continue_propagation()
|
||||
|
||||
bot.add_handler(MessageHandler(handler, filters=base_filters), group=0 + priority)
|
||||
bot.add_handler(
|
||||
MessageHandler(handler, filters=base_filters), group=0 + priority
|
||||
)
|
||||
if command:
|
||||
bot.add_handler(MessageHandler(handler, filters=sudo_filters), group=50 + priority)
|
||||
bot.add_handler(
|
||||
MessageHandler(handler, filters=sudo_filters), group=50 + priority
|
||||
)
|
||||
if not ignore_edited:
|
||||
bot.add_handler(EditedMessageHandler(handler, filters=base_filters), group=1 + priority)
|
||||
bot.add_handler(
|
||||
EditedMessageHandler(handler, filters=base_filters), group=1 + priority
|
||||
)
|
||||
if command:
|
||||
bot.add_handler(EditedMessageHandler(handler, filters=sudo_filters), group=51 + priority)
|
||||
bot.add_handler(
|
||||
EditedMessageHandler(handler, filters=sudo_filters),
|
||||
group=51 + priority,
|
||||
)
|
||||
|
||||
return handler
|
||||
|
||||
if description is not None and command is not None:
|
||||
if parameters is None:
|
||||
parameters = ""
|
||||
help_messages.update({
|
||||
f"{alias_command(command)}": {"permission": permission_name,
|
||||
"use": f"**{lang('use_method')}:** `,{command} {parameters}`\n"
|
||||
f"**{lang('need_permission')}:** `{permission_name}`\n"
|
||||
f"{description}",
|
||||
"priority": priority, }
|
||||
})
|
||||
help_messages.update(
|
||||
{
|
||||
f"{alias_command(command)}": {
|
||||
"permission": permission_name,
|
||||
"use": f"**{lang('use_method')}:** `,{command} {parameters}`\n"
|
||||
f"**{lang('need_permission')}:** `{permission_name}`\n"
|
||||
f"{description}",
|
||||
"priority": priority,
|
||||
}
|
||||
}
|
||||
)
|
||||
all_permissions.append(Permission(permission_name))
|
||||
|
||||
return decorator
|
||||
@ -261,49 +289,53 @@ def raw_listener(filter_s):
|
||||
except ContinuePropagation as e:
|
||||
raise ContinuePropagation from e
|
||||
except MessageIdInvalid:
|
||||
logs.warning(
|
||||
"Please Don't Delete Commands While it's Processing.."
|
||||
)
|
||||
logs.warning("Please Don't Delete Commands While it's Processing..")
|
||||
except AlreadyInConversationError:
|
||||
logs.warning(
|
||||
"Please Don't Send Commands In The Same Conversation.."
|
||||
)
|
||||
logs.warning("Please Don't Send Commands In The Same Conversation..")
|
||||
with contextlib.suppress(BaseException):
|
||||
await message.edit(lang("conversation_already_in_error"))
|
||||
except TimeoutConversationError:
|
||||
logs.warning(
|
||||
"Conversation Timed out while processing commands.."
|
||||
)
|
||||
logs.warning("Conversation Timed out while processing commands..")
|
||||
with contextlib.suppress(BaseException):
|
||||
await message.edit(lang("conversation_timed_out_error"))
|
||||
except ListenerCanceled:
|
||||
logs.warning(
|
||||
"Listener Canceled While Processing Commands.."
|
||||
)
|
||||
logs.warning("Listener Canceled While Processing Commands..")
|
||||
with contextlib.suppress(BaseException):
|
||||
await message.edit(lang("reload_des"))
|
||||
except SystemExit:
|
||||
await process_exit(start=False, _client=client, message=message)
|
||||
await Hook.shutdown()
|
||||
sys.exit(0)
|
||||
except (UserNotParticipant, MessageNotModified, MessageEmpty, Flood, Forbidden):
|
||||
except (
|
||||
UserNotParticipant,
|
||||
MessageNotModified,
|
||||
MessageEmpty,
|
||||
Flood,
|
||||
Forbidden,
|
||||
):
|
||||
pass
|
||||
except BaseException:
|
||||
exc_info = sys.exc_info()[1]
|
||||
exc_format = format_exc()
|
||||
with contextlib.suppress(BaseException):
|
||||
await message.edit(lang('run_error'), no_reply=True)
|
||||
await message.edit(lang("run_error"), no_reply=True)
|
||||
if Config.ERROR_REPORT:
|
||||
report = f"# Generated: {strftime('%H:%M %d/%m/%Y', gmtime())}. \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}\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,
|
||||
"Error report generated.")
|
||||
report = (
|
||||
f"# Generated: {strftime('%H:%M %d/%m/%Y', gmtime())}. \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}\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,
|
||||
"Error report generated.",
|
||||
)
|
||||
message.continue_propagation()
|
||||
|
||||
bot.add_handler(MessageHandler(handler, filters=filter_s), group=2)
|
||||
|
@ -12,9 +12,7 @@ def __list_modules():
|
||||
return [
|
||||
basename(file)[:-3]
|
||||
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")
|
||||
]
|
||||
|
||||
|
||||
@ -25,21 +23,15 @@ def __list_plugins():
|
||||
return [
|
||||
basename(file)[:-3]
|
||||
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")
|
||||
]
|
||||
|
||||
|
||||
module_list_string = "".join(
|
||||
f"{module}, " for module in sorted(__list_modules())
|
||||
)
|
||||
module_list_string = "".join(f"{module}, " for module in sorted(__list_modules()))
|
||||
|
||||
module_list_string = module_list_string[:-2]
|
||||
|
||||
plugin_list_string = "".join(
|
||||
f"{plugin}, " for plugin in sorted(__list_plugins())
|
||||
)
|
||||
plugin_list_string = "".join(f"{plugin}, " for plugin in sorted(__list_plugins()))
|
||||
|
||||
plugin_list_string = plugin_list_string[:-2]
|
||||
|
||||
|
@ -11,16 +11,19 @@ from pagermaid.utils import lang
|
||||
import contextlib
|
||||
|
||||
|
||||
@listener(is_plugin=False, command="profile",
|
||||
description=lang('profile_des'),
|
||||
parameters="<username>")
|
||||
@listener(
|
||||
is_plugin=False,
|
||||
command="profile",
|
||||
description=lang("profile_des"),
|
||||
parameters="<username>",
|
||||
)
|
||||
async def profile(client: Client, message: Message):
|
||||
""" Queries profile of a user. """
|
||||
"""Queries profile of a user."""
|
||||
if len(message.parameter) > 1:
|
||||
await message.edit(f"{lang('error_prefix')}{lang('arg_error')}")
|
||||
return
|
||||
if not Config.SILENT:
|
||||
message = await message.edit(lang('profile_process'))
|
||||
message = await message.edit(lang("profile_process"))
|
||||
if message.reply_to_message:
|
||||
user = message.reply_to_message.from_user
|
||||
if not user:
|
||||
@ -43,39 +46,54 @@ async def profile(client: Client, message: Message):
|
||||
try:
|
||||
user = await client.get_users(user)
|
||||
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:
|
||||
return await message.edit(f"{lang('error_prefix')}{lang('profile_e_nou')}")
|
||||
return await message.edit(
|
||||
f"{lang('error_prefix')}{lang('profile_e_nou')}"
|
||||
)
|
||||
except OverflowError:
|
||||
return await message.edit(f"{lang('error_prefix')}{lang('profile_e_long')}")
|
||||
return await message.edit(
|
||||
f"{lang('error_prefix')}{lang('profile_e_long')}"
|
||||
)
|
||||
except Exception as exception:
|
||||
raise exception
|
||||
user_type = "Bot" if user.is_bot else lang('profile_user')
|
||||
username_system = f"@{user.username}" if user.username is not None else lang('profile_noset')
|
||||
user_type = "Bot" if user.is_bot else lang("profile_user")
|
||||
username_system = (
|
||||
f"@{user.username}" if user.username is not None else lang("profile_noset")
|
||||
)
|
||||
if not user.first_name:
|
||||
await message.edit(f"{lang('error_prefix')}{lang('profile_e_no')}")
|
||||
return
|
||||
first_name = user.first_name.replace("\u2060", "")
|
||||
last_name = user.last_name.replace("\u2060", "") if user.last_name is not None else lang('profile_noset')
|
||||
verified = lang('profile_yes') if user.is_verified else lang('profile_no')
|
||||
restricted = lang('profile_yes') if user.is_restricted else lang('profile_no')
|
||||
caption = f"**{lang('profile_name')}:** \n" \
|
||||
f"{lang('profile_username')}: {username_system} \n" \
|
||||
f"ID: {user.id} \n" \
|
||||
f"{lang('profile_fname')}: {first_name} \n" \
|
||||
f"{lang('profile_lname')}: {last_name} \n" \
|
||||
f"{lang('profile_verified')}: {verified} \n" \
|
||||
f"{lang('profile_restricted')}: {restricted} \n" \
|
||||
f"{lang('profile_type')}: {user_type} \n" \
|
||||
f"[{first_name}](tg://user?id={user.id})"
|
||||
last_name = (
|
||||
user.last_name.replace("\u2060", "")
|
||||
if user.last_name is not None
|
||||
else lang("profile_noset")
|
||||
)
|
||||
verified = lang("profile_yes") if user.is_verified else lang("profile_no")
|
||||
restricted = lang("profile_yes") if user.is_restricted else lang("profile_no")
|
||||
caption = (
|
||||
f"**{lang('profile_name')}:** \n"
|
||||
f"{lang('profile_username')}: {username_system} \n"
|
||||
f"ID: {user.id} \n"
|
||||
f"{lang('profile_fname')}: {first_name} \n"
|
||||
f"{lang('profile_lname')}: {last_name} \n"
|
||||
f"{lang('profile_verified')}: {verified} \n"
|
||||
f"{lang('profile_restricted')}: {restricted} \n"
|
||||
f"{lang('profile_type')}: {user_type} \n"
|
||||
f"[{first_name}](tg://user?id={user.id})"
|
||||
)
|
||||
photo = await client.download_media(user.photo.big_file_id)
|
||||
reply_to = message.reply_to_message.id if message.reply_to_message else message.reply_to_top_message_id
|
||||
reply_to = (
|
||||
message.reply_to_message.id
|
||||
if message.reply_to_message
|
||||
else message.reply_to_top_message_id
|
||||
)
|
||||
try:
|
||||
await client.send_photo(
|
||||
message.chat.id,
|
||||
photo,
|
||||
caption=caption,
|
||||
reply_to_message_id=reply_to
|
||||
message.chat.id, photo, caption=caption, reply_to_message_id=reply_to
|
||||
)
|
||||
await message.delete()
|
||||
return remove(photo)
|
||||
@ -83,17 +101,21 @@ async def profile(client: Client, message: Message):
|
||||
await message.edit(caption)
|
||||
|
||||
|
||||
@listener(is_plugin=False, outgoing=True, command="block",
|
||||
need_admin=True,
|
||||
description=lang('block_des'),
|
||||
parameters="(username/uid/reply)")
|
||||
@listener(
|
||||
is_plugin=False,
|
||||
outgoing=True,
|
||||
command="block",
|
||||
need_admin=True,
|
||||
description=lang("block_des"),
|
||||
parameters="(username/uid/reply)",
|
||||
)
|
||||
async def block_user(client: Client, message: Message):
|
||||
""" Block a user. """
|
||||
"""Block a user."""
|
||||
if len(message.parameter) > 1:
|
||||
await message.edit(f"{lang('error_prefix')}{lang('arg_error')}")
|
||||
return
|
||||
if not Config.SILENT:
|
||||
message = await message.edit(lang('block_process'))
|
||||
message = await message.edit(lang("block_process"))
|
||||
user = message.obtain_user()
|
||||
if not user:
|
||||
return await message.edit(f"{lang('error_prefix')}{lang('arg_error')}")
|
||||
@ -103,17 +125,21 @@ async def block_user(client: Client, message: Message):
|
||||
await message.edit(f"`{user}` {lang('block_exist')}")
|
||||
|
||||
|
||||
@listener(is_plugin=False, outgoing=True, command="unblock",
|
||||
need_admin=True,
|
||||
description=lang('unblock_des'),
|
||||
parameters="<username/uid/reply>")
|
||||
@listener(
|
||||
is_plugin=False,
|
||||
outgoing=True,
|
||||
command="unblock",
|
||||
need_admin=True,
|
||||
description=lang("unblock_des"),
|
||||
parameters="<username/uid/reply>",
|
||||
)
|
||||
async def unblock_user(client: Client, message: Message):
|
||||
""" Unblock a user. """
|
||||
"""Unblock a user."""
|
||||
if len(message.parameter) > 1:
|
||||
await message.edit(f"{lang('error_prefix')}{lang('arg_error')}")
|
||||
return
|
||||
if not Config.SILENT:
|
||||
message = await message.edit(lang('unblock_process'))
|
||||
message = await message.edit(lang("unblock_process"))
|
||||
user = message.obtain_user()
|
||||
if not user:
|
||||
return await message.edit(f"{lang('error_prefix')}{lang('arg_error')}")
|
||||
|
@ -7,11 +7,15 @@ from pagermaid.enums import Client, Message
|
||||
from pagermaid.listener import listener
|
||||
|
||||
|
||||
@listener(is_plugin=False, outgoing=True, command="ghost",
|
||||
description=lang('ghost_des'),
|
||||
parameters="<true|false|status>")
|
||||
@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. """
|
||||
"""Toggles ghosting of a user."""
|
||||
if len(message.parameter) != 1:
|
||||
await message.edit(f"{lang('error_prefix')}{lang('arg_error')}")
|
||||
return
|
||||
@ -19,35 +23,43 @@ async def ghost(client: Client, message: Message):
|
||||
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'))
|
||||
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')}")
|
||||
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'))
|
||||
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'))
|
||||
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')}")
|
||||
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'))
|
||||
await message.edit(lang("ghost_e_exist"))
|
||||
else:
|
||||
await message.edit(lang('ghost_e_noexist'))
|
||||
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>")
|
||||
@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. """
|
||||
"""Toggles denying of a user."""
|
||||
if len(message.parameter) != 1:
|
||||
await message.edit(f"{lang('error_prefix')}{lang('arg_error')}")
|
||||
return
|
||||
@ -55,38 +67,38 @@ async def deny(client: Client, message: Message):
|
||||
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'))
|
||||
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'))
|
||||
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'))
|
||||
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'))
|
||||
await message.edit(lang("deny_e_exist"))
|
||||
else:
|
||||
await message.edit(lang('deny_e_noexist'))
|
||||
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. """
|
||||
"""Event handler to infinitely read ghosted messages."""
|
||||
if sqlite.get(f"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(message: Message):
|
||||
""" Event handler to infinitely delete denied messages. """
|
||||
"""Event handler to infinitely delete denied messages."""
|
||||
if sqlite.get(f"denied.chat_id.{str(message.chat.id)}", None):
|
||||
await message.safe_delete()
|
||||
|
@ -39,10 +39,11 @@ def un_tar_gz(filename, dirs):
|
||||
return False
|
||||
|
||||
|
||||
@listener(is_plugin=False, outgoing=True, command="backup",
|
||||
description=lang('backup_des'))
|
||||
@listener(
|
||||
is_plugin=False, outgoing=True, command="backup", description=lang("backup_des")
|
||||
)
|
||||
async def backup(message: Message):
|
||||
await message.edit(lang('backup_process'))
|
||||
await message.edit(lang("backup_process"))
|
||||
|
||||
# Remove old backup
|
||||
if os.path.exists(pgm_backup_zip_name):
|
||||
@ -50,7 +51,12 @@ async def backup(message: Message):
|
||||
|
||||
# remove mp3 , they are so big !
|
||||
for i in os.listdir("data"):
|
||||
if i.find(".mp3") != -1 or i.find(".jpg") != -1 or i.find(".flac") != -1 or i.find(".ogg") != -1:
|
||||
if (
|
||||
i.find(".mp3") != -1
|
||||
or i.find(".jpg") != -1
|
||||
or i.find(".flac") != -1
|
||||
or i.find(".ogg") != -1
|
||||
):
|
||||
os.remove(f"data{os.sep}{i}")
|
||||
|
||||
# run backup function
|
||||
@ -65,37 +71,41 @@ async def backup(message: Message):
|
||||
await message.edit(lang("backup_success"))
|
||||
|
||||
|
||||
@listener(is_plugin=False, outgoing=True, command="recovery",
|
||||
need_admin=True,
|
||||
description=lang('recovery_des'))
|
||||
@listener(
|
||||
is_plugin=False,
|
||||
outgoing=True,
|
||||
command="recovery",
|
||||
need_admin=True,
|
||||
description=lang("recovery_des"),
|
||||
)
|
||||
async def recovery(message: Message):
|
||||
reply = message.reply_to_message
|
||||
|
||||
if not reply:
|
||||
return await message.edit(lang('recovery_file_error'))
|
||||
return await message.edit(lang("recovery_file_error"))
|
||||
if not reply.document:
|
||||
return await message.edit(lang('recovery_file_error'))
|
||||
return await message.edit(lang("recovery_file_error"))
|
||||
|
||||
try:
|
||||
if ".tar.gz" not in reply.document.file_name:
|
||||
return await message.edit(lang('recovery_file_error'))
|
||||
await message.edit(lang('recovery_down'))
|
||||
return await message.edit(lang("recovery_file_error"))
|
||||
await message.edit(lang("recovery_down"))
|
||||
# Start download process
|
||||
pgm_backup_zip_name = await reply.download() # noqa
|
||||
except Exception as e: # noqa
|
||||
print(e, format_exc())
|
||||
return await message.edit(lang('recovery_file_error'))
|
||||
return await message.edit(lang("recovery_file_error"))
|
||||
# Extract backup files
|
||||
await message.edit(lang('recovery_process'))
|
||||
await message.edit(lang("recovery_process"))
|
||||
if not os.path.exists(pgm_backup_zip_name):
|
||||
return await message.edit(lang('recovery_file_not_found'))
|
||||
return await message.edit(lang("recovery_file_not_found"))
|
||||
elif not un_tar_gz(pgm_backup_zip_name, ""):
|
||||
os.remove(pgm_backup_zip_name)
|
||||
return await message.edit(lang('recovery_file_error'))
|
||||
return await message.edit(lang("recovery_file_error"))
|
||||
|
||||
# Cleanup
|
||||
if os.path.exists(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"))
|
||||
sys.exit(0)
|
||||
|
@ -8,11 +8,15 @@ from pagermaid.listener import listener
|
||||
from pagermaid.utils import lang, Message
|
||||
|
||||
|
||||
@listener(is_plugin=False, outgoing=True, command="time",
|
||||
description=lang('time_des'),
|
||||
parameters=lang('time_parameters'))
|
||||
@listener(
|
||||
is_plugin=False,
|
||||
outgoing=True,
|
||||
command="time",
|
||||
description=lang("time_des"),
|
||||
parameters=lang("time_parameters"),
|
||||
)
|
||||
async def time(message: Message):
|
||||
""" For querying time. """
|
||||
"""For querying time."""
|
||||
if len(message.parameter) == 1:
|
||||
country = message.parameter[0].title()
|
||||
else:
|
||||
@ -37,24 +41,24 @@ async def time(message: Message):
|
||||
time_zone = await get_timezone(country)
|
||||
if not time_zone:
|
||||
if len(message.parameter) < 1:
|
||||
await message.edit(lang('time_config'))
|
||||
await message.edit(lang("time_config"))
|
||||
return
|
||||
try:
|
||||
time_num, utc_num = int(message.parameter[0]), int(message.parameter[0])
|
||||
if time_num == 0:
|
||||
time_num, utc_num = '', ''
|
||||
time_num, utc_num = "", ""
|
||||
elif 0 < time_num < 13:
|
||||
time_num, utc_num = f'-{time_num}', f'+{time_num}'
|
||||
time_num, utc_num = f"-{time_num}", f"+{time_num}"
|
||||
elif -13 < time_num < 0:
|
||||
time_num, utc_num = f'+{-time_num}', f'{time_num}'
|
||||
time_num, utc_num = f"+{-time_num}", f"{time_num}"
|
||||
elif time_num < -12:
|
||||
time_num, utc_num = '+12', '-12'
|
||||
time_num, utc_num = "+12", "-12"
|
||||
elif time_num > 12:
|
||||
time_num, utc_num = '-12', '+12'
|
||||
time_zone = timezone(f'Etc/GMT{time_num}')
|
||||
country_name = f'UTC{utc_num}'
|
||||
time_num, utc_num = "-12", "+12"
|
||||
time_zone = timezone(f"Etc/GMT{time_num}")
|
||||
country_name = f"UTC{utc_num}"
|
||||
except ValueError:
|
||||
await message.edit(lang('arg_error'))
|
||||
await message.edit(lang("arg_error"))
|
||||
return
|
||||
else:
|
||||
try:
|
||||
@ -62,13 +66,15 @@ async def time(message: Message):
|
||||
except KeyError:
|
||||
country_name = country
|
||||
|
||||
await message.edit(f"**{country_name} {lang('time_time')}:**\n"
|
||||
f"`{datetime.now(time_zone).strftime(date_form)} "
|
||||
f"{datetime.now(time_zone).strftime(time_form)}`")
|
||||
await message.edit(
|
||||
f"**{country_name} {lang('time_time')}:**\n"
|
||||
f"`{datetime.now(time_zone).strftime(date_form)} "
|
||||
f"{datetime.now(time_zone).strftime(time_form)}`"
|
||||
)
|
||||
|
||||
|
||||
async def get_timezone(target):
|
||||
""" Returns timezone of the parameter in command. """
|
||||
"""Returns timezone of the parameter in command."""
|
||||
if "(Uk)" in target:
|
||||
target = target.replace("Uk", "UK")
|
||||
if "(Us)" in target:
|
||||
|
@ -15,76 +15,138 @@ from pagermaid.listener import listener
|
||||
import pathlib
|
||||
|
||||
|
||||
@listener(is_plugin=False, command="help",
|
||||
description=lang('help_des'),
|
||||
parameters=f"<{lang('command')}>")
|
||||
@listener(
|
||||
is_plugin=False,
|
||||
command="help",
|
||||
description=lang("help_des"),
|
||||
parameters=f"<{lang('command')}>",
|
||||
)
|
||||
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"]):
|
||||
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'))
|
||||
await message.edit(lang("help_no_permission"))
|
||||
else:
|
||||
await message.edit(lang('arg_error'))
|
||||
await message.edit(lang("arg_error"))
|
||||
else:
|
||||
result = f"**{lang('help_list')}: \n**"
|
||||
support_commands = ['username', 'name', 'pfp', 'bio', 'rmpfp',
|
||||
'profile', 'block', 'unblock', 'ghost', 'deny', 'convert',
|
||||
'caption', 'ocr', 'highlight', 'time', 'translate',
|
||||
'tts', 'google', 'animate',
|
||||
'teletype', 'widen', 'owo', 'flip',
|
||||
'rng', 'aaa', 'tuxsay', 'coin', 'help',
|
||||
'lang', 'alias', 'id', 'uslog', 'log',
|
||||
're', 'leave', 'hitokoto', 'apt', 'prune', 'selfprune',
|
||||
'yourprune', 'del', 'genqr', 'parseqr',
|
||||
'sb', 'sysinfo', 'status',
|
||||
'stats', 'speedtest', 'connection',
|
||||
'pingdc', 'ping', 'topcloud',
|
||||
's', 'sticker', 'sh', 'restart',
|
||||
'trace', 'chat', 'update']
|
||||
support_commands = [
|
||||
"username",
|
||||
"name",
|
||||
"pfp",
|
||||
"bio",
|
||||
"rmpfp",
|
||||
"profile",
|
||||
"block",
|
||||
"unblock",
|
||||
"ghost",
|
||||
"deny",
|
||||
"convert",
|
||||
"caption",
|
||||
"ocr",
|
||||
"highlight",
|
||||
"time",
|
||||
"translate",
|
||||
"tts",
|
||||
"google",
|
||||
"animate",
|
||||
"teletype",
|
||||
"widen",
|
||||
"owo",
|
||||
"flip",
|
||||
"rng",
|
||||
"aaa",
|
||||
"tuxsay",
|
||||
"coin",
|
||||
"help",
|
||||
"lang",
|
||||
"alias",
|
||||
"id",
|
||||
"uslog",
|
||||
"log",
|
||||
"re",
|
||||
"leave",
|
||||
"hitokoto",
|
||||
"apt",
|
||||
"prune",
|
||||
"selfprune",
|
||||
"yourprune",
|
||||
"del",
|
||||
"genqr",
|
||||
"parseqr",
|
||||
"sb",
|
||||
"sysinfo",
|
||||
"status",
|
||||
"stats",
|
||||
"speedtest",
|
||||
"connection",
|
||||
"pingdc",
|
||||
"ping",
|
||||
"topcloud",
|
||||
"s",
|
||||
"sticker",
|
||||
"sh",
|
||||
"restart",
|
||||
"trace",
|
||||
"chat",
|
||||
"update",
|
||||
]
|
||||
for command in sorted(help_messages, reverse=False):
|
||||
if str(command) in support_commands:
|
||||
continue
|
||||
if from_self(message) or \
|
||||
enforce_permission(from_msg_get_sudo_uid(message), help_messages[command]["permission"]):
|
||||
if from_self(message) or enforce_permission(
|
||||
from_msg_get_sudo_uid(message), help_messages[command]["permission"]
|
||||
):
|
||||
result += f"`{command}`, "
|
||||
if result == f"**{lang('help_list')}: \n**":
|
||||
""" The help raw command,"""
|
||||
"""The help raw command,"""
|
||||
for command in sorted(help_messages, reverse=False):
|
||||
if from_self(message) or \
|
||||
enforce_permission(from_msg_get_sudo_uid(message), help_messages[command]["permission"]):
|
||||
if from_self(message) or enforce_permission(
|
||||
from_msg_get_sudo_uid(message), help_messages[command]["permission"]
|
||||
):
|
||||
result += f"`{command}`, "
|
||||
await message.edit(result[
|
||||
:-2] + f"\n**{lang('help_send')} \",help <{lang('command')}>\" {lang('help_see')}**\n"
|
||||
f"[{lang('help_source')}](https://t.me/PagerMaid_Modify) "
|
||||
f"[{lang('help_plugin')}](https://index.xtaolabs.com/) "
|
||||
f"[{lang('help_module')}](https://wiki.xtaolabs.com/)",
|
||||
parse_mode=ParseMode.MARKDOWN,
|
||||
disable_web_page_preview=True)
|
||||
await message.edit(
|
||||
result[:-2]
|
||||
+ f"\n**{lang('help_send')} \",help <{lang('command')}>\" {lang('help_see')}**\n"
|
||||
f"[{lang('help_source')}](https://t.me/PagerMaid_Modify) "
|
||||
f"[{lang('help_plugin')}](https://index.xtaolabs.com/) "
|
||||
f"[{lang('help_module')}](https://wiki.xtaolabs.com/)",
|
||||
parse_mode=ParseMode.MARKDOWN,
|
||||
disable_web_page_preview=True,
|
||||
)
|
||||
|
||||
|
||||
@listener(is_plugin=False, command="help_raw",
|
||||
description=lang('help_des'),
|
||||
parameters=f"<{lang('command')}>")
|
||||
@listener(
|
||||
is_plugin=False,
|
||||
command="help_raw",
|
||||
description=lang("help_des"),
|
||||
parameters=f"<{lang('command')}>",
|
||||
)
|
||||
async def help_raw_command(message: Message):
|
||||
""" The help raw command,"""
|
||||
"""The help raw 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"]):
|
||||
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'))
|
||||
await message.edit(lang("help_no_permission"))
|
||||
else:
|
||||
await message.edit(lang('arg_error'))
|
||||
await message.edit(lang("arg_error"))
|
||||
else:
|
||||
result = f"**{lang('help_list')}: \n**"
|
||||
for command in sorted(help_messages, reverse=False):
|
||||
if from_self(message) or \
|
||||
enforce_permission(from_msg_get_sudo_uid(message), help_messages[command]["permission"]):
|
||||
if from_self(message) or enforce_permission(
|
||||
from_msg_get_sudo_uid(message), help_messages[command]["permission"]
|
||||
):
|
||||
result += f"`{command}`, "
|
||||
await message.edit(
|
||||
f"""{result[:-2]}\n**{lang('help_send')} ",help <{lang('command')}>" {lang('help_see')}** [{lang('help_source')}](https://t.me/PagerMaid_Modify)""",
|
||||
@ -93,57 +155,67 @@ async def help_raw_command(message: Message):
|
||||
)
|
||||
|
||||
|
||||
@listener(is_plugin=False, command="lang",
|
||||
need_admin=True,
|
||||
description=lang('lang_des'))
|
||||
@listener(
|
||||
is_plugin=False, command="lang", need_admin=True, description=lang("lang_des")
|
||||
)
|
||||
async def lang_change(message: Message):
|
||||
to_lang = message.arguments
|
||||
from_lang = Config.LANGUAGE
|
||||
dir_, dir__ = listdir('languages/built-in'), []
|
||||
dir_, dir__ = listdir("languages/built-in"), []
|
||||
for i in dir_:
|
||||
if i.find('yml') != -1:
|
||||
if i.find("yml") != -1:
|
||||
dir__.append(i[:-4])
|
||||
file = pathlib.Path('config.yml').read_text()
|
||||
file = pathlib.Path("config.yml").read_text()
|
||||
if to_lang in dir__:
|
||||
file = file.replace(f'application_language: "{from_lang}"', f'application_language: "{to_lang}"')
|
||||
with open('config.yml', 'w', encoding="utf-8") as f:
|
||||
file = file.replace(
|
||||
f'application_language: "{from_lang}"', f'application_language: "{to_lang}"'
|
||||
)
|
||||
with open("config.yml", "w", encoding="utf-8") as f:
|
||||
f.write(file)
|
||||
await message.edit(f"{lang('lang_change_to')} {to_lang}, {lang('lang_reboot')}")
|
||||
await reload_all()
|
||||
else:
|
||||
await message.edit(f'{lang("lang_current_lang")} {Config.LANGUAGE}\n\n'
|
||||
f'{lang("lang_all_lang")}{",".join(dir__)}')
|
||||
await message.edit(
|
||||
f'{lang("lang_current_lang")} {Config.LANGUAGE}\n\n'
|
||||
f'{lang("lang_all_lang")}{",".join(dir__)}'
|
||||
)
|
||||
|
||||
|
||||
@listener(is_plugin=False, outgoing=True, command="alias",
|
||||
disallow_alias=True,
|
||||
need_admin=True,
|
||||
description=lang('alias_des'),
|
||||
parameters='{list|del|set} <source> <to>')
|
||||
@listener(
|
||||
is_plugin=False,
|
||||
outgoing=True,
|
||||
command="alias",
|
||||
disallow_alias=True,
|
||||
need_admin=True,
|
||||
description=lang("alias_des"),
|
||||
parameters="{list|del|set} <source> <to>",
|
||||
)
|
||||
async def alias_commands(message: Message):
|
||||
alias_manager = AliasManager()
|
||||
if len(message.parameter) == 0:
|
||||
await message.edit(lang('arg_error'))
|
||||
await message.edit(lang("arg_error"))
|
||||
elif len(message.parameter) == 1:
|
||||
if alias_manager.alias_list:
|
||||
await message.edit(lang('alias_list') + '\n\n' + alias_manager.get_all_alias_text())
|
||||
await message.edit(
|
||||
lang("alias_list") + "\n\n" + alias_manager.get_all_alias_text()
|
||||
)
|
||||
else:
|
||||
await message.edit(lang('alias_no'))
|
||||
await message.edit(lang("alias_no"))
|
||||
elif len(message.parameter) == 2:
|
||||
source_command = message.parameter[1]
|
||||
try:
|
||||
alias_manager.delete_alias(source_command)
|
||||
await message.edit(lang('alias_success'))
|
||||
await message.edit(lang("alias_success"))
|
||||
await reload_all()
|
||||
except KeyError:
|
||||
await message.edit(lang('alias_no_exist'))
|
||||
await message.edit(lang("alias_no_exist"))
|
||||
return
|
||||
elif len(message.parameter) == 3:
|
||||
source_command = message.parameter[1]
|
||||
to_command = message.parameter[2]
|
||||
if to_command in help_messages:
|
||||
await message.edit(lang('alias_exist'))
|
||||
await message.edit(lang("alias_exist"))
|
||||
return
|
||||
alias_manager.add_alias(source_command, to_command)
|
||||
await message.edit(lang('alias_success'))
|
||||
await message.edit(lang("alias_success"))
|
||||
await reload_all()
|
||||
|
@ -10,10 +10,9 @@ from pagermaid.utils import lang
|
||||
from pagermaid.enums import Client, Message
|
||||
|
||||
|
||||
@listener(is_plugin=False, outgoing=True, command="id",
|
||||
description=lang("id_des"))
|
||||
@listener(is_plugin=False, outgoing=True, command="id", description=lang("id_des"))
|
||||
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
|
||||
text = f"Message ID: `{str(message.id)}" + "`\n\n"
|
||||
text += "**Chat**\nid:`" + str(message.chat.id) + "`\n"
|
||||
@ -36,7 +35,7 @@ async def userid(message: Message):
|
||||
return await message.edit(lang("leave_not_group"))
|
||||
text += f"protected: `{str(msg_from.has_protected_content)}" + "`\n"
|
||||
if reply:
|
||||
text += "\n" + lang('id_hint') + "\nMessage ID: `" + str(reply.id) + "`"
|
||||
text += "\n" + lang("id_hint") + "\nMessage ID: `" + str(reply.id) + "`"
|
||||
try:
|
||||
text += "\n\n**User**\nid: `" + str(reply.from_user.id) + "`"
|
||||
if reply.from_user.is_bot:
|
||||
@ -61,9 +60,14 @@ async def userid(message: Message):
|
||||
except AttributeError:
|
||||
pass
|
||||
if reply.forward_from_chat:
|
||||
text += "\n\n**Forward From Channel**\n" \
|
||||
"id: `" + str(reply.forward_from_chat.id) + \
|
||||
"`\ntitle: `" + reply.forward_from_chat.title + "`"
|
||||
text += (
|
||||
"\n\n**Forward From Channel**\n"
|
||||
"id: `"
|
||||
+ str(reply.forward_from_chat.id)
|
||||
+ "`\ntitle: `"
|
||||
+ reply.forward_from_chat.title
|
||||
+ "`"
|
||||
)
|
||||
if reply.forward_from_chat.username:
|
||||
text += "\nusername: @" + reply.forward_from_chat.username
|
||||
if reply.forward_from_message_id:
|
||||
@ -71,7 +75,9 @@ async def userid(message: Message):
|
||||
if reply.forward_sender_name:
|
||||
text += "\npost_author: `" + reply.forward_sender_name + "`"
|
||||
elif reply.forward_from:
|
||||
text += "\n\n**Forward From User**\nid: `" + str(reply.forward_from.id) + "`"
|
||||
text += (
|
||||
"\n\n**Forward From User**\nid: `" + str(reply.forward_from.id) + "`"
|
||||
)
|
||||
try:
|
||||
if reply.forward_from.is_bot:
|
||||
text += f"\nis_bot: {lang('id_is_bot_yes')}"
|
||||
@ -88,15 +94,23 @@ async def userid(message: Message):
|
||||
except AttributeError:
|
||||
pass
|
||||
elif reply.forward_sender_name:
|
||||
text += "\n\n**Forward From User**\nsender_name: `" + str(reply.forward_sender_name) + "`"
|
||||
text += (
|
||||
"\n\n**Forward From User**\nsender_name: `"
|
||||
+ str(reply.forward_sender_name)
|
||||
+ "`"
|
||||
)
|
||||
await message.edit(text)
|
||||
|
||||
|
||||
@listener(is_plugin=False, outgoing=True, command="uslog",
|
||||
description=lang('uslog_des'),
|
||||
parameters="<string>")
|
||||
@listener(
|
||||
is_plugin=False,
|
||||
outgoing=True,
|
||||
command="uslog",
|
||||
description=lang("uslog_des"),
|
||||
parameters="<string>",
|
||||
)
|
||||
async def uslog(message: Message):
|
||||
""" Forwards a message into log group """
|
||||
"""Forwards a message into log group"""
|
||||
if Config.LOG:
|
||||
if message.reply_to_message:
|
||||
reply_msg = message.reply_to_message
|
||||
@ -104,17 +118,21 @@ async def uslog(message: Message):
|
||||
elif message.arguments:
|
||||
await log(message.arguments)
|
||||
else:
|
||||
return await message.edit(lang('arg_error'))
|
||||
await message.edit(lang('uslog_success'))
|
||||
return await message.edit(lang("arg_error"))
|
||||
await message.edit(lang("uslog_success"))
|
||||
else:
|
||||
await message.edit(lang('uslog_log_disable'))
|
||||
await message.edit(lang("uslog_log_disable"))
|
||||
|
||||
|
||||
@listener(is_plugin=False, outgoing=True, command="log",
|
||||
description=lang('log_des'),
|
||||
parameters="<string>")
|
||||
@listener(
|
||||
is_plugin=False,
|
||||
outgoing=True,
|
||||
command="log",
|
||||
description=lang("log_des"),
|
||||
parameters="<string>",
|
||||
)
|
||||
async def logging(message: Message):
|
||||
""" Forwards a message into log group """
|
||||
"""Forwards a message into log group"""
|
||||
if Config.LOG:
|
||||
if message.reply_to_message:
|
||||
reply_msg = message.reply_to_message
|
||||
@ -122,38 +140,45 @@ async def logging(message: Message):
|
||||
elif message.arguments:
|
||||
await log(message.arguments)
|
||||
else:
|
||||
return await message.edit(lang('arg_error'))
|
||||
return await message.edit(lang("arg_error"))
|
||||
await message.safe_delete()
|
||||
else:
|
||||
await message.edit(lang('uslog_log_disable'))
|
||||
await message.edit(lang("uslog_log_disable"))
|
||||
|
||||
|
||||
@listener(is_plugin=False, outgoing=True, command="re",
|
||||
description=lang('re_des'),
|
||||
parameters=lang('re_parameters'))
|
||||
@listener(
|
||||
is_plugin=False,
|
||||
outgoing=True,
|
||||
command="re",
|
||||
description=lang("re_des"),
|
||||
parameters=lang("re_parameters"),
|
||||
)
|
||||
async def re(bot: Client, message: Message):
|
||||
""" Forwards a message into this group """
|
||||
"""Forwards a message into this group"""
|
||||
if reply := message.reply_to_message:
|
||||
if message.arguments == '':
|
||||
if message.arguments == "":
|
||||
num = 1
|
||||
else:
|
||||
try:
|
||||
num = int(message.arguments)
|
||||
if num > 100:
|
||||
await message.edit(lang('re_too_big'))
|
||||
await message.edit(lang("re_too_big"))
|
||||
except Exception:
|
||||
return await message.edit(lang('re_arg_error'))
|
||||
return await message.edit(lang("re_arg_error"))
|
||||
await message.safe_delete()
|
||||
for _ in range(num):
|
||||
try:
|
||||
if not message.chat.has_protected_content:
|
||||
await forward_msg(bot, message.reply_to_message)
|
||||
else:
|
||||
await reply.copy(reply.chat.id, reply_to_message_id=message.reply_to_top_message_id)
|
||||
await reply.copy(
|
||||
reply.chat.id,
|
||||
reply_to_message_id=message.reply_to_top_message_id,
|
||||
)
|
||||
except (Forbidden, FloodWait, Exception):
|
||||
return
|
||||
else:
|
||||
await message.edit(lang('not_reply'))
|
||||
await message.edit(lang("not_reply"))
|
||||
|
||||
|
||||
async def forward_msg(bot: Client, message: Message):
|
||||
|
@ -13,7 +13,7 @@ from pagermaid.hook import Hook
|
||||
class DatetimeSerializer(json.JSONEncoder):
|
||||
def default(self, obj):
|
||||
if isinstance(obj, datetime.datetime):
|
||||
fmt = '%Y-%m-%dT%H:%M:%S'
|
||||
fmt = "%Y-%m-%dT%H:%M:%S"
|
||||
return obj.strftime(fmt)
|
||||
|
||||
return json.JSONEncoder.default(self, obj)
|
||||
@ -37,57 +37,57 @@ class Mixpanel:
|
||||
@staticmethod
|
||||
def json_dumps(data, cls=None):
|
||||
# Separators are specified to eliminate whitespace.
|
||||
return json.dumps(data, separators=(',', ':'), cls=cls)
|
||||
return json.dumps(data, separators=(",", ":"), cls=cls)
|
||||
|
||||
async def api_call(self, endpoint, json_message):
|
||||
_endpoints = {
|
||||
'events': f'https://{self.api_host}/track',
|
||||
'people': f'https://{self.api_host}/engage',
|
||||
"events": f"https://{self.api_host}/track",
|
||||
"people": f"https://{self.api_host}/engage",
|
||||
}
|
||||
request_url = _endpoints.get(endpoint)
|
||||
if request_url is None:
|
||||
return
|
||||
params = {
|
||||
'data': json_message,
|
||||
'verbose': 1,
|
||||
'ip': 0,
|
||||
"data": json_message,
|
||||
"verbose": 1,
|
||||
"ip": 0,
|
||||
}
|
||||
start = self._now()
|
||||
with contextlib.suppress(Exception):
|
||||
await self._request.post(
|
||||
request_url,
|
||||
data=params,
|
||||
timeout=10.0
|
||||
)
|
||||
await self._request.post(request_url, data=params, timeout=10.0)
|
||||
logs.debug(f"Mixpanel request took {self._now() - start} seconds")
|
||||
|
||||
async def people_set(self, distinct_id: str, properties: dict):
|
||||
message = {
|
||||
'$distinct_id': distinct_id,
|
||||
'$set': properties,
|
||||
"$distinct_id": distinct_id,
|
||||
"$set": properties,
|
||||
}
|
||||
record = {'$token': self._token, '$time': self._now()}
|
||||
record = {"$token": self._token, "$time": self._now()}
|
||||
# sourcery skip: dict-assign-update-to-union
|
||||
record.update(message)
|
||||
return await self.api_call('people', self.json_dumps(record, cls=self._serializer))
|
||||
return await self.api_call(
|
||||
"people", self.json_dumps(record, cls=self._serializer)
|
||||
)
|
||||
|
||||
async def track(self, distinct_id: str, event_name: str, properties: dict):
|
||||
all_properties = {
|
||||
'token': self._token,
|
||||
'distinct_id': distinct_id,
|
||||
'time': self._now(),
|
||||
'$insert_id': self._make_insert_id(),
|
||||
'mp_lib': 'python',
|
||||
'$lib_version': '4.10.0',
|
||||
"token": self._token,
|
||||
"distinct_id": distinct_id,
|
||||
"time": self._now(),
|
||||
"$insert_id": self._make_insert_id(),
|
||||
"mp_lib": "python",
|
||||
"$lib_version": "4.10.0",
|
||||
}
|
||||
if properties:
|
||||
# sourcery skip: dict-assign-update-to-union
|
||||
all_properties.update(properties)
|
||||
event = {
|
||||
'event': event_name,
|
||||
'properties': all_properties,
|
||||
"event": event_name,
|
||||
"properties": all_properties,
|
||||
}
|
||||
return await self.api_call('events', self.json_dumps(event, cls=self._serializer))
|
||||
return await self.api_call(
|
||||
"events", self.json_dumps(event, cls=self._serializer)
|
||||
)
|
||||
|
||||
|
||||
mp = Mixpanel(Config.MIXPANEL_API)
|
||||
@ -97,7 +97,7 @@ mp = Mixpanel(Config.MIXPANEL_API)
|
||||
async def mixpanel_init_id(bot: Client):
|
||||
if not bot.me:
|
||||
bot.me = await bot.get_me()
|
||||
data = {'$first_name': bot.me.first_name}
|
||||
data = {"$first_name": bot.me.first_name}
|
||||
if bot.me.username:
|
||||
data["username"] = bot.me.username
|
||||
bot.loop.create_task(mp.people_set(str(bot.me.id), data))
|
||||
@ -113,4 +113,10 @@ async def mixpanel_report(bot: Client, message: Message, command):
|
||||
sender_id = message.sender_chat.id if message.sender_chat else sender_id
|
||||
if sender_id < 0 and message.outgoing:
|
||||
sender_id = bot.me.id
|
||||
bot.loop.create_task(mp.track(str(sender_id), f'Function {command}', {'command': command, "bot_id": bot.me.id}))
|
||||
bot.loop.create_task(
|
||||
mp.track(
|
||||
str(sender_id),
|
||||
f"Function {command}",
|
||||
{"command": command, "bot_id": bot.me.id},
|
||||
)
|
||||
)
|
||||
|
@ -33,50 +33,56 @@ def move_plugin(file_path):
|
||||
|
||||
def update_version(plugin_name, version):
|
||||
plugin_directory = f"{working_dir}{sep}plugins{sep}"
|
||||
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[plugin_name] = version
|
||||
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)
|
||||
|
||||
|
||||
@listener(is_plugin=False, outgoing=True, command="apt",
|
||||
need_admin=True,
|
||||
diagnostics=False,
|
||||
description=lang('apt_des'),
|
||||
parameters=lang('apt_parameters'))
|
||||
@listener(
|
||||
is_plugin=False,
|
||||
outgoing=True,
|
||||
command="apt",
|
||||
need_admin=True,
|
||||
diagnostics=False,
|
||||
description=lang("apt_des"),
|
||||
parameters=lang("apt_parameters"),
|
||||
)
|
||||
async def plugin(message: Message):
|
||||
if len(message.parameter) == 0:
|
||||
await message.edit(lang('arg_error'))
|
||||
await message.edit(lang("arg_error"))
|
||||
return
|
||||
reply = message.reply_to_message
|
||||
plugin_directory = f"{working_dir}{sep}plugins{sep}"
|
||||
if message.parameter[0] == "install":
|
||||
if len(message.parameter) == 1:
|
||||
message = await message.edit(lang('apt_processing'))
|
||||
message = await message.edit(lang("apt_processing"))
|
||||
file_path = None
|
||||
with contextlib.suppress(Exception):
|
||||
if reply:
|
||||
file_path = await reply.download()
|
||||
else:
|
||||
file_path = await message.download()
|
||||
if file_path is None or not file_path.endswith('.py'):
|
||||
await message.edit(lang('apt_no_py'))
|
||||
if file_path is None or not file_path.endswith(".py"):
|
||||
await message.edit(lang("apt_no_py"))
|
||||
try:
|
||||
remove(str(file_path))
|
||||
except FileNotFoundError:
|
||||
pass
|
||||
return
|
||||
move_plugin(file_path)
|
||||
await message.edit(f"<b>{lang('apt_name')}</b>\n\n"
|
||||
f"{lang('apt_plugin')} "
|
||||
f"{path.basename(file_path)[:-3]} {lang('apt_installed')}")
|
||||
await message.edit(
|
||||
f"<b>{lang('apt_name')}</b>\n\n"
|
||||
f"{lang('apt_plugin')} "
|
||||
f"{path.basename(file_path)[:-3]} {lang('apt_installed')}"
|
||||
)
|
||||
await log(f"{lang('apt_install_success')} {path.basename(file_path)[:-3]}.")
|
||||
await reload_all()
|
||||
elif len(message.parameter) >= 2:
|
||||
await plugin_manager.load_remote_plugins()
|
||||
process_list = message.parameter
|
||||
message = await message.edit(lang('apt_processing'))
|
||||
message = await message.edit(lang("apt_processing"))
|
||||
del process_list[0]
|
||||
success_list = []
|
||||
failed_list = []
|
||||
@ -98,30 +104,34 @@ async def plugin(message: Message):
|
||||
failed_list.append(i)
|
||||
text = f"<b>{lang('apt_name')}</b>\n\n"
|
||||
if len(success_list) > 0:
|
||||
text += lang('apt_install_success') + " : %s\n" % ", ".join(success_list)
|
||||
text += lang("apt_install_success") + " : %s\n" % ", ".join(
|
||||
success_list
|
||||
)
|
||||
if len(failed_list) > 0:
|
||||
text += lang('apt_not_found') + " %s\n" % ", ".join(failed_list)
|
||||
text += lang("apt_not_found") + " %s\n" % ", ".join(failed_list)
|
||||
if len(no_need_list) > 0:
|
||||
text += lang('apt_no_update') + " %s\n" % ", ".join(no_need_list)
|
||||
text += lang("apt_no_update") + " %s\n" % ", ".join(no_need_list)
|
||||
await log(text)
|
||||
restart = len(success_list) > 0
|
||||
await message.edit(text)
|
||||
if restart:
|
||||
await reload_all()
|
||||
else:
|
||||
await message.edit(lang('arg_error'))
|
||||
await message.edit(lang("arg_error"))
|
||||
elif message.parameter[0] == "remove":
|
||||
if len(message.parameter) == 2:
|
||||
if plugin_manager.remove_plugin(message.parameter[1]):
|
||||
await message.edit(f"{lang('apt_remove_success')} {message.parameter[1]}")
|
||||
await message.edit(
|
||||
f"{lang('apt_remove_success')} {message.parameter[1]}"
|
||||
)
|
||||
await log(f"{lang('apt_remove')} {message.parameter[1]}.")
|
||||
await reload_all()
|
||||
elif "/" in message.parameter[1]:
|
||||
await message.edit(lang('arg_error'))
|
||||
await message.edit(lang("arg_error"))
|
||||
else:
|
||||
await message.edit(lang('apt_not_exist'))
|
||||
await message.edit(lang("apt_not_exist"))
|
||||
else:
|
||||
await message.edit(lang('arg_error'))
|
||||
await message.edit(lang("arg_error"))
|
||||
elif message.parameter[0] == "status":
|
||||
if len(message.parameter) == 1:
|
||||
inactive_plugins = sorted(__list_plugins())
|
||||
@ -151,35 +161,41 @@ async def plugin(message: Message):
|
||||
inactive_plugins_string = f"`{lang('apt_no_load_failed_plugins')}`"
|
||||
if len(disabled_plugins) == 0:
|
||||
disabled_plugins_string = f"`{lang('apt_no_disabled_plugins')}`"
|
||||
output = f"**{lang('apt_plugin_list')}**\n" \
|
||||
f"{lang('apt_plugin_running')}: {active_plugins_string}\n" \
|
||||
f"{lang('apt_plugin_disabled')}: {disabled_plugins_string}\n" \
|
||||
f"{lang('apt_plugin_failed')}: {inactive_plugins_string}"
|
||||
output = (
|
||||
f"**{lang('apt_plugin_list')}**\n"
|
||||
f"{lang('apt_plugin_running')}: {active_plugins_string}\n"
|
||||
f"{lang('apt_plugin_disabled')}: {disabled_plugins_string}\n"
|
||||
f"{lang('apt_plugin_failed')}: {inactive_plugins_string}"
|
||||
)
|
||||
await message.edit(output)
|
||||
else:
|
||||
await message.edit(lang('arg_error'))
|
||||
await message.edit(lang("arg_error"))
|
||||
elif message.parameter[0] == "enable":
|
||||
if len(message.parameter) == 2:
|
||||
if plugin_manager.enable_plugin(message.parameter[1]):
|
||||
await message.edit(f"{lang('apt_plugin')} {message.parameter[1]} "
|
||||
f"{lang('apt_enable')}")
|
||||
await message.edit(
|
||||
f"{lang('apt_plugin')} {message.parameter[1]} "
|
||||
f"{lang('apt_enable')}"
|
||||
)
|
||||
await log(f"{lang('apt_enable')} {message.parameter[1]}.")
|
||||
await reload_all()
|
||||
else:
|
||||
await message.edit(lang('apt_not_exist'))
|
||||
await message.edit(lang("apt_not_exist"))
|
||||
else:
|
||||
await message.edit(lang('arg_error'))
|
||||
await message.edit(lang("arg_error"))
|
||||
elif message.parameter[0] == "disable":
|
||||
if len(message.parameter) == 2:
|
||||
if plugin_manager.disable_plugin(message.parameter[1]):
|
||||
await message.edit(f"{lang('apt_plugin')} {message.parameter[1]} "
|
||||
f"{lang('apt_disable')}")
|
||||
await message.edit(
|
||||
f"{lang('apt_plugin')} {message.parameter[1]} "
|
||||
f"{lang('apt_disable')}"
|
||||
)
|
||||
await log(f"{lang('apt_disable')} {message.parameter[1]}.")
|
||||
await reload_all()
|
||||
else:
|
||||
await message.edit(lang('apt_not_exist'))
|
||||
await message.edit(lang("apt_not_exist"))
|
||||
else:
|
||||
await message.edit(lang('arg_error'))
|
||||
await message.edit(lang("arg_error"))
|
||||
elif message.parameter[0] == "upload":
|
||||
if len(message.parameter) == 2:
|
||||
file_name = f"{message.parameter[1]}.py"
|
||||
@ -191,31 +207,41 @@ async def plugin(message: Message):
|
||||
elif exists(f"{plugin_directory}{file_name}.disabled"):
|
||||
copyfile(f"{plugin_directory}{file_name}.disabled", file_name)
|
||||
if exists(file_name):
|
||||
await message.edit(lang('apt_uploading'))
|
||||
await upload_attachment(file_name,
|
||||
message.chat.id, reply_id,
|
||||
thumb=f"pagermaid{sep}assets{sep}logo.jpg",
|
||||
caption=f"<b>{lang('apt_name')}</b>\n\n"
|
||||
f"PagerMaid-Pyro {message.parameter[1]} plugin.")
|
||||
await message.edit(lang("apt_uploading"))
|
||||
await upload_attachment(
|
||||
file_name,
|
||||
message.chat.id,
|
||||
reply_id,
|
||||
thumb=f"pagermaid{sep}assets{sep}logo.jpg",
|
||||
caption=f"<b>{lang('apt_name')}</b>\n\n"
|
||||
f"PagerMaid-Pyro {message.parameter[1]} plugin.",
|
||||
)
|
||||
remove(file_name)
|
||||
await message.safe_delete()
|
||||
else:
|
||||
await message.edit(lang('apt_not_exist'))
|
||||
await message.edit(lang("apt_not_exist"))
|
||||
else:
|
||||
await message.edit(lang('arg_error'))
|
||||
await message.edit(lang("arg_error"))
|
||||
elif message.parameter[0] == "update":
|
||||
if not exists(f"{plugin_directory}version.json"):
|
||||
await message.edit(lang('apt_why_not_install_a_plugin'))
|
||||
await message.edit(lang("apt_why_not_install_a_plugin"))
|
||||
return
|
||||
await plugin_manager.load_remote_plugins()
|
||||
updated_plugins = [i.name for i in await plugin_manager.update_all_remote_plugin() if i]
|
||||
updated_plugins = [
|
||||
i.name for i in await plugin_manager.update_all_remote_plugin() if i
|
||||
]
|
||||
if len(updated_plugins) == 0:
|
||||
await message.edit(f"<b>{lang('apt_name')}</b>\n\n" +
|
||||
lang("apt_loading_from_online_but_nothing_need_to_update"))
|
||||
await message.edit(
|
||||
f"<b>{lang('apt_name')}</b>\n\n"
|
||||
+ lang("apt_loading_from_online_but_nothing_need_to_update")
|
||||
)
|
||||
else:
|
||||
message = await message.edit(lang("apt_loading_from_online_and_updating"))
|
||||
await message.edit(
|
||||
f"<b>{lang('apt_name')}</b>\n\n" + lang("apt_reading_list") + "\n" + "、".join(updated_plugins)
|
||||
f"<b>{lang('apt_name')}</b>\n\n"
|
||||
+ lang("apt_reading_list")
|
||||
+ "\n"
|
||||
+ "、".join(updated_plugins)
|
||||
)
|
||||
await reload_all()
|
||||
elif message.parameter[0] == "search":
|
||||
@ -228,13 +254,25 @@ async def plugin(message: Message):
|
||||
plugin_online = plugin_list.json()["list"]
|
||||
for i in plugin_online:
|
||||
if search(plugin_name, i["name"], I):
|
||||
search_result.extend(['`' + i['name'] + '` / `' + i['version'] + '`\n ' + i['des-short']])
|
||||
search_result.extend(
|
||||
[
|
||||
"`"
|
||||
+ i["name"]
|
||||
+ "` / `"
|
||||
+ i["version"]
|
||||
+ "`\n "
|
||||
+ i["des-short"]
|
||||
]
|
||||
)
|
||||
if len(search_result) == 0:
|
||||
await message.edit(lang("apt_search_not_found"))
|
||||
else:
|
||||
await message.edit(f"{lang('apt_search_result_hint')}:\n\n" + '\n\n'.join(search_result))
|
||||
await message.edit(
|
||||
f"{lang('apt_search_result_hint')}:\n\n"
|
||||
+ "\n\n".join(search_result)
|
||||
)
|
||||
else:
|
||||
await message.edit(lang('arg_error'))
|
||||
await message.edit(lang("arg_error"))
|
||||
elif message.parameter[0] == "show":
|
||||
if len(message.parameter) == 1:
|
||||
await message.edit(lang("apt_search_no_name"))
|
||||
@ -249,15 +287,17 @@ async def plugin(message: Message):
|
||||
search_support = lang("apt_search_supporting")
|
||||
else:
|
||||
search_support = lang("apt_search_not_supporting")
|
||||
search_result = f"{lang('apt_plugin_name')}:`{i['name']}`\n" \
|
||||
f"{lang('apt_plugin_ver')}:`Ver {i['version']}`\n" \
|
||||
f"{lang('apt_plugin_section')}:`{i['section']}`\n" \
|
||||
f"{lang('apt_plugin_maintainer')}:`{i['maintainer']}`\n" \
|
||||
f"{lang('apt_plugin_size')}:`{i['size']}`\n" \
|
||||
f"{lang('apt_plugin_support')}:{search_support}\n" \
|
||||
f"{lang('apt_plugin_des_short')}:{i['des-short']}"
|
||||
search_result = (
|
||||
f"{lang('apt_plugin_name')}:`{i['name']}`\n"
|
||||
f"{lang('apt_plugin_ver')}:`Ver {i['version']}`\n"
|
||||
f"{lang('apt_plugin_section')}:`{i['section']}`\n"
|
||||
f"{lang('apt_plugin_maintainer')}:`{i['maintainer']}`\n"
|
||||
f"{lang('apt_plugin_size')}:`{i['size']}`\n"
|
||||
f"{lang('apt_plugin_support')}:{search_support}\n"
|
||||
f"{lang('apt_plugin_des_short')}:{i['des-short']}"
|
||||
)
|
||||
break
|
||||
if search_result == '':
|
||||
if search_result == "":
|
||||
await message.edit(lang("apt_search_not_found"))
|
||||
else:
|
||||
await message.edit(search_result)
|
||||
@ -267,7 +307,7 @@ async def plugin(message: Message):
|
||||
return
|
||||
message = await message.edit(lang("stats_loading"))
|
||||
list_plugin = []
|
||||
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)
|
||||
plugin_list = await client.get(f"{Config.GIT_SOURCE}list.json")
|
||||
plugin_online = plugin_list.json()["list"]
|
||||
|
@ -10,20 +10,26 @@ from pagermaid.utils import lang
|
||||
import contextlib
|
||||
|
||||
|
||||
@listener(is_plugin=False, outgoing=True, command="prune",
|
||||
need_admin=True,
|
||||
description=lang('prune_des'))
|
||||
@listener(
|
||||
is_plugin=False,
|
||||
outgoing=True,
|
||||
command="prune",
|
||||
need_admin=True,
|
||||
description=lang("prune_des"),
|
||||
)
|
||||
async def prune(client: Client, 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:
|
||||
await message.edit(lang('not_reply'))
|
||||
await message.edit(lang("not_reply"))
|
||||
return
|
||||
input_chat = message.chat.id
|
||||
messages = []
|
||||
count = 0
|
||||
limit = message.id - message.reply_to_message.id + 1
|
||||
if message.reply_to_top_message_id:
|
||||
func = client.get_discussion_replies(input_chat, message.reply_to_top_message_id, limit=limit)
|
||||
func = client.get_discussion_replies(
|
||||
input_chat, message.reply_to_top_message_id, limit=limit
|
||||
)
|
||||
else:
|
||||
func = client.get_chat_history(input_chat, limit=limit)
|
||||
async for msg in func:
|
||||
@ -45,24 +51,28 @@ async def prune(client: Client, message: Message):
|
||||
await notification.delete()
|
||||
|
||||
|
||||
@listener(is_plugin=False, outgoing=True, command="selfprune",
|
||||
need_admin=True,
|
||||
description=lang('sp_des'),
|
||||
parameters=lang('sp_parameters'))
|
||||
@listener(
|
||||
is_plugin=False,
|
||||
outgoing=True,
|
||||
command="selfprune",
|
||||
need_admin=True,
|
||||
description=lang("sp_des"),
|
||||
parameters=lang("sp_parameters"),
|
||||
)
|
||||
async def self_prune(bot: Client, message: Message):
|
||||
""" Deletes specific amount of messages you sent. """
|
||||
"""Deletes specific amount of messages you sent."""
|
||||
msgs = []
|
||||
count_buffer = 0
|
||||
offset = 0
|
||||
if len(message.parameter) != 1:
|
||||
if not message.reply_to_message:
|
||||
return await message.edit(lang('arg_error'))
|
||||
return await message.edit(lang("arg_error"))
|
||||
offset = message.reply_to_message.id
|
||||
try:
|
||||
count = int(message.parameter[0])
|
||||
await message.delete()
|
||||
except ValueError:
|
||||
await message.edit(lang('arg_error'))
|
||||
await message.edit(lang("arg_error"))
|
||||
return
|
||||
async for msg in bot.get_chat_history(message.chat.id, limit=100):
|
||||
if count_buffer == count:
|
||||
@ -73,7 +83,9 @@ async def self_prune(bot: Client, message: Message):
|
||||
if len(msgs) == 100:
|
||||
await bot.delete_messages(message.chat.id, msgs)
|
||||
msgs = []
|
||||
async for msg in bot.search_messages(message.chat.id, from_user="me", offset=offset):
|
||||
async for msg in bot.search_messages(
|
||||
message.chat.id, from_user="me", offset=offset
|
||||
):
|
||||
if count_buffer == count:
|
||||
break
|
||||
msgs.append(msg.id)
|
||||
@ -93,25 +105,29 @@ async def self_prune(bot: Client, message: Message):
|
||||
await notification.delete()
|
||||
|
||||
|
||||
@listener(is_plugin=False, outgoing=True, command="yourprune",
|
||||
need_admin=True,
|
||||
description=lang('yp_des'),
|
||||
parameters=lang('sp_parameters'))
|
||||
@listener(
|
||||
is_plugin=False,
|
||||
outgoing=True,
|
||||
command="yourprune",
|
||||
need_admin=True,
|
||||
description=lang("yp_des"),
|
||||
parameters=lang("sp_parameters"),
|
||||
)
|
||||
async def your_prune(bot: Client, message: Message):
|
||||
""" Deletes specific amount of messages someone sent. """
|
||||
"""Deletes specific amount of messages someone sent."""
|
||||
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
|
||||
if not target.from_user:
|
||||
return await message.edit(lang('not_reply'))
|
||||
return await message.edit(lang("not_reply"))
|
||||
if len(message.parameter) != 1:
|
||||
return await message.edit(lang('arg_error'))
|
||||
return await message.edit(lang("arg_error"))
|
||||
count = 0
|
||||
try:
|
||||
count = int(message.parameter[0])
|
||||
await message.delete()
|
||||
except ValueError:
|
||||
return await message.edit(lang('arg_error'))
|
||||
return await message.edit(lang("arg_error"))
|
||||
except Exception: # noqa
|
||||
pass
|
||||
count_buffer = 0
|
||||
@ -125,7 +141,9 @@ async def your_prune(bot: Client, message: Message):
|
||||
if len(msgs) == 100:
|
||||
await bot.delete_messages(message.chat.id, msgs)
|
||||
msgs = []
|
||||
async for msg in bot.search_messages(message.chat.id, from_user=target.from_user.id):
|
||||
async for msg in bot.search_messages(
|
||||
message.chat.id, from_user=target.from_user.id
|
||||
):
|
||||
if count_buffer == count:
|
||||
break
|
||||
count_buffer += 1
|
||||
@ -145,16 +163,20 @@ async def your_prune(bot: Client, message: Message):
|
||||
await notification.delete()
|
||||
|
||||
|
||||
@listener(is_plugin=False, outgoing=True, command="del",
|
||||
need_admin=True,
|
||||
description=lang('del_des'))
|
||||
@listener(
|
||||
is_plugin=False,
|
||||
outgoing=True,
|
||||
command="del",
|
||||
need_admin=True,
|
||||
description=lang("del_des"),
|
||||
)
|
||||
async def delete(message: Message):
|
||||
""" Deletes the message you replied to. """
|
||||
"""Deletes the message you replied to."""
|
||||
if target := message.reply_to_message:
|
||||
with contextlib.suppress(Exception):
|
||||
await target.delete()
|
||||
await message.delete()
|
||||
await log(lang('del_notification'))
|
||||
await log(lang("del_notification"))
|
||||
else:
|
||||
await message.delete()
|
||||
|
||||
|
@ -6,11 +6,11 @@ from pagermaid.services import scheduler
|
||||
from pagermaid.utils import lang
|
||||
|
||||
|
||||
@listener(is_plugin=False, command="reload",
|
||||
need_admin=True,
|
||||
description=lang('reload_des'))
|
||||
@listener(
|
||||
is_plugin=False, command="reload", need_admin=True, description=lang("reload_des")
|
||||
)
|
||||
async def reload_plugins(message: Message):
|
||||
""" To reload plugins. """
|
||||
"""To reload plugins."""
|
||||
await reload_all()
|
||||
await message.edit(lang("reload_ok"))
|
||||
|
||||
|
@ -17,7 +17,7 @@ def sentry_before_send(event, hint):
|
||||
exc_info = hint.get("exc_info")
|
||||
if exc_info and isinstance(exc_info[1], (Unauthorized, UsernameInvalid)):
|
||||
# The user has been deleted/deactivated or session revoked
|
||||
safe_remove('pagermaid.session')
|
||||
safe_remove("pagermaid.session")
|
||||
exit(1)
|
||||
if time() <= sentry_sdk_report_time + 30:
|
||||
sentry_sdk_report_time = time()
|
||||
@ -28,7 +28,9 @@ def sentry_before_send(event, hint):
|
||||
|
||||
|
||||
sentry_sdk_report_time = time()
|
||||
sentry_sdk_git_hash = run("git rev-parse HEAD", stdout=PIPE, shell=True).stdout.decode().strip()
|
||||
sentry_sdk_git_hash = (
|
||||
run("git rev-parse HEAD", stdout=PIPE, shell=True).stdout.decode().strip()
|
||||
)
|
||||
sentry_sdk.init(
|
||||
Config.SENTRY_API,
|
||||
traces_sample_rate=1.0,
|
||||
@ -55,9 +57,14 @@ async def sentry_init_id(bot: Client):
|
||||
async def sentry_report(message: Message, command, exc_info, **_):
|
||||
sender_id = message.from_user.id if message.from_user else ""
|
||||
sender_id = message.sender_chat.id if message.sender_chat else sender_id
|
||||
sentry_sdk.set_context("Target", {"ChatID": str(message.chat.id),
|
||||
"UserID": str(sender_id),
|
||||
"Msg": message.text or ""})
|
||||
sentry_sdk.set_context(
|
||||
"Target",
|
||||
{
|
||||
"ChatID": str(message.chat.id),
|
||||
"UserID": str(sender_id),
|
||||
"Msg": message.text or "",
|
||||
},
|
||||
)
|
||||
if command:
|
||||
sentry_sdk.set_tag("com", command)
|
||||
sentry_sdk.capture_exception(exc_info)
|
||||
|
@ -29,43 +29,41 @@ DCs = {
|
||||
2: "149.154.167.51",
|
||||
3: "149.154.175.100",
|
||||
4: "149.154.167.91",
|
||||
5: "91.108.56.130"
|
||||
5: "91.108.56.130",
|
||||
}
|
||||
|
||||
|
||||
@listener(is_plugin=False, command="sysinfo",
|
||||
description=lang('sysinfo_des'))
|
||||
@listener(is_plugin=False, command="sysinfo", description=lang("sysinfo_des"))
|
||||
async def sysinfo(message: Message):
|
||||
""" Retrieve system information via neofetch. """
|
||||
"""Retrieve system information via neofetch."""
|
||||
if not Config.SILENT:
|
||||
message = await message.edit(lang("sysinfo_loading"))
|
||||
if platform == 'win32':
|
||||
if platform == "win32":
|
||||
return await message.edit(neofetch_win(), parse_mode=ParseMode.HTML)
|
||||
result = await execute("neofetch --config none --stdout")
|
||||
await message.edit(f"`{result}`")
|
||||
|
||||
|
||||
@listener(is_plugin=False, command="status",
|
||||
description=lang('status_des'))
|
||||
@listener(is_plugin=False, command="status", description=lang("status_des"))
|
||||
async def status(message: Message):
|
||||
# database
|
||||
# database = lang('status_online') if redis_status() else lang('status_offline')
|
||||
# uptime https://gist.github.com/borgstrom/936ca741e885a1438c374824efb038b3
|
||||
uptime = await get_bot_uptime()
|
||||
text = (f"**{lang('status_hint')}** \n"
|
||||
f"{lang('status_name')}: `{uname().node}` \n"
|
||||
f"{lang('status_platform')}: `{platform}` \n"
|
||||
f"{lang('status_release')}: `{uname().release}` \n"
|
||||
f"{lang('status_python')}: `{python_version()}` \n"
|
||||
f"{lang('status_pyrogram')}: `{__version__}` \n"
|
||||
f"{lang('status_pgm')}: `{pgm_version}`\n"
|
||||
f"{lang('status_uptime')}: `{uptime}`"
|
||||
)
|
||||
text = (
|
||||
f"**{lang('status_hint')}** \n"
|
||||
f"{lang('status_name')}: `{uname().node}` \n"
|
||||
f"{lang('status_platform')}: `{platform}` \n"
|
||||
f"{lang('status_release')}: `{uname().release}` \n"
|
||||
f"{lang('status_python')}: `{python_version()}` \n"
|
||||
f"{lang('status_pyrogram')}: `{__version__}` \n"
|
||||
f"{lang('status_pgm')}: `{pgm_version}`\n"
|
||||
f"{lang('status_uptime')}: `{uptime}`"
|
||||
)
|
||||
await message.edit(text)
|
||||
|
||||
|
||||
@listener(is_plugin=False, command="stats",
|
||||
description=lang("stats_des"))
|
||||
@listener(is_plugin=False, command="stats", description=lang("stats_des"))
|
||||
async def stats(client: Client, message: Message):
|
||||
msg = await message.edit(lang("stats_loading"))
|
||||
a, u, g, s, c, b = 0, 0, 0, 0, 0, 0
|
||||
@ -82,21 +80,21 @@ async def stats(client: Client, message: Message):
|
||||
elif chat_type == ChatType.CHANNEL:
|
||||
c += 1
|
||||
a += 1
|
||||
text = (f"**{lang('stats_hint')}** \n"
|
||||
f"{lang('stats_dialogs')}: `{a}` \n"
|
||||
f"{lang('stats_private')}: `{u}` \n"
|
||||
f"{lang('stats_group')}: `{g}` \n"
|
||||
f"{lang('stats_supergroup')}: `{s}` \n"
|
||||
f"{lang('stats_channel')}: `{c}` \n"
|
||||
f"{lang('stats_bot')}: `{b}`"
|
||||
)
|
||||
text = (
|
||||
f"**{lang('stats_hint')}** \n"
|
||||
f"{lang('stats_dialogs')}: `{a}` \n"
|
||||
f"{lang('stats_private')}: `{u}` \n"
|
||||
f"{lang('stats_group')}: `{g}` \n"
|
||||
f"{lang('stats_supergroup')}: `{s}` \n"
|
||||
f"{lang('stats_channel')}: `{c}` \n"
|
||||
f"{lang('stats_bot')}: `{b}`"
|
||||
)
|
||||
await msg.edit(text)
|
||||
|
||||
|
||||
@listener(is_plugin=False, command="pingdc",
|
||||
description=lang("pingdc_des"))
|
||||
@listener(is_plugin=False, command="pingdc", description=lang("pingdc_des"))
|
||||
async def ping_dc(message: Message):
|
||||
""" Ping your or other data center's IP addresses. """
|
||||
"""Ping your or other data center's IP addresses."""
|
||||
data = []
|
||||
print("1")
|
||||
for dc in range(1, 6):
|
||||
@ -107,7 +105,9 @@ async def ping_dc(message: Message):
|
||||
else:
|
||||
data.append("0")
|
||||
else:
|
||||
result = await execute(f"ping -c 1 {DCs[dc]} | awk -F '/' " + "'END {print $5}'")
|
||||
result = await execute(
|
||||
f"ping -c 1 {DCs[dc]} | awk -F '/' " + "'END {print $5}'"
|
||||
)
|
||||
try:
|
||||
data.append(str(float(result)))
|
||||
except ValueError:
|
||||
@ -121,10 +121,9 @@ async def ping_dc(message: Message):
|
||||
)
|
||||
|
||||
|
||||
@listener(is_plugin=False, command="ping",
|
||||
description=lang("ping_des"))
|
||||
@listener(is_plugin=False, command="ping", description=lang("ping_des"))
|
||||
async def ping(client: Client, message: Message):
|
||||
""" Calculates latency between PagerMaid and Telegram. """
|
||||
"""Calculates latency between PagerMaid and Telegram."""
|
||||
start = datetime.now()
|
||||
await client.invoke(Ping(ping_id=0))
|
||||
end = datetime.now()
|
||||
@ -137,7 +136,7 @@ async def ping(client: Client, message: Message):
|
||||
|
||||
|
||||
def wmic(command: str):
|
||||
""" Fetch the wmic command to cmd """
|
||||
"""Fetch the wmic command to cmd"""
|
||||
try:
|
||||
p = Popen(command.split(" "), stdout=PIPE)
|
||||
except FileNotFoundError:
|
||||
@ -152,7 +151,7 @@ def wmic(command: str):
|
||||
|
||||
|
||||
def get_uptime():
|
||||
""" Get the device uptime """
|
||||
"""Get the device uptime"""
|
||||
delta = round(time() - boot_time())
|
||||
|
||||
hours, remainder = divmod(int(delta), 3600)
|
||||
@ -179,17 +178,17 @@ def get_uptime():
|
||||
return output
|
||||
|
||||
|
||||
def readable(num, suffix='B'):
|
||||
""" Convert Bytes into human-readable formats """
|
||||
for unit in ['', 'Ki', 'Mi', 'Gi', 'Ti', 'Pi', 'Ei', 'Zi']:
|
||||
def readable(num, suffix="B"):
|
||||
"""Convert Bytes into human-readable formats"""
|
||||
for unit in ["", "Ki", "Mi", "Gi", "Ti", "Pi", "Ei", "Zi"]:
|
||||
if abs(num) < 1024.0:
|
||||
return "%3.1f%s%s" % (num, unit, suffix)
|
||||
num /= 1024.0
|
||||
return "%.1f%s%s" % (num, 'Yi', suffix)
|
||||
return "%.1f%s%s" % (num, "Yi", suffix)
|
||||
|
||||
|
||||
def get_ram():
|
||||
""" Get RAM used/free/total """
|
||||
"""Get RAM used/free/total"""
|
||||
ram = virtual_memory()
|
||||
used = readable(ram.used)
|
||||
total = readable(ram.total)
|
||||
@ -200,7 +199,7 @@ def get_ram():
|
||||
|
||||
|
||||
def partitions():
|
||||
""" Find the disk partitions on current OS """
|
||||
"""Find the disk partitions on current OS"""
|
||||
parts = disk_partitions()
|
||||
listparts = []
|
||||
|
||||
@ -208,7 +207,9 @@ def partitions():
|
||||
try:
|
||||
total, used, free = disk_usage(g.device)
|
||||
percent_used = round(used / total * 100, 2)
|
||||
listparts.append(f" {g.device[:2]} {readable(used)} / {readable(total)} ({percent_used}%)")
|
||||
listparts.append(
|
||||
f" {g.device[:2]} {readable(used)} / {readable(total)} ({percent_used}%)"
|
||||
)
|
||||
except PermissionError:
|
||||
continue
|
||||
|
||||
@ -228,11 +229,11 @@ def neofetch_win():
|
||||
mboard = "Unknown..."
|
||||
cpu = wmic("wmic cpu get name")[-1]
|
||||
gpu = wmic("wmic path win32_VideoController get name")
|
||||
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()
|
||||
disks = '\n'.join(partitions())
|
||||
disks = "\n".join(partitions())
|
||||
return (
|
||||
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"<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>"
|
||||
)
|
||||
|
@ -1,8 +1,15 @@
|
||||
from pagermaid.single_utils import sqlite
|
||||
from pagermaid.listener import listener
|
||||
from pagermaid.group_manager import add_permission_for_group, Permission, remove_permission_for_group, \
|
||||
add_user_to_group, remove_user_from_group, add_permission_for_user, remove_permission_for_user, \
|
||||
permissions
|
||||
from pagermaid.group_manager import (
|
||||
add_permission_for_group,
|
||||
Permission,
|
||||
remove_permission_for_group,
|
||||
add_user_to_group,
|
||||
remove_user_from_group,
|
||||
add_permission_for_user,
|
||||
remove_permission_for_user,
|
||||
permissions,
|
||||
)
|
||||
from pagermaid.enums import Client, Message
|
||||
from pagermaid.utils import lang, edit_delete, _status_sudo
|
||||
from pagermaid.single_utils import get_sudo_list
|
||||
@ -15,17 +22,20 @@ def from_msg_get_sudo_id(message: Message) -> int:
|
||||
return message.chat.id
|
||||
|
||||
|
||||
@listener(is_plugin=False, command="sudo",
|
||||
need_admin=True,
|
||||
parameters="{on|off|add|remove|gaddp|gaddu|gdelp|gdelu|glist|uaddp|udelp|list}",
|
||||
description=lang('sudo_des'))
|
||||
@listener(
|
||||
is_plugin=False,
|
||||
command="sudo",
|
||||
need_admin=True,
|
||||
parameters="{on|off|add|remove|gaddp|gaddu|gdelp|gdelu|glist|uaddp|udelp|list}",
|
||||
description=lang("sudo_des"),
|
||||
)
|
||||
async def sudo_change(client: Client, message: Message):
|
||||
""" To enable or disable sudo of your userbot. """
|
||||
"""To enable or disable sudo of your userbot."""
|
||||
input_str = message.arguments
|
||||
sudo = get_sudo_list()
|
||||
if input_str == "on":
|
||||
if _status_sudo():
|
||||
return await edit_delete(message, lang('sudo_has_enabled'))
|
||||
return await edit_delete(message, lang("sudo_has_enabled"))
|
||||
sqlite["sudo_enable"] = True
|
||||
text = f"__{lang('sudo_enable')}__\n"
|
||||
if len(sudo) != 0:
|
||||
@ -48,7 +58,7 @@ async def sudo_change(client: Client, message: Message):
|
||||
return await message.edit(
|
||||
text,
|
||||
)
|
||||
await edit_delete(message, lang('sudo_has_disabled'))
|
||||
await edit_delete(message, lang("sudo_has_disabled"))
|
||||
elif input_str == "add":
|
||||
from_id = from_msg_get_sudo_id(message)
|
||||
if from_id in sudo:
|
||||
@ -85,7 +95,9 @@ async def sudo_change(client: Client, message: Message):
|
||||
for j in permissions.get_permissions_for_user(str(i)):
|
||||
text += f" • {'-' if j[2] == 'ejection' else ''}{j[1]}\n"
|
||||
except Exception:
|
||||
text += f"• `{i}` - {' '.join(permissions.get_roles_for_user(str(i)))}\n"
|
||||
text += (
|
||||
f"• `{i}` - {' '.join(permissions.get_roles_for_user(str(i)))}\n"
|
||||
)
|
||||
await message.edit(text)
|
||||
elif len(message.parameter) > 0:
|
||||
if len(message.parameter) == 2:
|
||||
@ -113,20 +125,26 @@ async def sudo_change(client: Client, message: Message):
|
||||
add_permission_for_user(str(from_id), Permission(message.parameter[1]))
|
||||
return await message.edit(lang("sudo_user_add_per"))
|
||||
elif message.parameter[0] == "udelp":
|
||||
remove_permission_for_user(str(from_id), Permission(message.parameter[1]))
|
||||
remove_permission_for_user(
|
||||
str(from_id), Permission(message.parameter[1])
|
||||
)
|
||||
return await message.edit(lang("sudo_user_del_per"))
|
||||
else:
|
||||
return await edit_delete(message, lang('arg_error'))
|
||||
return await edit_delete(message, lang("arg_error"))
|
||||
if len(message.parameter) == 3:
|
||||
if message.parameter[0] == "gaddp":
|
||||
add_permission_for_group(message.parameter[1], Permission(message.parameter[2]))
|
||||
add_permission_for_group(
|
||||
message.parameter[1], Permission(message.parameter[2])
|
||||
)
|
||||
return await message.edit(lang("sudo_group_add_per"))
|
||||
elif message.parameter[0] == "gdelp":
|
||||
remove_permission_for_group(message.parameter[1], Permission(message.parameter[2]))
|
||||
remove_permission_for_group(
|
||||
message.parameter[1], Permission(message.parameter[2])
|
||||
)
|
||||
return await message.edit(lang("sudo_group_del_per"))
|
||||
else:
|
||||
return await edit_delete(message, lang('arg_error'))
|
||||
return await edit_delete(message, lang("arg_error"))
|
||||
else:
|
||||
await edit_delete(message, lang('arg_error'))
|
||||
await edit_delete(message, lang("arg_error"))
|
||||
else:
|
||||
await edit_delete(message, lang('arg_error'))
|
||||
await edit_delete(message, lang("arg_error"))
|
||||
|
@ -11,24 +11,24 @@ from pagermaid.enums import Message
|
||||
from pagermaid.utils import attach_log, execute, lang, upload_attachment
|
||||
|
||||
|
||||
@listener(is_plugin=False, command="sh",
|
||||
need_admin=True,
|
||||
description=lang('sh_des'),
|
||||
parameters=lang('sh_parameters'))
|
||||
@listener(
|
||||
is_plugin=False,
|
||||
command="sh",
|
||||
need_admin=True,
|
||||
description=lang("sh_des"),
|
||||
parameters=lang("sh_parameters"),
|
||||
)
|
||||
async def sh(message: Message):
|
||||
""" Use the command-line from Telegram. """
|
||||
"""Use the command-line from Telegram."""
|
||||
user = getuser()
|
||||
command = message.arguments
|
||||
hostname = node()
|
||||
|
||||
if not command:
|
||||
await message.edit(lang('arg_error'))
|
||||
await message.edit(lang("arg_error"))
|
||||
return
|
||||
|
||||
message = await message.edit(
|
||||
f"`{user}`@{hostname} ~"
|
||||
f"\n> `$` {command}"
|
||||
)
|
||||
message = await message.edit(f"`{user}`@{hostname} ~" f"\n> `$` {command}")
|
||||
|
||||
result = await execute(command)
|
||||
|
||||
@ -38,36 +38,37 @@ async def sh(message: Message):
|
||||
return
|
||||
|
||||
await message.edit(
|
||||
f"`{user}`@{hostname} ~"
|
||||
f"\n> `#` {command}"
|
||||
f"\n`{result}`"
|
||||
f"`{user}`@{hostname} ~" f"\n> `#` {command}" f"\n`{result}`"
|
||||
)
|
||||
else:
|
||||
return
|
||||
|
||||
|
||||
@listener(is_plugin=False, command="restart",
|
||||
need_admin=True,
|
||||
description=lang('restart_des'))
|
||||
@listener(
|
||||
is_plugin=False, command="restart", need_admin=True, description=lang("restart_des")
|
||||
)
|
||||
async def restart(message: Message):
|
||||
""" To re-execute PagerMaid. """
|
||||
"""To re-execute PagerMaid."""
|
||||
if not message.text[0].isalpha():
|
||||
await message.edit(lang('restart_log'))
|
||||
await message.edit(lang("restart_log"))
|
||||
exit(0)
|
||||
|
||||
|
||||
@listener(is_plugin=False, command="eval",
|
||||
need_admin=True,
|
||||
description=lang('eval_des'),
|
||||
parameters=lang('eval_parameters'))
|
||||
@listener(
|
||||
is_plugin=False,
|
||||
command="eval",
|
||||
need_admin=True,
|
||||
description=lang("eval_des"),
|
||||
parameters=lang("eval_parameters"),
|
||||
)
|
||||
async def sh_eval(message: Message):
|
||||
""" Run python commands from Telegram. """
|
||||
"""Run python commands from Telegram."""
|
||||
dev_mode = exists(f"data{sep}dev")
|
||||
try:
|
||||
assert dev_mode
|
||||
cmd = message.text.split(" ", maxsplit=1)[1]
|
||||
except (IndexError, AssertionError):
|
||||
return await message.edit(lang('eval_need_dev'))
|
||||
return await message.edit(lang("eval_need_dev"))
|
||||
final_output = await run_eval(cmd, message)
|
||||
if len(final_output) > 4096:
|
||||
message = await message.edit(f"**>>>** `{cmd}`", parse_mode=ParseMode.MARKDOWN)
|
||||
@ -76,16 +77,21 @@ async def sh_eval(message: Message):
|
||||
await message.edit(final_output)
|
||||
|
||||
|
||||
@listener(is_plugin=False, command="send_log",
|
||||
need_admin=True,
|
||||
description=lang("send_log_des"))
|
||||
@listener(
|
||||
is_plugin=False,
|
||||
command="send_log",
|
||||
need_admin=True,
|
||||
description=lang("send_log_des"),
|
||||
)
|
||||
async def send_log(message: Message):
|
||||
""" Send log to a chat. """
|
||||
"""Send log to a chat."""
|
||||
if not exists("pagermaid.log.txt"):
|
||||
return await message.edit(lang("send_log_not_found"))
|
||||
await upload_attachment("pagermaid.log.txt",
|
||||
message.chat.id,
|
||||
message.reply_to_message_id or message.reply_to_top_message_id,
|
||||
thumb=f"pagermaid{sep}assets{sep}logo.jpg",
|
||||
caption=lang("send_log_caption"))
|
||||
await upload_attachment(
|
||||
"pagermaid.log.txt",
|
||||
message.chat.id,
|
||||
message.reply_to_message_id or message.reply_to_top_message_id,
|
||||
thumb=f"pagermaid{sep}assets{sep}logo.jpg",
|
||||
caption=lang("send_log_caption"),
|
||||
)
|
||||
await message.safe_delete()
|
||||
|
@ -5,11 +5,15 @@ from pagermaid.listener import listener
|
||||
from pagermaid.utils import lang, Message, alias_command
|
||||
|
||||
|
||||
@listener(is_plugin=False, outgoing=True, command=alias_command("update"),
|
||||
need_admin=True,
|
||||
description=lang('update_des'),
|
||||
parameters="<true/debug>")
|
||||
@listener(
|
||||
is_plugin=False,
|
||||
outgoing=True,
|
||||
command=alias_command("update"),
|
||||
need_admin=True,
|
||||
description=lang("update_des"),
|
||||
parameters="<true/debug>",
|
||||
)
|
||||
async def update(message: Message):
|
||||
await update_function(len(message.parameter) > 0)
|
||||
await message.edit(lang('update_success'))
|
||||
await message.edit(lang("update_success"))
|
||||
exit(0)
|
||||
|
@ -14,5 +14,7 @@ async def init_web():
|
||||
from pagermaid.web import app, init_web
|
||||
|
||||
init_web()
|
||||
server = uvicorn.Server(config=uvicorn.Config(app, host=Config.WEB_HOST, port=Config.WEB_PORT))
|
||||
server = uvicorn.Server(
|
||||
config=uvicorn.Config(app, host=Config.WEB_HOST, port=Config.WEB_PORT)
|
||||
)
|
||||
bot.loop.create_task(server.serve())
|
||||
|
@ -19,9 +19,12 @@ async def delete_message(message: Message) -> bool:
|
||||
|
||||
def add_delete_message_job(message: Message, delete_seconds: int = 60):
|
||||
scheduler.add_job(
|
||||
delete_message, "date",
|
||||
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(Config.TIME_ZONE)) + datetime.timedelta(seconds=delete_seconds),
|
||||
replace_existing=True)
|
||||
run_date=datetime.datetime.now(pytz.timezone(Config.TIME_ZONE))
|
||||
+ datetime.timedelta(seconds=delete_seconds),
|
||||
replace_existing=True,
|
||||
)
|
||||
|
@ -6,5 +6,11 @@ from pagermaid.utils import client
|
||||
|
||||
|
||||
def get(name: str):
|
||||
data = {"Client": bot, "Logger": logs, "SqliteDict": sqlite, "AsyncIOScheduler": scheduler, "AsyncClient": client}
|
||||
data = {
|
||||
"Client": bot,
|
||||
"Logger": logs,
|
||||
"SqliteDict": sqlite,
|
||||
"AsyncIOScheduler": scheduler,
|
||||
"AsyncClient": client,
|
||||
}
|
||||
return data.get(name, None)
|
||||
|
@ -9,7 +9,11 @@ from pyrogram import Client as OldClient
|
||||
from pyrogram.types import Chat as OldChat, Message as OldMessage, Dialog
|
||||
|
||||
from pyromod.utils.conversation import Conversation
|
||||
from pyromod.utils.errors import AlreadyInConversationError, TimeoutConversationError, ListenerCanceled
|
||||
from pyromod.utils.errors import (
|
||||
AlreadyInConversationError,
|
||||
TimeoutConversationError,
|
||||
ListenerCanceled,
|
||||
)
|
||||
|
||||
from sqlitedict import SqliteDict
|
||||
|
||||
@ -39,49 +43,54 @@ class Message(OldMessage):
|
||||
chat: "Chat"
|
||||
|
||||
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."""
|
||||
|
||||
def obtain_user(self) -> Optional[int]:
|
||||
""" Obtains a user from either the reply message or command arguments. """
|
||||
"""Obtains a user from either the reply message or command arguments."""
|
||||
|
||||
async def delay_delete(self, delete_seconds: int = 60) -> Optional[bool]:
|
||||
""" Deletes the message after a specified amount of seconds. """
|
||||
"""Deletes the message after a specified amount of seconds."""
|
||||
|
||||
async def safe_delete(self, revoke: bool = True) -> None:
|
||||
""" Safely deletes the message. """
|
||||
"""Safely deletes the message."""
|
||||
|
||||
|
||||
class Client(OldClient):
|
||||
job: Optional[AsyncIOScheduler] = None
|
||||
|
||||
async def listen(self, chat_id, filters=None, timeout=None) -> Optional[Message]:
|
||||
""" Listen for a message in a conversation. """
|
||||
"""Listen for a message in a conversation."""
|
||||
|
||||
async def ask(self, chat_id, text, filters=None, timeout=None, *args, **kwargs) -> Optional[Message]:
|
||||
""" Ask a message in a conversation. """
|
||||
async def ask(
|
||||
self, chat_id, text, filters=None, timeout=None, *args, **kwargs
|
||||
) -> Optional[Message]:
|
||||
"""Ask a message in a conversation."""
|
||||
|
||||
def cancel_listener(self, chat_id):
|
||||
""" Cancel the conversation with the given chat_id. """
|
||||
"""Cancel the conversation with the given chat_id."""
|
||||
|
||||
def cancel_all_listeners(self):
|
||||
""" Cancel all conversations. """
|
||||
"""Cancel all conversations."""
|
||||
|
||||
def conversation(self, chat_id: Union[int, str],
|
||||
once_timeout: int = 60, filters=None) -> Optional[Conversation]:
|
||||
""" Initialize a conversation with the given chat_id. """
|
||||
def conversation(
|
||||
self, chat_id: Union[int, str], once_timeout: int = 60, filters=None
|
||||
) -> Optional[Conversation]:
|
||||
"""Initialize a conversation with the given chat_id."""
|
||||
|
||||
async def get_dialogs_list(self) -> List[Dialog]:
|
||||
""" Get a list of all dialogs. """
|
||||
"""Get a list of all dialogs."""
|
||||
|
||||
|
||||
class Chat(OldChat):
|
||||
is_forum: Optional[bool] = None
|
||||
|
||||
async def listen(self, chat_id, filters=None, timeout=None) -> Optional[Message]:
|
||||
""" Listen for a message in a conversation. """
|
||||
"""Listen for a message in a conversation."""
|
||||
|
||||
async def ask(self, chat_id, text, filters=None, timeout=None, *args, **kwargs) -> Optional[Message]:
|
||||
""" Ask a message in a conversation. """
|
||||
async def ask(
|
||||
self, chat_id, text, filters=None, timeout=None, *args, **kwargs
|
||||
) -> Optional[Message]:
|
||||
"""Ask a message in a conversation."""
|
||||
|
||||
def cancel_listener(self, chat_id):
|
||||
""" Cancel the conversation with the given chat_id. """
|
||||
"""Cancel the conversation with the given chat_id."""
|
||||
|
@ -18,17 +18,17 @@ from pagermaid.single_utils import _status_sudo, get_sudo_list, Message, sqlite
|
||||
|
||||
|
||||
def lang(text: str) -> str:
|
||||
""" i18n """
|
||||
"""i18n"""
|
||||
return Config.lang_dict.get(text, text)
|
||||
|
||||
|
||||
def alias_command(command: str, disallow_alias: bool = False) -> str:
|
||||
""" alias """
|
||||
"""alias"""
|
||||
return command if disallow_alias else Config.alias_dict.get(command, command)
|
||||
|
||||
|
||||
async def attach_report(plaintext, file_name, reply_id=None, caption=None):
|
||||
""" Attach plaintext as logs. """
|
||||
"""Attach plaintext as logs."""
|
||||
with open(file_name, "w+") as file:
|
||||
file.write(plaintext)
|
||||
try:
|
||||
@ -36,7 +36,7 @@ async def attach_report(plaintext, file_name, reply_id=None, caption=None):
|
||||
"PagerMaid_Modify_bot",
|
||||
file_name,
|
||||
reply_to_message_id=reply_id,
|
||||
caption=caption
|
||||
caption=caption,
|
||||
)
|
||||
except Exception: # noqa
|
||||
return
|
||||
@ -44,20 +44,17 @@ 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):
|
||||
""" Attach plaintext as logs. """
|
||||
with open(file_name, "w+", encoding='utf-8') as file:
|
||||
"""Attach plaintext as logs."""
|
||||
with open(file_name, "w+", encoding="utf-8") as file:
|
||||
file.write(plaintext)
|
||||
await bot.send_document(
|
||||
chat_id,
|
||||
file_name,
|
||||
reply_to_message_id=reply_id,
|
||||
caption=caption
|
||||
chat_id, file_name, reply_to_message_id=reply_id, caption=caption
|
||||
)
|
||||
remove(file_name)
|
||||
|
||||
|
||||
async def upload_attachment(file_path, chat_id, reply_id, caption=None, thumb=None):
|
||||
""" Uploads a local attachment file. """
|
||||
"""Uploads a local attachment file."""
|
||||
if not exists(file_path):
|
||||
return False
|
||||
try:
|
||||
@ -66,7 +63,7 @@ async def upload_attachment(file_path, chat_id, reply_id, caption=None, thumb=No
|
||||
file_path,
|
||||
thumb=thumb,
|
||||
reply_to_message_id=reply_id,
|
||||
caption=caption
|
||||
caption=caption,
|
||||
)
|
||||
except BaseException as exception:
|
||||
raise exception
|
||||
@ -74,32 +71,31 @@ async def upload_attachment(file_path, chat_id, reply_id, caption=None, thumb=No
|
||||
|
||||
|
||||
async def execute(command, pass_error=True):
|
||||
""" Executes command and returns output, with the option of enabling stderr. """
|
||||
"""Executes command and returns output, with the option of enabling stderr."""
|
||||
executor = await create_subprocess_shell(
|
||||
command,
|
||||
stdout=PIPE,
|
||||
stderr=PIPE,
|
||||
stdin=PIPE
|
||||
command, stdout=PIPE, stderr=PIPE, stdin=PIPE
|
||||
)
|
||||
|
||||
stdout, stderr = await executor.communicate()
|
||||
if pass_error:
|
||||
try:
|
||||
result = str(stdout.decode().strip()) \
|
||||
+ str(stderr.decode().strip())
|
||||
result = str(stdout.decode().strip()) + str(stderr.decode().strip())
|
||||
except UnicodeDecodeError:
|
||||
result = str(stdout.decode('gbk').strip()) \
|
||||
+ str(stderr.decode('gbk').strip())
|
||||
result = str(stdout.decode("gbk").strip()) + str(
|
||||
stderr.decode("gbk").strip()
|
||||
)
|
||||
else:
|
||||
try:
|
||||
result = str(stdout.decode().strip())
|
||||
except UnicodeDecodeError:
|
||||
result = str(stdout.decode('gbk').strip())
|
||||
result = str(stdout.decode("gbk").strip())
|
||||
return result
|
||||
|
||||
|
||||
def pip_install(package: str, version: Optional[str] = "", alias: Optional[str] = "") -> bool:
|
||||
""" Auto install extra pypi packages """
|
||||
def pip_install(
|
||||
package: str, version: Optional[str] = "", alias: Optional[str] = ""
|
||||
) -> bool:
|
||||
"""Auto install extra pypi packages"""
|
||||
if not alias:
|
||||
# when import name is not provided, use package name
|
||||
alias = package
|
||||
@ -110,32 +106,42 @@ def pip_install(package: str, version: Optional[str] = "", alias: Optional[str]
|
||||
return True
|
||||
|
||||
|
||||
async def edit_delete(message: Message,
|
||||
text: str,
|
||||
time: int = 5,
|
||||
parse_mode: Optional["enums.ParseMode"] = None,
|
||||
disable_web_page_preview: bool = None):
|
||||
async def edit_delete(
|
||||
message: Message,
|
||||
text: str,
|
||||
time: int = 5,
|
||||
parse_mode: Optional["enums.ParseMode"] = None,
|
||||
disable_web_page_preview: bool = None,
|
||||
):
|
||||
sudo_users = get_sudo_list()
|
||||
from_id = message.from_user.id if message.from_user else message.sender_chat.id
|
||||
if from_id in sudo_users:
|
||||
reply_to = message.reply_to_message
|
||||
event = (
|
||||
await reply_to.reply(text, disable_web_page_preview=disable_web_page_preview, parse_mode=parse_mode)
|
||||
await reply_to.reply(
|
||||
text,
|
||||
disable_web_page_preview=disable_web_page_preview,
|
||||
parse_mode=parse_mode,
|
||||
)
|
||||
if reply_to
|
||||
else await message.reply(
|
||||
text, disable_web_page_preview=disable_web_page_preview, parse_mode=parse_mode
|
||||
text,
|
||||
disable_web_page_preview=disable_web_page_preview,
|
||||
parse_mode=parse_mode,
|
||||
)
|
||||
)
|
||||
else:
|
||||
event = await message.edit(
|
||||
text, disable_web_page_preview=disable_web_page_preview, parse_mode=parse_mode
|
||||
text,
|
||||
disable_web_page_preview=disable_web_page_preview,
|
||||
parse_mode=parse_mode,
|
||||
)
|
||||
await sleep(time)
|
||||
return await event.delete()
|
||||
|
||||
|
||||
def get_permission_name(is_plugin: bool, need_admin: bool, command: str) -> str:
|
||||
""" Get permission name. """
|
||||
"""Get permission name."""
|
||||
if is_plugin:
|
||||
return f"plugins_root.{command}" if need_admin else f"plugins.{command}"
|
||||
else:
|
||||
@ -147,7 +153,9 @@ def sudo_filter(permission: str):
|
||||
if not _status_sudo():
|
||||
return False
|
||||
try:
|
||||
from_id = message.from_user.id if message.from_user else message.sender_chat.id
|
||||
from_id = (
|
||||
message.from_user.id if message.from_user else message.sender_chat.id
|
||||
)
|
||||
sudo_list = get_sudo_list()
|
||||
if from_id not in sudo_list:
|
||||
if message.chat.id in sudo_list:
|
||||
@ -167,13 +175,15 @@ def from_self(message: Message) -> bool:
|
||||
|
||||
|
||||
def from_msg_get_sudo_uid(message: Message) -> int:
|
||||
""" Get the sudo uid from the message. """
|
||||
"""Get the sudo uid from the message."""
|
||||
from_id = message.from_user.id if message.from_user else message.sender_chat.id
|
||||
return from_id if from_id in get_sudo_list() else message.chat.id
|
||||
|
||||
|
||||
def check_manage_subs(message: Message) -> bool:
|
||||
return from_self(message) or enforce_permission(from_msg_get_sudo_uid(message), "modules.manage_subs")
|
||||
return from_self(message) or enforce_permission(
|
||||
from_msg_get_sudo_uid(message), "modules.manage_subs"
|
||||
)
|
||||
|
||||
|
||||
async def process_exit(start: int, _client, message=None):
|
||||
@ -184,8 +194,13 @@ async def process_exit(start: int, _client, message=None):
|
||||
msg: Message = await _client.get_messages(cid, mid)
|
||||
if msg:
|
||||
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")}')
|
||||
(
|
||||
(msg.text or msg.caption)
|
||||
if msg.from_user.is_self and (msg.text or msg.caption)
|
||||
else ""
|
||||
)
|
||||
+ f'\n\n> {lang("restart_complete")}'
|
||||
)
|
||||
del sqlite["exit_msg"]
|
||||
if message:
|
||||
sqlite["exit_msg"] = {"cid": message.chat.id, "mid": message.id}
|
||||
|
@ -7,13 +7,13 @@ from pagermaid.config import Config
|
||||
from pagermaid.web.api import base_api_router
|
||||
from pagermaid.web.pages import admin_app, login_page
|
||||
|
||||
requestAdaptor = '''
|
||||
requestAdaptor = """
|
||||
requestAdaptor(api) {
|
||||
api.headers["token"] = localStorage.getItem("token");
|
||||
return api;
|
||||
},
|
||||
'''
|
||||
responseAdaptor = '''
|
||||
"""
|
||||
responseAdaptor = """
|
||||
responseAdaptor(api, payload, query, request, response) {
|
||||
if (response.data.detail == '登录验证失败或已失效,请重新登录') {
|
||||
window.location.href = '/login'
|
||||
@ -23,8 +23,8 @@ responseAdaptor(api, payload, query, request, response) {
|
||||
}
|
||||
return payload
|
||||
},
|
||||
'''
|
||||
icon_path = 'https://xtaolabs.com/pagermaid-logo.png'
|
||||
"""
|
||||
icon_path = "https://xtaolabs.com/pagermaid-logo.png"
|
||||
app: FastAPI = FastAPI()
|
||||
|
||||
|
||||
@ -36,25 +36,25 @@ def init_web():
|
||||
allow_origins=Config.WEB_ORIGINS,
|
||||
allow_credentials=True,
|
||||
allow_methods=["*"],
|
||||
allow_headers=["*"]
|
||||
allow_headers=["*"],
|
||||
)
|
||||
|
||||
@app.get('/', response_class=RedirectResponse)
|
||||
@app.get("/", response_class=RedirectResponse)
|
||||
async def index():
|
||||
return '/admin'
|
||||
return "/admin"
|
||||
|
||||
@app.get('/admin', response_class=HTMLResponse)
|
||||
@app.get("/admin", response_class=HTMLResponse)
|
||||
async def admin():
|
||||
return admin_app.render(
|
||||
site_title='PagerMaid-Pyro 后台管理',
|
||||
site_title="PagerMaid-Pyro 后台管理",
|
||||
site_icon=icon_path,
|
||||
requestAdaptor=requestAdaptor,
|
||||
responseAdaptor=responseAdaptor
|
||||
responseAdaptor=responseAdaptor,
|
||||
)
|
||||
|
||||
@app.get('/login', response_class=HTMLResponse)
|
||||
@app.get("/login", response_class=HTMLResponse)
|
||||
async def login():
|
||||
return login_page.render(
|
||||
site_title='登录 | PagerMaid-Pyro 后台管理',
|
||||
site_title="登录 | PagerMaid-Pyro 后台管理",
|
||||
site_icon=icon_path,
|
||||
)
|
||||
|
@ -8,7 +8,7 @@ from pagermaid.web.api.login import route as login_route
|
||||
from pagermaid.web.api.plugin import route as plugin_route
|
||||
from pagermaid.web.api.status import route as status_route
|
||||
|
||||
base_api_router = APIRouter(prefix='/pagermaid/api')
|
||||
base_api_router = APIRouter(prefix="/pagermaid/api")
|
||||
|
||||
base_api_router.include_router(plugin_route)
|
||||
base_api_router.include_router(bot_info_route)
|
||||
|
@ -10,16 +10,15 @@ from pagermaid.common.update import update
|
||||
route = APIRouter()
|
||||
|
||||
|
||||
@route.post('/bot_update', response_class=JSONResponse, dependencies=[authentication()])
|
||||
@route.post("/bot_update", response_class=JSONResponse, dependencies=[authentication()])
|
||||
async def bot_update():
|
||||
await update()
|
||||
return {
|
||||
"status": 0,
|
||||
"msg": "更新成功,请重启 PagerMaid-Pyro 以应用更新。"
|
||||
}
|
||||
return {"status": 0, "msg": "更新成功,请重启 PagerMaid-Pyro 以应用更新。"}
|
||||
|
||||
|
||||
@route.post('/bot_restart', response_class=JSONResponse, dependencies=[authentication()])
|
||||
@route.post(
|
||||
"/bot_restart", response_class=JSONResponse, dependencies=[authentication()]
|
||||
)
|
||||
async def bot_restart():
|
||||
os.kill(os.getpid(), signal.SIGINT)
|
||||
return {}
|
||||
|
@ -7,41 +7,41 @@ from pagermaid.web.api.utils import authentication
|
||||
route = APIRouter()
|
||||
|
||||
|
||||
@route.get('/command_alias', response_class=JSONResponse, dependencies=[authentication()])
|
||||
@route.get(
|
||||
"/command_alias", response_class=JSONResponse, dependencies=[authentication()]
|
||||
)
|
||||
async def get_command_alias():
|
||||
alias = AliasManager()
|
||||
return {
|
||||
'status': 0,
|
||||
'msg': 'ok',
|
||||
'data': {
|
||||
'items': alias.get_all_alias_dict(),
|
||||
}
|
||||
"status": 0,
|
||||
"msg": "ok",
|
||||
"data": {
|
||||
"items": alias.get_all_alias_dict(),
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
@route.post('/command_alias', response_class=JSONResponse, dependencies=[authentication()])
|
||||
@route.post(
|
||||
"/command_alias", response_class=JSONResponse, dependencies=[authentication()]
|
||||
)
|
||||
async def add_command_alias(data: dict):
|
||||
data = data['items']
|
||||
data = data["items"]
|
||||
try:
|
||||
await AliasManager.save_from_web(data)
|
||||
return {
|
||||
'status': 0,
|
||||
'msg': '命令别名保存成功'
|
||||
}
|
||||
return {"status": 0, "msg": "命令别名保存成功"}
|
||||
except Exception:
|
||||
return {
|
||||
'status': 1,
|
||||
'msg': '命令别名保存失败'
|
||||
}
|
||||
return {"status": 1, "msg": "命令别名保存失败"}
|
||||
|
||||
|
||||
@route.get('/test_command_alias', response_class=JSONResponse, dependencies=[authentication()])
|
||||
@route.get(
|
||||
"/test_command_alias", response_class=JSONResponse, dependencies=[authentication()]
|
||||
)
|
||||
async def test_command_alias(message: str):
|
||||
alias = AliasManager()
|
||||
return {
|
||||
'status': 0,
|
||||
'msg': '测试成功',
|
||||
'data': {
|
||||
'new_msg': alias.test_alias(message),
|
||||
}
|
||||
"status": 0,
|
||||
"msg": "测试成功",
|
||||
"data": {
|
||||
"new_msg": alias.test_alias(message),
|
||||
},
|
||||
}
|
||||
|
@ -7,39 +7,40 @@ from pagermaid.web.api import authentication
|
||||
route = APIRouter()
|
||||
|
||||
|
||||
@route.get("/get_ignore_group_list", response_class=JSONResponse, dependencies=[authentication()])
|
||||
@route.get(
|
||||
"/get_ignore_group_list",
|
||||
response_class=JSONResponse,
|
||||
dependencies=[authentication()],
|
||||
)
|
||||
async def get_ignore_group_list():
|
||||
try:
|
||||
groups = []
|
||||
for data in await get_group_list():
|
||||
data["status"] = ignore_groups_manager.check_id(data["id"])
|
||||
groups.append(data)
|
||||
return {
|
||||
'status': 0,
|
||||
'msg': 'ok',
|
||||
'data': {
|
||||
'groups': groups
|
||||
}
|
||||
}
|
||||
return {"status": 0, "msg": "ok", "data": {"groups": groups}}
|
||||
except BaseException:
|
||||
return {
|
||||
'status': -100,
|
||||
'msg': '获取群组列表失败'
|
||||
}
|
||||
return {"status": -100, "msg": "获取群组列表失败"}
|
||||
|
||||
|
||||
@route.post('/set_ignore_group_status', response_class=JSONResponse, dependencies=[authentication()])
|
||||
@route.post(
|
||||
"/set_ignore_group_status",
|
||||
response_class=JSONResponse,
|
||||
dependencies=[authentication()],
|
||||
)
|
||||
async def set_ignore_group_status(data: dict):
|
||||
cid: int = data.get('id')
|
||||
status: bool = data.get('status')
|
||||
cid: int = data.get("id")
|
||||
status: bool = data.get("status")
|
||||
if status:
|
||||
ignore_groups_manager.add_id(cid)
|
||||
else:
|
||||
ignore_groups_manager.del_id(cid)
|
||||
return {'status': 0, 'msg': f'成功{"忽略" if status else "取消忽略"} {cid}'}
|
||||
return {"status": 0, "msg": f'成功{"忽略" if status else "取消忽略"} {cid}'}
|
||||
|
||||
|
||||
@route.post('/clear_ignore_group', response_class=JSONResponse, dependencies=[authentication()])
|
||||
@route.post(
|
||||
"/clear_ignore_group", response_class=JSONResponse, dependencies=[authentication()]
|
||||
)
|
||||
async def clear_ignore_group():
|
||||
ignore_groups_manager.clear_subs()
|
||||
return {'status': 0, 'msg': '成功清空忽略列表'}
|
||||
return {"status": 0, "msg": "成功清空忽略列表"}
|
||||
|
@ -14,19 +14,13 @@ class UserModel(BaseModel):
|
||||
route = APIRouter()
|
||||
|
||||
|
||||
@route.post('/login', response_class=JSONResponse)
|
||||
@route.post("/login", response_class=JSONResponse)
|
||||
async def login(user: UserModel):
|
||||
if user.password != Config.WEB_SECRET_KEY:
|
||||
return {
|
||||
"status": -100,
|
||||
"msg": "登录失败,请重新输入密钥"
|
||||
}
|
||||
return {"status": -100, "msg": "登录失败,请重新输入密钥"}
|
||||
token = create_token()
|
||||
return {
|
||||
"status": 0,
|
||||
"msg": "登录成功",
|
||||
"data": {
|
||||
"version": pgm_version_code,
|
||||
"token": token
|
||||
}
|
||||
"msg": "登录成功",
|
||||
"data": {"version": pgm_version_code, "token": token},
|
||||
}
|
||||
|
@ -8,68 +8,68 @@ from pagermaid.web.api.utils import authentication
|
||||
route = APIRouter()
|
||||
|
||||
|
||||
@route.get('/get_local_plugins', response_class=JSONResponse, dependencies=[authentication()])
|
||||
@route.get(
|
||||
"/get_local_plugins", response_class=JSONResponse, dependencies=[authentication()]
|
||||
)
|
||||
async def get_local_plugins():
|
||||
plugins = [i.dict() for i in plugin_manager.plugins]
|
||||
plugins.sort(key=lambda x: x['name'])
|
||||
return {
|
||||
'status': 0,
|
||||
'msg': 'ok',
|
||||
'data': {
|
||||
'rows': plugins,
|
||||
'total': len(plugins)
|
||||
}
|
||||
}
|
||||
plugins.sort(key=lambda x: x["name"])
|
||||
return {"status": 0, "msg": "ok", "data": {"rows": plugins, "total": len(plugins)}}
|
||||
|
||||
|
||||
@route.post('/set_local_plugin_status', response_class=JSONResponse, dependencies=[authentication()])
|
||||
@route.post(
|
||||
"/set_local_plugin_status",
|
||||
response_class=JSONResponse,
|
||||
dependencies=[authentication()],
|
||||
)
|
||||
async def set_local_plugin_status(data: dict):
|
||||
module_name: str = data.get('plugin')
|
||||
status: bool = data.get('status')
|
||||
module_name: str = data.get("plugin")
|
||||
status: bool = data.get("status")
|
||||
if not (plugin := plugin_manager.get_local_plugin(module_name)):
|
||||
return {'status': -100, 'msg': f'插件 {module_name} 不存在'}
|
||||
return {"status": -100, "msg": f"插件 {module_name} 不存在"}
|
||||
if status:
|
||||
plugin.enable()
|
||||
else:
|
||||
plugin.disable()
|
||||
await reload_all()
|
||||
return {'status': 0, 'msg': f'成功{"开启" if status else "关闭"} {module_name}'}
|
||||
return {"status": 0, "msg": f'成功{"开启" if status else "关闭"} {module_name}'}
|
||||
|
||||
|
||||
@route.post('/remove_local_plugin', response_class=JSONResponse, dependencies=[authentication()])
|
||||
@route.post(
|
||||
"/remove_local_plugin", response_class=JSONResponse, dependencies=[authentication()]
|
||||
)
|
||||
async def remove_local_plugin(data: dict):
|
||||
module_name: str = data.get('plugin')
|
||||
module_name: str = data.get("plugin")
|
||||
if not (plugin := plugin_manager.get_local_plugin(module_name)):
|
||||
return {'status': -100, 'msg': f'插件 {module_name} 不存在'}
|
||||
return {"status": -100, "msg": f"插件 {module_name} 不存在"}
|
||||
plugin_manager.remove_plugin(plugin.name)
|
||||
await reload_all()
|
||||
return {'status': 0, 'msg': f'成功卸载 {module_name}'}
|
||||
return {"status": 0, "msg": f"成功卸载 {module_name}"}
|
||||
|
||||
|
||||
@route.get('/get_remote_plugins', response_class=JSONResponse, dependencies=[authentication()])
|
||||
@route.get(
|
||||
"/get_remote_plugins", response_class=JSONResponse, dependencies=[authentication()]
|
||||
)
|
||||
async def get_remote_plugins():
|
||||
await plugin_manager.load_remote_plugins()
|
||||
plugins = [i.dict() for i in plugin_manager.remote_plugins]
|
||||
plugins.sort(key=lambda x: x['name'])
|
||||
return {
|
||||
'status': 0,
|
||||
'msg': 'ok',
|
||||
'data': {
|
||||
'rows': plugins,
|
||||
'total': len(plugins)
|
||||
}
|
||||
}
|
||||
plugins.sort(key=lambda x: x["name"])
|
||||
return {"status": 0, "msg": "ok", "data": {"rows": plugins, "total": len(plugins)}}
|
||||
|
||||
|
||||
@route.post('/set_remote_plugin_status', response_class=JSONResponse, dependencies=[authentication()])
|
||||
@route.post(
|
||||
"/set_remote_plugin_status",
|
||||
response_class=JSONResponse,
|
||||
dependencies=[authentication()],
|
||||
)
|
||||
async def set_remote_plugin_status(data: dict):
|
||||
module_name: str = data.get('plugin')
|
||||
status: bool = data.get('status')
|
||||
module_name: str = data.get("plugin")
|
||||
status: bool = data.get("status")
|
||||
if not plugin_manager.get_remote_plugin(module_name):
|
||||
return {'status': 1, 'msg': f'插件 {module_name} 不存在'}
|
||||
return {"status": 1, "msg": f"插件 {module_name} 不存在"}
|
||||
if status:
|
||||
await plugin_manager.install_remote_plugin(module_name)
|
||||
else:
|
||||
plugin_manager.remove_plugin(module_name)
|
||||
await reload_all()
|
||||
return {'status': 0, 'msg': f'成功{"开启" if status else "关闭"} {module_name}'}
|
||||
return {"status": 0, "msg": f'成功{"开启" if status else "关闭"} {module_name}'}
|
||||
|
@ -13,7 +13,7 @@ from pagermaid.web.api.utils import authentication
|
||||
route = APIRouter()
|
||||
|
||||
|
||||
@route.get('/log')
|
||||
@route.get("/log")
|
||||
async def get_log(token: Optional[str] = Header(...), num: Union[int, str] = 100):
|
||||
if token != Config.WEB_SECRET_KEY:
|
||||
return "非法请求"
|
||||
@ -31,8 +31,8 @@ async def get_log(token: Optional[str] = Header(...), num: Union[int, str] = 100
|
||||
return StreamingResponse(streaming_logs())
|
||||
|
||||
|
||||
@route.get('/run_eval')
|
||||
async def run_cmd(token: Optional[str] = Header(...), cmd: str = ''):
|
||||
@route.get("/run_eval")
|
||||
async def run_cmd(token: Optional[str] = Header(...), cmd: str = ""):
|
||||
if token != Config.WEB_SECRET_KEY:
|
||||
return "非法请求"
|
||||
|
||||
@ -45,8 +45,8 @@ async def run_cmd(token: Optional[str] = Header(...), cmd: str = ''):
|
||||
return StreamingResponse(run_cmd_func()) if cmd else "无效命令"
|
||||
|
||||
|
||||
@route.get('/run_sh')
|
||||
async def run_sh(token: Optional[str] = Header(...), cmd: str = ''):
|
||||
@route.get("/run_sh")
|
||||
async def run_sh(token: Optional[str] = Header(...), cmd: str = ""):
|
||||
if token != Config.WEB_SECRET_KEY:
|
||||
return "非法请求"
|
||||
|
||||
@ -59,6 +59,6 @@ async def run_sh(token: Optional[str] = Header(...), cmd: str = ''):
|
||||
return StreamingResponse(run_sh_func()) if cmd else "无效命令"
|
||||
|
||||
|
||||
@route.get('/status', response_class=JSONResponse, dependencies=[authentication()])
|
||||
@route.get("/status", response_class=JSONResponse, dependencies=[authentication()])
|
||||
async def status():
|
||||
return (await get_status()).dict()
|
||||
|
@ -6,7 +6,7 @@ from jose import jwt
|
||||
|
||||
from pagermaid.config import Config
|
||||
|
||||
ALGORITHM = 'HS256'
|
||||
ALGORITHM = "HS256"
|
||||
TOKEN_EXPIRE_MINUTES = 30
|
||||
|
||||
|
||||
@ -18,13 +18,14 @@ def authentication():
|
||||
try:
|
||||
jwt.decode(token, Config.WEB_SECRET_KEY, algorithms=ALGORITHM)
|
||||
except (jwt.JWTError, jwt.ExpiredSignatureError, AttributeError):
|
||||
raise HTTPException(status_code=400, detail='登录验证失败或已失效,请重新登录')
|
||||
raise HTTPException(status_code=400, detail="登录验证失败或已失效,请重新登录")
|
||||
|
||||
return Depends(inner)
|
||||
|
||||
|
||||
def create_token():
|
||||
data = {
|
||||
"exp": datetime.datetime.now(datetime.timezone.utc) + datetime.timedelta(minutes=TOKEN_EXPIRE_MINUTES),
|
||||
"exp": datetime.datetime.now(datetime.timezone.utc)
|
||||
+ datetime.timedelta(minutes=TOKEN_EXPIRE_MINUTES),
|
||||
}
|
||||
return jwt.encode(data, Config.WEB_SECRET_KEY, algorithm=ALGORITHM)
|
||||
|
@ -5,20 +5,20 @@ html_base_path = Path(__file__).parent
|
||||
|
||||
def get_html(path: Path) -> str:
|
||||
"""获取 HTML 模板。"""
|
||||
with open(path, 'r', encoding='utf-8') as f:
|
||||
with open(path, "r", encoding="utf-8") as f:
|
||||
return f.read()
|
||||
|
||||
|
||||
def get_logo() -> str:
|
||||
"""获取 logo。"""
|
||||
return get_html(html_base_path / 'logo.html')
|
||||
return get_html(html_base_path / "logo.html")
|
||||
|
||||
|
||||
def get_github_logo() -> str:
|
||||
"""获取 github logo。"""
|
||||
return get_html(html_base_path / 'github_logo.html')
|
||||
return get_html(html_base_path / "github_logo.html")
|
||||
|
||||
|
||||
def get_footer() -> str:
|
||||
"""获取 footer。"""
|
||||
return get_html(html_base_path / 'footer.html')
|
||||
return get_html(html_base_path / "footer.html")
|
||||
|
@ -1,50 +1,52 @@
|
||||
from amis import Form, InputSubForm, InputText, Static, Alert, PageSchema, Page
|
||||
|
||||
main_form = Form(
|
||||
title='命令别名',
|
||||
initApi='get:/pagermaid/api/command_alias',
|
||||
api='post:/pagermaid/api/command_alias',
|
||||
submitText='保存',
|
||||
title="命令别名",
|
||||
initApi="get:/pagermaid/api/command_alias",
|
||||
api="post:/pagermaid/api/command_alias",
|
||||
submitText="保存",
|
||||
body=[
|
||||
InputSubForm(
|
||||
name='items',
|
||||
label='已设置的命令别名',
|
||||
name="items",
|
||||
label="已设置的命令别名",
|
||||
multiple=True,
|
||||
btnLabel='${alias} >> ${command}',
|
||||
btnLabel="${alias} >> ${command}",
|
||||
draggable=True,
|
||||
addable=True,
|
||||
removable=True,
|
||||
addButtonText='添加命令别名',
|
||||
addButtonText="添加命令别名",
|
||||
showErrorMsg=False,
|
||||
form=Form(
|
||||
title='命令别名',
|
||||
title="命令别名",
|
||||
body=[
|
||||
InputText(name='alias', label='命令别名', required=True),
|
||||
InputText(name='command', label='原命令', required=True),
|
||||
]
|
||||
)
|
||||
InputText(name="alias", label="命令别名", required=True),
|
||||
InputText(name="command", label="原命令", required=True),
|
||||
],
|
||||
),
|
||||
)
|
||||
]
|
||||
],
|
||||
)
|
||||
|
||||
test_form = Form(
|
||||
title='测试',
|
||||
api='get:/pagermaid/api/test_command_alias?message=${message}',
|
||||
submitText='测试',
|
||||
title="测试",
|
||||
api="get:/pagermaid/api/test_command_alias?message=${message}",
|
||||
submitText="测试",
|
||||
body=[
|
||||
InputText(name='message', label='测试消息(无需输入逗号前缀)', required=True),
|
||||
Static(className='text-red-600', name='new_msg', label='命令别名修改后消息',
|
||||
visibleOn="typeof data.new_msg !== 'undefined'")
|
||||
]
|
||||
InputText(name="message", label="测试消息(无需输入逗号前缀)", required=True),
|
||||
Static(
|
||||
className="text-red-600",
|
||||
name="new_msg",
|
||||
label="命令别名修改后消息",
|
||||
visibleOn="typeof data.new_msg !== 'undefined'",
|
||||
),
|
||||
],
|
||||
)
|
||||
|
||||
tips = Alert(level='info')
|
||||
tips = Alert(level="info")
|
||||
|
||||
page = PageSchema(
|
||||
url='/bot_config/command_alias',
|
||||
icon='fa fa-link', label='命令别名',
|
||||
schema=Page(
|
||||
title='',
|
||||
body=[tips, main_form, test_form]
|
||||
)
|
||||
url="/bot_config/command_alias",
|
||||
icon="fa fa-link",
|
||||
label="命令别名",
|
||||
schema=Page(title="", body=[tips, main_form, test_form]),
|
||||
)
|
||||
|
@ -1,49 +1,50 @@
|
||||
from amis import Page, PageSchema, Html, Property, Service, Flex, ActionType, LevelEnum, Divider, Log, Alert, Form, \
|
||||
Dialog, Select, Group, InputText, DisplayModeEnum, Horizontal
|
||||
from amis import (
|
||||
Page,
|
||||
PageSchema,
|
||||
Html,
|
||||
Property,
|
||||
Service,
|
||||
Flex,
|
||||
ActionType,
|
||||
LevelEnum,
|
||||
Divider,
|
||||
Log,
|
||||
Alert,
|
||||
Form,
|
||||
Dialog,
|
||||
Select,
|
||||
Group,
|
||||
InputText,
|
||||
DisplayModeEnum,
|
||||
Horizontal,
|
||||
)
|
||||
|
||||
from pagermaid.config import Config
|
||||
from pagermaid.web.html import get_logo
|
||||
|
||||
logo = Html(html=get_logo())
|
||||
select_log_num = Select(
|
||||
label='日志数量',
|
||||
name='log_num',
|
||||
label="日志数量",
|
||||
name="log_num",
|
||||
value=100,
|
||||
options=[
|
||||
{
|
||||
'label': 100,
|
||||
'value': 100
|
||||
},
|
||||
{
|
||||
'label': 200,
|
||||
'value': 200
|
||||
},
|
||||
{
|
||||
'label': 300,
|
||||
'value': 300
|
||||
},
|
||||
{
|
||||
'label': 400,
|
||||
'value': 400
|
||||
},
|
||||
{
|
||||
'label': 500,
|
||||
'value': 500
|
||||
}
|
||||
]
|
||||
{"label": 100, "value": 100},
|
||||
{"label": 200, "value": 200},
|
||||
{"label": 300, "value": 300},
|
||||
{"label": 400, "value": 400},
|
||||
{"label": 500, "value": 500},
|
||||
],
|
||||
)
|
||||
|
||||
log_page = Log(
|
||||
autoScroll=True,
|
||||
placeholder='暂无日志数据...',
|
||||
operation=['stop', 'showLineNumber', 'filter'],
|
||||
placeholder="暂无日志数据...",
|
||||
operation=["stop", "showLineNumber", "filter"],
|
||||
source={
|
||||
'method': 'get',
|
||||
'url': '/pagermaid/api/log?num=${log_num | raw}',
|
||||
'headers': {
|
||||
'token': Config.WEB_SECRET_KEY
|
||||
}
|
||||
}
|
||||
"method": "get",
|
||||
"url": "/pagermaid/api/log?num=${log_num | raw}",
|
||||
"headers": {"token": Config.WEB_SECRET_KEY},
|
||||
},
|
||||
)
|
||||
|
||||
cmd_input = Form(
|
||||
@ -51,132 +52,126 @@ cmd_input = Form(
|
||||
horizontal=Horizontal(left=0),
|
||||
wrapWithPanel=False,
|
||||
body=[
|
||||
InputText(name='command', required=True, clearable=True, addOn=ActionType.Dialog(
|
||||
label='执行',
|
||||
level=LevelEnum.primary,
|
||||
dialog=Dialog(
|
||||
title='命令执行结果',
|
||||
size='xl',
|
||||
body=Log(
|
||||
autoScroll=True,
|
||||
placeholder='执行命令中,请稍候...',
|
||||
operation=['stop', 'showLineNumber', 'filter'],
|
||||
source={
|
||||
'method': 'get',
|
||||
'url': '/pagermaid/api/run_sh?cmd=${command | raw}',
|
||||
'headers': {
|
||||
'token': Config.WEB_SECRET_KEY
|
||||
}
|
||||
}),
|
||||
)
|
||||
))
|
||||
]
|
||||
InputText(
|
||||
name="command",
|
||||
required=True,
|
||||
clearable=True,
|
||||
addOn=ActionType.Dialog(
|
||||
label="执行",
|
||||
level=LevelEnum.primary,
|
||||
dialog=Dialog(
|
||||
title="命令执行结果",
|
||||
size="xl",
|
||||
body=Log(
|
||||
autoScroll=True,
|
||||
placeholder="执行命令中,请稍候...",
|
||||
operation=["stop", "showLineNumber", "filter"],
|
||||
source={
|
||||
"method": "get",
|
||||
"url": "/pagermaid/api/run_sh?cmd=${command | raw}",
|
||||
"headers": {"token": Config.WEB_SECRET_KEY},
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
)
|
||||
],
|
||||
)
|
||||
eval_input = Form(
|
||||
mode=DisplayModeEnum.horizontal,
|
||||
horizontal=Horizontal(left=0),
|
||||
wrapWithPanel=False,
|
||||
body=[
|
||||
InputText(name='command', required=True, clearable=True, addOn=ActionType.Dialog(
|
||||
label='执行',
|
||||
InputText(
|
||||
name="command",
|
||||
required=True,
|
||||
clearable=True,
|
||||
addOn=ActionType.Dialog(
|
||||
label="执行",
|
||||
level=LevelEnum.primary,
|
||||
dialog=Dialog(
|
||||
title="命令执行结果",
|
||||
size="xl",
|
||||
body=Log(
|
||||
autoScroll=True,
|
||||
placeholder="执行命令中,请稍候...",
|
||||
operation=["stop", "showLineNumber", "filter"],
|
||||
source={
|
||||
"method": "get",
|
||||
"url": "/pagermaid/api/run_eval?cmd=${command | raw}",
|
||||
"headers": {"token": Config.WEB_SECRET_KEY},
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
)
|
||||
],
|
||||
)
|
||||
|
||||
operation_button = Flex(
|
||||
justify="center",
|
||||
items=[
|
||||
ActionType.Ajax(
|
||||
label="更新",
|
||||
api="/pagermaid/api/bot_update",
|
||||
confirmText="该操作会更新 PagerMaid-Pyro ,请在更新完成后手动重启,请确认执行该操作",
|
||||
level=LevelEnum.info,
|
||||
),
|
||||
ActionType.Ajax(
|
||||
label="重启",
|
||||
className="m-l",
|
||||
api="/pagermaid/api/bot_restart",
|
||||
confirmText="该操作会重启 PagerMaid-Pyro ,请耐心等待重启",
|
||||
level=LevelEnum.danger,
|
||||
),
|
||||
ActionType.Dialog(
|
||||
label="日志",
|
||||
className="m-l",
|
||||
level=LevelEnum.primary,
|
||||
dialog=Dialog(
|
||||
title='命令执行结果',
|
||||
size='xl',
|
||||
body=Log(
|
||||
autoScroll=True,
|
||||
placeholder='执行命令中,请稍候...',
|
||||
operation=['stop', 'showLineNumber', 'filter'],
|
||||
source={
|
||||
'method': 'get',
|
||||
'url': '/pagermaid/api/run_eval?cmd=${command | raw}',
|
||||
'headers': {
|
||||
'token': Config.WEB_SECRET_KEY
|
||||
}
|
||||
}),
|
||||
)
|
||||
))
|
||||
]
|
||||
title="查看日志",
|
||||
size="xl",
|
||||
actions=[],
|
||||
body=[
|
||||
Alert(
|
||||
level=LevelEnum.info,
|
||||
body='查看最近最多500条日志,不会自动刷新,需要手动点击两次"暂停键"来进行刷新。',
|
||||
),
|
||||
Form(body=[Group(body=[select_log_num]), log_page]),
|
||||
],
|
||||
),
|
||||
),
|
||||
ActionType.Dialog(
|
||||
label="shell",
|
||||
className="m-l",
|
||||
level=LevelEnum.warning,
|
||||
dialog=Dialog(title="shell", size="lg", actions=[], body=[cmd_input]),
|
||||
),
|
||||
ActionType.Dialog(
|
||||
label="eval",
|
||||
className="m-l",
|
||||
level=LevelEnum.warning,
|
||||
dialog=Dialog(title="eval", size="lg", actions=[], body=[eval_input]),
|
||||
),
|
||||
],
|
||||
)
|
||||
|
||||
operation_button = Flex(justify='center', items=[
|
||||
ActionType.Ajax(
|
||||
label='更新',
|
||||
api='/pagermaid/api/bot_update',
|
||||
confirmText='该操作会更新 PagerMaid-Pyro ,请在更新完成后手动重启,请确认执行该操作',
|
||||
level=LevelEnum.info
|
||||
),
|
||||
ActionType.Ajax(
|
||||
label='重启',
|
||||
className='m-l',
|
||||
api='/pagermaid/api/bot_restart',
|
||||
confirmText='该操作会重启 PagerMaid-Pyro ,请耐心等待重启',
|
||||
level=LevelEnum.danger
|
||||
),
|
||||
ActionType.Dialog(
|
||||
label='日志',
|
||||
className='m-l',
|
||||
level=LevelEnum.primary,
|
||||
dialog=Dialog(title='查看日志',
|
||||
size='xl',
|
||||
actions=[],
|
||||
body=[
|
||||
Alert(level=LevelEnum.info,
|
||||
body='查看最近最多500条日志,不会自动刷新,需要手动点击两次"暂停键"来进行刷新。'),
|
||||
Form(
|
||||
body=[Group(body=[select_log_num]), log_page]
|
||||
)])
|
||||
),
|
||||
ActionType.Dialog(
|
||||
label='shell',
|
||||
className='m-l',
|
||||
level=LevelEnum.warning,
|
||||
dialog=Dialog(title='shell',
|
||||
size='lg',
|
||||
actions=[],
|
||||
body=[cmd_input])
|
||||
),
|
||||
ActionType.Dialog(
|
||||
label='eval',
|
||||
className='m-l',
|
||||
level=LevelEnum.warning,
|
||||
dialog=Dialog(title='eval',
|
||||
size='lg',
|
||||
actions=[],
|
||||
body=[eval_input])
|
||||
)
|
||||
])
|
||||
|
||||
status = Service(
|
||||
api='/pagermaid/api/status',
|
||||
api="/pagermaid/api/status",
|
||||
body=Property(
|
||||
title='运行信息',
|
||||
title="运行信息",
|
||||
column=2,
|
||||
items=[
|
||||
Property.Item(
|
||||
label='Bot 版本',
|
||||
content='${version}'
|
||||
),
|
||||
Property.Item(
|
||||
label='Bot 运行时间',
|
||||
content='${run_time}'
|
||||
),
|
||||
Property.Item(
|
||||
label='CPU占用率',
|
||||
content='${cpu_percent}'
|
||||
),
|
||||
Property.Item(
|
||||
label='RAM占用率',
|
||||
content='${ram_percent}'
|
||||
),
|
||||
Property.Item(
|
||||
label='SWAP占用率',
|
||||
content='${swap_percent}',
|
||||
span=2
|
||||
),
|
||||
]
|
||||
)
|
||||
Property.Item(label="Bot 版本", content="${version}"),
|
||||
Property.Item(label="Bot 运行时间", content="${run_time}"),
|
||||
Property.Item(label="CPU占用率", content="${cpu_percent}"),
|
||||
Property.Item(label="RAM占用率", content="${ram_percent}"),
|
||||
Property.Item(label="SWAP占用率", content="${swap_percent}", span=2),
|
||||
],
|
||||
),
|
||||
)
|
||||
|
||||
page_detail = Page(title='', body=[logo, operation_button, Divider(), status])
|
||||
page = PageSchema(url='/home', label='首页', icon='fa fa-home', isDefaultPage=True, schema=page_detail)
|
||||
page_detail = Page(title="", body=[logo, operation_button, Divider(), status])
|
||||
page = PageSchema(
|
||||
url="/home", label="首页", icon="fa fa-home", isDefaultPage=True, schema=page_detail
|
||||
)
|
||||
|
@ -1,63 +1,71 @@
|
||||
from amis import InputText, Switch, Card, Tpl, CardsCRUD, PageSchema, Page, Button, Select
|
||||
from amis import (
|
||||
InputText,
|
||||
Switch,
|
||||
Card,
|
||||
Tpl,
|
||||
CardsCRUD,
|
||||
PageSchema,
|
||||
Page,
|
||||
Button,
|
||||
Select,
|
||||
)
|
||||
|
||||
card = Card(
|
||||
header=Card.Header(
|
||||
title='$title',
|
||||
description='$id',
|
||||
avatarText='$title',
|
||||
avatarTextClassName='overflow-hidden'
|
||||
title="$title",
|
||||
description="$id",
|
||||
avatarText="$title",
|
||||
avatarTextClassName="overflow-hidden",
|
||||
),
|
||||
actions=[],
|
||||
toolbar=[
|
||||
Switch(
|
||||
name='enable',
|
||||
value='${status}',
|
||||
onText='已忽略',
|
||||
offText='未忽略',
|
||||
name="enable",
|
||||
value="${status}",
|
||||
onText="已忽略",
|
||||
offText="未忽略",
|
||||
onEvent={
|
||||
'change': {
|
||||
'actions': {
|
||||
'actionType': 'ajax',
|
||||
'args': {
|
||||
'api': {
|
||||
'url': '/pagermaid/api/set_ignore_group_status',
|
||||
'method': 'post'
|
||||
"change": {
|
||||
"actions": {
|
||||
"actionType": "ajax",
|
||||
"args": {
|
||||
"api": {
|
||||
"url": "/pagermaid/api/set_ignore_group_status",
|
||||
"method": "post",
|
||||
},
|
||||
'messages': {
|
||||
'success': '成功${IF(event.data.value, "忽略", "取消忽略")}了 ${title}',
|
||||
'failed': '操作失败'
|
||||
"messages": {
|
||||
"success": '成功${IF(event.data.value, "忽略", "取消忽略")}了 ${title}',
|
||||
"failed": "操作失败",
|
||||
},
|
||||
'status': '${event.data.value}',
|
||||
'id': '${id}'
|
||||
}
|
||||
"status": "${event.data.value}",
|
||||
"id": "${id}",
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
)
|
||||
]
|
||||
],
|
||||
)
|
||||
cards_curd = CardsCRUD(
|
||||
mode='cards',
|
||||
title='',
|
||||
mode="cards",
|
||||
title="",
|
||||
syncLocation=False,
|
||||
api='/pagermaid/api/get_ignore_group_list',
|
||||
api="/pagermaid/api/get_ignore_group_list",
|
||||
loadDataOnce=True,
|
||||
source='${groups | filter:title:match:keywords_name}',
|
||||
filter={
|
||||
'body': [
|
||||
InputText(name='keywords_name', label='群组名')
|
||||
]
|
||||
},
|
||||
source="${groups | filter:title:match:keywords_name}",
|
||||
filter={"body": [InputText(name="keywords_name", label="群组名")]},
|
||||
perPage=12,
|
||||
autoJumpToTopOnPagerChange=True,
|
||||
placeholder='群组列表为空',
|
||||
footerToolbar=['switch-per-page', 'pagination'],
|
||||
placeholder="群组列表为空",
|
||||
footerToolbar=["switch-per-page", "pagination"],
|
||||
columnsCount=3,
|
||||
card=card
|
||||
card=card,
|
||||
)
|
||||
page = PageSchema(
|
||||
url='/bot_config/ignore_groups',
|
||||
icon='fa fa-ban',
|
||||
label='忽略群组',
|
||||
schema=Page(title='忽略群组', subTitle="忽略后,Bot 不再响应指定群组的消息(群组列表将会缓存一小时)", body=cards_curd)
|
||||
url="/bot_config/ignore_groups",
|
||||
icon="fa fa-ban",
|
||||
label="忽略群组",
|
||||
schema=Page(
|
||||
title="忽略群组", subTitle="忽略后,Bot 不再响应指定群组的消息(群组列表将会缓存一小时)", body=cards_curd
|
||||
),
|
||||
)
|
||||
|
@ -1,32 +1,42 @@
|
||||
from amis import Form, InputPassword, DisplayModeEnum, Horizontal, Remark, Html, Page, AmisAPI, Wrapper
|
||||
from amis import (
|
||||
Form,
|
||||
InputPassword,
|
||||
DisplayModeEnum,
|
||||
Horizontal,
|
||||
Remark,
|
||||
Html,
|
||||
Page,
|
||||
AmisAPI,
|
||||
Wrapper,
|
||||
)
|
||||
|
||||
from pagermaid.web.html import get_logo
|
||||
|
||||
logo = Html(html=get_logo())
|
||||
login_api = AmisAPI(
|
||||
url='/pagermaid/api/login',
|
||||
method='post',
|
||||
adaptor='''
|
||||
url="/pagermaid/api/login",
|
||||
method="post",
|
||||
adaptor="""
|
||||
if (payload.status == 0) {
|
||||
localStorage.setItem("token", payload.data.token);
|
||||
}
|
||||
return payload;
|
||||
'''
|
||||
""",
|
||||
)
|
||||
|
||||
login_form = Form(
|
||||
api=login_api,
|
||||
title='',
|
||||
title="",
|
||||
body=[
|
||||
InputPassword(
|
||||
name='password',
|
||||
label='密码',
|
||||
labelRemark=Remark(shape='circle', content='登录密码')
|
||||
name="password",
|
||||
label="密码",
|
||||
labelRemark=Remark(shape="circle", content="登录密码"),
|
||||
),
|
||||
],
|
||||
mode=DisplayModeEnum.horizontal,
|
||||
horizontal=Horizontal(left=3, right=9, offset=5),
|
||||
redirect='/admin',
|
||||
redirect="/admin",
|
||||
)
|
||||
body = Wrapper(className='w-2/5 mx-auto my-0 m:w-full', body=login_form)
|
||||
login_page = Page(title='', body=[logo, body])
|
||||
body = Wrapper(className="w-2/5 mx-auto my-0 m:w-full", body=login_form)
|
||||
login_page = Page(title="", body=[logo, body])
|
||||
|
@ -8,25 +8,33 @@ from pagermaid.web.pages.plugin_local_manage import page as plugin_local_manage_
|
||||
from pagermaid.web.pages.plugin_remote_manage import page as plugin_remote_manage_page
|
||||
|
||||
github_logo = Tpl(
|
||||
className='w-full',
|
||||
className="w-full",
|
||||
tpl=get_github_logo(),
|
||||
)
|
||||
header = Flex(className='w-full', justify='flex-end', alignItems='flex-end', items=[github_logo])
|
||||
header = Flex(
|
||||
className="w-full", justify="flex-end", alignItems="flex-end", items=[github_logo]
|
||||
)
|
||||
admin_app = App(
|
||||
brandName='pagermaid',
|
||||
logo='https://xtaolabs.com/pagermaid-logo.png',
|
||||
brandName="pagermaid",
|
||||
logo="https://xtaolabs.com/pagermaid-logo.png",
|
||||
header=header,
|
||||
pages=[
|
||||
{
|
||||
'children': [
|
||||
"children": [
|
||||
home_page,
|
||||
PageSchema(label='Bot 设置', icon='fa fa-wrench',
|
||||
children=[command_alias_page, ignore_groups_page]),
|
||||
PageSchema(label='插件管理', icon='fa fa-cube',
|
||||
children=[plugin_local_manage_page, plugin_remote_manage_page]),
|
||||
PageSchema(
|
||||
label="Bot 设置",
|
||||
icon="fa fa-wrench",
|
||||
children=[command_alias_page, ignore_groups_page],
|
||||
),
|
||||
PageSchema(
|
||||
label="插件管理",
|
||||
icon="fa fa-cube",
|
||||
children=[plugin_local_manage_page, plugin_remote_manage_page],
|
||||
),
|
||||
]
|
||||
}
|
||||
],
|
||||
footer=get_footer(),
|
||||
)
|
||||
blank_page = Page(title='PagerMaid-Pyro 404', body='404')
|
||||
blank_page = Page(title="PagerMaid-Pyro 404", body="404")
|
||||
|
@ -2,63 +2,57 @@ from amis import InputText, Switch, Card, CardsCRUD, PageSchema, Page
|
||||
|
||||
card = Card(
|
||||
header=Card.Header(
|
||||
title='$name',
|
||||
avatarText='$name',
|
||||
avatarTextClassName='overflow-hidden'
|
||||
title="$name", avatarText="$name", avatarTextClassName="overflow-hidden"
|
||||
),
|
||||
actions=[],
|
||||
toolbar=[
|
||||
Switch(
|
||||
name='enable',
|
||||
value='${status}',
|
||||
onText='启用',
|
||||
offText='禁用',
|
||||
name="enable",
|
||||
value="${status}",
|
||||
onText="启用",
|
||||
offText="禁用",
|
||||
onEvent={
|
||||
'change': {
|
||||
'actions': [
|
||||
"change": {
|
||||
"actions": [
|
||||
{
|
||||
'actionType': 'ajax',
|
||||
'args': {
|
||||
'api': {
|
||||
'url': '/pagermaid/api/set_local_plugin_status',
|
||||
'method': 'post'
|
||||
"actionType": "ajax",
|
||||
"args": {
|
||||
"api": {
|
||||
"url": "/pagermaid/api/set_local_plugin_status",
|
||||
"method": "post",
|
||||
},
|
||||
'messages': {
|
||||
'success': '成功${IF(event.data.value, "开启", "禁用")}了 ${name}',
|
||||
'failed': '操作失败'
|
||||
"messages": {
|
||||
"success": '成功${IF(event.data.value, "开启", "禁用")}了 ${name}',
|
||||
"failed": "操作失败",
|
||||
},
|
||||
'status': '${event.data.value}',
|
||||
'plugin': '${name}'
|
||||
}
|
||||
"status": "${event.data.value}",
|
||||
"plugin": "${name}",
|
||||
},
|
||||
},
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
)
|
||||
]
|
||||
],
|
||||
)
|
||||
cards_curd = CardsCRUD(
|
||||
mode='cards',
|
||||
title='',
|
||||
mode="cards",
|
||||
title="",
|
||||
syncLocation=False,
|
||||
api='/pagermaid/api/get_local_plugins',
|
||||
api="/pagermaid/api/get_local_plugins",
|
||||
loadDataOnce=True,
|
||||
source='${rows | filter:name:match:keywords_name}',
|
||||
filter={
|
||||
'body': [
|
||||
InputText(name='keywords_name', label='插件名')
|
||||
]
|
||||
},
|
||||
source="${rows | filter:name:match:keywords_name}",
|
||||
filter={"body": [InputText(name="keywords_name", label="插件名")]},
|
||||
perPage=12,
|
||||
autoJumpToTopOnPagerChange=True,
|
||||
placeholder='暂无插件信息',
|
||||
footerToolbar=['switch-per-page', 'pagination'],
|
||||
placeholder="暂无插件信息",
|
||||
footerToolbar=["switch-per-page", "pagination"],
|
||||
columnsCount=3,
|
||||
card=card
|
||||
card=card,
|
||||
)
|
||||
page = PageSchema(
|
||||
url='/plugins/local',
|
||||
icon='fa fa-database',
|
||||
label='本地插件管理',
|
||||
schema=Page(title='本地插件管理', body=cards_curd)
|
||||
url="/plugins/local",
|
||||
icon="fa fa-database",
|
||||
label="本地插件管理",
|
||||
schema=Page(title="本地插件管理", body=cards_curd),
|
||||
)
|
||||
|
@ -2,63 +2,63 @@ from amis import InputText, Switch, Card, Tpl, CardsCRUD, PageSchema, Page, Butt
|
||||
|
||||
card = Card(
|
||||
header=Card.Header(
|
||||
title='$name',
|
||||
description='$des',
|
||||
avatarText='$name',
|
||||
avatarTextClassName='overflow-hidden'
|
||||
title="$name",
|
||||
description="$des",
|
||||
avatarText="$name",
|
||||
avatarTextClassName="overflow-hidden",
|
||||
),
|
||||
actions=[],
|
||||
toolbar=[
|
||||
Switch(
|
||||
name='enable',
|
||||
value='${status}',
|
||||
onText='已安装',
|
||||
offText='未安装',
|
||||
name="enable",
|
||||
value="${status}",
|
||||
onText="已安装",
|
||||
offText="未安装",
|
||||
onEvent={
|
||||
'change': {
|
||||
'actions': {
|
||||
'actionType': 'ajax',
|
||||
'args': {
|
||||
'api': {
|
||||
'url': '/pagermaid/api/set_remote_plugin_status',
|
||||
'method': 'post'
|
||||
"change": {
|
||||
"actions": {
|
||||
"actionType": "ajax",
|
||||
"args": {
|
||||
"api": {
|
||||
"url": "/pagermaid/api/set_remote_plugin_status",
|
||||
"method": "post",
|
||||
},
|
||||
'messages': {
|
||||
'success': '成功${IF(event.data.value, "安装", "卸载")}了 ${name}',
|
||||
'failed': '操作失败'
|
||||
"messages": {
|
||||
"success": '成功${IF(event.data.value, "安装", "卸载")}了 ${name}',
|
||||
"failed": "操作失败",
|
||||
},
|
||||
'status': '${event.data.value}',
|
||||
'plugin': '${name}'
|
||||
}
|
||||
"status": "${event.data.value}",
|
||||
"plugin": "${name}",
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
)
|
||||
]
|
||||
],
|
||||
)
|
||||
cards_curd = CardsCRUD(
|
||||
mode='cards',
|
||||
title='',
|
||||
mode="cards",
|
||||
title="",
|
||||
syncLocation=False,
|
||||
api='/pagermaid/api/get_remote_plugins',
|
||||
api="/pagermaid/api/get_remote_plugins",
|
||||
loadDataOnce=True,
|
||||
source='${rows | filter:name:match:keywords_name | filter:des:match:keywords_description}',
|
||||
source="${rows | filter:name:match:keywords_name | filter:des:match:keywords_description}",
|
||||
filter={
|
||||
'body': [
|
||||
InputText(name='keywords_name', label='插件名'),
|
||||
InputText(name='keywords_description', label='插件描述')
|
||||
"body": [
|
||||
InputText(name="keywords_name", label="插件名"),
|
||||
InputText(name="keywords_description", label="插件描述"),
|
||||
]
|
||||
},
|
||||
perPage=12,
|
||||
autoJumpToTopOnPagerChange=True,
|
||||
placeholder='暂无插件信息',
|
||||
footerToolbar=['switch-per-page', 'pagination'],
|
||||
placeholder="暂无插件信息",
|
||||
footerToolbar=["switch-per-page", "pagination"],
|
||||
columnsCount=3,
|
||||
card=card
|
||||
card=card,
|
||||
)
|
||||
page = PageSchema(
|
||||
url='/plugins/remote',
|
||||
icon='fa fa-cloud-download',
|
||||
label='插件仓库',
|
||||
schema=Page(title='插件仓库', body=cards_curd)
|
||||
url="/plugins/remote",
|
||||
icon="fa fa-cloud-download",
|
||||
label="插件仓库",
|
||||
schema=Page(title="插件仓库", body=cards_curd),
|
||||
)
|
||||
|
@ -22,7 +22,7 @@ import pyrogram
|
||||
|
||||
|
||||
def dice(ctx, message):
|
||||
return hasattr(message, 'dice') and message.dice
|
||||
return hasattr(message, "dice") and message.dice
|
||||
|
||||
|
||||
pyrogram.filters.dice = dice
|
||||
|
@ -54,12 +54,8 @@ class Client:
|
||||
chat_id = chat.id
|
||||
|
||||
future = self.loop.create_future()
|
||||
future.add_done_callback(
|
||||
functools.partial(self.clear_listener, chat_id)
|
||||
)
|
||||
self.listening.update({
|
||||
chat_id: {"future": future, "filters": filters}
|
||||
})
|
||||
future.add_done_callback(functools.partial(self.clear_listener, chat_id))
|
||||
self.listening.update({chat_id: {"future": future, "filters": filters}})
|
||||
try:
|
||||
return await asyncio.wait_for(future, timeout)
|
||||
except asyncio.exceptions.TimeoutError as e:
|
||||
@ -81,11 +77,11 @@ class Client:
|
||||
@patchable
|
||||
def cancel_listener(self, chat_id):
|
||||
listener = self.listening.get(chat_id)
|
||||
if not listener or listener['future'].done():
|
||||
if not listener or listener["future"].done():
|
||||
return
|
||||
|
||||
listener['future'].set_exception(ListenerCanceled())
|
||||
self.clear_listener(chat_id, listener['future'])
|
||||
listener["future"].set_exception(ListenerCanceled())
|
||||
self.clear_listener(chat_id, listener["future"])
|
||||
|
||||
@patchable
|
||||
def cancel_all_listener(self):
|
||||
@ -93,25 +89,25 @@ class Client:
|
||||
self.cancel_listener(chat_id)
|
||||
|
||||
@patchable
|
||||
def conversation(self, chat_id: Union[int, str], once_timeout: int = 60, filters=None):
|
||||
def conversation(
|
||||
self, chat_id: Union[int, str], once_timeout: int = 60, filters=None
|
||||
):
|
||||
return Conversation(self, chat_id, once_timeout, filters)
|
||||
|
||||
@patchable
|
||||
async def read_chat_history(
|
||||
self: "pyrogram.Client",
|
||||
chat_id: Union[int, str],
|
||||
max_id: int = 0
|
||||
self: "pyrogram.Client", chat_id: Union[int, str], max_id: int = 0
|
||||
) -> bool:
|
||||
peer = await self.resolve_peer(chat_id)
|
||||
if isinstance(peer, pyrogram.raw.types.InputPeerChannel):
|
||||
with contextlib.suppress(pyrogram.errors.BadRequest): # noqa
|
||||
with contextlib.suppress(pyrogram.errors.BadRequest): # noqa
|
||||
topics: pyrogram.raw.types.messages.ForumTopics = await self.invoke(
|
||||
pyrogram.raw.functions.channels.GetForumTopics(
|
||||
channel=peer, # noqa
|
||||
channel=peer, # noqa
|
||||
offset_date=0,
|
||||
offset_id=0,
|
||||
offset_topic=0,
|
||||
limit=0
|
||||
limit=0,
|
||||
)
|
||||
)
|
||||
for i in topics.topics:
|
||||
@ -139,25 +135,25 @@ class MessageHandler:
|
||||
@patchable
|
||||
async def resolve_listener(self, client, message, *args):
|
||||
listener = client.listening.get(message.chat.id)
|
||||
if listener and not listener['future'].done():
|
||||
listener['future'].set_result(message)
|
||||
if listener and not listener["future"].done():
|
||||
listener["future"].set_result(message)
|
||||
else:
|
||||
if listener and listener['future'].done():
|
||||
client.clear_listener(message.chat.id, listener['future'])
|
||||
if listener and listener["future"].done():
|
||||
client.clear_listener(message.chat.id, listener["future"])
|
||||
await self.user_callback(client, message, *args)
|
||||
|
||||
@patchable
|
||||
async def check(self, client, update):
|
||||
listener = client.listening.get(update.chat.id)
|
||||
|
||||
if listener and not listener['future'].done():
|
||||
return await listener['filters'](client, update) if callable(listener['filters']) else True
|
||||
if listener and not listener["future"].done():
|
||||
return (
|
||||
await listener["filters"](client, update)
|
||||
if callable(listener["filters"])
|
||||
else True
|
||||
)
|
||||
|
||||
return (
|
||||
await self.filters(client, update)
|
||||
if callable(self.filters)
|
||||
else True
|
||||
)
|
||||
return await self.filters(client, update) if callable(self.filters) else True
|
||||
|
||||
|
||||
@patch(pyrogram.handlers.edited_message_handler.EditedMessageHandler)
|
||||
@ -170,25 +166,25 @@ class EditedMessageHandler:
|
||||
@patchable
|
||||
async def resolve_listener(self, client, message, *args):
|
||||
listener = client.listening.get(message.chat.id)
|
||||
if listener and not listener['future'].done():
|
||||
listener['future'].set_result(message)
|
||||
if listener and not listener["future"].done():
|
||||
listener["future"].set_result(message)
|
||||
else:
|
||||
if listener and listener['future'].done():
|
||||
client.clear_listener(message.chat.id, listener['future'])
|
||||
if listener and listener["future"].done():
|
||||
client.clear_listener(message.chat.id, listener["future"])
|
||||
await self.user_callback(client, message, *args)
|
||||
|
||||
@patchable
|
||||
async def check(self, client, update):
|
||||
listener = client.listening.get(update.chat.id)
|
||||
|
||||
if listener and not listener['future'].done():
|
||||
return await listener['filters'](client, update) if callable(listener['filters']) else True
|
||||
if listener and not listener["future"].done():
|
||||
return (
|
||||
await listener["filters"](client, update)
|
||||
if callable(listener["filters"])
|
||||
else True
|
||||
)
|
||||
|
||||
return (
|
||||
await self.filters(client, update)
|
||||
if callable(self.filters)
|
||||
else True
|
||||
)
|
||||
return await self.filters(client, update) if callable(self.filters) else True
|
||||
|
||||
|
||||
@patch(pyrogram.types.user_and_chats.chat.Chat)
|
||||
@ -208,21 +204,27 @@ class Chat(pyrogram.types.Chat):
|
||||
@patchable
|
||||
@staticmethod
|
||||
def _parse_user_chat(client, user: pyrogram.raw.types.User) -> "Chat":
|
||||
chat = pyrogram.types.user_and_chats.chat.Chat.old_parse_user_chat(client, user) # noqa
|
||||
chat = pyrogram.types.user_and_chats.chat.Chat.old_parse_user_chat(
|
||||
client, user
|
||||
) # noqa
|
||||
chat.is_forum = None
|
||||
return chat
|
||||
|
||||
@patchable
|
||||
@staticmethod
|
||||
def _parse_chat_chat(client, chat: pyrogram.raw.types.Chat) -> "Chat":
|
||||
chat = pyrogram.types.user_and_chats.chat.Chat.old_parse_chat_chat(client, chat) # noqa
|
||||
chat = pyrogram.types.user_and_chats.chat.Chat.old_parse_chat_chat(
|
||||
client, chat
|
||||
) # noqa
|
||||
chat.is_forum = None
|
||||
return chat
|
||||
|
||||
@patchable
|
||||
@staticmethod
|
||||
def _parse_channel_chat(client, channel: pyrogram.raw.types.Channel) -> "Chat":
|
||||
chat = pyrogram.types.user_and_chats.chat.Chat.old_parse_channel_chat(client, channel) # noqa
|
||||
chat = pyrogram.types.user_and_chats.chat.Chat.old_parse_channel_chat(
|
||||
client, channel
|
||||
) # noqa
|
||||
chat.is_forum = getattr(channel, "forum", None)
|
||||
return chat
|
||||
|
||||
@ -251,23 +253,21 @@ class Message(pyrogram.types.Message):
|
||||
async def safe_delete(self, revoke: bool = True):
|
||||
try:
|
||||
return await self._client.delete_messages(
|
||||
chat_id=self.chat.id,
|
||||
message_ids=self.id,
|
||||
revoke=revoke
|
||||
chat_id=self.chat.id, message_ids=self.id, revoke=revoke
|
||||
)
|
||||
except Exception: # noqa
|
||||
return False
|
||||
|
||||
@patchable
|
||||
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 or (
|
||||
self.reply_to_message.text if self.reply_to_message else None
|
||||
)
|
||||
|
||||
@patchable
|
||||
def obtain_user(self) -> Optional[int]:
|
||||
""" Obtains a user from either the reply message or command arguments. """
|
||||
"""Obtains a user from either the reply message or command arguments."""
|
||||
user = None
|
||||
# Priority: reply > argument > current_chat
|
||||
if self.reply_to_message: # Reply to a user
|
||||
@ -279,9 +279,14 @@ class Message(pyrogram.types.Message):
|
||||
if raw_user.isnumeric():
|
||||
user = int(raw_user)
|
||||
elif self.entities is not None:
|
||||
if self.entities[0].type == pyrogram.enums.MessageEntityType.TEXT_MENTION:
|
||||
if (
|
||||
self.entities[0].type
|
||||
== pyrogram.enums.MessageEntityType.TEXT_MENTION
|
||||
):
|
||||
user = self.entities[0].user.id
|
||||
if not user and self.chat.type == pyrogram.enums.ChatType.PRIVATE: # Current chat
|
||||
if (
|
||||
not user and self.chat.type == pyrogram.enums.ChatType.PRIVATE
|
||||
): # Current chat
|
||||
user = self.chat.id
|
||||
return user
|
||||
|
||||
@ -291,13 +296,13 @@ class Message(pyrogram.types.Message):
|
||||
|
||||
@patchable
|
||||
async def edit_text(
|
||||
self,
|
||||
text: str,
|
||||
parse_mode: Optional["pyrogram.enums.ParseMode"] = None,
|
||||
entities: List["pyrogram.types.MessageEntity"] = None,
|
||||
disable_web_page_preview: bool = None,
|
||||
reply_markup: "pyrogram.types.InlineKeyboardMarkup" = None,
|
||||
no_reply: bool = None,
|
||||
self,
|
||||
text: str,
|
||||
parse_mode: Optional["pyrogram.enums.ParseMode"] = None,
|
||||
entities: List["pyrogram.types.MessageEntity"] = None,
|
||||
disable_web_page_preview: bool = None,
|
||||
reply_markup: "pyrogram.types.InlineKeyboardMarkup" = None,
|
||||
no_reply: bool = None,
|
||||
) -> "Message":
|
||||
msg = None
|
||||
sudo_users = get_sudo_list()
|
||||
@ -317,7 +322,7 @@ class Message(pyrogram.types.Message):
|
||||
text=text,
|
||||
parse_mode=parse_mode,
|
||||
disable_web_page_preview=disable_web_page_preview,
|
||||
quote=True
|
||||
quote=True,
|
||||
)
|
||||
elif is_self:
|
||||
msg = await self._client.edit_message_text(
|
||||
@ -327,14 +332,14 @@ class Message(pyrogram.types.Message):
|
||||
parse_mode=parse_mode,
|
||||
entities=entities,
|
||||
disable_web_page_preview=disable_web_page_preview,
|
||||
reply_markup=reply_markup
|
||||
reply_markup=reply_markup,
|
||||
)
|
||||
elif not no_reply:
|
||||
msg = await self.reply(
|
||||
text=text,
|
||||
parse_mode=parse_mode,
|
||||
disable_web_page_preview=disable_web_page_preview,
|
||||
quote=True
|
||||
quote=True,
|
||||
)
|
||||
else:
|
||||
try:
|
||||
@ -345,9 +350,11 @@ class Message(pyrogram.types.Message):
|
||||
parse_mode=parse_mode,
|
||||
entities=entities,
|
||||
disable_web_page_preview=disable_web_page_preview,
|
||||
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 not no_reply:
|
||||
msg = await self.reply(
|
||||
text=text,
|
||||
@ -355,15 +362,13 @@ class Message(pyrogram.types.Message):
|
||||
entities=entities,
|
||||
disable_web_page_preview=disable_web_page_preview,
|
||||
reply_markup=reply_markup,
|
||||
quote=True
|
||||
quote=True,
|
||||
)
|
||||
else:
|
||||
with open("output.log", "w+") as file:
|
||||
file.write(text)
|
||||
msg = await self._client.send_document(
|
||||
chat_id=self.chat.id,
|
||||
document="output.log",
|
||||
reply_to_message_id=self.id
|
||||
chat_id=self.chat.id, document="output.log", reply_to_message_id=self.id
|
||||
)
|
||||
if not msg:
|
||||
return self
|
||||
@ -381,9 +386,11 @@ class Message(pyrogram.types.Message):
|
||||
users: dict,
|
||||
chats: dict,
|
||||
is_scheduled: bool = False,
|
||||
replies: int = 1
|
||||
replies: int = 1,
|
||||
):
|
||||
parsed = await pyrogram.types.Message.old_parse(client, message, users, chats, is_scheduled, replies) # noqa
|
||||
parsed = await pyrogram.types.Message.old_parse(
|
||||
client, message, users, chats, is_scheduled, replies
|
||||
) # noqa
|
||||
# forum topic
|
||||
if isinstance(message, pyrogram.raw.types.Message):
|
||||
parsed.forum_topic = getattr(message.reply_to, "forum_topic", None)
|
||||
@ -414,8 +421,8 @@ class Message(pyrogram.types.Message):
|
||||
"pyrogram.types.InlineKeyboardMarkup",
|
||||
"pyrogram.types.ReplyKeyboardMarkup",
|
||||
"pyrogram.types.ReplyKeyboardRemove",
|
||||
"pyrogram.types.ForceReply"
|
||||
] = object
|
||||
"pyrogram.types.ForceReply",
|
||||
] = object,
|
||||
) -> Union["pyrogram.types.Message", List["pyrogram.types.Message"]]:
|
||||
if self.media:
|
||||
self.text = None
|
||||
|
@ -30,14 +30,20 @@ async def sign_in_qrcode(
|
||||
await client.session.stop()
|
||||
await client.storage.dc_id(req.dc_id)
|
||||
await client.storage.auth_key(
|
||||
await Auth(client, await client.storage.dc_id(), await client.storage.test_mode()).create()
|
||||
await Auth(
|
||||
client, await client.storage.dc_id(), await client.storage.test_mode()
|
||||
).create()
|
||||
)
|
||||
client.session = Session(
|
||||
client, await client.storage.dc_id(),
|
||||
await client.storage.auth_key(), await client.storage.test_mode()
|
||||
client,
|
||||
await client.storage.dc_id(),
|
||||
await client.storage.auth_key(),
|
||||
await client.storage.test_mode(),
|
||||
)
|
||||
await client.session.start()
|
||||
req = await client.invoke(pyrogram.raw.functions.auth.ImportLoginToken(token=req.token))
|
||||
req = await client.invoke(
|
||||
pyrogram.raw.functions.auth.ImportLoginToken(token=req.token)
|
||||
)
|
||||
await client.storage.user_id(req.authorization.user.id)
|
||||
await client.storage.is_bot(False)
|
||||
return pyrogram.types.User._parse(client, req.authorization.user)
|
||||
@ -51,8 +57,10 @@ async def authorize_by_qrcode(
|
||||
client: Client,
|
||||
):
|
||||
print(f"Welcome to Pyrogram (version {pyrogram.__version__})")
|
||||
print(f"Pyrogram is free software and comes with ABSOLUTELY NO WARRANTY. Licensed\n"
|
||||
f"under the terms of the {pyrogram.__license__}.\n")
|
||||
print(
|
||||
f"Pyrogram is free software and comes with ABSOLUTELY NO WARRANTY. Licensed\n"
|
||||
f"under the terms of the {pyrogram.__license__}.\n"
|
||||
)
|
||||
|
||||
while True:
|
||||
qrcode = None
|
||||
@ -66,7 +74,9 @@ async def authorize_by_qrcode(
|
||||
print(f"Password hint: {await client.get_password_hint()}")
|
||||
|
||||
if not client.password:
|
||||
client.password = await ainput("Enter password (empty to recover): ", hide=client.hide_password)
|
||||
client.password = await ainput(
|
||||
"Enter password (empty to recover): ", hide=client.hide_password
|
||||
)
|
||||
|
||||
try:
|
||||
if client.password:
|
||||
@ -96,8 +106,12 @@ async def authorize_by_qrcode(
|
||||
except Exception:
|
||||
print("Save qrcode.png failed.")
|
||||
print(qr_obj.terminal())
|
||||
print(f"Scan the QR code above, the qrcode.png file or visit {qrcode} to log in.\n")
|
||||
print("QR code will expire in 20 seconds. If you have scanned it, please wait...")
|
||||
print(
|
||||
f"Scan the QR code above, the qrcode.png file or visit {qrcode} to log in.\n"
|
||||
)
|
||||
print(
|
||||
"QR code will expire in 20 seconds. If you have scanned it, please wait..."
|
||||
)
|
||||
await asyncio.sleep(20)
|
||||
elif isinstance(qrcode, pyrogram.types.User):
|
||||
return qrcode
|
||||
@ -114,7 +128,9 @@ async def start_client(client: Client):
|
||||
await client.authorize()
|
||||
|
||||
if not await client.storage.is_bot() and client.takeout:
|
||||
client.takeout_id = (await client.invoke(pyrogram.raw.functions.account.InitTakeoutSession())).id
|
||||
client.takeout_id = (
|
||||
await client.invoke(pyrogram.raw.functions.account.InitTakeoutSession())
|
||||
).id
|
||||
|
||||
await client.invoke(pyrogram.raw.functions.updates.GetState())
|
||||
except (Exception, KeyboardInterrupt):
|
||||
|
@ -12,12 +12,14 @@ def _checks_cancelled(f):
|
||||
raise asyncio.CancelledError("The conversation was cancelled before")
|
||||
|
||||
return f(self, *args, **kwargs)
|
||||
|
||||
return wrapper
|
||||
|
||||
|
||||
class Conversation:
|
||||
def __init__(self, client, chat_id: Union[int, str],
|
||||
once_timeout: int = 60, filters=None):
|
||||
def __init__(
|
||||
self, client, chat_id: Union[int, str], once_timeout: int = 60, filters=None
|
||||
):
|
||||
self._client = client
|
||||
self._chat_id = chat_id
|
||||
self._once_timeout = once_timeout
|
||||
@ -56,7 +58,9 @@ class Conversation:
|
||||
async def ask(self, text, filters=None, timeout=None, *args, **kwargs):
|
||||
filters = filters or self._filters
|
||||
timeout = timeout or self._once_timeout
|
||||
return await self._client.ask(self._chat_id, text, filters=filters, timeout=timeout, *args, **kwargs)
|
||||
return await self._client.ask(
|
||||
self._chat_id, text, filters=filters, timeout=timeout, *args, **kwargs
|
||||
)
|
||||
|
||||
@_checks_cancelled
|
||||
async def get_response(self, filters=None, timeout=None):
|
||||
@ -65,7 +69,9 @@ class Conversation:
|
||||
return await self._client.listen(self._chat_id, filters, timeout)
|
||||
|
||||
def mark_as_read(self, message=None):
|
||||
return self._client.read_chat_history(self._chat_id, max_id=message.id if message else 0)
|
||||
return self._client.read_chat_history(
|
||||
self._chat_id, max_id=message.id if message else 0
|
||||
)
|
||||
|
||||
def cancel(self):
|
||||
self._cancelled = True
|
||||
|
@ -2,6 +2,7 @@ class AlreadyInConversationError(Exception):
|
||||
"""
|
||||
Occurs when another exclusive conversation is opened in the same chat.
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
super().__init__(
|
||||
"Cannot open exclusive conversation in a "
|
||||
@ -13,10 +14,9 @@ class TimeoutConversationError(Exception):
|
||||
"""
|
||||
Occurs when the conversation times out.
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
super().__init__(
|
||||
"Response read timed out"
|
||||
)
|
||||
super().__init__("Response read timed out")
|
||||
|
||||
|
||||
class ListenerCanceled(Exception):
|
||||
@ -25,6 +25,4 @@ class ListenerCanceled(Exception):
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
super().__init__(
|
||||
"Listener was canceled"
|
||||
)
|
||||
super().__init__("Listener was canceled")
|
||||
|
@ -21,12 +21,12 @@ along with pyromod. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
def patch(obj):
|
||||
def is_patchable(item):
|
||||
return getattr(item[1], 'patchable', False)
|
||||
return getattr(item[1], "patchable", False)
|
||||
|
||||
def wrapper(container):
|
||||
for name, func in filter(is_patchable, container.__dict__.items()):
|
||||
old = getattr(obj, name, None)
|
||||
setattr(obj, f'old{name}', old)
|
||||
setattr(obj, f"old{name}", old)
|
||||
setattr(obj, name, func)
|
||||
return container
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
pyrogram==2.0.100
|
||||
pyrogram==2.0.101
|
||||
TgCrypto==1.2.5
|
||||
Pillow>=8.4.0
|
||||
pytz>=2021.3
|
||||
@ -6,15 +6,15 @@ PyYAML>=6.0
|
||||
coloredlogs>=15.0.1
|
||||
psutil>=5.8.0
|
||||
httpx~=0.23.3
|
||||
apscheduler==3.10.0
|
||||
apscheduler>=3.10.1
|
||||
sqlitedict~=2.1.0
|
||||
casbin==1.17.6
|
||||
casbin==1.18.0
|
||||
sentry-sdk==1.16.0
|
||||
PyQRCode>=1.2.1
|
||||
PyPng
|
||||
fastapi==0.92.0
|
||||
fastapi==0.94.0
|
||||
amis-python==1.0.7
|
||||
python-jose
|
||||
uvicorn
|
||||
pydantic==1.10.5
|
||||
starlette==0.25.0
|
||||
pydantic==1.10.6
|
||||
starlette==0.26.0.post1
|
||||
|
@ -5,6 +5,7 @@ from sys import executable, exit
|
||||
try:
|
||||
from pyrogram.errors import ApiIdInvalid, PhoneNumberInvalid
|
||||
from pyrogram import Client
|
||||
|
||||
print("Found an existing installation of Pyrogram...\nSuccessfully Imported.")
|
||||
except ImportError:
|
||||
print("Installing Pyrogram...")
|
||||
@ -32,10 +33,14 @@ async def main():
|
||||
"me",
|
||||
f"**PagerMaid** `String SESSION`:\n\n`{await bot.export_session_string()}`",
|
||||
)
|
||||
print("Your SESSION has been generated. Check your telegram saved messages!")
|
||||
print(
|
||||
"Your SESSION has been generated. Check your telegram saved messages!"
|
||||
)
|
||||
exit(0)
|
||||
except ApiIdInvalid:
|
||||
print("Your API ID/API HASH combination is invalid. Kindly recheck.\nQuitting...")
|
||||
print(
|
||||
"Your API ID/API HASH combination is invalid. Kindly recheck.\nQuitting..."
|
||||
)
|
||||
exit(0)
|
||||
except ValueError:
|
||||
print("API HASH must not be empty!\nQuitting...")
|
||||
|
Loading…
Reference in New Issue
Block a user