148 lines
3.2 KiB
TypeScript
148 lines
3.2 KiB
TypeScript
import { randomBytes } from 'crypto';
|
|
|
|
import { EventEmitter } from 'events';
|
|
import { IPlugin } from '../plugin';
|
|
import { IMessage, IMessageTarget } from './message';
|
|
import { Formatter } from './message-format';
|
|
import { ProtocolFeatureFlag } from './protocol-flags';
|
|
|
|
/**
|
|
* The base class for a protocol handler.
|
|
*/
|
|
export class Protocol extends EventEmitter {
|
|
/**
|
|
* Protocol message formatter.
|
|
*/
|
|
public format: Formatter = new Formatter(false, false, this.flags);
|
|
|
|
/**
|
|
* Connection ID
|
|
*/
|
|
public id = randomBytes(4).toString('hex');
|
|
|
|
/**
|
|
* Protocol type name.
|
|
*/
|
|
public type = 'GenericProtocol';
|
|
|
|
/**
|
|
* Indicates that the protocol is currently running.
|
|
*/
|
|
public running = false;
|
|
|
|
/**
|
|
* This should be set to true when the protocol was stopped for any reason
|
|
* at any time.
|
|
*/
|
|
public stopped = false;
|
|
|
|
/**
|
|
* This will be set to true when the protocol fails for any reason
|
|
*/
|
|
public failed = false;
|
|
|
|
/**
|
|
* This identifies the bot itself.
|
|
*/
|
|
public me: IMessageTarget = {
|
|
id: '',
|
|
name: '',
|
|
};
|
|
|
|
/**
|
|
* @param plugin Reference to the plugin which provides this protocol.
|
|
* @param config Protocol connection instance configuration.
|
|
* @param flags Feature flags which describe this protocol.
|
|
*/
|
|
constructor(
|
|
public plugin: IPlugin,
|
|
public config: any,
|
|
public flags: ProtocolFeatureFlag[] = [
|
|
ProtocolFeatureFlag.EVENT_MESSAGE,
|
|
ProtocolFeatureFlag.PLAIN,
|
|
]
|
|
) {
|
|
super();
|
|
this.passEvents();
|
|
}
|
|
|
|
/**
|
|
* Protocol connection's configured name.
|
|
*/
|
|
public get name(): string {
|
|
return this.config.name;
|
|
}
|
|
|
|
/**
|
|
* Protocol's running status.
|
|
*/
|
|
public get status(): boolean {
|
|
return this.running;
|
|
}
|
|
|
|
/**
|
|
* Start the protocol. Create connections here.
|
|
* @param args Start arguments
|
|
*/
|
|
public start(...args: any[]): void {
|
|
this.running = true;
|
|
this.emit('running');
|
|
}
|
|
|
|
/**
|
|
* Stop the protocol. This should stop any connections.
|
|
* @param force Force stop
|
|
*/
|
|
public stop(force = false): void {
|
|
if (!this.running) {
|
|
return;
|
|
}
|
|
|
|
this.running = false;
|
|
this.stopped = true;
|
|
|
|
if (force) {
|
|
this.failed = true;
|
|
}
|
|
|
|
this.emit('stopped');
|
|
}
|
|
|
|
public resolve(message: IMessage, ...data: any[]): void {
|
|
throw new Error('Method not implemented.');
|
|
}
|
|
|
|
public async sendTo(target: string, ...data: any[]): Promise<boolean> {
|
|
throw new Error('Method not implemented.');
|
|
}
|
|
|
|
/**
|
|
* Full name of this protocol (`<plugin name>/<protocol connection name>`)
|
|
*/
|
|
public get fullName(): string {
|
|
return this.plugin.manifest.name + '/' + this.name;
|
|
}
|
|
|
|
/**
|
|
* Check if this protocol supports a feature flag
|
|
* @param flag Feature flag to check for
|
|
* @returns Boolean
|
|
*/
|
|
public supports(flag: ProtocolFeatureFlag | ProtocolFeatureFlag[]) {
|
|
return Array.isArray(flag)
|
|
? flag.every((entry) => this.flags.includes(entry))
|
|
: this.flags.includes(flag);
|
|
}
|
|
|
|
protected passEvents(): void {
|
|
this.on('stop', (force) => this.stop(force));
|
|
this.on('start', (...args: any[]) => {
|
|
// Prevent restarting from here, it's unsafe
|
|
if (this.status || (!this.status && this.stopped)) {
|
|
return;
|
|
}
|
|
this.start(...args);
|
|
});
|
|
}
|
|
}
|