Merge pull request #467 from RockChinQ/perf-plugin-update

[Perf] 优化插件更新相关操作
This commit is contained in:
Rock Chin 2023-05-14 18:45:36 +08:00 committed by GitHub
commit 6272e98474
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 73 additions and 34 deletions

View File

@ -8,6 +8,7 @@ import sys
import shutil import shutil
import traceback import traceback
import pkg.utils.updater as updater
import pkg.utils.context as context import pkg.utils.context as context
import pkg.plugin.switch as switch import pkg.plugin.switch as switch
import pkg.plugin.settings as settings import pkg.plugin.settings as settings
@ -79,7 +80,7 @@ def walk_plugin_path(module, prefix='', path_prefix=''):
__current_module_path__ = "plugins/"+path_prefix + item.name + '.py' __current_module_path__ = "plugins/"+path_prefix + item.name + '.py'
importlib.import_module(module.__name__ + '.' + item.name) importlib.import_module(module.__name__ + '.' + item.name)
logging.info('加载模块: plugins/{} 成功'.format(path_prefix + item.name + '.py')) logging.debug('加载模块: plugins/{} 成功'.format(path_prefix + item.name + '.py'))
except: except:
logging.error('加载模块: plugins/{} 失败: {}'.format(path_prefix + item.name + '.py', sys.exc_info())) logging.error('加载模块: plugins/{} 失败: {}'.format(path_prefix + item.name + '.py', sys.exc_info()))
traceback.print_exc() traceback.print_exc()
@ -177,6 +178,43 @@ def uninstall_plugin(plugin_name: str) -> str:
return "plugins/"+plugin_path return "plugins/"+plugin_path
def update_plugin(plugin_name: str):
"""更新插件"""
# 检查是否有远程地址记录
target_plugin_dir = "plugins/" + __plugins__[plugin_name]['path'].replace("\\", "/").split("plugins/")[1].split("/")[0]
remote_url = updater.get_remote_url(target_plugin_dir)
if remote_url == "https://github.com/RockChinQ/QChatGPT" or remote_url == "https://gitee.com/RockChin/QChatGPT" \
or remote_url == "" or remote_url is None or remote_url == "http://github.com/RockChinQ/QChatGPT" or remote_url == "http://gitee.com/RockChin/QChatGPT":
raise Exception("插件没有远程地址记录,无法更新")
# 把远程clone到temp/plugins/update/插件名
logging.info("克隆插件储存库: {}".format(remote_url))
from dulwich import porcelain
clone_target_dir = "temp/plugins/update/"+target_plugin_dir.split("/")[-1]+"/"
if os.path.exists(clone_target_dir):
shutil.rmtree(clone_target_dir)
if not os.path.exists(clone_target_dir):
os.makedirs(clone_target_dir)
repo = porcelain.clone(remote_url, clone_target_dir, checkout=True)
# 检查此目录是否包含requirements.txt
if os.path.exists(clone_target_dir+"requirements.txt"):
logging.info("检测到requirements.txt正在安装依赖")
import pkg.utils.pkgmgr
pkg.utils.pkgmgr.install_requirements(clone_target_dir+"requirements.txt")
import pkg.utils.log as log
log.reset_logging()
# 将temp/plugins/update/插件名 覆盖到 plugins/插件名
shutil.rmtree(target_plugin_dir)
shutil.copytree(clone_target_dir, target_plugin_dir)
class EventContext: class EventContext:
"""事件上下文""" """事件上下文"""
eid = 0 eid = 0
@ -344,3 +382,6 @@ class PluginHost:
event_context.__return_value__)) event_context.__return_value__))
return event_context return event_context
if __name__ == "__main__":
pass

View File

@ -97,37 +97,34 @@ class PluginUpdateCommand(AbstractCommandNode):
plugin_list = plugin_host.__plugins__ plugin_list = plugin_host.__plugins__
reply = [] reply = []
def closure():
try:
import pkg.utils.context
updated = []
for key in plugin_list:
plugin = plugin_list[key]
if updater.is_repo("/".join(plugin['path'].split('/')[:-1])):
success = updater.pull_latest("/".join(plugin['path'].split('/')[:-1]))
if success:
updated.append(plugin['name'])
# 检查是否有requirements.txt if len(ctx.crt_params) > 0:
pkg.utils.context.get_qqbot_manager().notify_admin("正在安装依赖...") def closure():
for key in plugin_list: try:
plugin = plugin_list[key] import pkg.utils.context
if os.path.exists("/".join(plugin['path'].split('/')[:-1])+"/requirements.txt"):
logging.info("{}检测到requirements.txt安装依赖".format(plugin['name'])) updated = []
import pkg.utils.pkgmgr
pkg.utils.pkgmgr.install_requirements("/".join(plugin['path'].split('/')[:-1])+"/requirements.txt")
import pkg.utils.log as log if ctx.crt_params[0] == 'all':
log.reset_logging() for key in plugin_list:
plugin_host.update_plugin(key)
updated.append(key)
else:
if ctx.crt_params[0] in plugin_list:
plugin_host.update_plugin(ctx.crt_params[0])
updated.append(ctx.crt_params[0])
else:
raise Exception("未找到插件: {}".format(ctx.crt_params[0]))
pkg.utils.context.get_qqbot_manager().notify_admin("已更新插件: {}".format(", ".join(updated))) pkg.utils.context.get_qqbot_manager().notify_admin("已更新插件: {}, 请发送 !reload 重载插件".format(", ".join(updated)))
except Exception as e: except Exception as e:
logging.error("插件更新失败:{}".format(e)) logging.error("插件更新失败:{}".format(e))
pkg.utils.context.get_qqbot_manager().notify_admin("插件更新失败:{} 请尝试手动更新插件".format(e)) pkg.utils.context.get_qqbot_manager().notify_admin("插件更新失败:{} 请尝试手动更新插件".format(e))
reply = ["[bot]正在更新插件,请勿重复发起..."]
threading.Thread(target=closure).start() threading.Thread(target=closure).start()
reply = ["[bot]正在更新所有插件,请勿重复发起..."] else:
reply = ["[bot]请指定要更新的插件, 或使用 !plugin update all 更新所有插件"]
return True, reply return True, reply

View File

@ -23,15 +23,16 @@ QChatGPT 插件使用Wiki
## 管理 ## 管理
### !plugin ### !plugin
``` ```
!plugin 列出所有已安装的插件 !plugin 列出所有已安装的插件
!plugin get <储存库地址> 从Git储存库安装插件(需要管理员权限) !plugin get <储存库地址> 从Git储存库安装插件(需要管理员权限)
!plugin update 更新所有插件(需要管理员权限,仅支持从储存库安装的插件) !plugin update all 更新所有插件(需要管理员权限,仅支持从储存库安装的插件)
!plugin del <插件名> 删除插件(需要管理员权限) !plugin update <插件名> 更新指定插件
!plugin on <插件名> 启用插件(需要管理员权限) !plugin del <插件名> 删除插件(需要管理员权限)
!plugin off <插件名> 禁用插件(需要管理员权限) !plugin on <插件名> 启用插件(需要管理员权限)
!plugin off <插件名> 禁用插件(需要管理员权限)
``` ```
### 控制插件执行顺序 ### 控制插件执行顺序