Files
AstrBot/util/updator/plugin_updator.py
T
Soulter 8a50786e61 feat: 支持设置控制台日志级别;
refactor: 重写了后端与仪表盘的日志通信
2024-09-22 10:23:26 -04:00

85 lines
3.8 KiB
Python

import os, zipfile, shutil
from util.updator.zip_updator import RepoZipUpdator
from util.io import remove_dir
from type.register import RegisteredPlugin
from typing import Union
from util.log import LogManager
from logging import Logger
from util.io import on_error
logger: Logger = LogManager.GetLogger(log_name='astrbot')
class PluginUpdator(RepoZipUpdator):
def __init__(self) -> None:
self.plugin_store_path = os.path.abspath(os.path.join(os.path.dirname(os.path.abspath(__file__)), "../../data/plugins"))
def get_plugin_store_path(self) -> str:
return self.plugin_store_path
async def update(self, plugin: Union[RegisteredPlugin, str]) -> str:
repo_url = None
if not isinstance(plugin, str):
plugin_path = os.path.join(self.plugin_store_path, plugin.root_dir_name)
if not os.path.exists(os.path.join(plugin_path, "REPO")):
raise Exception("插件更新信息文件 `REPO` 不存在,请手动升级,或者先卸载然后重新安装该插件。")
with open(os.path.join(plugin_path, "REPO"), "r", encoding='utf-8') as f:
repo_url = f.read()
else:
repo_url = plugin
plugin_path = os.path.join(self.plugin_store_path, self.format_repo_name(repo_url))
logger.info(f"正在更新插件,路径: {plugin_path},仓库地址: {repo_url}")
await self.download_from_repo_url(plugin_path, repo_url)
try:
remove_dir(plugin_path)
except BaseException as e:
logger.error(f"删除旧版本插件 {plugin.metadata.plugin_name} 文件夹失败: {str(e)},使用覆盖安装。")
self.unzip_file(plugin_path + ".zip", plugin_path)
return plugin_path
def unzip_file(self, zip_path: str, target_dir: str):
os.makedirs(target_dir, exist_ok=True)
update_dir = ""
logger.info(f"解压文件: {zip_path}")
with zipfile.ZipFile(zip_path, 'r') as z:
update_dir = z.namelist()[0]
z.extractall(target_dir)
avoid_dirs = ["logs", "data", "configs", "temp_plugins", update_dir]
# copy addons/plugins to the target_dir temporarily
# if os.path.exists(os.path.join(target_dir, "addons/plugins")):
# logger.info("备份插件目录:从 addons/plugins 到 temp_plugins")
# shutil.copytree(os.path.join(target_dir, "addons/plugins"), "temp_plugins")
files = os.listdir(os.path.join(target_dir, update_dir))
for f in files:
logger.info(f"移动更新文件/目录: {f}")
if os.path.isdir(os.path.join(target_dir, update_dir, f)):
if f in avoid_dirs: continue
if os.path.exists(os.path.join(target_dir, f)):
shutil.rmtree(os.path.join(target_dir, f), onerror=on_error)
else:
if os.path.exists(os.path.join(target_dir, f)):
os.remove(os.path.join(target_dir, f))
shutil.move(os.path.join(target_dir, update_dir, f), target_dir)
# move back
# if os.path.exists("temp_plugins"):
# logger.info("恢复插件目录:从 temp_plugins 到 addons/plugins")
# shutil.rmtree(os.path.join(target_dir, "addons/plugins"), onerror=on_error)
# shutil.move("temp_plugins", os.path.join(target_dir, "addons/plugins"))
try:
logger.info(f"删除临时更新文件: {zip_path}{os.path.join(target_dir, update_dir)}")
shutil.rmtree(os.path.join(target_dir, update_dir), onerror=on_error)
os.remove(zip_path)
except:
logger.warn(f"删除更新文件失败,可以手动删除 {zip_path}{os.path.join(target_dir, update_dir)}")