mirror of
https://github.com/NapNeko/NapCatQQ.git
synced 2025-07-19 12:03:37 +00:00
Merge pull request #144 from Guation/main
feat: http与ws允许监听同一端口,快速登录允许自动选择QQ号,允许禁用webUI
This commit is contained in:
@@ -9,7 +9,15 @@ type RegisterHandler = (res: Response, payload: any) => Promise<any>
|
||||
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();
|
||||
|
@@ -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() || '/';
|
||||
@@ -50,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) {
|
||||
|
@@ -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;
|
||||
|
22
src/index.ts
22
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 <type>', '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; // undefine、true、string
|
||||
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);
|
||||
}
|
||||
|
||||
|
@@ -46,6 +46,10 @@ export let DeviceList = new Array<LineDevice>();
|
||||
//peer->cached(boolen)
|
||||
// const PokeCache = new Map<string, boolean>();
|
||||
|
||||
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,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 (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);
|
||||
}
|
||||
}
|
||||
if (ob11Config.reverseWs.enable) {
|
||||
ob11ReverseWebsockets.start();
|
||||
@@ -379,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) {
|
||||
|
@@ -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);
|
||||
}
|
||||
|
@@ -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) => {
|
||||
|
Reference in New Issue
Block a user