refactor: moveplugins and temp folder to data/
This commit is contained in:
@@ -22,6 +22,7 @@ jobs:
|
||||
pip install -r requirements.txt
|
||||
pip install pytest pytest-cov pytest-asyncio
|
||||
mkdir data
|
||||
mkdir data/plugins
|
||||
mkdir data/config
|
||||
mkdir temp
|
||||
|
||||
|
||||
@@ -1,10 +0,0 @@
|
||||
# helloworld
|
||||
|
||||
AstrBot 插件模板
|
||||
|
||||
A template plugin for AstrBot plugin feature
|
||||
|
||||
# 支持
|
||||
|
||||
[帮助文档](https://astrbot.soulter.top/center/docs/%E5%BC%80%E5%8F%91/%E6%8F%92%E4%BB%B6%E5%BC%80%E5%8F%91/
|
||||
)
|
||||
@@ -1 +0,0 @@
|
||||
https://github.com/Soulter/helloworld
|
||||
@@ -1,36 +0,0 @@
|
||||
flag_not_support = False
|
||||
try:
|
||||
from util.plugin_dev.api.v1 import (
|
||||
Context,
|
||||
CommandResult,
|
||||
AstrMessageEvent,
|
||||
Middleware,
|
||||
)
|
||||
except ImportError:
|
||||
flag_not_support = True
|
||||
print("导入接口失败。请升级到 AstrBot 最新版本。")
|
||||
|
||||
'''
|
||||
注意以格式 XXXPlugin 或 Main 来修改插件名。
|
||||
提示:把此模板仓库 fork 之后 clone 到机器人文件夹下的 addons/plugins/ 目录下,然后用 Pycharm/VSC 等工具打开可获更棒的编程体验(自动补全等)
|
||||
'''
|
||||
class HelloWorldPlugin:
|
||||
"""
|
||||
AstrBot 会传递 context 给插件。
|
||||
|
||||
- context.register_commands: 注册指令
|
||||
- context.register_task: 注册任务
|
||||
- context.message_handler: 消息处理器(平台类插件用)
|
||||
"""
|
||||
def __init__(self, context: Context) -> None:
|
||||
self.context = context
|
||||
self.context.register_commands("helloworld", "helloworld", "内置测试指令。", 1, self.helloworld)
|
||||
|
||||
"""
|
||||
指令处理函数。
|
||||
|
||||
- 需要接收两个参数:message: AstrMessageEvent, context: Context
|
||||
- 返回 CommandResult 对象
|
||||
"""
|
||||
async def helloworld(self, message: AstrMessageEvent, context: Context):
|
||||
return CommandResult().message("Hello, World!")
|
||||
@@ -1,6 +0,0 @@
|
||||
name: helloworld # 这是你的插件的唯一识别名。
|
||||
desc: 这是 AstrBot 的默认插件。
|
||||
help:
|
||||
version: v1.3 # 插件版本号。格式:v1.1.1 或者 v1.1
|
||||
author: Soulter # 作者
|
||||
repo: https://github.com/Soulter/helloworld # 插件的仓库地址
|
||||
@@ -1,21 +1,20 @@
|
||||
import asyncio
|
||||
import traceback
|
||||
import os
|
||||
from astrbot.message.handler import MessageHandler
|
||||
from astrbot.persist.helper import dbConn
|
||||
from dashboard.server import AstrBotDashBoard
|
||||
from model.provider.provider import Provider
|
||||
from model.command.manager import CommandManager
|
||||
from model.command.internal_handler import InternalCommandHandler
|
||||
from model.plugin.manager import PluginManager
|
||||
from model.platform.manager import PlatformManager
|
||||
from typing import Dict, List, Union
|
||||
from typing import Union
|
||||
from type.types import Context
|
||||
from type.config import VERSION
|
||||
from SparkleLogging.utils.core import LogManager
|
||||
from logging import Logger
|
||||
from util.cmd_config import AstrBotConfig
|
||||
from util.cmd_config import AstrBotConfig, try_migrate
|
||||
from util.metrics import MetricUploader
|
||||
from util.config_utils import *
|
||||
from util.updator.astrbot_updator import AstrBotUpdator
|
||||
|
||||
logger: Logger = LogManager.GetLogger(log_name='astrbot')
|
||||
@@ -26,7 +25,7 @@ class AstrBotBootstrap():
|
||||
self.context = Context()
|
||||
|
||||
# load configs and ensure the backward compatibility
|
||||
try_migrate_config()
|
||||
try_migrate()
|
||||
self.config_helper = AstrBotConfig()
|
||||
self.context.config_helper = self.config_helper
|
||||
logger.info("AstrBot v" + VERSION)
|
||||
|
||||
+1
-2
@@ -228,8 +228,7 @@ class AstrBotDashBoard():
|
||||
file = request.files['file']
|
||||
print(file.filename)
|
||||
logger.info(f"正在安装用户上传的插件 {file.filename}")
|
||||
# save file to temp/
|
||||
file_path = f"temp/{uuid.uuid4()}.zip"
|
||||
file_path = f"data/temp/{uuid.uuid4()}.zip"
|
||||
file.save(file_path)
|
||||
self.plugin_manager.install_plugin_from_file(file_path)
|
||||
logger.info(f"安装插件 {file.filename} 成功")
|
||||
|
||||
@@ -42,7 +42,8 @@ def check_env():
|
||||
exit()
|
||||
|
||||
os.makedirs("data/config", exist_ok=True)
|
||||
os.makedirs("temp", exist_ok=True)
|
||||
os.makedirs("data/plugins", exist_ok=True)
|
||||
os.makedirs("data/temp", exist_ok=True)
|
||||
|
||||
# workaround for issue #181
|
||||
mimetypes.add_type("text/javascript", ".js")
|
||||
|
||||
@@ -19,23 +19,23 @@ class InternalCommandHandler:
|
||||
self.plugin_manager = plugin_manager
|
||||
|
||||
self.manager.register("help", "查看帮助", 10, self.help)
|
||||
self.manager.register("wake", "设置机器人唤醒词", 10, self.set_nick)
|
||||
self.manager.register("update", "更新 AstrBot", 10, self.update)
|
||||
self.manager.register("wake", "唤醒前缀", 10, self.set_nick)
|
||||
self.manager.register("update", "更新管理", 10, self.update)
|
||||
self.manager.register("plugin", "插件管理", 10, self.plugin)
|
||||
self.manager.register("reboot", "重启 AstrBot", 10, self.reboot)
|
||||
self.manager.register("websearch", "网页搜索开关", 10, self.web_search)
|
||||
self.manager.register("t2i", "文本转图片开关", 10, self.t2i_toggle)
|
||||
self.manager.register("myid", "获取你在此平台上的ID", 10, self.myid)
|
||||
self.manager.register("provider", "查看和切换当前使用的 LLM 资源来源", 10, self.provider)
|
||||
self.manager.register("websearch", "网页搜索", 10, self.web_search)
|
||||
self.manager.register("t2i", "文转图", 10, self.t2i_toggle)
|
||||
self.manager.register("myid", "用户ID", 10, self.myid)
|
||||
self.manager.register("provider", "LLM 接入源", 10, self.provider)
|
||||
|
||||
def provider(self, message: AstrMessageEvent, context: Context):
|
||||
if len(context.llms) == 0:
|
||||
return CommandResult().message("当前没有加载任何 LLM 资源。")
|
||||
return CommandResult().message("当前没有加载任何 LLM 接入源。")
|
||||
|
||||
tokens = self.manager.command_parser.parse(message.message_str)
|
||||
|
||||
if tokens.len == 1:
|
||||
ret = "## 当前载入的 LLM 资源\n"
|
||||
ret = "## 当前载入的 LLM 接入源\n"
|
||||
for idx, llm in enumerate(context.llms):
|
||||
ret += f"{idx}. {llm.llm_name}"
|
||||
if llm.origin:
|
||||
@@ -44,7 +44,7 @@ class InternalCommandHandler:
|
||||
ret += " (当前使用)"
|
||||
ret += "\n"
|
||||
|
||||
ret += "\n使用 provider <序号> 切换 LLM 资源。"
|
||||
ret += "\n使用 provider <序号> 切换 LLM 接入源。"
|
||||
return CommandResult().message(ret)
|
||||
else:
|
||||
try:
|
||||
@@ -52,7 +52,7 @@ class InternalCommandHandler:
|
||||
if idx >= len(context.llms):
|
||||
return CommandResult().message("provider: 无效的序号。")
|
||||
context.message_handler.set_provider(context.llms[idx].llm_instance)
|
||||
return CommandResult().message(f"已经成功切换到 LLM 资源 {context.llms[idx].llm_name}。")
|
||||
return CommandResult().message(f"已经成功切换到 LLM 接入源 {context.llms[idx].llm_name}。")
|
||||
except BaseException as e:
|
||||
return CommandResult().message("provider: 参数错误。")
|
||||
|
||||
@@ -71,7 +71,7 @@ class InternalCommandHandler:
|
||||
return CommandResult(
|
||||
hit=True,
|
||||
success=True,
|
||||
message_chain=f"已经成功将唤醒词设定为 {nick}。",
|
||||
message_chain=f"已经成功将唤醒前缀设定为 {nick}。",
|
||||
)
|
||||
|
||||
def update(self, message: AstrMessageEvent, context: Context):
|
||||
@@ -280,5 +280,5 @@ class InternalCommandHandler:
|
||||
return CommandResult(
|
||||
hit=True,
|
||||
success=False,
|
||||
message_chain=f"在 {message.platform} 上获取你的ID失败,原因: {str(e)}",
|
||||
message_chain=f"获取失败,原因: {str(e)}",
|
||||
)
|
||||
|
||||
@@ -24,4 +24,3 @@ class PluginCommandBridge():
|
||||
|
||||
def register_command(self, plugin_name, command_name, description, priority, handler, use_regex=False, ignore_prefix=False):
|
||||
self.plugin_commands_waitlist.append(CommandRegisterRequest(command_name, description, priority, handler, use_regex, plugin_name, ignore_prefix))
|
||||
|
||||
@@ -184,7 +184,7 @@ class PluginManager():
|
||||
|
||||
self.check_plugin_dept_update(target_plugin=root_dir_name)
|
||||
|
||||
module = __import__("addons.plugins." +
|
||||
module = __import__("data.plugins." +
|
||||
root_dir_name + "." + p, fromlist=[p])
|
||||
|
||||
cls = self.get_classes(module)
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
VERSION = '3.3.9'
|
||||
VERSION = '3.3.12'
|
||||
|
||||
DEFAULT_CONFIG = {
|
||||
"qqbot": {
|
||||
|
||||
+26
-1
@@ -1,6 +1,8 @@
|
||||
import os
|
||||
import json
|
||||
import shutil
|
||||
import logging
|
||||
from util.io import on_error
|
||||
from type.config import DEFAULT_CONFIG, DEFAULT_CONFIG_VERSION_2, MAPPINGS_1_2
|
||||
from dataclasses import dataclass, field, asdict
|
||||
from typing import List, Dict, Optional
|
||||
@@ -295,4 +297,27 @@ class AstrBotConfig():
|
||||
raise KeyError(f"Key {key} not found in config.")
|
||||
|
||||
def check_exist(self) -> bool:
|
||||
return os.path.exists(ASTRBOT_CONFIG_PATH)
|
||||
return os.path.exists(ASTRBOT_CONFIG_PATH)
|
||||
|
||||
def try_migrate():
|
||||
'''
|
||||
- 将 cmd_config.json 迁移至 data/cmd_config.json (如果存在)
|
||||
- 将 addons/plugins 迁移至 data/plugins (如果存在)
|
||||
'''
|
||||
if os.path.exists("cmd_config.json") and not os.path.exists("data/cmd_config.json"):
|
||||
try:
|
||||
shutil.move("cmd_config.json", "data/cmd_config.json")
|
||||
except:
|
||||
logger.error("迁移 cmd_config.json 失败。")
|
||||
|
||||
if os.path.exists("addons/plugins"):
|
||||
if os.path.exists("data/plugins"):
|
||||
try:
|
||||
shutil.rmtree("data/plugins", onerror=on_error)
|
||||
except:
|
||||
logger.error("删除 data/plugins 失败。")
|
||||
try:
|
||||
shutil.move("addons/plugins", "data/")
|
||||
shutil.rmtree("addons", onerror=on_error)
|
||||
except:
|
||||
logger.error("迁移 addons/plugins 失败。")
|
||||
@@ -1,15 +0,0 @@
|
||||
import json, os, shutil
|
||||
import logging
|
||||
|
||||
logger = logging.getLogger("astrbot")
|
||||
|
||||
def try_migrate_config():
|
||||
'''
|
||||
将 cmd_config.json 迁移至 data/cmd_config.json (如果存在的话)
|
||||
'''
|
||||
if os.path.exists("cmd_config.json") and not os.path.exists("data/cmd_config.json"):
|
||||
try:
|
||||
shutil.move("cmd_config.json", "data/cmd_config.json")
|
||||
except:
|
||||
logger.error("迁移 cmd_config.json 失败。AstrBot 将不会读取配置文件,你可以手动将 cmd_config.json 迁移至 data/cmd_config.json。")
|
||||
|
||||
+4
-6
@@ -47,13 +47,11 @@ def port_checker(port: int, host: str = "localhost"):
|
||||
|
||||
|
||||
def save_temp_img(img: Image) -> str:
|
||||
if not os.path.exists("temp"):
|
||||
os.makedirs("temp")
|
||||
|
||||
os.makedirs("data/temp", exist_ok=True)
|
||||
# 获得文件创建时间,清除超过1小时的
|
||||
try:
|
||||
for f in os.listdir("temp"):
|
||||
path = os.path.join("temp", f)
|
||||
for f in os.listdir("data/temp"):
|
||||
path = os.path.join("data/temp", f)
|
||||
if os.path.isfile(path):
|
||||
ctime = os.path.getctime(path)
|
||||
if time.time() - ctime > 3600:
|
||||
@@ -63,7 +61,7 @@ def save_temp_img(img: Image) -> str:
|
||||
|
||||
# 获得时间戳
|
||||
timestamp = int(time.time())
|
||||
p = f"temp/{timestamp}.jpg"
|
||||
p = f"data/temp/{timestamp}.jpg"
|
||||
|
||||
if isinstance(img, Image.Image):
|
||||
img.save(p)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import os, psutil, sys, zipfile, shutil, time
|
||||
import os, psutil, sys, time
|
||||
from util.updator.zip_updator import ReleaseInfo, RepoZipUpdator
|
||||
from SparkleLogging.utils.core import LogManager
|
||||
from logging import Logger
|
||||
@@ -65,7 +65,6 @@ class AstrBotUpdator(RepoZipUpdator):
|
||||
raise Exception(f"未找到版本号为 {version} 的更新文件。")
|
||||
|
||||
try:
|
||||
# self.download_from_repo_url("temp", file_url)
|
||||
download_file(file_url, "temp.zip")
|
||||
self.unzip_file("temp.zip", self.MAIN_PATH)
|
||||
except BaseException as e:
|
||||
@@ -78,40 +77,4 @@ class AstrBotUpdator(RepoZipUpdator):
|
||||
'''
|
||||
解压缩文件, 并将压缩包内**第一个**文件夹内的文件移动到 target_dir
|
||||
'''
|
||||
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)}")
|
||||
pass
|
||||
@@ -1,19 +1,19 @@
|
||||
import os
|
||||
import os, zipfile, shutil
|
||||
|
||||
from util.updator.zip_updator import RepoZipUpdator
|
||||
from util.io import remove_dir
|
||||
from type.plugin import PluginMetadata
|
||||
from type.register import RegisteredPlugin
|
||||
from typing import Union
|
||||
from SparkleLogging.utils.core 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__)), "../../addons/plugins"))
|
||||
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
|
||||
@@ -44,5 +44,41 @@ class PluginUpdator(RepoZipUpdator):
|
||||
|
||||
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)}")
|
||||
|
||||
Reference in New Issue
Block a user