🔖 Update to v1.4.9

This commit is contained in:
xtaodada 2024-02-05 21:16:25 +08:00
parent 0e7379ecc8
commit e5f74f4d97
Signed by: xtaodada
GPG Key ID: 4CBB3F4FA8C85659
15 changed files with 114 additions and 31 deletions

View File

@ -89,3 +89,6 @@ start_form: "%m/%d %H:%M"
# Silent to reduce editing times # Silent to reduce editing times
silent: "True" silent: "True"
# Eval use pb or not
use_pb: "True"

View File

@ -503,6 +503,10 @@ eval_parameters: <command>
eval_channel: Something went wrong ~ The current PagerMaid-Pyro configuration prohibits the execution of Python commands in the channel. eval_channel: Something went wrong ~ The current PagerMaid-Pyro configuration prohibits the execution of Python commands in the channel.
eval_success: execute Python commands remotely eval_success: execute Python commands remotely
eval_need_dev: '**Please note: This command can directly operate your account** This command is only for developers. If you know what you are doing, please manually configure the `dev` item in the Redis database to any value or create the `dev` file in the `data` folder.' eval_need_dev: '**Please note: This command can directly operate your account** This command is only for developers. If you know what you are doing, please manually configure the `dev` item in the Redis database to any value or create the `dev` file in the `data` folder.'
eval_executing: '🔃 Executing...'
eval_code: '💻 Code:'
eval_result: '✨ Result:'
eval_time: 'Completed in {}s.'
## send_log ## send_log
send_log_des: Send the log file to the specified user. send_log_des: Send the log file to the specified user.
send_log_not_found: The log file does not exist. send_log_not_found: The log file does not exist.

View File

@ -503,6 +503,10 @@ eval_parameters: <command>
eval_channel: Something went wrong ~ The current Maid-Pyro configuration prohibits the execution of Python commands in the channel. eval_channel: Something went wrong ~ The current Maid-Pyro configuration prohibits the execution of Python commands in the channel.
eval_success: execute Python commands remotey eval_success: execute Python commands remotey
eval_need_dev: '**Please note: This command can directly operate your account** This command is only for developers. If you know what you are doing, and please manually configure the `dev` item in the Redis database to any value or create the `dev` file in the `data` folder。' eval_need_dev: '**Please note: This command can directly operate your account** This command is only for developers. If you know what you are doing, and please manually configure the `dev` item in the Redis database to any value or create the `dev` file in the `data` folder。'
eval_executing: '🔃 実行中...'
eval_code: '💻 コード:'
eval_result: '✨ 結果:'
eval_time: '{}2番 で完了しました。'
## send_log ## send_log
send_log_des: 指定したユーザーにログ ファイルを送信します。 send_log_des: 指定したユーザーにログ ファイルを送信します。
send_log_not_found: ログファイルが存在しません。 send_log_not_found: ログファイルが存在しません。

View File

@ -503,6 +503,10 @@ eval_parameters: <命令>
eval_channel: 出错了呜呜呜 ~ 当前 PagerMaid-Pyro 的配置禁止在频道中执行 Python 命令。 eval_channel: 出错了呜呜呜 ~ 当前 PagerMaid-Pyro 的配置禁止在频道中执行 Python 命令。
eval_success: 远程执行 Python 命令 eval_success: 远程执行 Python 命令
eval_need_dev: '**请注意:此命令可以直接操作您的账户** 此命令仅适用于开发者,如果您知道您在做什么的话,请手动在 Redis 数据库配置 dev 项为任意值或者在 data 文件夹下创建 dev 文件。' eval_need_dev: '**请注意:此命令可以直接操作您的账户** 此命令仅适用于开发者,如果您知道您在做什么的话,请手动在 Redis 数据库配置 dev 项为任意值或者在 data 文件夹下创建 dev 文件。'
eval_executing: '🔃 正在执行...'
eval_code: '💻 代码:'
eval_result: '✨ 运行结果:'
eval_time: '耗时 {} 秒'
## send_log ## send_log
send_log_des: 将日志文件发送给指定用户 send_log_des: 将日志文件发送给指定用户
send_log_not_found: 日志文件不存在。 send_log_not_found: 日志文件不存在。

View File

