🔖 Update to v1.2.4

This commit is contained in:
xtaodada 2022-08-02 00:04:45 +08:00
parent e1660d0dec
commit 21f58ba3d4
Signed by: xtaodada
GPG Key ID: 4CBB3F4FA8C85659
9 changed files with 201 additions and 65 deletions

View File

@ -14,7 +14,7 @@ import pyromod.listen
from pyrogram import Client
import sys
pgm_version = "1.2.3"
pgm_version = "1.2.4"
CMD_LIST = {}
module_dir = __path__[0]
working_dir = getcwd()

View File

@ -7,6 +7,7 @@ from pyrogram import idle
from pagermaid import bot, logs, working_dir
from pagermaid.hook import Hook
from pagermaid.modules import module_list, plugin_list
from pagermaid.single_utils import safe_remove
from pagermaid.utils import lang, process_exit
path.insert(1, f"{working_dir}{sep}plugins")
@ -18,6 +19,9 @@ async def main():
await bot.start()
me = await bot.get_me()
if me.is_bot:
safe_remove("pagermaid.session")
exit()
logs.info(f"{lang('save_id')} {me.first_name}({me.id})")
for module_name in module_list:

View File

@ -5,7 +5,7 @@ from yaml import load, FullLoader, safe_load
from shutil import copyfile
def strtobool(val):
def strtobool(val, default=False):
"""Convert a string representation of truth to true (1) or false (0).
True values are 'y', 'yes', 't', 'true', 'on', and '1'; false values
@ -18,7 +18,8 @@ def strtobool(val):
elif val in ('n', 'no', 'f', 'false', 'off', '0'):
return 0
else:
raise ValueError("invalid truth value %r" % (val,))
print("[Degrade] invalid truth value %r" % (val,))
return default
try:
@ -35,17 +36,20 @@ class Config:
API_HASH = os.environ.get("API_HASH", config["api_hash"])
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"]))
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"])
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://0785960e63e04279a694d0486d47d9ea@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"])
START_FORM = os.environ.get("PGM_START_FORM", config["start_form"])
SILENT = strtobool(os.environ.get("PGM_PGM_SILENT", config["silent"]))
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 = None

View File

@ -1,4 +1,5 @@
import asyncio
import sys
from pyrogram import StopPropagation
@ -81,30 +82,63 @@ class Hook:
logs.info(f"[shutdown]: {type(exception)}: {exception}")
@staticmethod
async def command_pre(message: Message):
if cors := [pre(**inject(message, pre)) for pre in hook_functions["command_pre"]]: # noqa
async def command_pre(message: Message, command):
cors = []
try:
for pre in hook_functions["command_pre"]:
try:
data = inject(message, pre, command=command)
except Exception as exception:
logs.info(f"[process_error]: {type(exception)}: {exception}")
continue
cors.append(pre(**data)) # noqa
if cors:
await asyncio.gather(*cors)
except SystemExit:
await Hook.shutdown()
sys.exit(0)
except StopPropagation as e:
raise StopPropagation from e
except Exception as exception:
logs.info(f"[command_pre]: {type(exception)}: {exception}")
@staticmethod
async def command_post(message: Message):
if cors := [post(**inject(message, post)) for post in hook_functions["command_post"]]: # noqa
async def command_post(message: Message, command):
cors = []
try:
for post in hook_functions["command_post"]:
try:
data = inject(message, post, command=command)
except Exception as exception:
logs.info(f"[process_error]: {type(exception)}: {exception}")
continue
cors.append(post(**data)) # noqa
if cors:
await asyncio.gather(*cors)
except SystemExit:
await Hook.shutdown()
sys.exit(0)
except StopPropagation as e:
raise StopPropagation from e
except Exception as exception:
logs.info(f"[command_post]: {type(exception)}: {exception}")
@staticmethod
async def process_error_exec(message: Message, exc_info: BaseException, exc_format: str):
if cors := [error(**inject(message, error, exc_info=exc_info, exc_format=exc_format)) for error in hook_functions["process_error"]]: # noqa
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)
except Exception as exception:
logs.info(f"[process_error]: {type(exception)}: {exception}")
continue
cors.append(error(**data)) # noqa
if cors:
await asyncio.gather(*cors)
except SystemExit:
await Hook.shutdown()
sys.exit(0)
except StopPropagation as e:
raise StopPropagation from e
except Exception as exception:

View File

@ -6,6 +6,7 @@ from time import strftime, gmtime, time
from traceback import format_exc
from pyrogram import ContinuePropagation, StopPropagation, filters, Client
from pyrogram.errors import Flood, Forbidden
from pyrogram.errors.exceptions.bad_request_400 import (
MessageIdInvalid,
MessageNotModified,
@ -139,7 +140,7 @@ def listener(**args):
read_context[(message.chat.id, message.id)] = True
if command:
await Hook.command_pre(message)
await Hook.command_pre(message, command)
if data := inject(message, function):
await function(**data)
else:
@ -150,12 +151,12 @@ def listener(**args):
elif function.__code__.co_argcount == 2:
await function(client, message)
if command:
await Hook.command_post(message)
await Hook.command_post(message, command)
except StopPropagation as e:
raise StopPropagation from e
except KeyboardInterrupt as e:
raise KeyboardInterrupt from e
except MessageNotModified:
except (UserNotParticipant, MessageNotModified, MessageEmpty, Flood, Forbidden):
pass
except MessageIdInvalid:
logs.warning(
@ -179,8 +180,6 @@ def listener(**args):
)
with contextlib.suppress(BaseException):
await message.edit(lang("reload_des"))
except UserNotParticipant:
pass
except ContinuePropagation as e:
if block_process:
raise StopPropagation from e
@ -196,12 +195,12 @@ def listener(**args):
await message.edit(lang("run_error"), no_reply=True) # noqa
if not diagnostics:
return
await Hook.process_error_exec(message, exc_info, exc_format)
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)
if (message.chat.id, message.id) in read_context:
del read_context[(message.chat.id, message.id)]
if block_process:
@ -274,9 +273,7 @@ def raw_listener(filter_s):
await process_exit(start=False, _client=client, message=message)
await Hook.shutdown()
sys.exit(0)
except UserNotParticipant:
pass
except MessageEmpty:
except (UserNotParticipant, MessageNotModified, MessageEmpty, Flood, Forbidden):
pass
except BaseException:
exc_info = sys.exc_info()[1]

View File

@ -0,0 +1,29 @@
from pagermaid import Config
from pagermaid.enums import Client, Message
from pagermaid.hook import Hook
from mixpanel import Mixpanel
mp = Mixpanel(Config.MIXPANEL_API)
@Hook.on_startup()
async def mixpanel_init_id(bot: Client):
me = await bot.get_me()
if me.username:
mp.people_set(str(me.id), {'$first_name': me.first_name, "username": me.username})
else:
mp.people_set(str(me.id), {'$first_name': me.first_name})
@Hook.command_postprocessor()
async def mixpanel_report(bot: Client, message: Message, command):
if not Config.ALLOW_ANALYTIC:
return
me = await bot.get_me()
sender_id = message.from_user.id if message.from_user else ""
sender_id = message.sender_chat.id if message.sender_chat else sender_id
if sender_id < 0 and message.outgoing:
sender_id = me.id
mp.track(str(sender_id), f'Function {command}', {'command': command, "bot_id": me.id})

View File

@ -4,7 +4,8 @@ from asyncio import sleep
from pagermaid import log
from pagermaid.listener import listener
from pagermaid.utils import lang, Message
from pagermaid.enums import Client, Message
from pagermaid.utils import lang
import contextlib
@ -44,40 +45,31 @@ async def prune(message: Message):
need_admin=True,
description=lang('sp_des'),
parameters=lang('sp_parameters'))
async def self_prune(message: Message):
async def self_prune(bot: Client, message: Message):
""" 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'))
async for msg in message.bot.search_messages(
message.chat.id,
from_user="me",
offset=message.reply_to_message.id,
):
msgs.append(msg.id)
count_buffer += 1
if len(msgs) == 100:
await message.bot.delete_messages(message.chat.id, msgs)
msgs = []
if msgs:
await message.bot.delete_messages(message.chat.id, msgs)
if count_buffer == 0:
await message.delete()
count_buffer += 1
await log(f"{lang('prune_hint1')}{lang('sp_hint')} {str(count_buffer)} {lang('prune_hint2')}")
notification = await send_prune_notify(message, count_buffer, count_buffer)
await sleep(1)
await notification.delete()
return
offset = message.reply_to_message.id
try:
count = int(message.parameter[0])
await message.delete()
except ValueError:
await message.edit(lang('arg_error'))
return
async for msg in message.bot.search_messages(message.chat.id, from_user="me"):
async for msg in bot.get_chat_history(message.chat.id, limit=100):
if count_buffer == count:
break
if msg.from_user and msg.from_user.is_self:
msgs.append(msg.id)
count_buffer += 1
if len(msgs) == 100:
await message.bot.delete_messages(message.chat.id, msgs)
msgs = []
async for msg in bot.search_messages(message.chat.id, from_user="me", offset=offset):
if count_buffer == count:
break
msgs.append(msg.id)
@ -101,7 +93,7 @@ async def self_prune(message: Message):
need_admin=True,
description=lang('yp_des'),
parameters=lang('sp_parameters'))
async def your_prune(message: Message):
async def your_prune(bot: Client, message: Message):
""" Deletes specific amount of messages someone sent. """
if not message.reply_to_message:
return await message.edit(lang('not_reply'))
@ -119,15 +111,31 @@ async def your_prune(message: Message):
except Exception: # noqa
pass
count_buffer = 0
async for msg in message.bot.search_messages(message.chat.id, from_user=target.from_user.id):
msgs = []
async for msg in bot.get_chat_history(message.chat.id, limit=100):
if count_buffer == count:
break
await msg.delete()
if msg.from_user and msg.from_user.id == target.from_user.id:
msgs.append(msg.id)
count_buffer += 1
if len(msgs) == 100:
await message.bot.delete_messages(message.chat.id, msgs)
msgs = []
async for msg in bot.search_messages(message.chat.id, from_user=target.from_user.id):
if count_buffer == count:
break
count_buffer += 1
msgs.append(msg.id)
if len(msgs) == 100:
await message.bot.delete_messages(message.chat.id, msgs)
msgs = []
if msgs:
await message.bot.delete_messages(message.chat.id, msgs)
await log(
f"{lang('prune_hint1')}{lang('yp_hint')} {str(count_buffer)} / {count} {lang('prune_hint2')}"
)
with contextlib.suppress(ValueError):
notification = await send_prune_notify(message, count_buffer, count)
await sleep(1)
await notification.delete()

