diff --git a/.gitignore b/.gitignore index 5bb6dfd..fdd3432 100644 --- a/.gitignore +++ b/.gitignore @@ -32,6 +32,7 @@ __pycache__/ test_**.html logs/ report/ +data/ /resources/*/*/test/ plugins/genshin/daily/daily.json metadata/data/ diff --git a/plugins/system/update.py b/plugins/system/update.py new file mode 100644 index 0000000..15803fb --- /dev/null +++ b/plugins/system/update.py @@ -0,0 +1,53 @@ +import json +import os + +from aiofiles import open as async_open +from telegram import Update, Message +from telegram.error import BadRequest, Forbidden +from telegram.ext import CallbackContext, CommandHandler + +from core.bot import bot +from core.plugin import handler, Plugin +from utils.bot import get_all_args +from utils.decorators.admins import bot_admins_rights_check +from utils.helpers import execute +from utils.log import logger + +current_dir = os.getcwd() + +UPDATE_DATA = os.path.join(current_dir, "data", "update.json") + + +class UpdatePlugin(Plugin): + + @staticmethod + async def __async_init__(): + if os.path.exists(UPDATE_DATA): + async with async_open(UPDATE_DATA) as file: + data = json.loads(await file.read()) + try: + reply_text = Message.de_json(data, bot.app.bot) + await reply_text.edit_text("重启成功") + except (BadRequest, Forbidden, KeyError) as exc: + logger.error("UpdatePlugin 编辑消息出现错误") + logger.exception(exc) + os.remove(UPDATE_DATA) + + @handler(CommandHandler, command="update") + @bot_admins_rights_check + async def update(self, update: Update, context: CallbackContext): + user = update.effective_user + message = update.effective_message + args = get_all_args(context) + logger.info(f"用户 {user.full_name}[{user.id}] update命令请求") + reply_text = await message.reply_text("正在更新") + await execute("git fetch --all") + if len(args) > 0: + await execute("git reset --hard origin/main") + await execute("git pull --all") + if len(args) > 0: + await execute("poetry install --extras all") + await reply_text.edit_text("自动更新成功 正在重启") + async with async_open(UPDATE_DATA, mode='w', encoding='utf-8') as file: + await file.write(reply_text.to_json()) + raise SystemExit diff --git a/utils/helpers.py b/utils/helpers.py index de626af..45c9106 100644 --- a/utils/helpers.py +++ b/utils/helpers.py @@ -1,5 +1,7 @@ import hashlib import os +from asyncio import create_subprocess_shell +from asyncio.subprocess import PIPE from pathlib import Path from typing import Optional, Tuple, TypeVar, Union, cast @@ -134,3 +136,28 @@ def region_server(uid: Union[int, str]) -> RegionEnum: return region else: raise TypeError(f"UID {uid} isn't associated with any region") + + +async def execute(command, pass_error=True): + """ Executes command and returns output, with the option of enabling stderr. """ + executor = await create_subprocess_shell( + 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()) + except UnicodeDecodeError: + 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()) + return result