import { formatWithOptions } from 'util'; import { IRCConnector } from '../types/impl.interface'; import { SimpleEventEmitter } from '../utility/simple-event-emitter'; export class IRCWebSocketConnector extends SimpleEventEmitter implements IRCConnector { connected = false; private socket?: WebSocket; constructor( public secure: boolean, public host: string, public port?: number, ) { super(); } connect(): Promise { const url = `ws${this.secure ? 's' : ''}://${this.host}:${ this.port || 6667 }`; return new Promise((resolve, reject) => { const onConnect = () => { this.connected = true; resolve(); }; try { this.socket = new WebSocket(url); } catch (e: unknown) { return reject(e); } this.socket?.addEventListener('open', onConnect); this.handle(); }); } async destroy(): Promise { this.connected = false; this.socket?.close(); this.socket = undefined; } write(format: string, ...args: any[]): void { this.socket?.send( formatWithOptions({ colors: false }, format, ...args) + '\r\n', ); } private handle() { let buffer: string = ''; this.socket?.addEventListener('message', (event) => { const chunk = event.data.toString(); buffer += chunk; const data = buffer.split('\r\n'); buffer = data.pop() || ''; data.forEach((line: string) => { if (line.indexOf('PING') === 0) { this.socket?.send('PONG' + line.substring(4) + '\r\n'); return; } this.emit('data', line); }); }); this.socket?.addEventListener('error', (err) => this.emit('error', err)); this.socket?.addEventListener('close', (err) => { this.connected = false; this.socket = undefined; this.emit('close', err); }); } }