mirror of
https://github.com/NapNeko/NapCatQQ.git
synced 2026-03-03 09:10:25 +00:00
Introduced new interface definitions in napcat-common for logging, status, and subscription. Refactored napcat-webui-backend to use these interfaces, decoupling it from napcat-core and napcat-onebot. Moved OneBot config schema to backend and updated imports. Updated framework and shell to pass subscriptions to InitWebUi. Improved type safety and modularity across backend and shared packages.
80 lines
2.5 KiB
TypeScript
80 lines
2.5 KiB
TypeScript
import type { RequestHandler } from 'express';
|
||
import { sendError, sendSuccess } from '../utils/response';
|
||
import { terminalManager } from '../terminal/terminal_manager';
|
||
import { logSubscription, WebUiConfig } from '@/napcat-webui-backend/index';
|
||
// 判断是否是 macos
|
||
const isMacOS = process.platform === 'darwin';
|
||
|
||
// 日志脱敏函数
|
||
const sanitizeLog = (log: string): string => {
|
||
// 脱敏 token 参数,将 token=xxx 替换为 token=***
|
||
return log.replace(/token=[\w\d]+/gi, 'token=***');
|
||
};
|
||
// 日志记录
|
||
export const LogHandler: RequestHandler = async (req, res) => {
|
||
const filename = req.query['id'];
|
||
if (!filename || typeof filename !== 'string') {
|
||
return sendError(res, 'ID不能为空');
|
||
}
|
||
|
||
if (filename.includes('..')) {
|
||
return sendError(res, 'ID不合法');
|
||
}
|
||
const logContent = await WebUiConfig.GetLogContent(filename);
|
||
const sanitizedLogContent = sanitizeLog(logContent);
|
||
return sendSuccess(res, sanitizedLogContent);
|
||
};
|
||
|
||
// 日志列表
|
||
export const LogListHandler: RequestHandler = async (_, res) => {
|
||
const logList = await WebUiConfig.GetLogsList();
|
||
return sendSuccess(res, logList);
|
||
};
|
||
|
||
// 实时日志(SSE)
|
||
export const LogRealTimeHandler: RequestHandler = async (req, res) => {
|
||
res.setHeader('Content-Type', 'text/event-stream');
|
||
res.setHeader('Connection', 'keep-alive');
|
||
const listener = (log: string) => {
|
||
try {
|
||
const sanitizedLog = sanitizeLog(log);
|
||
res.write(`data: ${sanitizedLog}\n\n`);
|
||
} catch (error) {
|
||
console.error('向客户端写入日志数据时出错:', error);
|
||
}
|
||
};
|
||
logSubscription.subscribe(listener);
|
||
req.on('close', () => {
|
||
logSubscription.unsubscribe(listener);
|
||
});
|
||
};
|
||
|
||
// 终端相关处理器
|
||
export const CreateTerminalHandler: RequestHandler = async (req, res) => {
|
||
if (isMacOS) {
|
||
return sendError(res, 'MacOS不支持终端');
|
||
}
|
||
try {
|
||
const { cols, rows } = req.body;
|
||
const { id } = terminalManager.createTerminal(cols, rows);
|
||
return sendSuccess(res, { id });
|
||
} catch (error) {
|
||
console.error('Failed to create terminal:', error);
|
||
return sendError(res, '创建终端失败');
|
||
}
|
||
};
|
||
|
||
export const GetTerminalListHandler: RequestHandler = (_, res) => {
|
||
const list = terminalManager.getTerminalList();
|
||
return sendSuccess(res, list);
|
||
};
|
||
|
||
export const CloseTerminalHandler: RequestHandler = (req, res) => {
|
||
const id = req.params['id'];
|
||
if (!id) {
|
||
return sendError(res, 'ID不能为空');
|
||
}
|
||
terminalManager.closeTerminal(id);
|
||
return sendSuccess(res, {});
|
||
};
|