mirror of
https://github.com/NapNeko/NapCatQQ.git
synced 2026-03-03 09:10:25 +00:00
Commented out ImportLocalPluginHandler import and the multer upload configuration (50MB limit and .zip file filter). Temporarily disables local plugin .zip uploads, likely for debugging or while refactoring the upload/import flow; can be re-enabled when upload handling is restored.
169 lines
5.5 KiB
TypeScript
169 lines
5.5 KiB
TypeScript
import { Router } from 'express';
|
|
// import multer from 'multer';
|
|
import path from 'path';
|
|
import fs from 'fs';
|
|
import os from 'os';
|
|
import {
|
|
GetPluginListHandler,
|
|
SetPluginStatusHandler,
|
|
UninstallPluginHandler,
|
|
GetPluginConfigHandler,
|
|
SetPluginConfigHandler,
|
|
RegisterPluginManagerHandler,
|
|
PluginConfigSSEHandler,
|
|
PluginConfigChangeHandler,
|
|
// ImportLocalPluginHandler,
|
|
GetPluginIconHandler
|
|
} from '@/napcat-webui-backend/src/api/Plugin';
|
|
import {
|
|
GetPluginStoreListHandler,
|
|
GetPluginStoreDetailHandler,
|
|
InstallPluginFromStoreHandler,
|
|
InstallPluginFromStoreSSEHandler
|
|
} from '@/napcat-webui-backend/src/api/PluginStore';
|
|
import { WebUiDataRuntime } from '@/napcat-webui-backend/src/helper/Data';
|
|
import { NapCatOneBot11Adapter } from '@/napcat-onebot/index';
|
|
import { OB11PluginMangerAdapter } from '@/napcat-onebot/network/plugin-manger';
|
|
|
|
// 配置 multer 用于文件上传
|
|
const uploadDir = path.join(os.tmpdir(), 'napcat-plugin-uploads');
|
|
if (!fs.existsSync(uploadDir)) {
|
|
fs.mkdirSync(uploadDir, { recursive: true });
|
|
}
|
|
|
|
// const storage = multer.diskStorage({
|
|
// destination: (_req, _file, cb) => {
|
|
// cb(null, uploadDir);
|
|
// },
|
|
// filename: (_req, file, cb) => {
|
|
// const uniqueSuffix = Date.now() + '-' + Math.round(Math.random() * 1E9);
|
|
// cb(null, uniqueSuffix + '-' + file.originalname);
|
|
// }
|
|
// });
|
|
|
|
// const upload = multer({
|
|
// storage,
|
|
// limits: {
|
|
// fileSize: 50 * 1024 * 1024, // 50MB 限制
|
|
// },
|
|
// fileFilter: (_req, file, cb) => {
|
|
// // 只允许 .zip 文件
|
|
// if (file.mimetype === 'application/zip' ||
|
|
// file.mimetype === 'application/x-zip-compressed' ||
|
|
// file.originalname.endsWith('.zip')) {
|
|
// cb(null, true);
|
|
// } else {
|
|
// cb(new Error('Only .zip files are allowed'));
|
|
// }
|
|
// }
|
|
// });
|
|
|
|
const router: Router = Router();
|
|
|
|
router.get('/List', GetPluginListHandler);
|
|
router.post('/SetStatus', SetPluginStatusHandler);
|
|
router.post('/Uninstall', UninstallPluginHandler);
|
|
router.get('/Config', GetPluginConfigHandler);
|
|
router.post('/Config', SetPluginConfigHandler);
|
|
router.get('/Config/SSE', PluginConfigSSEHandler);
|
|
router.post('/Config/Change', PluginConfigChangeHandler);
|
|
router.post('/RegisterManager', RegisterPluginManagerHandler);
|
|
// router.post('/Import', upload.single('plugin'), ImportLocalPluginHandler); // 禁用插件上传
|
|
router.get('/Icon/:pluginId', GetPluginIconHandler);
|
|
|
|
// 插件商店相关路由
|
|
router.get('/Store/List', GetPluginStoreListHandler);
|
|
router.get('/Store/Detail/:id', GetPluginStoreDetailHandler);
|
|
router.post('/Store/Install', InstallPluginFromStoreHandler);
|
|
router.get('/Store/Install/SSE', InstallPluginFromStoreSSEHandler);
|
|
|
|
// 插件扩展路由 - 动态挂载插件注册的 API 路由
|
|
router.use('/ext/:pluginId', (req, res, next): void => {
|
|
const { pluginId } = req.params;
|
|
|
|
if (!pluginId) {
|
|
res.status(400).json({ code: -1, message: 'Plugin ID is required' });
|
|
return;
|
|
}
|
|
|
|
// 获取插件管理器
|
|
const ob11 = WebUiDataRuntime.getOneBotContext() as NapCatOneBot11Adapter;
|
|
if (!ob11) {
|
|
res.status(503).json({ code: -1, message: 'OneBot context not available' });
|
|
return;
|
|
}
|
|
|
|
const pluginManager = ob11.networkManager.findSomeAdapter('plugin_manager') as OB11PluginMangerAdapter;
|
|
if (!pluginManager) {
|
|
res.status(503).json({ code: -1, message: 'Plugin manager not available' });
|
|
return;
|
|
}
|
|
|
|
// 获取插件路由
|
|
const routerRegistry = pluginManager.getPluginRouter(pluginId);
|
|
if (!routerRegistry || !routerRegistry.hasApiRoutes()) {
|
|
res.status(404).json({ code: -1, message: `Plugin '${pluginId}' has no registered API routes` });
|
|
return;
|
|
}
|
|
|
|
// 构建并执行插件路由
|
|
const pluginRouter = routerRegistry.buildApiRouter();
|
|
pluginRouter(req, res, next);
|
|
});
|
|
|
|
// 插件页面路由 - 服务插件注册的 HTML 页面
|
|
router.get('/page/:pluginId/:pagePath', (req, res): void => {
|
|
const { pluginId, pagePath } = req.params;
|
|
|
|
if (!pluginId) {
|
|
res.status(400).json({ code: -1, message: 'Plugin ID is required' });
|
|
return;
|
|
}
|
|
|
|
// 获取插件管理器
|
|
const ob11 = WebUiDataRuntime.getOneBotContext() as NapCatOneBot11Adapter;
|
|
if (!ob11) {
|
|
res.status(503).json({ code: -1, message: 'OneBot context not available' });
|
|
return;
|
|
}
|
|
|
|
const pluginManager = ob11.networkManager.findSomeAdapter('plugin_manager') as OB11PluginMangerAdapter;
|
|
if (!pluginManager) {
|
|
res.status(503).json({ code: -1, message: 'Plugin manager not available' });
|
|
return;
|
|
}
|
|
|
|
// 获取插件路由
|
|
const routerRegistry = pluginManager.getPluginRouter(pluginId);
|
|
if (!routerRegistry || !routerRegistry.hasPages()) {
|
|
res.status(404).json({ code: -1, message: `Plugin '${pluginId}' has no registered pages` });
|
|
return;
|
|
}
|
|
|
|
// 查找匹配的页面
|
|
const pages = routerRegistry.getPages();
|
|
const page = pages.find(p => p.path === '/' + pagePath || p.path === pagePath);
|
|
if (!page) {
|
|
res.status(404).json({ code: -1, message: `Page '${pagePath}' not found in plugin '${pluginId}'` });
|
|
return;
|
|
}
|
|
|
|
// 获取插件路径
|
|
const pluginPath = routerRegistry.getPluginPath();
|
|
if (!pluginPath) {
|
|
res.status(500).json({ code: -1, message: 'Plugin path not available' });
|
|
return;
|
|
}
|
|
|
|
// 构建 HTML 文件路径并发送
|
|
const htmlFilePath = path.join(pluginPath, page.htmlFile);
|
|
if (!fs.existsSync(htmlFilePath)) {
|
|
res.status(404).json({ code: -1, message: `HTML file not found: ${page.htmlFile}` });
|
|
return;
|
|
}
|
|
|
|
res.sendFile(htmlFilePath);
|
|
});
|
|
|
|
export { router as PluginRouter };
|