From 7f05aee11d8f11c0f0a5adca97c2e1eb22e173a3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=89=8B=E7=93=9C=E4=B8=80=E5=8D=81=E9=9B=AA?= Date: Thu, 29 Jan 2026 15:44:26 +0800 Subject: [PATCH] Add manual plugin manager registration support Introduces backend and frontend logic to manually register the plugin manager if not already loaded. Adds a new API endpoint and frontend UI prompt to guide users through registration after plugin installation when necessary. --- .../napcat-webui-backend/src/api/Plugin.ts | 44 +++++++++++++++++++ .../napcat-webui-backend/src/router/Plugin.ts | 4 +- .../src/controllers/plugin_manager.ts | 8 ++++ .../src/pages/dashboard/plugin_store.tsx | 32 ++++++++++++++ 4 files changed, 87 insertions(+), 1 deletion(-) diff --git a/packages/napcat-webui-backend/src/api/Plugin.ts b/packages/napcat-webui-backend/src/api/Plugin.ts index 653855fe..3e1a7ede 100644 --- a/packages/napcat-webui-backend/src/api/Plugin.ts +++ b/packages/napcat-webui-backend/src/api/Plugin.ts @@ -3,6 +3,7 @@ import { WebUiDataRuntime } from '@/napcat-webui-backend/src/helper/Data'; import { sendError, sendSuccess } from '@/napcat-webui-backend/src/utils/response'; import { NapCatOneBot11Adapter } from '@/napcat-onebot/index'; import { OB11PluginMangerAdapter } from '@/napcat-onebot/network/plugin-manger'; +import { webUiPathWrapper } from '@/napcat-webui-backend/index'; import path from 'path'; import fs from 'fs'; @@ -13,6 +14,49 @@ const getPluginManager = (): OB11PluginMangerAdapter | null => { return ob11.networkManager.findSomeAdapter('plugin_manager') as OB11PluginMangerAdapter; }; +// Helper to get OneBot context +const getOneBotContext = (): NapCatOneBot11Adapter | null => { + return WebUiDataRuntime.getOneBotContext() as NapCatOneBot11Adapter; +}; + +/** + * 手动注册插件管理器到 NetworkManager + */ +export const RegisterPluginManagerHandler: RequestHandler = async (_req, res) => { + const ob11 = getOneBotContext(); + if (!ob11) { + return sendError(res, 'OneBot context not found'); + } + + // 检查是否已经注册 + const existingManager = ob11.networkManager.findSomeAdapter('plugin_manager'); + if (existingManager) { + return sendError(res, '插件管理器已经注册'); + } + + try { + // 确保插件目录存在 + const pluginPath = webUiPathWrapper.pluginPath; + if (!fs.existsSync(pluginPath)) { + fs.mkdirSync(pluginPath, { recursive: true }); + } + + // 创建并注册插件管理器 + const pluginManager = new OB11PluginMangerAdapter( + 'plugin_manager', + ob11.core, + ob11, + ob11.actions + ); + + await ob11.networkManager.registerAdapterAndOpen(pluginManager); + + return sendSuccess(res, { message: '插件管理器注册成功' }); + } catch (e: any) { + return sendError(res, '注册插件管理器失败: ' + e.message); + } +}; + export const GetPluginListHandler: RequestHandler = async (_req, res) => { const pluginManager = getPluginManager(); if (!pluginManager) { diff --git a/packages/napcat-webui-backend/src/router/Plugin.ts b/packages/napcat-webui-backend/src/router/Plugin.ts index c175cfa9..2b426007 100644 --- a/packages/napcat-webui-backend/src/router/Plugin.ts +++ b/packages/napcat-webui-backend/src/router/Plugin.ts @@ -4,7 +4,8 @@ import { SetPluginStatusHandler, UninstallPluginHandler, GetPluginConfigHandler, - SetPluginConfigHandler + SetPluginConfigHandler, + RegisterPluginManagerHandler } from '@/napcat-webui-backend/src/api/Plugin'; import { GetPluginStoreListHandler, @@ -20,6 +21,7 @@ router.post('/SetStatus', SetPluginStatusHandler); router.post('/Uninstall', UninstallPluginHandler); router.get('/Config', GetPluginConfigHandler); router.post('/Config', SetPluginConfigHandler); +router.post('/RegisterManager', RegisterPluginManagerHandler); // 插件商店相关路由 router.get('/Store/List', GetPluginStoreListHandler); diff --git a/packages/napcat-webui-frontend/src/controllers/plugin_manager.ts b/packages/napcat-webui-frontend/src/controllers/plugin_manager.ts index fbe400bc..aad26b1e 100644 --- a/packages/napcat-webui-frontend/src/controllers/plugin_manager.ts +++ b/packages/napcat-webui-frontend/src/controllers/plugin_manager.ts @@ -43,6 +43,14 @@ export default class PluginManager { return data.data; } + /** + * 手动注册插件管理器到 NetworkManager + */ + public static async registerPluginManager () { + const { data } = await serverRequest.post>('/Plugin/RegisterManager'); + return data.data; + } + public static async setPluginStatus (name: string, enable: boolean, filename?: string) { diff --git a/packages/napcat-webui-frontend/src/pages/dashboard/plugin_store.tsx b/packages/napcat-webui-frontend/src/pages/dashboard/plugin_store.tsx index 96ee58d3..352ee127 100644 --- a/packages/napcat-webui-frontend/src/pages/dashboard/plugin_store.tsx +++ b/packages/napcat-webui-frontend/src/pages/dashboard/plugin_store.tsx @@ -38,6 +38,7 @@ export default function PluginStorePage () { const [loading, setLoading] = useState(false); const [searchQuery, setSearchQuery] = useState(''); const [activeTab, setActiveTab] = useState('all'); + const [pluginManagerNotFound, setPluginManagerNotFound] = useState(false); const dialog = useDialog(); // 获取镜像列表 @@ -52,6 +53,10 @@ export default function PluginStorePage () { try { const data = await PluginManager.getPluginStoreList(); setPlugins(data.plugins); + + // 检查插件管理器是否已加载 + const listResult = await PluginManager.getPluginList(); + setPluginManagerNotFound(listResult.pluginManagerNotFound); } catch (e: any) { toast.error(e.message); } finally { @@ -195,6 +200,33 @@ export default function PluginStorePage () { } else if (data.success) { toast.success('插件安装成功!', { id: loadingToast }); eventSource.close(); + // 安装成功后检查插件管理器状态 + if (pluginManagerNotFound) { + dialog.confirm({ + title: '插件管理器未加载', + content: ( +
+

+ 插件已安装成功,但插件管理器尚未加载。 +

+

+ 是否立即注册插件管理器?注册后插件才能正常运行。 +

+
+ ), + confirmText: '注册插件管理器', + cancelText: '稍后再说', + onConfirm: async () => { + try { + await PluginManager.registerPluginManager(); + toast.success('插件管理器注册成功'); + setPluginManagerNotFound(false); + } catch (e: any) { + toast.error('注册失败: ' + e.message); + } + }, + }); + } } else if (data.message) { toast.loading(data.message, { id: loadingToast }); }