rename classes, add irc connection interface
This commit is contained in:
parent
a5c7c22d54
commit
d32ae78c56
@ -9,7 +9,7 @@ Zero dependencies library for creating anything using the IRC protocol - bots, c
|
||||
There is an example usage documented in [src/examples/connection-test.ts](https://gitlab.icynet.eu/IcyNetwork/irclib/-/blob/master/src/examples/connection-test.ts), but basically you have two ways to create an IRC client connection:
|
||||
|
||||
1. Use the `IRCBot` class. This just takes connection options and it uses `IRCSocketConnector` (so it will not work in the browser!)
|
||||
2. Use the `IRCConnectionWrapper` class directly. To use this, you need to provide your own connector in addition to the options.
|
||||
2. Use the `IRCConnection` class directly. To use this, you need to provide your own connector in addition to the options.
|
||||
|
||||
### Connection options
|
||||
|
||||
|
20
src/bot.ts
20
src/bot.ts
@ -1,22 +1,30 @@
|
||||
import { IRCSocketConnector } from './connector/net.connector';
|
||||
import { IRCConnectionWrapper } from './irc';
|
||||
import { IRCConnection } from './irc';
|
||||
import { IIRCOptions } from './types/irc.interfaces';
|
||||
import { formatstr } from './utility/formatstr';
|
||||
|
||||
export class IRCBot extends IRCConnectionWrapper {
|
||||
export class IRCBot extends IRCConnection {
|
||||
constructor(options: IIRCOptions) {
|
||||
super(options, IRCSocketConnector);
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a message to the server (`PRIVMSG`)
|
||||
* @param to Recipient, a channel or a nick
|
||||
* @param message Message to send
|
||||
* @param args Additional arguments for message
|
||||
*/
|
||||
send(to: string, message: string, ...args: any[]) {
|
||||
this.write('PRIVMSG %s :%s', to, formatstr(message, ...args));
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a message to the server (`NOTICE`)
|
||||
* @param to Recipient, a channel or a nick
|
||||
* @param message Message to send
|
||||
* @param args Additional arguments for message
|
||||
*/
|
||||
notice(to: string, message: string, ...args: any[]) {
|
||||
this.write('NOTICE %s :%s', to, formatstr(message, ...args));
|
||||
}
|
||||
|
||||
nick(newNick: string) {
|
||||
this.write('NICK %s', newNick);
|
||||
}
|
||||
}
|
||||
|
@ -1,13 +1,13 @@
|
||||
import net, { Socket } from 'net';
|
||||
import tls, { TLSSocket } from 'tls';
|
||||
import { ConnectorEvents } from '../types/events';
|
||||
import { IRCConnector } from '../types/impl.interface';
|
||||
import { IIRCConnector } from '../types/impl.interface';
|
||||
import { formatstr } from '../utility/formatstr';
|
||||
import { TypedEventEmitter } from '../utility/typed-event-emitter';
|
||||
|
||||
export class IRCSocketConnector
|
||||
extends TypedEventEmitter<ConnectorEvents>
|
||||
implements IRCConnector
|
||||
implements IIRCConnector
|
||||
{
|
||||
connected = false;
|
||||
private socket?: Socket | TLSSocket;
|
||||
|
@ -1,11 +1,11 @@
|
||||
import { ConnectorEvents } from '../types/events';
|
||||
import { IRCConnector } from '../types/impl.interface';
|
||||
import { IIRCConnector } from '../types/impl.interface';
|
||||
import { formatstr } from '../utility/formatstr';
|
||||
import { TypedEventEmitter } from '../utility/typed-event-emitter';
|
||||
|
||||
export class IRCWebSocketConnector
|
||||
extends TypedEventEmitter<ConnectorEvents>
|
||||
implements IRCConnector
|
||||
implements IIRCConnector
|
||||
{
|
||||
connected = false;
|
||||
private socket?: WebSocket;
|
||||
|
84
src/irc.ts
84
src/irc.ts
@ -1,8 +1,9 @@
|
||||
import { IRCCommunicatorEvents } from './types/events';
|
||||
import {
|
||||
IRCCommunicator,
|
||||
IRCConnector,
|
||||
IRCConnectorConstructor,
|
||||
IWritableEventEmitter,
|
||||
IIRCConnector,
|
||||
IIRCConnectorConstructor,
|
||||
IIRCWrapper,
|
||||
} from './types/impl.interface';
|
||||
import {
|
||||
IIRCLine,
|
||||
@ -22,42 +23,27 @@ import { TypedEventEmitter } from './utility/typed-event-emitter';
|
||||
import { parseWho, WhoResponse } from './utility/who-parser';
|
||||
import { parseWhois, WhoisResponse } from './utility/whois-parser';
|
||||
|
||||
export class IRCConnectionWrapper
|
||||
export class IRCConnection
|
||||
extends TypedEventEmitter<IRCCommunicatorEvents>
|
||||
implements IRCCommunicator
|
||||
implements IIRCWrapper
|
||||
{
|
||||
/**
|
||||
* Channels the bot is currently in.
|
||||
*/
|
||||
public channels: string[] = [];
|
||||
|
||||
/**
|
||||
* Current collectors waiting for their reply.
|
||||
*/
|
||||
public queue: IQueue[] = [];
|
||||
|
||||
/**
|
||||
* Login success status.
|
||||
*/
|
||||
public authenticated = false;
|
||||
|
||||
/**
|
||||
* Information about the IRC server gathered during runtime
|
||||
*/
|
||||
public serverData: IIRCServerData = {
|
||||
name: '',
|
||||
supportedModes: {},
|
||||
serverSupports: {},
|
||||
};
|
||||
|
||||
private connection?: IRCConnector;
|
||||
private connection?: IIRCConnector;
|
||||
|
||||
private _supportsDone = false;
|
||||
private _lastLineWasSupports = false;
|
||||
|
||||
constructor(
|
||||
public options: IIRCOptions,
|
||||
public connector: IRCConnectorConstructor,
|
||||
public connector: IIRCConnectorConstructor,
|
||||
) {
|
||||
super();
|
||||
if (!options.username) {
|
||||
@ -66,14 +52,6 @@ export class IRCConnectionWrapper
|
||||
this.handlers();
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a raw command to the server.
|
||||
*
|
||||
* **WARNING:** Line break characters could have an unintended side-effect!
|
||||
* Filter user-generated content!
|
||||
* @param format Command
|
||||
* @param args Command arguments
|
||||
*/
|
||||
write(format: string, ...args: any[]): void {
|
||||
this.connection?.write(format, ...args);
|
||||
}
|
||||
@ -487,9 +465,6 @@ export class IRCConnectionWrapper
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new connection to the configured IRC server.
|
||||
*/
|
||||
public async connect(): Promise<void> {
|
||||
if (this.connection) {
|
||||
await this.connection.destroy();
|
||||
@ -529,10 +504,6 @@ export class IRCConnectionWrapper
|
||||
this.authenticate();
|
||||
}
|
||||
|
||||
/**
|
||||
* Disconnect from the IRC server gracefully, sends `QUIT`.
|
||||
* @param reason Reason for disconnection
|
||||
*/
|
||||
public async disconnect(reason?: string): Promise<void> {
|
||||
if (!this.connected) {
|
||||
if (this.connection) {
|
||||
@ -554,18 +525,10 @@ export class IRCConnectionWrapper
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Get connection status. `authenticated` is a more reliable indicator
|
||||
* of a successful connection.
|
||||
*/
|
||||
public get connected() {
|
||||
return this.connection?.connected ?? false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a new nickname for self.
|
||||
* @param newNick New nickname
|
||||
*/
|
||||
public setNick(newNick: string): void {
|
||||
this.write('NICK %s', newNick);
|
||||
this.emit('nick', {
|
||||
@ -575,10 +538,6 @@ export class IRCConnectionWrapper
|
||||
this.options.nick = newNick;
|
||||
}
|
||||
|
||||
/**
|
||||
* Asynchronously ping the server.
|
||||
* @returns Ping in milliseconds
|
||||
*/
|
||||
public async getPing(): Promise<number> {
|
||||
return new Promise<number>((resolve) => {
|
||||
const sendTime = Date.now();
|
||||
@ -593,11 +552,6 @@ export class IRCConnectionWrapper
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Asynchronous WHOIS query on `nick`
|
||||
* @param nick Nick to query
|
||||
* @returns Parsed WHOIS response object
|
||||
*/
|
||||
public async whois(nick: string): Promise<WhoisResponse> {
|
||||
return new Promise((resolve) => {
|
||||
this.useCollector(
|
||||
@ -608,11 +562,6 @@ export class IRCConnectionWrapper
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Asynchronous WHO query on `target`
|
||||
* @param target Channel or nick to query
|
||||
* @returns Parsed WHO response object array
|
||||
*/
|
||||
public async who(target: string): Promise<WhoResponse[]> {
|
||||
return new Promise((resolve) => {
|
||||
this.useCollector(
|
||||
@ -623,11 +572,6 @@ export class IRCConnectionWrapper
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a list of names in a channel asynchronously
|
||||
* @param channel Channel to query
|
||||
* @returns String list of nicks (with mode prefixes preserved)
|
||||
*/
|
||||
public async names(channel: string): Promise<string[]> {
|
||||
return new Promise((resolve) => {
|
||||
this.useCollector(
|
||||
@ -646,10 +590,6 @@ export class IRCConnectionWrapper
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a list of channels asynchronously
|
||||
* @returns Channel list in `[<channel>, <# visible>, <topic>][]` format
|
||||
*/
|
||||
public async list(): Promise<string[][]> {
|
||||
return new Promise((resolve) => {
|
||||
this.useCollector(
|
||||
@ -669,14 +609,6 @@ export class IRCConnectionWrapper
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a collector to the queue.
|
||||
* This is used to grab lines from the server, wait for them
|
||||
* and return them in a callback.
|
||||
* @param collector IRC line collector
|
||||
* @param line Command to send to the server
|
||||
* @param args Arguments to the command
|
||||
*/
|
||||
public useCollector(collector: IQueue, line: string, ...args: any[]) {
|
||||
this.queue.push(collector);
|
||||
this.write(line, ...args);
|
||||
|
@ -1,20 +1,124 @@
|
||||
export interface IRCCommunicator {
|
||||
import { WhoResponse } from '../utility/who-parser';
|
||||
import { WhoisResponse } from '../utility/whois-parser';
|
||||
import { IIRCOptions, IIRCServerData, IQueue } from './irc.interfaces';
|
||||
|
||||
export interface IWritableEventEmitter {
|
||||
emit(event: string, ...args: any[]): void;
|
||||
on(event: string, handler: (...args: any[]) => void): void;
|
||||
write(format: string, ...args: any[]): void;
|
||||
}
|
||||
|
||||
export interface IRCConnector extends IRCCommunicator {
|
||||
export interface IIRCConnector extends IWritableEventEmitter {
|
||||
/**
|
||||
* Current connection status.
|
||||
*/
|
||||
connected: boolean;
|
||||
/**
|
||||
* Connect the socket to the server.
|
||||
*/
|
||||
connect(): Promise<void>;
|
||||
/**
|
||||
* Forcefully disconnect the socket from the server.
|
||||
*/
|
||||
destroy(): Promise<void>;
|
||||
}
|
||||
|
||||
export interface IRCConnectorConstructor {
|
||||
export interface IIRCWrapper extends IWritableEventEmitter {
|
||||
/**
|
||||
* Connection options for the IRC server.
|
||||
*/
|
||||
options: IIRCOptions;
|
||||
/**
|
||||
* The connector to use for connecting to the IRC server.
|
||||
*/
|
||||
connector: IIRCConnectorConstructor;
|
||||
/**
|
||||
* Get connection status. `authenticated` is a more reliable indicator
|
||||
* of a successful connection.
|
||||
*/
|
||||
connected: boolean;
|
||||
/**
|
||||
* Channels the bot is currently in.
|
||||
*/
|
||||
channels: string[];
|
||||
/**
|
||||
* Current collectors waiting for their reply.
|
||||
*/
|
||||
queue: IQueue[];
|
||||
/**
|
||||
* Login success status.
|
||||
*/
|
||||
authenticated: boolean;
|
||||
/**
|
||||
* Information about the IRC server gathered during runtime
|
||||
*/
|
||||
serverData: IIRCServerData;
|
||||
/**
|
||||
* Send a raw command to the server.
|
||||
*
|
||||
* **WARNING:** Line break characters could have an unintended side-effect!
|
||||
* Filter user-generated content!
|
||||
* @param format Command
|
||||
* @param args Command arguments
|
||||
*/
|
||||
write(format: string, ...args: any[]): void;
|
||||
/**
|
||||
* Create a new connection to the configured IRC server.
|
||||
*/
|
||||
connect(): Promise<void>;
|
||||
/**
|
||||
* Disconnect from the IRC server gracefully, sends `QUIT`.
|
||||
* @param reason Reason for disconnection
|
||||
*/
|
||||
disconnect(reason?: string): Promise<void>;
|
||||
/**
|
||||
* Asynchronously ping the server.
|
||||
* @returns Ping in milliseconds
|
||||
*/
|
||||
getPing(): Promise<number>;
|
||||
/**
|
||||
* Asynchronous WHOIS query on `nick`
|
||||
* @param nick Nick to query
|
||||
* @returns Parsed WHOIS response object
|
||||
*/
|
||||
whois(nick: string): Promise<WhoisResponse>;
|
||||
/**
|
||||
* Asynchronous WHO query on `target`
|
||||
* @param target Channel or nick to query
|
||||
* @returns Parsed WHO response object array
|
||||
*/
|
||||
who(target: string): Promise<WhoResponse[]>;
|
||||
/**
|
||||
* Get a list of names in a channel asynchronously
|
||||
* @param channel Channel to query
|
||||
* @returns String list of nicks (with mode prefixes preserved)
|
||||
*/
|
||||
names(channel: string): Promise<string[]>;
|
||||
/**
|
||||
* Get a list of channels asynchronously
|
||||
* @returns Channel list in `[<channel>, <# visible>, <topic>][]` format
|
||||
*/
|
||||
list(): Promise<string[][]>;
|
||||
/**
|
||||
* Add a collector to the queue.
|
||||
* This is used to grab lines from the server, wait for them
|
||||
* and return them in a callback.
|
||||
* @param collector IRC line collector
|
||||
* @param line Command to send to the server
|
||||
* @param args Arguments to the command
|
||||
*/
|
||||
useCollector(collector: IQueue, line: string, ...args: any[]): void;
|
||||
}
|
||||
|
||||
export interface IIRCConnectorConstructor {
|
||||
new (
|
||||
secure: boolean,
|
||||
host: string,
|
||||
port?: number,
|
||||
opts?: Record<string, unknown>,
|
||||
): IRCConnector;
|
||||
): IIRCConnector;
|
||||
}
|
||||
|
||||
export interface IIRCConnetionConstructor {
|
||||
new (options: IIRCOptions, connector: IIRCConnectorConstructor): IIRCWrapper;
|
||||
}
|
||||
|
@ -161,5 +161,8 @@ export interface IIRCServerData {
|
||||
* Supported channel user modes from the server (e.g. `ohv: @%+`)
|
||||
*/
|
||||
supportedModes: Record<string, string>;
|
||||
/**
|
||||
* Name of the IRC network. May not be present.
|
||||
*/
|
||||
network?: string;
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { IRCConnectionWrapper } from '../../irc';
|
||||
import { IIRCWrapper } from '../../types/impl.interface';
|
||||
import { modeFromPrefix } from '../mode-from-prefix';
|
||||
import { TypedEventEmitter } from '../typed-event-emitter';
|
||||
import { WhoResponse } from '../who-parser';
|
||||
@ -11,7 +11,7 @@ import { INicklistChannel } from './nicklist.interfaces';
|
||||
export class IRCNickList extends TypedEventEmitter<NickListEvents> {
|
||||
public channels: INicklistChannel[] = [];
|
||||
|
||||
constructor(public irc: IRCConnectionWrapper) {
|
||||
constructor(public irc: IIRCWrapper) {
|
||||
super();
|
||||
this.handlers();
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { IRCConnectionWrapper } from '../irc';
|
||||
import { IRCConnection } from '../irc';
|
||||
import { INickServOptions } from '../types/irc.interfaces';
|
||||
import { Collector } from './collector';
|
||||
|
||||
@ -35,7 +35,7 @@ export class NickServCollector extends Collector {
|
||||
export class NickServValidator {
|
||||
public nickservStore: { [key: string]: INickStore } = {};
|
||||
|
||||
constructor(public irc: IRCConnectionWrapper) {
|
||||
constructor(public irc: IRCConnection) {
|
||||
this.irc.on('leave', ({ nickname }) => {
|
||||
if (this.nickservStore[nickname]) {
|
||||
delete this.nickservStore[nickname];
|
||||
|
Loading…
Reference in New Issue
Block a user