irclib/src/connector/net.connector.ts

84 lines
1.9 KiB
TypeScript

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<void> {
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<void> {
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);
});
}
}