diff --git a/astrbot/core/star/star.py b/astrbot/core/star/star.py index e2bec4594..521513449 100644 --- a/astrbot/core/star/star.py +++ b/astrbot/core/star/star.py @@ -14,6 +14,8 @@ star_map: Dict[str, StarMetadata] = {} class StarMetadata: """ 插件的元数据。 + + 当 activated 为 False 时,star_cls 可能为 None,请不要在插件未激活时调用 star_cls 的方法。 """ name: str diff --git a/astrbot/core/star/star_manager.py b/astrbot/core/star/star_manager.py index faa454306..be476f33f 100644 --- a/astrbot/core/star/star_manager.py +++ b/astrbot/core/star/star_manager.py @@ -168,7 +168,6 @@ class PluginManager: async def reload(self, specified_plugin_name=None): """扫描并加载所有的插件 当 specified_module_path 指定时,重载指定插件""" - specified_module_path = None if specified_plugin_name: for smd in star_registry: @@ -208,17 +207,23 @@ class PluginManager: await self._unbind_plugin(smd.name, specified_module_path) + await self.load(specified_module_path) + + async def load(self, specified_module_path=None, specified_dir_name=None): + """载入插件。 + 当 specified_module_path 或者 specified_dir_name 不为 None 时,只载入指定的插件。 + """ + inactivated_plugins: list = sp.get("inactivated_plugins", []) + inactivated_llm_tools: list = sp.get("inactivated_llm_tools", []) + + alter_cmd = sp.get("alter_cmd", {}) + plugin_modules = self._get_plugin_modules() if plugin_modules is None: return False, "未找到任何插件模块" fail_rec = "" - inactivated_plugins: list = sp.get("inactivated_plugins", []) - inactivated_llm_tools: list = sp.get("inactivated_llm_tools", []) - - alter_cmd = sp.get("alter_cmd", {}) - # 导入插件模块,并尝试实例化插件类 for plugin_module in plugin_modules: try: @@ -232,8 +237,11 @@ class PluginManager: path = "data.plugins." if not reserved else "packages." path += root_dir_name + "." + module_str + # 检查是否需要载入指定的插件 if specified_module_path and path != specified_module_path: continue + if specified_dir_name and root_dir_name != specified_dir_name: + continue logger.info(f"正在载入插件 {root_dir_name} ...") @@ -287,18 +295,22 @@ class PluginManager: except Exception: pass - if plugin_config: - metadata.config = plugin_config - try: - metadata.star_cls = metadata.star_cls_type( - context=self.context, config=plugin_config - ) - except TypeError as _: - metadata.star_cls = metadata.star_cls_type( - context=self.context - ) + if path not in inactivated_plugins: + # 只有没有禁用插件时才实例化插件类 + if plugin_config: + metadata.config = plugin_config + try: + metadata.star_cls = metadata.star_cls_type( + context=self.context, config=plugin_config + ) + except TypeError as _: + metadata.star_cls = metadata.star_cls_type( + context=self.context + ) + else: + metadata.star_cls = metadata.star_cls_type(context=self.context) else: - metadata.star_cls = metadata.star_cls_type(context=self.context) + logger.info(f"插件 {metadata.name} 已被禁用。") metadata.module = module metadata.root_dir_name = root_dir_name @@ -331,19 +343,23 @@ class PluginManager: ) classes = self._get_classes(module) - if plugin_config: - try: - obj = getattr(module, classes[0])( - context=self.context, config=plugin_config - ) # 实例化插件类 - except TypeError as _: + if path not in inactivated_plugins: + # 只有没有禁用插件时才实例化插件类 + if plugin_config: + try: + obj = getattr(module, classes[0])( + context=self.context, config=plugin_config + ) # 实例化插件类 + except TypeError as _: + obj = getattr(module, classes[0])( + context=self.context + ) # 实例化插件类 + else: obj = getattr(module, classes[0])( context=self.context ) # 实例化插件类 else: - obj = getattr(module, classes[0])( - context=self.context - ) # 实例化插件类 + logger.info(f"插件 {metadata.name} 已被禁用。") metadata = None metadata = self._load_plugin_metadata( @@ -426,7 +442,8 @@ class PluginManager: async def install_plugin(self, repo_url: str, proxy=""): plugin_path = await self.updator.install(repo_url, proxy) # reload the plugin - await self.reload() + dir_name = os.path.basename(plugin_path) + await self.load(specified_dir_name=dir_name) return plugin_path async def uninstall_plugin(self, plugin_name: str): @@ -576,4 +593,5 @@ class PluginManager: os.remove(zip_file_path) except BaseException as e: logger.warning(f"删除插件压缩包失败: {str(e)}") - await self.reload() + # await self.reload() + await self.load(desti_dir) diff --git a/astrbot/dashboard/routes/plugin.py b/astrbot/dashboard/routes/plugin.py index fee6dc6b4..6e90d73e6 100644 --- a/astrbot/dashboard/routes/plugin.py +++ b/astrbot/dashboard/routes/plugin.py @@ -188,7 +188,7 @@ class PluginRoute(Route): try: logger.info(f"正在安装插件 {repo_url}") await self.plugin_manager.install_plugin(repo_url, proxy) - self.core_lifecycle.restart() + # self.core_lifecycle.restart() logger.info(f"安装插件 {repo_url} 成功。") return Response().ok(None, "安装成功。").__dict__ except Exception as e: @@ -203,7 +203,7 @@ class PluginRoute(Route): file_path = f"data/temp/{file.filename}" await file.save(file_path) await self.plugin_manager.install_plugin_from_file(file_path) - self.core_lifecycle.restart() + # self.core_lifecycle.restart() logger.info(f"安装插件 {file.filename} 成功") return Response().ok(None, "安装成功。").__dict__ except Exception as e: @@ -229,7 +229,8 @@ class PluginRoute(Route): try: logger.info(f"正在更新插件 {plugin_name}") await self.plugin_manager.update_plugin(plugin_name, proxy) - self.core_lifecycle.restart() + # self.core_lifecycle.restart() + await self.plugin_manager.reload(plugin_name) logger.info(f"更新插件 {plugin_name} 成功。") return Response().ok(None, "更新成功。").__dict__ except Exception as e: diff --git a/dashboard/src/views/ExtensionMarketplace.vue b/dashboard/src/views/ExtensionMarketplace.vue index efb7fafcf..532c8a92c 100644 --- a/dashboard/src/views/ExtensionMarketplace.vue +++ b/dashboard/src/views/ExtensionMarketplace.vue @@ -339,7 +339,7 @@ export default { this.upload_file = ""; this.onLoadingDialogResult(1, res.data.message); this.dialog = false; - this.$refs.wfr.check(); + // this.$refs.wfr.check(); }).catch((err) => { this.loading_ = false; this.onLoadingDialogResult(2, err, -1); @@ -362,7 +362,7 @@ export default { this.extension_url = ""; this.onLoadingDialogResult(1, res.data.message); this.dialog = false; - this.$refs.wfr.check(); + // this.$refs.wfr.check(); }).catch((err) => { this.loading_ = false; this.toast("安装插件失败: " + err, "error"); diff --git a/packages/astrbot/main.py b/packages/astrbot/main.py index 34712fbd8..626e67c0e 100644 --- a/packages/astrbot/main.py +++ b/packages/astrbot/main.py @@ -164,8 +164,11 @@ AstrBot 指令: plugin_list_info = "已加载的插件:\n" for plugin in self.context.get_all_stars(): plugin_list_info += ( - f"- `{plugin.name}` By {plugin.author}: {plugin.desc}\n" + f"- `{plugin.name}` By {plugin.author}: {plugin.desc}" ) + if not plugin.activated: + plugin_list_info += " (未启用)" + plugin_list_info += "\n" if plugin_list_info.strip() == "": plugin_list_info = "没有加载任何插件。" @@ -199,12 +202,8 @@ AstrBot 指令: if plugin is None: event.set_result(MessageEventResult().message("未找到此插件。")) return - help_msg = ( - plugin.star_cls.__doc__ - if plugin.star_cls.__doc__ - else "帮助信息: 未提供" - ) - help_msg += f"\n\n作者: {plugin.author}\n版本: {plugin.version}" + help_msg = "" + help_msg += f"\n\n✨ 作者: {plugin.author}\n✨ 版本: {plugin.version}" command_handlers = [] command_names = [] for handler in star_handlers_registry: @@ -221,13 +220,16 @@ AstrBot 指令: command_names.append(filter_.group_name) if len(command_handlers) > 0: - help_msg += "\n\n指令列表:\n" + help_msg += "\n\n🔧 指令列表:\n" for i in range(len(command_handlers)): - help_msg += f"{command_names[i]}: {command_handlers[i].desc}\n" + help_msg += f"- {command_names[i]}" + if command_handlers[i].desc: + help_msg += f": {command_handlers[i].desc}" + help_msg += "\n" help_msg += "\nTip: 指令的触发需要添加唤醒前缀,默认为 /。" - ret = f"插件 {oper1} 帮助信息:\n" + help_msg + ret = f"🧩 插件 {oper1} 帮助信息:\n" + help_msg ret += "更多帮助信息请查看插件仓库 README。" event.set_result(MessageEventResult().message(ret).use_t2i(False))