mirror of
https://github.com/NapNeko/NapCatQQ.git
synced 2026-02-05 15:11:15 +00:00
Implemented backend API and frontend UI for importing local plugin zip files. The backend now supports file uploads via a new /Plugin/Import endpoint using multer, and the frontend provides a button to upload and import plugins directly from the dashboard. Prompt to register plugin manager if not loaded Renames plugin_develop.ts to plugin-develop.ts for consistency. Updates the plugin import handler to prompt the user to register the plugin manager if it is not loaded, improving user experience and error handling.
76 lines
2.3 KiB
TypeScript
76 lines
2.3 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
|
|
} from '@/napcat-webui-backend/src/api/Plugin';
|
|
import {
|
|
GetPluginStoreListHandler,
|
|
GetPluginStoreDetailHandler,
|
|
InstallPluginFromStoreHandler,
|
|
InstallPluginFromStoreSSEHandler
|
|
} from '@/napcat-webui-backend/src/api/PluginStore';
|
|
|
|
// 配置 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('/Store/List', GetPluginStoreListHandler);
|
|
router.get('/Store/Detail/:id', GetPluginStoreDetailHandler);
|
|
router.post('/Store/Install', InstallPluginFromStoreHandler);
|
|
router.get('/Store/Install/SSE', InstallPluginFromStoreSSEHandler);
|
|
|
|
export { router as PluginRouter };
|