80 lines
1.8 KiB
TypeScript
80 lines
1.8 KiB
TypeScript
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<void> {
|
|
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<void> {
|
|
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);
|
|
});
|
|
}
|
|
}
|