diff --git a/src/onebot/config/config.ts b/src/onebot/config/config.ts index 5e610175..daaaa7a1 100644 --- a/src/onebot/config/config.ts +++ b/src/onebot/config/config.ts @@ -78,6 +78,7 @@ export const websocketClientDefaultConfigs = createDefaultAdapterConfig({ url: 'ws://localhost:8082', messagePostFormat: 'array', reportSelfMessage: false, + reconnectInterval: 5000, token: '', debug: false, heartInterval: 30000, diff --git a/src/onebot/index.ts b/src/onebot/index.ts index e1c13f8f..2dbb01b5 100644 --- a/src/onebot/index.ts +++ b/src/onebot/index.ts @@ -110,14 +110,14 @@ export class NapCatOneBot11Adapter { for (const key of ob11Config.network.httpServers) { if (key.enable) { this.networkManager.registerAdapter( - new OB11PassiveHttpAdapter(key.name, key.port, key.token, this.core, this.actions) + new OB11PassiveHttpAdapter(key.name, key, this.core, this.actions) ); } } for (const key of ob11Config.network.httpClients) { if (key.enable) { this.networkManager.registerAdapter( - new OB11ActiveHttpAdapter(key.name, key.url, key.token, this.core, this) + new OB11ActiveHttpAdapter(key.name, key, this.core, this, this.actions) ); } } @@ -126,10 +126,7 @@ export class NapCatOneBot11Adapter { this.networkManager.registerAdapter( new OB11PassiveWebSocketAdapter( key.name, - key.host, - key.port, - key.heartInterval, - key.token, + key, this.core, this.actions ) @@ -141,10 +138,7 @@ export class NapCatOneBot11Adapter { this.networkManager.registerAdapter( new OB11ActiveWebSocketAdapter( key.name, - key.url, - 5000, - key.heartInterval, - key.token, + key, this.core, this.actions ) @@ -215,7 +209,7 @@ export class NapCatOneBot11Adapter { const prevServer = prev.network.httpServers.find(s => s.name === server.name); if (prevServer && prevServer.enable !== server.enable) { if (server.enable) { - let adapter = new OB11PassiveHttpAdapter(server.name, server.port, server.token, this.core, this.actions); + let adapter = new OB11PassiveHttpAdapter(server.name, server, this.core, this.actions); adapter.open(); this.networkManager.registerAdapter( adapter @@ -231,7 +225,7 @@ export class NapCatOneBot11Adapter { const prevClient = prev.network.httpClients.find(c => c.name === client.name); if (prevClient && prevClient.enable !== client.enable) { if (client.enable) { - let adapter = new OB11ActiveHttpAdapter(client.name, client.url, client.token, this.core, this); + let adapter = new OB11ActiveHttpAdapter(client.name, client, this.core, this,this.actions); adapter.open(); this.networkManager.registerAdapter( adapter @@ -249,10 +243,7 @@ export class NapCatOneBot11Adapter { if (server.enable) { let adapter = new OB11PassiveWebSocketAdapter( server.name, - server.host, - server.port, - server.heartInterval, - server.token, + server, this.core, this.actions ); @@ -273,10 +264,7 @@ export class NapCatOneBot11Adapter { if (client.enable) { let adapter = new OB11ActiveWebSocketAdapter( client.name, - client.url, - 5000, - client.heartInterval, - client.token, + client, this.core, this.actions ) @@ -292,7 +280,7 @@ export class NapCatOneBot11Adapter { // 注册新的 HTTP 服务器 for (const server of addedHttpServers) { if (server.enable) { - let adapter = new OB11PassiveHttpAdapter(server.name, server.port, server.token, this.core, this.actions); + let adapter = new OB11PassiveHttpAdapter(server.name, server, this.core, this.actions); adapter.open(); this.networkManager.registerAdapter(adapter); } @@ -302,7 +290,7 @@ export class NapCatOneBot11Adapter { for (const client of addedHttpClients) { if (client.enable) { - let adapter = new OB11ActiveHttpAdapter(client.name, client.url, client.token, this.core, this); + let adapter = new OB11ActiveHttpAdapter(client.name, client, this.core, this,this.actions); adapter.open(); this.networkManager.registerAdapter(adapter); } @@ -313,10 +301,7 @@ export class NapCatOneBot11Adapter { if (server.enable) { let adapter = new OB11PassiveWebSocketAdapter( server.name, - server.host, - server.port, - server.heartInterval, - server.token, + server, this.core, this.actions ); @@ -330,10 +315,7 @@ export class NapCatOneBot11Adapter { if (client.enable) { let adapter = new OB11ActiveWebSocketAdapter( client.name, - client.url, - 5000, - client.heartInterval, - client.token, + client, this.core, this.actions ) diff --git a/src/onebot/network/active-http.ts b/src/onebot/network/active-http.ts index 356f6e21..1c53b4bd 100644 --- a/src/onebot/network/active-http.ts +++ b/src/onebot/network/active-http.ts @@ -5,23 +5,27 @@ import { QuickAction, QuickActionEvent } from '../types'; import { NapCatCore } from '@/core'; import { NapCatOneBot11Adapter } from '..'; import { RequestUtil } from '@/common/request'; +import { HttpClientConfig } from '../config/config'; +import { ActionMap } from '../action'; export class OB11ActiveHttpAdapter implements IOB11NetworkAdapter { logger: LogWrapper; - isOpen: boolean = false; - + isEnable: boolean = false; + config: HttpClientConfig; constructor( public name: string, - public url: string, - public secret: string | undefined, + config: HttpClientConfig, public core: NapCatCore, public obContext: NapCatOneBot11Adapter, + public actions: ActionMap, ) { this.logger = core.context.logger; + this.config = structuredClone(config); } + onEvent(event: T) { - if (!this.isOpen) { + if (!this.isEnable) { return; } const headers: Record = { @@ -29,13 +33,13 @@ export class OB11ActiveHttpAdapter implements IOB11NetworkAdapter { 'x-self-id': this.core.selfInfo.uin, }; const msgStr = JSON.stringify(event); - if (this.secret && this.secret.length > 0) { - const hmac = createHmac('sha1', this.secret); + if (this.config.token && this.config.token.length > 0) { + const hmac = createHmac('sha1', this.config.token); hmac.update(msgStr); const sig = hmac.digest('hex'); headers['x-signature'] = 'sha1=' + sig; } - RequestUtil.HttpGetText(this.url, 'POST', msgStr, headers).then(async (res) => { + RequestUtil.HttpGetText(this.config.url, 'POST', msgStr, headers).then(async (res) => { let resJson: QuickAction; try { resJson = JSON.parse(res); @@ -57,10 +61,13 @@ export class OB11ActiveHttpAdapter implements IOB11NetworkAdapter { } open() { - this.isOpen = true; + this.isEnable = true; } close() { - this.isOpen = false; + this.isEnable = false; + } + async reload(config: HttpClientConfig){ + this.config = structuredClone(config); } } diff --git a/src/onebot/network/active-websocket.ts b/src/onebot/network/active-websocket.ts index fc9f5bdb..15229140 100644 --- a/src/onebot/network/active-websocket.ts +++ b/src/onebot/network/active-websocket.ts @@ -7,23 +7,23 @@ import { OB11Response } from '@/onebot/action/OB11Response'; import { LogWrapper } from '@/common/log'; import { ActionMap } from '@/onebot/action'; import { LifeCycleSubType, OB11LifeCycleEvent } from '../event/meta/OB11LifeCycleEvent'; +import { WebsocketClientConfig } from '../config/config'; export class OB11ActiveWebSocketAdapter implements IOB11NetworkAdapter { - isClosed: boolean = false; + isEnable: boolean = false; logger: LogWrapper; private connection: WebSocket | null = null; private heartbeatRef: NodeJS.Timeout | null = null; + config: WebsocketClientConfig; constructor( public name: string, - public url: string, - public reconnectIntervalInMillis: number, - public heartbeatIntervalInMillis: number, - private readonly token: string, + confg: WebsocketClientConfig, public core: NapCatCore, public actions: ActionMap, ) { this.logger = core.context.logger; + this.config = structuredClone(confg); } onEvent(event: T) { @@ -36,23 +36,23 @@ export class OB11ActiveWebSocketAdapter implements IOB11NetworkAdapter { if (this.connection) { return; } - if (this.heartbeatIntervalInMillis > 0) { + if (this.config.heartInterval > 0) { this.heartbeatRef = setInterval(() => { if (this.connection && this.connection.readyState === WebSocket.OPEN) { - this.connection.send(JSON.stringify(new OB11HeartbeatEvent(this.core, this.heartbeatIntervalInMillis, this.core.selfInfo.online ?? true, true))); + this.connection.send(JSON.stringify(new OB11HeartbeatEvent(this.core, this.config.heartInterval, this.core.selfInfo.online ?? true, true))); } - }, this.heartbeatIntervalInMillis); + }, this.config.heartInterval); } await this.tryConnect(); } close() { - if (this.isClosed) { + if (!this.isEnable) { this.logger.logDebug('Cannot close a closed WebSocket connection'); return; } - this.isClosed = true; + this.isEnable = false; if (this.connection) { this.connection.close(); this.connection = null; @@ -70,16 +70,16 @@ export class OB11ActiveWebSocketAdapter implements IOB11NetworkAdapter { } private async tryConnect() { - if (!this.connection && !this.isClosed) { + if (!this.connection && this.isEnable) { let isClosedByError = false; - this.connection = new WebSocket(this.url, { + this.connection = new WebSocket(this.config.url, { maxPayload: 1024 * 1024 * 1024, handshakeTimeout: 2000, perMessageDeflate: false, headers: { 'X-Self-ID': this.core.selfInfo.uin, - 'Authorization': `Bearer ${this.token}`, + 'Authorization': `Bearer ${this.config.token}`, 'x-client-role': 'Universal', // koishi-adapter-onebot 需要这个字段 'User-Agent': 'OneBot/11', }, @@ -104,21 +104,21 @@ export class OB11ActiveWebSocketAdapter implements IOB11NetworkAdapter { }); this.connection.once('close', () => { if (!isClosedByError) { - this.logger.logError.bind(this.logger)(`[OneBot] [WebSocket Client] 反向WebSocket (${this.url}) 连接意外关闭`); - this.logger.logError.bind(this.logger)(`[OneBot] [WebSocket Client] 在 ${Math.floor(this.reconnectIntervalInMillis / 1000)} 秒后尝试重新连接`); - if (!this.isClosed) { + this.logger.logError.bind(this.logger)(`[OneBot] [WebSocket Client] 反向WebSocket (${this.config.url}) 连接意外关闭`); + this.logger.logError.bind(this.logger)(`[OneBot] [WebSocket Client] 在 ${Math.floor(this.config.reconnectInterval / 1000)} 秒后尝试重新连接`); + if (this.isEnable) { this.connection = null; - setTimeout(() => this.tryConnect(), this.reconnectIntervalInMillis); + setTimeout(() => this.tryConnect(), this.config.reconnectInterval); } } }); this.connection.on('error', (err) => { isClosedByError = true; - this.logger.logError.bind(this.logger)(`[OneBot] [WebSocket Client] 反向WebSocket (${this.url}) 连接错误`, err); - this.logger.logError.bind(this.logger)(`[OneBot] [WebSocket Client] 在 ${Math.floor(this.reconnectIntervalInMillis / 1000)} 秒后尝试重新连接`); - if (!this.isClosed) { + this.logger.logError.bind(this.logger)(`[OneBot] [WebSocket Client] 反向WebSocket (${this.config.url}) 连接错误`, err); + this.logger.logError.bind(this.logger)(`[OneBot] [WebSocket Client] 在 ${Math.floor(this.config.reconnectInterval / 1000)} 秒后尝试重新连接`); + if (this.isEnable) { this.connection = null; - setTimeout(() => this.tryConnect(), this.reconnectIntervalInMillis); + setTimeout(() => this.tryConnect(), this.config.reconnectInterval); } }); } @@ -154,4 +154,7 @@ export class OB11ActiveWebSocketAdapter implements IOB11NetworkAdapter { const retdata = await action.websocketHandle(receiveData.params, echo ?? '', this.name); this.checkStateAndReply({ ...retdata }); } + async reload(config: WebsocketClientConfig) { + + } } diff --git a/src/onebot/network/index.ts b/src/onebot/network/index.ts index 7373a9bb..68a29bd6 100644 --- a/src/onebot/network/index.ts +++ b/src/onebot/network/index.ts @@ -5,14 +5,17 @@ import { ActionMap } from '@/onebot/action'; export type OB11EmitEventContent = OB11BaseEvent | OB11Message; export interface IOB11NetworkAdapter { - actions?: ActionMap; + actions: ActionMap; name: string; + isEnable: boolean; onEvent(event: T): void; open(): void | Promise; close(): void | Promise; + + reload(config: any): void | Promise; } export class OB11NetworkManager { @@ -34,7 +37,7 @@ export class OB11NetworkManager { } })); } - async emitEventByNames(map:Map){ + async emitEventByNames(map: Map) { return Promise.all(Array.from(map.entries()).map(([name, event]) => { const adapter = this.adapters.get(name); if (adapter) { @@ -71,6 +74,16 @@ export class OB11NetworkManager { await Promise.all(Array.from(this.adapters.values()).map(adapter => adapter.close())); this.adapters.clear(); } + + async readloadAdapter(name: string, config: T) { + const adapter = this.adapters.get(name); + if (adapter) { + await adapter.reload(config); + } + } + async readloadSomeAdapters(configMap: Map) { + await Promise.all(Array.from(configMap.entries()).map(([name, config]) => this.readloadAdapter(name, config))); + } } export * from './active-http'; diff --git a/src/onebot/network/passive-http.ts b/src/onebot/network/passive-http.ts index bab26cd8..97c0196c 100644 --- a/src/onebot/network/passive-http.ts +++ b/src/onebot/network/passive-http.ts @@ -5,19 +5,21 @@ import { NapCatCore } from '@/core'; import { OB11Response } from '../action/OB11Response'; import { ActionMap } from '@/onebot/action'; import cors from 'cors'; +import { HttpServerConfig } from '../config/config'; export class OB11PassiveHttpAdapter implements IOB11NetworkAdapter { private app: Express | undefined; private server: http.Server | undefined; - private isOpen: boolean = false; + isEnable: boolean = false; + config: HttpServerConfig; constructor( public name: string, - public port: number, - public token: string, + config: HttpServerConfig, public core: NapCatCore, public actions: ActionMap, ) { + this.config = structuredClone(config); } onEvent() { @@ -26,13 +28,13 @@ export class OB11PassiveHttpAdapter implements IOB11NetworkAdapter { open() { try { - if (this.isOpen) { + if (this.isEnable) { this.core.context.logger.logError('Cannot open a closed HTTP server'); return; } - if (!this.isOpen) { + if (!this.isEnable) { this.initializeServer(); - this.isOpen = true; + this.isEnable = true; } } catch (e) { this.core.context.logger.logError(`[OneBot] [HTTP Server Adapter] Boot Error: ${e}`); @@ -41,7 +43,7 @@ export class OB11PassiveHttpAdapter implements IOB11NetworkAdapter { } async close() { - this.isOpen = false; + this.isEnable = false; this.server?.close(); this.app = undefined; } @@ -64,12 +66,12 @@ export class OB11PassiveHttpAdapter implements IOB11NetworkAdapter { }); }); - this.app.use((req, res, next) => this.authorize(this.token, req, res, next)); + this.app.use((req, res, next) => this.authorize(this.config.token, req, res, next)); this.app.use(async (req, res, _) => { await this.handleRequest(req, res); }); - this.server.listen(this.port, () => { - this.core.context.logger.log(`[OneBot] [HTTP Server Adapter] Start On Port ${this.port}`); + this.server.listen(this.config.port, () => { + this.core.context.logger.log(`[OneBot] [HTTP Server Adapter] Start On Port ${this.config.port}`); }); } @@ -86,7 +88,7 @@ export class OB11PassiveHttpAdapter implements IOB11NetworkAdapter { } private async handleRequest(req: Request, res: Response) { - if (!this.isOpen) { + if (!this.isEnable) { this.core.context.logger.log(`[OneBot] [HTTP Server Adapter] Server is closed`); return res.json(OB11Response.error('Server is closed', 200)); } @@ -102,7 +104,7 @@ export class OB11PassiveHttpAdapter implements IOB11NetworkAdapter { const action = this.actions.get(actionName); if (action) { try { - const result = await action.handle(payload,this.name); + const result = await action.handle(payload, this.name); return res.json(result); } catch (error: any) { return res.json(OB11Response.error(error?.stack?.toString() || error?.message || 'Error Handle', 200)); @@ -111,4 +113,7 @@ export class OB11PassiveHttpAdapter implements IOB11NetworkAdapter { return res.json(OB11Response.error('不支持的api ' + actionName, 200)); } } + async reload(config: HttpServerConfig) { + + } } diff --git a/src/onebot/network/passive-websocket.ts b/src/onebot/network/passive-websocket.ts index af59e368..d37a69b1 100644 --- a/src/onebot/network/passive-websocket.ts +++ b/src/onebot/network/passive-websocket.ts @@ -10,47 +10,44 @@ import { OB11HeartbeatEvent } from '../event/meta/OB11HeartbeatEvent'; import { IncomingMessage } from 'http'; import { ActionMap } from '@/onebot/action'; import { LifeCycleSubType, OB11LifeCycleEvent } from '../event/meta/OB11LifeCycleEvent'; +import { WebsocketServerConfig } from '../config/config'; export class OB11PassiveWebSocketAdapter implements IOB11NetworkAdapter { wsServer: WebSocketServer; wsClients: WebSocket[] = []; wsClientsMutex = new Mutex(); - isOpen: boolean = false; + isEnable: boolean = false; hasBeenClosed: boolean = false; heartbeatInterval: number = 0; - core: NapCatCore; logger: LogWrapper; + config: WebsocketServerConfig; private heartbeatIntervalId: NodeJS.Timeout | null = null; wsClientWithEvent: WebSocket[] = []; constructor( public name: string, - ip: string, - port: number, - heartbeatInterval: number, - token: string, - core: NapCatCore, + config: WebsocketServerConfig, + public core: NapCatCore, public actions: ActionMap, ) { - this.core = core; + this.config = structuredClone(config); this.logger = core.context.logger; - if (ip === '0.0.0.0') { + if (this.config.host === '0.0.0.0') { //兼容配置同时处理0.0.0.0逻辑 - ip = ''; + this.config.host = ''; } - this.heartbeatInterval = heartbeatInterval; this.wsServer = new WebSocketServer({ - port: port, - host: ip, + port: this.config.port, + host: this.config.host, maxPayload: 1024 * 1024 * 1024, }); this.wsServer.on('connection', async (wsClient, wsReq) => { - if (!this.isOpen) { + if (!this.isEnable) { wsClient.close(); return; } //鉴权 - this.authorize(token, wsClient, wsReq); + this.authorize(this.config.token, wsClient, wsReq); const paramUrl = wsReq.url?.indexOf('?') !== -1 ? wsReq.url?.substring(0, wsReq.url?.indexOf('?')) : wsReq.url; const isApiConnect = paramUrl === '/api' || paramUrl === '/api/'; if (!isApiConnect) { @@ -106,7 +103,7 @@ export class OB11PassiveWebSocketAdapter implements IOB11NetworkAdapter { } open() { - if (this.isOpen) { + if (this.isEnable) { this.logger.logError.bind(this.logger)('[OneBot] [WebSocket Server] Cannot open a opened WebSocket server'); return; } @@ -117,7 +114,7 @@ export class OB11PassiveWebSocketAdapter implements IOB11NetworkAdapter { const addressInfo = this.wsServer.address(); this.logger.log('[OneBot] [WebSocket Server] Server Started', typeof (addressInfo) === 'string' ? addressInfo : addressInfo?.address + ':' + addressInfo?.port); - this.isOpen = true; + this.isEnable = true; if (this.heartbeatInterval > 0) { this.registerHeartBeat(); } @@ -125,7 +122,7 @@ export class OB11PassiveWebSocketAdapter implements IOB11NetworkAdapter { } async close() { - this.isOpen = false; + this.isEnable = false; this.wsServer.close((err) => { if (err) { this.logger.logError.bind(this.logger)('[OneBot] [WebSocket Server] Error closing server:', err.message); @@ -198,5 +195,8 @@ export class OB11PassiveWebSocketAdapter implements IOB11NetworkAdapter { const retdata = await action.websocketHandle(receiveData.params, echo ?? '', this.name); this.checkStateAndReply({ ...retdata }, wsClient); } + async reload(config: WebsocketServerConfig) { + + } }