2020-12-02 12:29:52 +00:00
|
|
|
import { Collection } from '../utils/collection.ts'
|
|
|
|
import { Command } from './command.ts'
|
|
|
|
import { CommandClient } from './commandClient.ts'
|
2020-11-11 09:04:49 +00:00
|
|
|
|
|
|
|
export type ExtensionEventCallback = (ext: Extension, ...args: any[]) => any
|
|
|
|
|
2020-12-03 03:19:39 +00:00
|
|
|
/** Extension Commands Manager */
|
2020-11-11 09:04:49 +00:00
|
|
|
export class ExtensionCommands {
|
|
|
|
extension: Extension
|
|
|
|
|
|
|
|
constructor(ext: Extension) {
|
|
|
|
this.extension = ext
|
|
|
|
}
|
|
|
|
|
2020-12-05 02:24:08 +00:00
|
|
|
/** Gets a list of Extension's Commands */
|
2020-11-11 09:04:49 +00:00
|
|
|
get list(): Collection<string, Command> {
|
2020-12-02 12:29:52 +00:00
|
|
|
return this.extension.client.commands.list.filter(
|
|
|
|
(c) => c.extension?.name === this.extension.name
|
|
|
|
)
|
2020-11-11 09:04:49 +00:00
|
|
|
}
|
|
|
|
|
2020-12-05 02:24:08 +00:00
|
|
|
/** Gets an Extension Command */
|
2020-11-11 09:04:49 +00:00
|
|
|
get(cmd: string): Command | undefined {
|
|
|
|
const find = this.extension.client.commands.find(cmd)
|
|
|
|
// linter sucks
|
|
|
|
if (find === undefined) return undefined
|
|
|
|
else if (find.extension === undefined) return undefined
|
|
|
|
else if (find.extension.name !== this.extension.name) return undefined
|
|
|
|
else return find
|
|
|
|
}
|
|
|
|
|
2020-12-05 02:24:08 +00:00
|
|
|
/** Adds an Extension Command */
|
2020-11-11 09:04:49 +00:00
|
|
|
add(Cmd: Command | typeof Command): boolean {
|
|
|
|
const cmd = Cmd instanceof Command ? Cmd : new Cmd()
|
|
|
|
cmd.extension = this.extension
|
|
|
|
return this.extension.client.commands.add(cmd)
|
|
|
|
}
|
|
|
|
|
2020-12-05 02:24:08 +00:00
|
|
|
/** Deletes an Extension Command */
|
2020-11-11 09:04:49 +00:00
|
|
|
delete(cmd: Command | string): boolean {
|
2020-12-02 12:29:52 +00:00
|
|
|
const find = this.extension.client.commands.find(
|
|
|
|
typeof cmd === 'string' ? cmd : cmd.name
|
|
|
|
)
|
2020-11-11 09:04:49 +00:00
|
|
|
if (find === undefined) return false
|
2020-12-02 12:29:52 +00:00
|
|
|
if (
|
|
|
|
find.extension !== undefined &&
|
|
|
|
find.extension.name !== this.extension.name
|
|
|
|
)
|
|
|
|
return false
|
2020-11-11 09:04:49 +00:00
|
|
|
else return this.extension.client.commands.delete(find)
|
|
|
|
}
|
|
|
|
|
2020-12-05 02:24:08 +00:00
|
|
|
/** Deletes all Commands of an Extension */
|
2020-11-11 09:04:49 +00:00
|
|
|
deleteAll(): void {
|
|
|
|
for (const [cmd] of this.list) {
|
|
|
|
this.delete(cmd)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-12-03 03:19:39 +00:00
|
|
|
/** Customizable, isolated and pluggable Extensions are a great way of writing certain Modules independent of others */
|
2020-11-11 09:04:49 +00:00
|
|
|
export class Extension {
|
|
|
|
client: CommandClient
|
2020-12-03 03:19:39 +00:00
|
|
|
/** Name of the Extension */
|
2020-11-11 09:04:49 +00:00
|
|
|
name: string = ''
|
2020-12-03 03:19:39 +00:00
|
|
|
/** Description of the Extension */
|
2020-11-11 09:04:49 +00:00
|
|
|
description?: string
|
2020-12-03 03:19:39 +00:00
|
|
|
/** Extensions's Commands Manager */
|
2020-11-11 09:04:49 +00:00
|
|
|
commands: ExtensionCommands = new ExtensionCommands(this)
|
2020-12-08 06:43:06 +00:00
|
|
|
/** Sub-Prefix to be used for ALL of Extenion's Commands. */
|
|
|
|
subPrefix?: string
|
2020-12-03 03:19:39 +00:00
|
|
|
/** Events registered by this Extension */
|
2020-11-11 09:04:49 +00:00
|
|
|
events: { [name: string]: (...args: any[]) => {} } = {}
|
2020-12-06 07:41:37 +00:00
|
|
|
|
|
|
|
_decoratedCommands?: { [name: string]: Command }
|
|
|
|
_decoratedEvents?: { [name: string]: (...args: any[]) => any }
|
2020-11-11 09:04:49 +00:00
|
|
|
|
|
|
|
constructor(client: CommandClient) {
|
|
|
|
this.client = client
|
2020-12-06 07:41:37 +00:00
|
|
|
if (this._decoratedCommands !== undefined) {
|
|
|
|
Object.entries(this._decoratedCommands).forEach((entry) => {
|
2020-12-08 06:43:06 +00:00
|
|
|
entry[1].extension = this
|
2020-12-06 07:28:01 +00:00
|
|
|
this.commands.add(entry[1])
|
|
|
|
})
|
2020-12-06 07:41:37 +00:00
|
|
|
this._decoratedCommands = undefined
|
|
|
|
}
|
|
|
|
|
|
|
|
if (
|
|
|
|
this._decoratedEvents !== undefined &&
|
|
|
|
Object.keys(this._decoratedEvents).length !== 0
|
|
|
|
) {
|
|
|
|
Object.entries(this._decoratedEvents).forEach((entry) => {
|
|
|
|
this.listen(entry[0], entry[1])
|
|
|
|
})
|
|
|
|
this._decoratedEvents = undefined
|
2020-12-06 07:28:01 +00:00
|
|
|
}
|
2020-11-11 09:04:49 +00:00
|
|
|
}
|
|
|
|
|
2020-12-05 02:24:08 +00:00
|
|
|
/** Listens for an Event through Extension. */
|
2020-11-11 09:04:49 +00:00
|
|
|
listen(event: string, cb: ExtensionEventCallback): boolean {
|
|
|
|
if (this.events[event] !== undefined) return false
|
|
|
|
else {
|
|
|
|
const fn = (...args: any[]): any => {
|
|
|
|
// eslint-disable-next-line standard/no-callback-literal
|
|
|
|
cb(this, ...args)
|
2020-12-02 12:29:52 +00:00
|
|
|
}
|
2020-11-11 09:04:49 +00:00
|
|
|
this.client.on(event, fn)
|
|
|
|
this.events[event] = fn
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-12-03 03:19:39 +00:00
|
|
|
/** Method called upon loading of an Extension */
|
2020-11-11 09:04:49 +00:00
|
|
|
load(): any {}
|
2020-12-03 03:19:39 +00:00
|
|
|
/** Method called upon unloading of an Extension */
|
2020-11-11 09:04:49 +00:00
|
|
|
unload(): any {}
|
|
|
|
}
|
|
|
|
|
2020-12-03 03:19:39 +00:00
|
|
|
/** Extensions Manager for CommandClient */
|
2020-11-11 09:04:49 +00:00
|
|
|
export class ExtensionsManager {
|
|
|
|
client: CommandClient
|
|
|
|
list: Collection<string, Extension> = new Collection()
|
|
|
|
|
|
|
|
constructor(client: CommandClient) {
|
|
|
|
this.client = client
|
|
|
|
}
|
|
|
|
|
2020-12-05 02:24:08 +00:00
|
|
|
/** Gets an Extension by name */
|
2020-11-11 09:04:49 +00:00
|
|
|
get(ext: string): Extension | undefined {
|
|
|
|
return this.list.get(ext)
|
|
|
|
}
|
|
|
|
|
2020-12-05 02:24:08 +00:00
|
|
|
/** Checks whether an Extension exists or not */
|
2020-11-11 09:04:49 +00:00
|
|
|
exists(ext: string): boolean {
|
|
|
|
return this.get(ext) !== undefined
|
|
|
|
}
|
|
|
|
|
2020-12-05 02:24:08 +00:00
|
|
|
/** Loads an Extension onto Command Client */
|
2020-11-11 09:04:49 +00:00
|
|
|
load(ext: Extension | typeof Extension): void {
|
|
|
|
// eslint-disable-next-line new-cap
|
|
|
|
if (!(ext instanceof Extension)) ext = new ext(this.client)
|
2020-12-02 12:29:52 +00:00
|
|
|
if (this.exists(ext.name))
|
|
|
|
throw new Error(`Extension with name '${ext.name}' already exists`)
|
2020-11-11 09:04:49 +00:00
|
|
|
this.list.set(ext.name, ext)
|
|
|
|
ext.load()
|
|
|
|
}
|
|
|
|
|
2020-12-05 02:24:08 +00:00
|
|
|
/** Unloads an Extension from Command Client */
|
2020-11-11 09:04:49 +00:00
|
|
|
unload(ext: Extension | string): boolean {
|
|
|
|
const name = typeof ext === 'string' ? ext : ext.name
|
|
|
|
const extension = this.get(name)
|
|
|
|
if (extension === undefined) return false
|
|
|
|
extension.commands.deleteAll()
|
|
|
|
for (const [k, v] of Object.entries(extension.events)) {
|
|
|
|
this.client.removeListener(k, v)
|
|
|
|
// eslint-disable-next-line @typescript-eslint/no-dynamic-delete
|
|
|
|
delete extension.events[k]
|
|
|
|
}
|
|
|
|
extension.unload()
|
|
|
|
return this.list.delete(name)
|
|
|
|
}
|
2020-12-02 12:29:52 +00:00
|
|
|
}
|