@ -503,6 +503,10 @@ eval_parameters: <指令>
eval_channel: Error不能在頻道執行指令。 eval_channel: Error不能在頻道執行指令。
eval_success: 執行 Python 指令 eval_success: 執行 Python 指令
eval_need_dev: '**請注意:此命令可以直接操作您的賬戶** 此命令僅適用於開發者,如果您知道您在做什麼的話,請手動在 Redis 數據庫配置 dev 項為任意值或者在 data 文件夾下創建 dev 文件。' eval_need_dev: '**請注意:此命令可以直接操作您的賬戶** 此命令僅適用於開發者,如果您知道您在做什麼的話,請手動在 Redis 數據庫配置 dev 項為任意值或者在 data 文件夾下創建 dev 文件。'
eval_executing: '🔃 正在執行...'
eval_code: '💻 代碼:'
eval_result: '✨ 運行結果:'
eval_time: '耗時 {} 秒'
## send_log ## send_log
send_log_des: 將日誌文件發送到指定的用戶 send_log_des: 將日誌文件發送到指定的用戶
send_log_not_found: 日誌文件不存在 send_log_not_found: 日誌文件不存在

View File

@ -22,8 +22,8 @@ from pagermaid.scheduler import scheduler
import pyromod.listen import pyromod.listen
from pyrogram import Client from pyrogram import Client
pgm_version = "1.4.8" pgm_version = "1.4.9"
pgm_version_code = 1408 pgm_version_code = 1409
CMD_LIST = {} CMD_LIST = {}
module_dir = __path__[0] module_dir = __path__[0]
working_dir = getcwd() working_dir = getcwd()

View File

@ -1,11 +1,13 @@
import io import io
import sys import sys
import traceback import traceback
from typing import Optional
from pagermaid import bot from pagermaid import bot
from pagermaid.services import client as httpx_client
async def run_eval(cmd: str, message=None, only_result: bool = False) -> str: async def run_eval(cmd: str, message=None) -> str:
old_stderr = sys.stderr old_stderr = sys.stderr
old_stdout = sys.stdout old_stdout = sys.stdout
redirected_output = sys.stdout = io.StringIO() redirected_output = sys.stdout = io.StringIO()
@ -27,7 +29,7 @@ async def run_eval(cmd: str, message=None, only_result: bool = False) -> str:
evaluation = stdout evaluation = stdout
else: else:
evaluation = "Success" evaluation = "Success"
return evaluation if only_result else f"**>>>** `{cmd}` \n`{evaluation}`" return evaluation
async def aexec(code, event, client): async def aexec(code, event, client):
@ -43,3 +45,19 @@ async def aexec(code, event, client):
) )
return await locals()["__aexec"](event, client) return await locals()["__aexec"](event, client)
async def paste_pb(
content: str, private: bool = True, sunset: int = 3600
) -> Optional[str]:
data = {
"c": content,
}
if private:
data["p"] = "1"
if sunset:
data["sunset"] = sunset
result = await httpx_client.post("https://fars.ee", data=data)
if result.is_error:
return None
return result.headers.get("location")

View File

@ -17,6 +17,8 @@ def strtobool(val, default=False):
are 'n', 'no', 'f', 'false', 'off', and '0'. Raises ValueError if are 'n', 'no', 'f', 'false', 'off', and '0'. Raises ValueError if
'val' is anything else. 'val' is anything else.
""" """
if val is None:
return default
val = val.lower() val = val.lower()
if val in ("y", "yes", "t", "true", "on", "1"): if val in ("y", "yes", "t", "true", "on", "1"):
return 1 return 1
@ -143,6 +145,7 @@ class Config:
WEB_HOST = os.environ.get("WEB_HOST", web_interface.get("host", "127.0.0.1")) 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_PORT = int(os.environ.get("WEB_PORT", web_interface.get("port", 3333)))
WEB_ORIGINS = web_interface.get("origins", ["*"]) WEB_ORIGINS = web_interface.get("origins", ["*"])
USE_PB = strtobool(os.environ.get("PGM_USE_PB", config.get("use_pb")), True)
except ValueError as e: except ValueError as e:
print(e) print(e)
sys.exit(1) sys.exit(1)

View File

