From f7bdc35ed642dae7fc60c3504e9dc2a4b647c19c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=8C=82=E7=A5=9E?= Date: Mon, 22 Jul 2024 18:41:31 +0800 Subject: [PATCH 1/2] =?UTF-8?q?feat:=20http=E4=B8=8Ews=E5=85=81=E8=AE=B8?= =?UTF-8?q?=E7=9B=91=E5=90=AC=E5=90=8C=E4=B8=80=E7=AB=AF=E5=8F=A3=EF=BC=8C?= =?UTF-8?q?=E5=BF=AB=E9=80=9F=E7=99=BB=E5=BD=95=E5=85=81=E8=AE=B8=E8=87=AA?= =?UTF-8?q?=E5=8A=A8=E9=80=89=E6=8B=A9QQ=E5=8F=B7=EF=BC=8C=E5=85=81?= =?UTF-8?q?=E8=AE=B8=E7=A6=81=E7=94=A8webUI?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/common/server/http.ts | 10 +++++- src/common/server/websocket.ts | 42 +++++++++++++++++------ src/index.ts | 22 +++++++++--- src/onebot11/main.ts | 6 +++- src/onebot11/server/ws/WebsocketServer.ts | 3 +- src/webui/index.ts | 4 +++ 6 files changed, 69 insertions(+), 18 deletions(-) diff --git a/src/common/server/http.ts b/src/common/server/http.ts index c3c20133..b8610fd6 100644 --- a/src/common/server/http.ts +++ b/src/common/server/http.ts @@ -9,7 +9,15 @@ type RegisterHandler = (res: Response, payload: any) => Promise export abstract class HttpServerBase { name: string = 'NapCatQQ'; private readonly expressAPP: Express; - private server: http.Server | null = null; + private _server: http.Server | null = null; + + public get server(): http.Server | null { + return this._server; + } + + private set server(value: http.Server | null) { + this._server = value; + } constructor() { this.expressAPP = express(); diff --git a/src/common/server/websocket.ts b/src/common/server/websocket.ts index bbe0ef60..0351ca4c 100644 --- a/src/common/server/websocket.ts +++ b/src/common/server/websocket.ts @@ -1,4 +1,5 @@ import { WebSocket, WebSocketServer } from 'ws'; +import http from 'http'; import urlParse from 'url'; import { IncomingMessage } from 'node:http'; import { log } from '@/common/utils/log'; @@ -27,17 +28,36 @@ export class WebsocketServerBase { constructor() { } - start(port: number, host: string = '') { - try { - this.ws = new WebSocketServer({ - port, - host: '', - maxPayload: 1024 * 1024 * 1024 - }).on('error', () => { - }); - log(`ws服务启动成功, ${host}:${port}`); - } catch (e: any) { - throw Error('ws服务启动失败, 请检查监听的ip和端口' + e.toString()); + start(port: number | http.Server, host: string = '') { + if (port instanceof http.Server) { + try { + const wss = new WebSocketServer({ + noServer: true, + maxPayload: 1024 * 1024 * 1024 + }).on('error', () => { + }); + this.ws = wss; + port.on('upgrade', function upgrade(request, socket, head) { + wss.handleUpgrade(request, socket, head, function done(ws) { + wss.emit('connection', ws, request); + }); + }); + log(`ws服务启动成功, 绑定到HTTP服务`); + } catch (e: any) { + throw Error('ws服务启动失败, 可能是绑定的HTTP服务异常' + e.toString()); + } + } else { + try { + this.ws = new WebSocketServer({ + port, + host: '', + maxPayload: 1024 * 1024 * 1024 + }).on('error', () => { + }); + log(`ws服务启动成功, ${host}:${port}`); + } catch (e: any) { + throw Error('ws服务启动失败, 请检查监听的ip和端口' + e.toString()); + } } this.ws.on('connection', (wsClient, req) => { const url: string = req.url!.split('?').shift() || '/'; diff --git a/src/index.ts b/src/index.ts index b9bd9ae8..55936af5 100644 --- a/src/index.ts +++ b/src/index.ts @@ -21,7 +21,7 @@ const __filename = fileURLToPath(import.meta.url); const __dirname = dirname(__filename); const tagColor = chalk.cyan; program - .option('-q, --qq ', 'QQ号') + .option('-q, --qq [type]', 'QQ号') .parse(process.argv); //deleteOldFiles(path.join(__dirname, 'logs'), 3).then().catch(); @@ -69,7 +69,18 @@ const showQRCode = async (url: string, base64: string, buffer: Buffer) => { }); }); }; -const quickLoginQQ = cmdOptions.qq; + +let quickLoginQQ = cmdOptions.qq; +const QuickLoginList = await napCatCore.getQuickLoginList(); +if (quickLoginQQ == true) { + if (QuickLoginList.LocalLoginInfoList.length > 0) { + quickLoginQQ = QuickLoginList.LocalLoginInfoList[0].uin; + log('-q 指令指定使用最近的QQ进行快速登录'); + } else { + quickLoginQQ = ''; + } +} + // napCatCore.on('system.login.error', (result) => { // console.error('登录失败', result); // napCatCore.qrLogin().then().catch(console.error); @@ -107,11 +118,14 @@ if (quickLoginQQ) { logError('快速登录错误:', res.loginErrorInfo.errMsg); } }).catch((e) => { - logError(e); + logError('快速登录错误:', e); napCatCore.qrLogin(showQRCode); }); } else { - log('没有 -q 参数指定快速登录的QQ,将使用二维码登录方式'); + log('没有 -q 指令指定快速登录,将使用二维码登录方式'); + if (QuickLoginList.LocalLoginInfoList.length > 0) { + log(`可用于快速登录的QQ:${QuickLoginList.LocalLoginInfoList.map((u, index) => `\n${index}: ${u.uin} ${u.nickName}`)}`); + } napCatCore.qrLogin(showQRCode); } diff --git a/src/onebot11/main.ts b/src/onebot11/main.ts index a44d8de8..9143d8fb 100644 --- a/src/onebot11/main.ts +++ b/src/onebot11/main.ts @@ -73,7 +73,11 @@ export class NapCatOnebot11 { ob11HTTPServer.start(ob11Config.http.port, ob11Config.http.host); } if (ob11Config.ws.enable) { - ob11WebsocketServer.start(ob11Config.ws.port, ob11Config.ws.host); + if (ob11Config.http.port == ob11Config.ws.port && ob11Config.http.host == ob11Config.ws.host && ob11HTTPServer.server) { + ob11WebsocketServer.start(ob11HTTPServer.server); + } else { + ob11WebsocketServer.start(ob11Config.ws.port, ob11Config.ws.host); + } } if (ob11Config.reverseWs.enable) { ob11ReverseWebsockets.start(); diff --git a/src/onebot11/server/ws/WebsocketServer.ts b/src/onebot11/server/ws/WebsocketServer.ts index 27bffe54..838de2a5 100644 --- a/src/onebot11/server/ws/WebsocketServer.ts +++ b/src/onebot11/server/ws/WebsocketServer.ts @@ -1,4 +1,5 @@ import { WebSocket } from 'ws'; +import http from 'http'; import { actionMap } from '../../action'; import { OB11Response } from '../../action/OB11Response'; import { postWsEvent, registerWsEventSender, unregisterWsEventSender } from '../postOB11Event'; @@ -18,7 +19,7 @@ const heartbeatRunning = false; class OB11WebsocketServer extends WebsocketServerBase { - public start(port: number, host: string) { + public start(port: number | http.Server, host: string = '') { this.token = ob11Config.token; super.start(port, host); } diff --git a/src/webui/index.ts b/src/webui/index.ts index 57539704..98366e38 100644 --- a/src/webui/index.ts +++ b/src/webui/index.ts @@ -21,6 +21,10 @@ const __dirname = dirname(__filename); */ export async function InitWebUi() { const config = await WebUiConfig.GetWebUIConfig(); + if (config.port == 0) { + log('[NapCat] [WebUi] Current WebUi is not run.'); + return; + } app.use(express.json()); // 初始服务 app.all('/', (_req, res) => { From 25bca8385d128bc86063f0481d1c18559a3c5963 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=8C=82=E7=A5=9E?= Date: Wed, 24 Jul 2024 13:02:37 +0800 Subject: [PATCH 2/2] =?UTF-8?q?feat:=20http=E4=B8=8Ews=E5=85=B1=E7=AB=99?= =?UTF-8?q?=E6=94=AF=E6=8C=81=E7=83=AD=E9=87=8D=E8=BD=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/common/server/websocket.ts | 10 +++-- src/common/utils/log.ts | 6 ++- src/index.ts | 2 +- src/onebot11/main.ts | 81 +++++++++++++++++++++------------- 4 files changed, 62 insertions(+), 37 deletions(-) diff --git a/src/common/server/websocket.ts b/src/common/server/websocket.ts index 0351ca4c..9f0bf69e 100644 --- a/src/common/server/websocket.ts +++ b/src/common/server/websocket.ts @@ -70,10 +70,12 @@ export class WebsocketServerBase { } stop() { - this.ws && this.ws.close((err) => { - log('ws server close failed!', err); - }); - this.ws = null; + if (this.ws) { + this.ws.close((err) => { + if (err) log('ws server close failed!', err); + }); + this.ws = null; + } } restart(port: number) { diff --git a/src/common/utils/log.ts b/src/common/utils/log.ts index cd6edcc8..73e61033 100644 --- a/src/common/utils/log.ts +++ b/src/common/utils/log.ts @@ -91,8 +91,10 @@ export function enableConsoleLog(enable: boolean) { function formatMsg(msg: any[]) { let logMsg = ''; for (const msgItem of msg) { - // 判断是否是对象 - if (typeof msgItem === 'object') { + if (msgItem instanceof Error) { // 判断是否是错误 + logMsg += msgItem.stack + ' '; + continue; + } else if (typeof msgItem === 'object') { // 判断是否是对象 const obj = JSON.parse(JSON.stringify(msgItem, null, 2)); logMsg += JSON.stringify(truncateString(obj)) + ' '; continue; diff --git a/src/index.ts b/src/index.ts index 55936af5..51cb42ef 100644 --- a/src/index.ts +++ b/src/index.ts @@ -70,7 +70,7 @@ const showQRCode = async (url: string, base64: string, buffer: Buffer) => { }); }; -let quickLoginQQ = cmdOptions.qq; +let quickLoginQQ = cmdOptions.qq; // undefine、true、string const QuickLoginList = await napCatCore.getQuickLoginList(); if (quickLoginQQ == true) { if (QuickLoginList.LocalLoginInfoList.length > 0) { diff --git a/src/onebot11/main.ts b/src/onebot11/main.ts index 9143d8fb..d98d404f 100644 --- a/src/onebot11/main.ts +++ b/src/onebot11/main.ts @@ -46,6 +46,10 @@ export let DeviceList = new Array(); //peer->cached(boolen) // const PokeCache = new Map(); +function check_http_ws_equal(conf: any) { // 放在NapCatOnebot11里能被onReady调用却不能被SetConfig调用 不知道为什么 只能放这里了 + return isEqual(conf.http.port, conf.ws.port) && isEqual(conf.http.host, conf.ws.host); +} + export class NapCatOnebot11 { private bootTime: number = Date.now() / 1000; // 秒 @@ -73,7 +77,7 @@ export class NapCatOnebot11 { ob11HTTPServer.start(ob11Config.http.port, ob11Config.http.host); } if (ob11Config.ws.enable) { - if (ob11Config.http.port == ob11Config.ws.port && ob11Config.http.host == ob11Config.ws.host && ob11HTTPServer.server) { + if (check_http_ws_equal(ob11Config) && ob11HTTPServer.server) { // ob11HTTPServer.server != null 隐含了 ob11Config.http.enable == true 的条件 ob11WebsocketServer.start(ob11HTTPServer.server); } else { ob11WebsocketServer.start(ob11Config.ws.port, ob11Config.ws.host); @@ -383,49 +387,66 @@ export class NapCatOnebot11 { const OldConfig = JSON.parse(JSON.stringify(ob11Config)); //进行深拷贝 ob11Config.save(NewOb11);//保存新配置 - const isHttpChanged = !isEqual(NewOb11.http.port, OldConfig.http.port); - const isHttpEnableChanged = !isEqual(NewOb11.http.enable, OldConfig.http.enable); + const isHttpChanged = !isEqual(NewOb11.http.enable, OldConfig.http.enable) || + !isEqual(NewOb11.http.host, OldConfig.http.host) || + !isEqual(NewOb11.http.port, OldConfig.http.port); // const isHttpPostChanged = !isEqual(NewOb11.http.postUrls, OldConfig.http.postUrls); // const isEnanleHttpPostChanged = !isEqual(NewOb11.http.enablePost, OldConfig.http.enablePost); - const isWsChanged = !isEqual(NewOb11.ws.port, OldConfig.ws.port); - const isEnableWsChanged = !isEqual(NewOb11.ws.enable, OldConfig.ws.enable); + const isWsChanged = !isEqual(NewOb11.ws.enable, OldConfig.ws.enable) || + !isEqual(NewOb11.ws.host, OldConfig.ws.host) || + !isEqual(NewOb11.ws.port, OldConfig.ws.port); - const isEnableWsReverseChanged = !isEqual(NewOb11.reverseWs.enable, OldConfig.reverseWs.enable); - const isWsReverseUrlsChanged = !isEqual(NewOb11.reverseWs.urls, OldConfig.reverseWs.urls); + const isWsReverseChanged = !isEqual(NewOb11.reverseWs.enable, OldConfig.reverseWs.enable) || + !isEqual(NewOb11.reverseWs.urls, OldConfig.reverseWs.urls); //const isEnableHeartBeatChanged = !isEqual(NewOb11.heartInterval, OldConfig.heartInterval); - // http重启逻辑 - // console.log(isHttpEnableChanged, isHttpChanged, NewOb11.http.enable); - if ((isHttpEnableChanged || isHttpChanged) && NewOb11.http.enable) { - if (OldConfig.http.enable) { - ob11HTTPServer.stop(); - } - ob11HTTPServer.start(NewOb11.http.port, NewOb11.http.host); - } else if (isHttpEnableChanged && !NewOb11.http.enable) { - ob11HTTPServer.stop(); - } - - // ws重启逻辑 - if ((isEnableWsChanged || isWsChanged) && NewOb11.ws.enable) { - if (OldConfig.ws.enable) { + if (check_http_ws_equal(NewOb11) || check_http_ws_equal(OldConfig)) { + // http与ws共站 需要同步重启 + if (isHttpChanged || isWsChanged) { + log("http与ws进行热重载") ob11WebsocketServer.stop(); + ob11HTTPServer.stop(); + if (NewOb11.http.enable) { + ob11HTTPServer.start(NewOb11.http.port, NewOb11.http.host); + } + if (NewOb11.ws.enable) { + if (check_http_ws_equal(NewOb11) && ob11HTTPServer.server) { + ob11WebsocketServer.start(ob11HTTPServer.server); + } else { + ob11WebsocketServer.start(NewOb11.ws.port, NewOb11.ws.host); + } + } + } + } else { + // http重启逻辑 + if (isHttpChanged) { + log("http进行热重载") + ob11HTTPServer.stop(); + if (NewOb11.http.enable) { + ob11HTTPServer.start(NewOb11.http.port, NewOb11.http.host); + } + } + + // ws重启逻辑 + if (isWsChanged) { + log("ws进行热重载") + ob11WebsocketServer.stop(); + if (NewOb11.ws.enable) { + ob11WebsocketServer.start(NewOb11.ws.port, NewOb11.ws.host); + } } - ob11WebsocketServer.start(NewOb11.ws.port, NewOb11.ws.host); - } else if (isHttpEnableChanged && !NewOb11.http.enable) { - ob11WebsocketServer.stop(); } // 反向ws重启逻辑 - if ((isEnableWsReverseChanged || isWsReverseUrlsChanged) && NewOb11.reverseWs.enable) { - if (OldConfig.reverseWs.enable) { - ob11ReverseWebsockets.stop(); - } - ob11ReverseWebsockets.start(); - } else if (isHttpEnableChanged && !NewOb11.http.enable) { + if (isWsReverseChanged) { + log("反向ws进行热重载") ob11ReverseWebsockets.stop(); + if (NewOb11.reverseWs.enable) { + ob11ReverseWebsockets.start(); + } } } catch (e) {