diff --git a/src/onebot/action/index.ts b/src/onebot/action/index.ts index 1b7f57ed..7716fa1b 100644 --- a/src/onebot/action/index.ts +++ b/src/onebot/action/index.ts @@ -162,7 +162,7 @@ export function createActionMap(onebotContext: NapCatOneBot11Adapter, coreContex new FetchCustomFace(onebotContext, coreContext), new GoCQHTTPUploadPrivateFile(onebotContext, coreContext), ]; - const actionMap = new Map>(); + const actionMap = new Map(); for (const action of actionHandlers) { actionMap.set(action.actionName, action); actionMap.set(action.actionName + '_async', action); diff --git a/src/onebot/index.ts b/src/onebot/index.ts index de1f86af..7df2f99b 100644 --- a/src/onebot/index.ts +++ b/src/onebot/index.ts @@ -20,7 +20,7 @@ import { } from '@/onebot/network'; import { NapCatPathWrapper } from '@/common/framework/napcat'; import { OneBotFriendApi, OneBotGroupApi, OneBotUserApi } from '@/onebot/api'; -import { createActionMap } from '@/onebot/action'; +import { ActionMap, createActionMap } from '@/onebot/action'; import { WebUiDataRuntime } from '@/webui/src/helper/Data'; import { OB11InputStatusEvent } from '@/onebot/event/notice/OB11InputStatusEvent'; import { MessageUnique } from '@/common/utils/MessageUnique'; @@ -42,6 +42,7 @@ export class NapCatOneBot11Adapter { configLoader: OB11ConfigLoader; apiContext: OneBotApiContextType; networkManager: OB11NetworkManager; + actions: ActionMap; private bootTime = Date.now() / 1000; @@ -54,6 +55,7 @@ export class NapCatOneBot11Adapter { UserApi: new OneBotUserApi(this, core), FriendApi: new OneBotFriendApi(this, core), }; + this.actions = createActionMap(this, core); this.networkManager = new OB11NetworkManager(); this.InitOneBot() .catch(e => this.context.logger.logError('初始化OneBot失败', e)); @@ -77,34 +79,32 @@ export class NapCatOneBot11Adapter { this.context.logger.log(`[Notice] [OneBot11] ${serviceInfo}`); //创建NetWork服务 - const actions = createActionMap(this, this.core); if (ob11Config.http.enable) { - await this.networkManager.registerAdapter(new OB11PassiveHttpAdapter( - ob11Config.http.port, ob11Config.token, this.core, this, + this.networkManager.registerAdapter(new OB11PassiveHttpAdapter( + ob11Config.http.port, ob11Config.token, this.core, this.actions )); } if (ob11Config.http.enablePost) { ob11Config.http.postUrls.forEach(url => { this.networkManager.registerAdapter(new OB11ActiveHttpAdapter( - url, ob11Config.heartInterval, ob11Config.token, this.core, this, + url, ob11Config.token, this.core )); }); } if (ob11Config.ws.enable) { const OBPassiveWebSocketAdapter = new OB11PassiveWebSocketAdapter( - ob11Config.ws.host, ob11Config.ws.port, ob11Config.heartInterval, ob11Config.token, this.core, this, + ob11Config.ws.host, ob11Config.ws.port, ob11Config.heartInterval, ob11Config.token, this.core, this.actions, ); - await this.networkManager.registerAdapter(OBPassiveWebSocketAdapter); + this.networkManager.registerAdapter(OBPassiveWebSocketAdapter); } if (ob11Config.reverseWs.enable) { ob11Config.reverseWs.urls.forEach(url => { this.networkManager.registerAdapter(new OB11ActiveWebSocketAdapter( - url, 5000, ob11Config.heartInterval, ob11Config.token, this.core, this, + url, 5000, ob11Config.heartInterval, ob11Config.token, this.core, this.actions )); }); } - await this.networkManager.registerAllActions(actions); await this.networkManager.openAllAdapters(); this.initMsgListener(); @@ -131,8 +131,8 @@ export class NapCatOneBot11Adapter { // check difference in passive http (Http) if (prev.http.enable !== now.http.enable) { if (now.http.enable) { - await this.networkManager.registerAdapter(new OB11PassiveHttpAdapter( - now.http.port, now.token, this.core, this, + await this.networkManager.registerAdapterAndOpen(new OB11PassiveHttpAdapter( + now.http.port, now.token, this.core, this.actions )); } else { await this.networkManager.closeAdapterByPredicate(adapter => adapter instanceof OB11PassiveHttpAdapter,); @@ -143,8 +143,8 @@ export class NapCatOneBot11Adapter { if (prev.http.enablePost !== now.http.enablePost) { if (now.http.enablePost) { now.http.postUrls.forEach(url => { - this.networkManager.registerAdapter(new OB11ActiveHttpAdapter( - url, now.heartInterval, now.token, this.core, this, + this.networkManager.registerAdapterAndOpen(new OB11ActiveHttpAdapter( + url, now.token, this.core )); }); } else { @@ -153,11 +153,11 @@ export class NapCatOneBot11Adapter { } else { if (now.http.enablePost) { const { added, removed } = this.findDifference(prev.http.postUrls, now.http.postUrls); - for (const url of added) { - await this.networkManager.registerAdapter(new OB11ActiveHttpAdapter( - url, now.heartInterval, now.token, this.core, this, + added.forEach(url => { + this.networkManager.registerAdapterAndOpen(new OB11ActiveHttpAdapter( + url, now.token, this.core )); - } + }); await this.networkManager.closeAdapterByPredicate( adapter => adapter instanceof OB11ActiveHttpAdapter && removed.includes(adapter.url), ); @@ -167,8 +167,8 @@ export class NapCatOneBot11Adapter { // check difference in passive websocket (Ws) if (prev.ws.enable !== now.ws.enable) { if (now.ws.enable) { - await this.networkManager.registerAdapter(new OB11PassiveWebSocketAdapter( - now.ws.host, now.ws.port, now.heartInterval, now.token, this.core, this, + await this.networkManager.registerAdapterAndOpen(new OB11PassiveWebSocketAdapter( + now.ws.host, now.ws.port, now.heartInterval, now.token, this.core, this.actions, )); } else { await this.networkManager.closeAdapterByPredicate( @@ -181,8 +181,8 @@ export class NapCatOneBot11Adapter { if (prev.reverseWs.enable !== now.reverseWs.enable) { if (now.reverseWs.enable) { now.reverseWs.urls.forEach(url => { - this.networkManager.registerAdapter(new OB11ActiveWebSocketAdapter( - url, 5000, now.heartInterval, now.token, this.core, this, + this.networkManager.registerAdapterAndOpen(new OB11ActiveWebSocketAdapter( + url, 5000, now.heartInterval, now.token, this.core, this.actions )); }); } else { @@ -193,11 +193,11 @@ export class NapCatOneBot11Adapter { } else { if (now.reverseWs.enable) { const { added, removed } = this.findDifference(prev.reverseWs.urls, now.reverseWs.urls); - for (const url of added) { - await this.networkManager.registerAdapter(new OB11ActiveWebSocketAdapter( - url, 5000, now.heartInterval, now.token, this.core, this, + added.forEach(url => { + this.networkManager.registerAdapterAndOpen(new OB11ActiveWebSocketAdapter( + url, 5000, now.heartInterval, now.token, this.core, this.actions )); - } + }); await this.networkManager.closeAdapterByPredicate( adapter => adapter instanceof OB11ActiveWebSocketAdapter && removed.includes(adapter.url), ); diff --git a/src/onebot/network/active-http.ts b/src/onebot/network/active-http.ts index 96eda19c..79216814 100644 --- a/src/onebot/network/active-http.ts +++ b/src/onebot/network/active-http.ts @@ -1,37 +1,22 @@ import { IOB11NetworkAdapter, OB11EmitEventContent } from '@/onebot/network/index'; -import BaseAction from '@/onebot/action/BaseAction'; import { createHmac } from 'crypto'; import { LogWrapper } from '@/common/utils/log'; import { QuickAction, QuickActionEvent } from '../types'; import { NapCatCore } from '@/core'; import { handleQuickOperation } from '../helper/quick'; -import { NapCatOneBot11Adapter } from '@/onebot'; export class OB11ActiveHttpAdapter implements IOB11NetworkAdapter { - url: string; - heartbeatInterval: number; - secret: string | undefined; - coreContext: NapCatCore; - obContext: NapCatOneBot11Adapter; logger: LogWrapper; isOpen: boolean = false; - constructor(url: string, heartbeatInterval: number, secret: string | undefined, coreContext: NapCatCore, onebotContext: NapCatOneBot11Adapter) { - this.heartbeatInterval = heartbeatInterval; - this.url = url; - this.secret = secret; - this.coreContext = coreContext; - this.obContext = onebotContext; + constructor( + public url: string, + public secret: string | undefined, + public coreContext: NapCatCore + ) { this.logger = coreContext.context.logger; } - registerActionMap(actionMap: Map>) { - } - - registerAction, P, R>(action: T) { - // Passive http adapter does not need to register actions - } - onEvent(event: T) { if (!this.isOpen) { return; diff --git a/src/onebot/network/active-websocket.ts b/src/onebot/network/active-websocket.ts index 5a8d860b..11983af6 100644 --- a/src/onebot/network/active-websocket.ts +++ b/src/onebot/network/active-websocket.ts @@ -1,44 +1,29 @@ import { IOB11NetworkAdapter, OB11EmitEventContent } from '@/onebot/network/index'; import { WebSocket } from 'ws'; -import BaseAction from '@/onebot/action/BaseAction'; import { OB11HeartbeatEvent } from '../event/meta/OB11HeartbeatEvent'; import { NapCatCore } from '@/core'; import { ActionName } from '@/onebot/action/types'; import { OB11Response } from '@/onebot/action/OB11Response'; import { LogWrapper } from '@/common/utils/log'; -import { NapCatOneBot11Adapter } from '@/onebot'; +import { ActionMap } from '@/onebot/action'; export class OB11ActiveWebSocketAdapter implements IOB11NetworkAdapter { - url: string; - reconnectIntervalInMillis: number; isClosed: boolean = false; - heartbeatInterval: number; - obContext: NapCatOneBot11Adapter; - coreContext: NapCatCore; logger: LogWrapper; private connection: WebSocket | null = null; - private actionMap: Map> = new Map(); private heartbeatRef: NodeJS.Timeout | null = null; - private readonly token: string; - - constructor(url: string, reconnectIntervalInMillis: number, heartbeatInterval: number, token:string, coreContext: NapCatCore, onebotContext: NapCatOneBot11Adapter) { - this.url = url; - this.token = token; - this.heartbeatInterval = heartbeatInterval; - this.reconnectIntervalInMillis = reconnectIntervalInMillis; - this.coreContext = coreContext; - this.obContext = onebotContext; + + constructor( + public url: string, + public reconnectIntervalInMillis: number, + public heartbeatIntervalInMillis: number, + private token: string, + public coreContext: NapCatCore, + public actions: ActionMap, + ) { this.logger = coreContext.context.logger; } - registerActionMap(actionMap: Map>) { - this.actionMap = actionMap; - } - - registerAction, P, R>(action: T) { - this.actionMap.set(action.actionName, action); - } - onEvent(event: T) { if (this.connection) { this.connection.send(JSON.stringify(event)); @@ -51,9 +36,9 @@ export class OB11ActiveWebSocketAdapter implements IOB11NetworkAdapter { } this.heartbeatRef = setInterval(() => { if (this.connection && this.connection.readyState === WebSocket.OPEN) { - this.connection.send(JSON.stringify(new OB11HeartbeatEvent(this.coreContext, this.heartbeatInterval, this.coreContext.selfInfo.online, true))); + this.connection.send(JSON.stringify(new OB11HeartbeatEvent(this.coreContext, this.heartbeatIntervalInMillis, this.coreContext.selfInfo.online, true))); } - }, this.heartbeatInterval); + }, this.heartbeatIntervalInMillis); await this.tryConnect(); } @@ -61,7 +46,6 @@ export class OB11ActiveWebSocketAdapter implements IOB11NetworkAdapter { if (this.isClosed) { this.logger.logDebug('Cannot close a closed WebSocket connection'); return; - //throw new Error('Cannot close a closed WebSocket connection'); } this.isClosed = true; if (this.connection) { @@ -130,7 +114,7 @@ export class OB11ActiveWebSocketAdapter implements IOB11NetworkAdapter { this.checkStateAndReply(OB11Response.error('json解析失败,请检查数据格式', 1400, echo)); } receiveData.params = (receiveData?.params) ? receiveData.params : {};//兼容类型验证 - const retdata = await this.actionMap.get(receiveData.action) + const retdata = await this.actions.get(receiveData.action) ?.websocketHandle(receiveData.params, echo || ''); const packet = Object.assign({}, retdata); this.checkStateAndReply(packet); diff --git a/src/onebot/network/index.ts b/src/onebot/network/index.ts index b8317ac2..941b3cfc 100644 --- a/src/onebot/network/index.ts +++ b/src/onebot/network/index.ts @@ -1,13 +1,12 @@ import BaseAction from '@/onebot/action/BaseAction'; import { OB11BaseEvent } from '@/onebot/event/OB11BaseEvent'; import { OB11Message } from '@/onebot'; +import { ActionMap } from '@/onebot/action'; export type OB11EmitEventContent = OB11BaseEvent | OB11Message; export interface IOB11NetworkAdapter { - registerAction, P, R>(action: T): void; - - registerActionMap(actionMap: Map>): void; + actions?: ActionMap; onEvent(event: T): void; @@ -19,27 +18,22 @@ export interface IOB11NetworkAdapter { export class OB11NetworkManager { adapters: IOB11NetworkAdapter[] = []; - async getAllAdapters() { - return this.adapters; - } - async openAllAdapters() { return Promise.all(this.adapters.map(adapter => adapter.open())); } - async registerAllActions(actions: Map>) { - return Promise.all(this.adapters.map(adapter => adapter.registerActionMap(actions))); - } - async emitEvent(event: OB11EmitEventContent) { //console.log('adapters', this.adapters.length); return Promise.all(this.adapters.map(adapter => adapter.onEvent(event))); } - async registerAdapter(adapter: IOB11NetworkAdapter) { - //console.log('Registering adapter:', adapter); + registerAdapter(adapter: IOB11NetworkAdapter) { this.adapters.push(adapter); - //console.log('Current adapters:', this.adapters.length); + } + + async registerAdapterAndOpen(adapter: IOB11NetworkAdapter) { + this.registerAdapter(adapter); + await adapter.open(); } async closeSomeAdapters(adaptersToClose: IOB11NetworkAdapter[]) { @@ -55,10 +49,8 @@ export class OB11NetworkManager { } async closeAllAdapters() { - //console.log('Closing all adapters'); await Promise.all(this.adapters.map(adapter => adapter.close())); this.adapters = []; - //console.log('All adapters closed. Current adapters:', this.adapters.length); } } diff --git a/src/onebot/network/passive-http.ts b/src/onebot/network/passive-http.ts index 6466f851..bba5b091 100644 --- a/src/onebot/network/passive-http.ts +++ b/src/onebot/network/passive-http.ts @@ -1,38 +1,25 @@ import { IOB11NetworkAdapter, OB11EmitEventContent } from './index'; -import BaseAction from '@/onebot/action/BaseAction'; import express, { Express, Request, Response } from 'express'; import http from 'http'; import { NapCatCore } from '@/core'; import { OB11Response } from '../action/OB11Response'; -import { NapCatOneBot11Adapter } from '@/onebot'; +import { ActionMap } from '@/onebot/action'; export class OB11PassiveHttpAdapter implements IOB11NetworkAdapter { - token: string; - coreContext: NapCatCore; - obContext: NapCatOneBot11Adapter; private app: Express | undefined; private server: http.Server | undefined; private isOpen: boolean = false; - private actionMap: Map> = new Map(); - private port: number; - constructor(port: number, token: string, coreContext: NapCatCore, onebotContext: NapCatOneBot11Adapter) { - this.port = port; - this.token = token; - this.coreContext = coreContext; - this.obContext = onebotContext; + constructor( + public port: number, + public token: string, + public coreContext: NapCatCore, + public actions: ActionMap, + ) { } - registerAction, P, R>(action: T) { - this.actionMap.set(action.actionName, action); - } - - registerActionMap(actionMap: Map>) { - this.actionMap = actionMap; - } - - onEvent(event: T) { - // 事件处理逻辑可以在这里实现 + onEvent() { + // http server is passive, no need to emit event } open() { @@ -97,7 +84,7 @@ export class OB11PassiveHttpAdapter implements IOB11NetworkAdapter { } const actionName = req.path.split('/')[1]; - const action = this.actionMap.get(actionName); + const action = this.actions.get(actionName); if (action) { try { const result = await action.handle(payload); diff --git a/src/onebot/network/passive-websocket.ts b/src/onebot/network/passive-websocket.ts index f6d0566a..05899902 100644 --- a/src/onebot/network/passive-websocket.ts +++ b/src/onebot/network/passive-websocket.ts @@ -10,6 +10,7 @@ import { NapCatOneBot11Adapter } from '..'; import { LogWrapper } from '@/common/utils/log'; import { OB11HeartbeatEvent } from '../event/meta/OB11HeartbeatEvent'; import { IncomingMessage } from 'http'; +import { ActionMap } from '@/onebot/action'; export class OB11PassiveWebSocketAdapter implements IOB11NetworkAdapter { wsServer: WebSocketServer; @@ -18,15 +19,19 @@ export class OB11PassiveWebSocketAdapter implements IOB11NetworkAdapter { isOpen: boolean = false; hasBeenClosed: boolean = false; heartbeatInterval: number = 0; - obContext: NapCatOneBot11Adapter; coreContext: NapCatCore; logger: LogWrapper; - private actionMap: Map> = new Map(); private heartbeatIntervalId: NodeJS.Timeout | null = null; - constructor(ip: string, port: number, heartbeatInterval: number, token: string, coreContext: NapCatCore, onebotContext: NapCatOneBot11Adapter) { + constructor( + ip: string, + port: number, + heartbeatInterval: number, + token: string, + coreContext: NapCatCore, + public actions: ActionMap + ) { this.coreContext = coreContext; - this.obContext = onebotContext; this.logger = coreContext.context.logger; this.heartbeatInterval = heartbeatInterval; @@ -58,14 +63,6 @@ export class OB11PassiveWebSocketAdapter implements IOB11NetworkAdapter { }).on('error', (err) => this.logger.log('[OneBot] [WebSocket Server] Server Error:', err.message)); } - registerActionMap(actionMap: Map>) { - this.actionMap = actionMap; - } - - registerAction, P, R>(action: T) { - this.actionMap.set(action.actionName, action); - } - onEvent(event: T) { this.wsClientsMutex.runExclusive(async () => { this.wsClients.forEach((wsClient) => { @@ -79,7 +76,11 @@ export class OB11PassiveWebSocketAdapter implements IOB11NetworkAdapter { this.logger.logError('[OneBot] [WebSocket Server] Cannot open a opened WebSocket server'); return; } - let addressInfo = this.wsServer.address(); + if (this.hasBeenClosed) { + this.logger.logError('[OneBot] [WebSocket Server] Cannot open a WebSocket server that has been closed'); + return; + } + const addressInfo = this.wsServer.address(); this.logger.log('[OneBot] [WebSocket Server] Server Started', typeof (addressInfo) === 'string' ? addressInfo : addressInfo?.address + ':' + addressInfo?.port); this.isOpen = true; @@ -137,7 +138,7 @@ export class OB11PassiveWebSocketAdapter implements IOB11NetworkAdapter { this.checkStateAndReply(OB11Response.error('json解析失败,请检查数据格式', 1400, echo), wsClient); } receiveData.params = (receiveData?.params) ? receiveData.params : {};//兼容类型验证 - const retdata = await this.actionMap.get(receiveData.action)?.websocketHandle(receiveData.params, echo || ''); + const retdata = await this.actions.get(receiveData.action)?.websocketHandle(receiveData.params, echo || ''); const packet = Object.assign({}, retdata); this.checkStateAndReply(packet, wsClient); } catch (e) {