diff --git a/languages/built-in/en.yml b/languages/built-in/en.yml index 94b73ee..ed8a039 100644 --- a/languages/built-in/en.yml +++ b/languages/built-in/en.yml @@ -500,6 +500,8 @@ update_failed: update failed update_auto_upgrade_git_failed_ubuntu: It is detected that your system is Ubuntu or Debain. Try to upgrade git automatically but failed. Please upgrade manually. update_auto_upgrade_git_failed_cent: It is detected that your system is CentOS, try to upgrade git automatically but failed, please upgrade manually. update_auto_upgrade_git_hint: Your git version is too low and has tried to automatically upgrade for you. If you are reminded of this error again, please upgrade manually. +update_master: Received a known CVE and is forcing an update to the PagerMaid-Modify instance +update_plugins: Received a known CVE and is forcing an update to the relevant plugin # sb sb_des: Ban a user in the common group of administrator privileges. diff --git a/languages/built-in/zh-cn.yml b/languages/built-in/zh-cn.yml index 12446e1..cfcdbbf 100644 --- a/languages/built-in/zh-cn.yml +++ b/languages/built-in/zh-cn.yml @@ -516,6 +516,8 @@ update_failed: 更新失败 update_auto_upgrade_git_failed_ubuntu: 检测到您的系统是Ubuntu或Debain,尝试自动升级git但失败,请手动升级. update_auto_upgrade_git_failed_cent: 检测到您的系统是CentOS,尝试自动升级git但失败,请手动升级. update_auto_upgrade_git_hint: 您的git版本过低,已尝试为您自动升级. 如再次提醒此错误,请手动升级. +update_master: 收到已知的 CVE ,正在强制更新 PagerMaid-Modify 实例 +update_plugins: 收到已知的 CVE ,正在强制更新相关插件 # sb sb_des: 在自己拥有管理员权限的共同群组中封禁一位用户。 diff --git a/languages/built-in/zh-tw.yml b/languages/built-in/zh-tw.yml index 967956b..593cf5e 100644 --- a/languages/built-in/zh-tw.yml +++ b/languages/built-in/zh-tw.yml @@ -500,6 +500,8 @@ update_failed: 更新失敗 update_auto_upgrade_git_failed_ubuntu: 檢測到您的系統為Ubuntu/Debian,嘗試自動升級Git失敗,請手動。 update_auto_upgrade_git_failed_cent: 檢測到您的系統為CentOS/RedHat Linux,嘗試自動升級Git失敗,請手動。 update_auto_upgrade_git_hint: 檢測到您Git版本過低,已嘗試自動升級。若此錯誤持續發生,請手動。 +update_master: 收到已知的 CVE ,正在強制更新 PagerMaid-Modify 實例 +update_plugins: 收到已知的 CVE ,正在強制更新相關插件 # sb sb_des: 在自己擁有管理員權限的共同群組中封禁一位用戶。 diff --git a/pagermaid/__init__.py b/pagermaid/__init__.py index 9ddad02..0b0fb9d 100644 --- a/pagermaid/__init__.py +++ b/pagermaid/__init__.py @@ -6,7 +6,6 @@ from concurrent.futures import CancelledError import sentry_sdk from sentry_sdk.integrations.redis import RedisIntegration -from asyncio import CancelledError as CancelError from subprocess import run, PIPE from datetime import datetime from time import time @@ -20,6 +19,7 @@ from redis import StrictRedis from logging import getLogger, INFO, DEBUG, ERROR, StreamHandler, basicConfig from distutils.util import strtobool from coloredlogs import ColoredFormatter +from apscheduler.schedulers.asyncio import AsyncIOScheduler from telethon import TelegramClient from telethon.sessions import StringSession @@ -32,6 +32,9 @@ from telethon.errors.rpcerrorlist import MessageNotModifiedError, MessageIdInval from telethon.errors.common import AlreadyInConversationError from requests.exceptions import ChunkedEncodingError from requests.exceptions import ConnectionError as ConnectedError +from asyncio import CancelledError as CancelError +from asyncio import TimeoutError as AsyncTimeoutError +from aiohttp.client_exceptions import ServerDisconnectedError from sqlite3 import OperationalError from http.client import RemoteDisconnected from urllib.error import URLError @@ -43,6 +46,11 @@ module_dir = __path__[0] working_dir = getcwd() config = None help_messages = {} +scheduler = AsyncIOScheduler() +if not scheduler.running: + scheduler.configure(timezone="Asia/ShangHai") + scheduler.start() +version = 0.1 logs = getLogger(__name__) logging_format = "%(levelname)s [%(asctime)s] [%(name)s] %(message)s" logging_handler = StreamHandler() @@ -274,7 +282,7 @@ def before_send(event, hint): OSError, AuthKeyDuplicatedError, ResponseError, SlowModeWaitError, PeerFloodError, MessageEditTimeExpiredError, PeerIdInvalidError, AuthKeyUnregisteredError, UserBannedInChannelError, AuthKeyError, - CancelError)): + CancelError, AsyncTimeoutError, ServerDisconnectedError)): return elif exc_info and isinstance(exc_info[1], UserDeactivatedBanError): # The user has been deleted/deactivated @@ -295,7 +303,7 @@ report_time = time() start_time = datetime.utcnow() git_hash = run("git rev-parse HEAD", stdout=PIPE, shell=True).stdout.decode() sentry_sdk.init( - "https://88b676b38216473db3eb3dd5e1da0133@o416616.ingest.sentry.io/5312335", + "https://58c6c9990d5c4d3784aec0aecb7509d3@o416616.ingest.sentry.io/5312335", traces_sample_rate=1.0, release=git_hash, before_send=before_send, diff --git a/pagermaid/modules/update.py b/pagermaid/modules/update.py index 14439ca..1519bde 100644 --- a/pagermaid/modules/update.py +++ b/pagermaid/modules/update.py @@ -1,124 +1,70 @@ """ Pulls in the new version of PagerMaid from the git server. """ import platform -import time from datetime import datetime from distutils.util import strtobool -from json import JSONDecodeError +from json import JSONDecodeError, loads, load from os import remove +from os.path import exists from subprocess import run, PIPE from sys import executable from git import Repo from git.exc import GitCommandError, InvalidGitRepositoryError, NoSuchPathError -from pagermaid import log, config, silent +from telethon.tl.functions.channels import GetFullChannelRequest + +from pagermaid import log, config, silent, scheduler, bot, version, working_dir, logs from pagermaid.listener import listener -from pagermaid.utils import execute, lang, alias_command, get +from pagermaid.modules.plugin import remove_plugin, update_version, download +from pagermaid.utils import execute, lang, alias_command try: - git_api = config['git_api'] - git_ssh = config['git_ssh'] + git_ssh = config["git_ssh"] need_update_check = strtobool(config['update_check']) - update_time = config['update_time'] - update_username = config['update_username'] - update_delete = strtobool(config['update_delete']) except KeyError: - git_api = "https://api.github.com/repos/Xtao-Labs/PagerMaid-Modify/commits/master" - git_ssh = 'https://github.com/Xtao-Labs/PagerMaid-Modify.git' + git_ssh = "https://github.com/Xtao-Labs/PagerMaid-Modify.git" need_update_check = True - update_time = 86400 - update_username = 'PagerMaid_Modify_bot' - update_delete = True -try: - update_time = int(update_time) -except ValueError: - update_time = 86400 -try: - update_username = int(update_username) -except ValueError: - pass -async def update_get(): - try: - data = (await get(git_api)).json() - except JSONDecodeError as e: - raise e - return data - - -update_get_time = 0 -update_id = 0 - - -@listener(incoming=True, ignore_edited=True) -async def update_refresher(context): - global update_get_time, update_id +@scheduler.scheduled_job("cron", minute="*/30", id="0") +async def run_every_30_minute(): if not need_update_check: return - if time.time() - update_get_time > update_time: - update_get_time = time.time() - changelog = None - try: - repo = Repo() - active_branch = repo.active_branch.name - if not await branch_check(active_branch): - return - repo.create_remote('upstream', git_ssh) - upstream_remote = repo.remote('upstream') - upstream_remote.fetch(active_branch) - changelog = await changelog_gen(repo, f'HEAD..upstream/{active_branch}') - if not changelog: - return - else: - if update_username == 'self': - user = await context.client.get_me(input_peer=True) - else: - try: - user = await context.client.get_input_entity(update_username) - except ValueError: - user = await context.client.get_me(input_peer=True) - if not update_id == 0 and update_delete: - try: - await context.client.delete_messages(user, update_id) - except: - pass - try: - msg = await context.client.send_message(user, - f'**{lang("update_found_update_in_branch")} ' - f'{active_branch}.\n\n' - f'{lang("update_change_log")}:**\n`{changelog}`') - update_id = msg.id - except: - pass - except: + result = await bot(GetFullChannelRequest("UGFnZXJNYWlk")) # noqa + async for msg in bot.iter_messages("UGFnZXJNYWlk"): + if msg.text: try: - data = await update_get() - git_hash = run("git rev-parse HEAD", stdout=PIPE, shell=True).stdout.decode().strip() - if not data['sha'] == git_hash: - if update_username == 'self': - user = await context.client.get_me(input_peer=True) - else: - try: - user = await context.client.get_input_entity(update_username) - except ValueError: - user = await context.client.get_me(input_peer=True) - changelog = data['commit']['message'] - if not update_id == 0 and update_delete: - try: - await context.client.delete_messages(user, update_id) - except: - pass + data_ = loads(msg.text.strip("`")) + except JSONDecodeError: + continue + need_restart = False + for data in data_["data"]: + if data["mode"] == "master": + if version < data["version"]: + logs.info(lang('update_master')) + await execute("git reset --hard") + await execute("git pull") + await execute(f"{executable} -m pip install -r requirements.txt --upgrade") + await execute(f"{executable} -m pip install -r requirements.txt") + need_restart = True + elif data["mode"] == "plugins": + if not exists(f"{working_dir}/plugins/version.json"): + return + with open(f"{working_dir}/plugins/version.json", 'r', encoding="utf-8") as f: + version_json = load(f) try: - msg = await context.client.send_message(user, f'**{lang("update_found_update_in_branch")} ' - f'master.\n\n' - f'{lang("update_change_log")}:**\n`{changelog}`') - update_id = msg.id - except: - pass - except Exception as e: - await log(f"Warning: module update failed to refresh git commit data.\n{e}") + plugin_version = version_json[data["name"]] + except KeyError: + return + if (float(data["version"]) - float(plugin_version)) > 0: + logs.info(lang('update_plugins')) + remove_plugin(data["name"]) + await download(data["name"]) + update_version(data["name"], data["version"]) + need_restart = True + if need_restart: + await bot.disconnect() @listener(is_plugin=False, outgoing=True, command=alias_command("update"), diff --git a/pagermaid/utils.py b/pagermaid/utils.py index 213d273..9900b1f 100644 --- a/pagermaid/utils.py +++ b/pagermaid/utils.py @@ -301,6 +301,7 @@ async def request(method: str, config_["proxy"] = f"http://{http_addr}:{http_port}" session = aiohttp.ClientSession(timeout=aiohttp.ClientTimeout(total=timeout)) resp = await session.request(**config_) + await session.close() # 返回请求 try: resp_data = await resp.text() @@ -308,7 +309,6 @@ async def request(method: str, resp_data = await resp.read() content = await resp.content.read() status_code = resp.status - await session.close() return AiohttpResp(resp_data, content, status_code) diff --git a/requirements.txt b/requirements.txt index 8701990..d1d8d0b 100644 --- a/requirements.txt +++ b/requirements.txt @@ -35,6 +35,7 @@ cheroot>=8.5.2 python-socks[asyncio]>=1.2.4 certifi>=2021.5.30 magic_google>=0.2.9 -sentry-sdk>=1.5.1 +sentry-sdk>=1.5.2 analytics-python>=1.4.0 beautifulsoup4>=4.9.3 +apscheduler>=3.8.1