View File

@ -0,0 +1,58 @@
import sentry_sdk
from subprocess import run, PIPE
from time import time
from pyrogram.errors import Unauthorized
from pagermaid import Config
from pagermaid.enums import Client, Message
from pagermaid.hook import Hook
from pagermaid.single_utils import safe_remove
def sentry_before_send(event, hint):
global sentry_sdk_report_time
exc_info = hint.get("exc_info")
if exc_info and isinstance(exc_info[1], Unauthorized):
# The user has been deleted/deactivated or session revoked
safe_remove('pagermaid.session')
exit(1)
if time() <= sentry_sdk_report_time + 30:
sentry_sdk_report_time = time()
return None
else:
sentry_sdk_report_time = time()
return event
sentry_sdk_report_time = time()
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,
release=sentry_sdk_git_hash,
before_send=sentry_before_send,
environment="production",
)
@Hook.on_startup()
async def sentry_init_id(bot: Client):
me = await bot.get_me()
if me.username:
sentry_sdk.set_user({"id": me.id, "name": me.first_name, "username": me.username, "ip_address": "{{auto}}"})
else:
sentry_sdk.set_user({"id": me.id, "name": me.first_name, "ip_address": "{{auto}}"})
@Hook.process_error()
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 ""})
if command:
sentry_sdk.set_tag("com", command)
sentry_sdk.capture_exception(exc_info)

View File

@ -8,4 +8,6 @@ psutil>=5.8.0
httpx
apscheduler
sqlitedict
casbin==1.16.9
casbin==1.16.11
mixpanel
sentry-sdk==1.9.0