diff --git a/src/onebot/network/active-websocket.ts b/src/onebot/network/active-websocket.ts new file mode 100644 index 00000000..5de14540 --- /dev/null +++ b/src/onebot/network/active-websocket.ts @@ -0,0 +1,74 @@ +import { IOB11NetworkAdapter } from '@/onebot/network/index'; + +import { WebSocket as NodeWebSocket } from 'ws'; +import BaseAction from '@/onebot/action/BaseAction'; +import { OB11BaseEvent } from '@/onebot/event/OB11BaseEvent'; +import { sleep } from '@/common/utils/helper'; + +export class OB11ActiveWebSocketAdapter implements IOB11NetworkAdapter { + url: string; + reconnectIntervalInMillis: number; + isClosed: boolean = false; + + private connection: NodeWebSocket | null = null; + private actionMap: Map> = new Map(); + + constructor(url: string, reconnectIntervalInMillis: number) { + this.url = url; + this.reconnectIntervalInMillis = reconnectIntervalInMillis; + } + + registerAction, P, R>(action: T) { + this.actionMap.set(action.actionName, action); + } + + onEvent(event: T) { + if (this.connection) { + // this.connection.send(JSON.stringify(event)); + // TODO: wrap the event, and send the wrapped to the server. + // TODO: consider using a utility function + } + } + + async open() { + if (this.connection) { + return; + } + await this.tryConnect(); + } + + close() { + this.isClosed = true; + if (this.isClosed) { + throw new Error('Cannot close a closed WebSocket connection'); + } + if (this.connection) { + this.connection.close(); + this.connection = null; + } + } + + private async tryConnect() { + while (!this.connection) { + try { + this.connection = new NodeWebSocket(this.url); + } catch (e) { + this.connection = null; + console.error('Failed to connect to the server, retrying in 5 seconds...'); + await sleep(5000); + } + } + + this.connection.on('message', (data) => { + // TODO: extract action name and payload from the message, then call the corresponding action. + // TODO: consider using a utility function + }); + + this.connection.once('close', () => { + if (!this.isClosed) { + this.connection = new NodeWebSocket(this.url); + this.tryConnect(); + } + }); + } +} diff --git a/src/onebot/network/passive-websocket.ts b/src/onebot/network/passive-websocket.ts index da321a61..d32bd3ff 100644 --- a/src/onebot/network/passive-websocket.ts +++ b/src/onebot/network/passive-websocket.ts @@ -29,6 +29,7 @@ export class OB11PassiveWebSocketAdapter implements IOB11NetworkAdapter { } wsClient.on('message', (message) => { // TODO: extract action name and payload from the message, then call the corresponding action. + // TODO: consider using a utility function }); wsClient.once('close', () => { this.wsClientsMutex.runExclusive(async () => { @@ -53,6 +54,7 @@ export class OB11PassiveWebSocketAdapter implements IOB11NetworkAdapter { this.wsClients.forEach((wsClient) => { // wsClient.send(JSON.stringify(event)); // TODO: wrap the event, and send the wrapped to the client. + // TODO: consider using a utility function }); }); }