@ -32,6 +32,7 @@ from pagermaid.utils import (
alias_command, alias_command,
get_permission_name, get_permission_name,
process_exit, process_exit,
format_exc as format_exc_text,
) )
from pagermaid.hook import Hook from pagermaid.hook import Hook
from pagermaid.web import web from pagermaid.web import web
@ -212,11 +213,13 @@ def listener(**args):
await process_exit(start=False, _client=client, message=message) await process_exit(start=False, _client=client, message=message)
await Hook.shutdown() await Hook.shutdown()
web.stop() web.stop()
except BaseException: except BaseException as exc:
exc_info = sys.exc_info()[1] exc_info = sys.exc_info()[1]
exc_format = format_exc() exc_format = format_exc()
with contextlib.suppress(BaseException): with contextlib.suppress(BaseException):
await message.edit(lang("run_error"), no_reply=True) # noqa exc_text = format_exc_text(exc)
text = f'{lang("run_error")}\n\n{exc_text}'
await message.edit(text, no_reply=True) # noqa
if not diagnostics: if not diagnostics:
return return
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""" 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"""
@ -229,9 +232,7 @@ def listener(**args):
None, None,
"PGP Error report generated.", "PGP Error report generated.",
) )
await Hook.process_error_exec( await Hook.process_error_exec(message, command, exc_info, exc_format)
message, command, exc_info, exc_format
)
if (message.chat.id, message.id) in read_context: if (message.chat.id, message.id) in read_context:
del read_context[(message.chat.id, message.id)] del read_context[(message.chat.id, message.id)]
if block_process: if block_process:

View File

