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