@ -86,11 +86,7 @@ async def profile(client: Client, message: Message):
f"[{first_name}](tg://user?id={user.id})" f"[{first_name}](tg://user?id={user.id})"
) )
photo = await client.download_media(user.photo.big_file_id) if user.photo else None photo = await client.download_media(user.photo.big_file_id) if user.photo else None
reply_to = ( reply_to = message.reply_to_message.id if message.reply_to_message else None
message.reply_to_message.id
if message.reply_to_message
else None
)
if photo: if photo:
try: try:
await client.send_photo( await client.send_photo(

View File

@ -169,7 +169,9 @@ async def re(bot: Client, message: Message):
for _ in range(num): for _ in range(num):
try: try:
if not message.chat.has_protected_content: if not message.chat.has_protected_content:
await reply.forward(reply.chat.id, message_thread_id=reply.message_thread_id) await reply.forward(
reply.chat.id, message_thread_id=reply.message_thread_id
)
else: else:
await reply.copy( await reply.copy(
reply.chat.id, reply.chat.id,

View File

@ -59,7 +59,9 @@ class Mixpanel:
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") logs.debug(f"Mixpanel request took {self._now() - start} seconds")
async def people_set(self, distinct_id: str, properties: dict, force_update: bool = False): async def people_set(
self, distinct_id: str, properties: dict, force_update: bool = False
):
if self.is_people_set and (not force_update): if self.is_people_set and (not force_update):
return return
message = { message = {

View File

@ -1,15 +1,24 @@
import html
import sys import sys
from getpass import getuser from getpass import getuser
from os.path import exists, sep from os.path import exists, sep
from platform import node from platform import node
from time import perf_counter
from pyrogram.enums import ParseMode from pagermaid import Config
from pagermaid.common.system import run_eval, paste_pb
from pagermaid.common.system import run_eval
from pagermaid.enums import Message from pagermaid.enums import Message
from pagermaid.listener import listener from pagermaid.listener import listener
from pagermaid.utils import attach_log, execute, lang, upload_attachment from pagermaid.utils import attach_log, execute, lang, upload_attachment
code_result = (
f"<b>{lang('eval_code')}</b>\n"
'<pre language="{}">{}</pre>\n\n'
f'<b>{lang("eval_result")}</b>\n'
"{}\n"
f"<b>{lang('eval_time')}</b>"
)
@listener( @listener(
is_plugin=False, is_plugin=False,
@ -28,18 +37,24 @@ async def sh(message: Message):
await message.edit(lang("arg_error")) await message.edit(lang("arg_error"))
return return
message = await message.edit(f"`{user}`@{hostname} ~" f"\n> `$` {command}") message = await message.edit(f"`{user}`@{hostname} ~\n> `$` {command}")
result = await execute(command) result = await execute(command)
if result: if result:
if len(result) > 4096: final_result = None
if len(result) > 3072:
if Config.USE_PB:
url = await paste_pb(result)
if url:
final_result = html.escape(f"{url}/bash")
else:
final_result = f"<code>{html.escape(result)}</code>"
if (len(result) > 3072 and not Config.USE_PB) or final_result is None:
await attach_log(result, message.chat.id, "output.log", message.id) await attach_log(result, message.chat.id, "output.log", message.id)
return return
await message.edit(f"`{user}`@{hostname} ~\n> `#` {command}\n\n{final_result}")
await message.edit(
f"`{user}`@{hostname} ~" f"\n> `#` {command}" f"\n`{result}`"
)
else: else:
return return
@ -70,12 +85,29 @@ async def sh_eval(message: Message):
cmd = message.text.split(" ", maxsplit=1)[1] cmd = message.text.split(" ", maxsplit=1)[1]
except (IndexError, AssertionError): except (IndexError, AssertionError):
return await message.edit(lang("eval_need_dev")) return await message.edit(lang("eval_need_dev"))
message = await message.edit_text(f"<b>{lang('eval_executing')}</b>")
start_time = perf_counter()
final_output = await run_eval(cmd, message) final_output = await run_eval(cmd, message)
if len(final_output) > 4096: stop_time = perf_counter()
message = await message.edit(f"**>>>** `{cmd}`", parse_mode=ParseMode.MARKDOWN)
await attach_log(final_output, message.chat.id, "output.log", message.id) result = None
if len(final_output) > 3072:
if Config.USE_PB:
url = await paste_pb(final_output)
if url:
result = html.escape(f"{url}/python")
else: else:
await message.edit(final_output) result = f"<code>{html.escape(final_output)}</code>"
text = code_result.format(
"python",
html.escape(cmd),
result if result else "...",
round(stop_time - start_time, 5),
)
await message.edit(text)
if (len(final_output) > 3072 and not Config.USE_PB) or result is None:
await attach_log(final_output, message.chat.id, "output.log", message.id)
@listener( @listener(

View File

@ -11,6 +11,8 @@ from asyncio import create_subprocess_shell, sleep
from asyncio.subprocess import PIPE from asyncio.subprocess import PIPE
from pyrogram import filters from pyrogram import filters
from pyrogram.errors import RPCError
from pagermaid.config import Config from pagermaid.config import Config
from pagermaid import bot from pagermaid import bot
from pagermaid.group_manager import enforce_permission from pagermaid.group_manager import enforce_permission
@ -53,7 +55,9 @@ async def attach_log(plaintext, chat_id, file_name, reply_id=None, caption=None)
remove(file_name) remove(file_name)
async def upload_attachment(file_path, chat_id, reply_id, message_thread_id=None, caption=None, thumb=None): async def upload_attachment(
file_path, chat_id, reply_id, message_thread_id=None, caption=None, thumb=None
):
"""Uploads a local attachment file.""" """Uploads a local attachment file."""
if not exists(file_path): if not exists(file_path):
return False return False
@ -207,6 +211,12 @@ async def process_exit(start: int, _client, message=None):
sqlite["exit_msg"] = {"cid": message.chat.id, "mid": message.id} sqlite["exit_msg"] = {"cid": message.chat.id, "mid": message.id}
def format_exc(e: BaseException) -> str:
if isinstance(e, RPCError):
return f"<code>API [{e.CODE} {e.ID or e.NAME}] — {e.MESSAGE.format(value=e.value)}</code>"
return f"<code>{e.__class__.__name__}: {e}</code>"
""" Init httpx client """ """ Init httpx client """
# 使用自定义 UA # 使用自定义 UA
headers = { headers = {

View File

@ -37,7 +37,7 @@ async def run_cmd(token: Optional[str] = Header(...), cmd: str = ""):
return "非法请求" return "非法请求"
async def run_cmd_func(): async def run_cmd_func():
result = (await run_eval(cmd, only_result=True)).split("\n") result = (await run_eval(cmd)).split("\n")
for i in result: for i in result:
yield i + "\n" yield i + "\n"
await asyncio.sleep(0.02) await asyncio.sleep(0.02)