add commands loader
This commit is contained in:
parent
5007dc6029
commit
2d6f3d46f3
4 changed files with 103 additions and 21 deletions
2
deps.ts
2
deps.ts
|
@ -7,3 +7,5 @@ export type {
|
||||||
Redis,
|
Redis,
|
||||||
RedisConnectOptions
|
RedisConnectOptions
|
||||||
} from 'https://deno.land/x/redis@v0.14.1/mod.ts'
|
} from 'https://deno.land/x/redis@v0.14.1/mod.ts'
|
||||||
|
export { walk } from 'https://deno.land/std@0.86.0/fs/walk.ts'
|
||||||
|
export { join } from 'https://deno.land/std@0.86.0/path/mod.ts'
|
||||||
|
|
|
@ -5,7 +5,7 @@ import { User } from '../structures/user.ts'
|
||||||
import { Collection } from '../utils/collection.ts'
|
import { Collection } from '../utils/collection.ts'
|
||||||
import { CommandClient } from './commandClient.ts'
|
import { CommandClient } from './commandClient.ts'
|
||||||
import { Extension } from './extensions.ts'
|
import { Extension } from './extensions.ts'
|
||||||
import { parse } from '../../deps.ts'
|
import { join, parse, walk } from '../../deps.ts'
|
||||||
|
|
||||||
export interface CommandContext {
|
export interface CommandContext {
|
||||||
/** The Client object */
|
/** The Client object */
|
||||||
|
@ -284,13 +284,103 @@ export class CommandBuilder extends Command {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export class CommandsLoader {
|
||||||
|
client: CommandClient
|
||||||
|
#importSeq: { [name: string]: number } = {}
|
||||||
|
|
||||||
|
constructor(client: CommandClient) {
|
||||||
|
this.client = client
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Load a Command from file.
|
||||||
|
*
|
||||||
|
* @param filePath Path of Command file.
|
||||||
|
* @param exportName Export name. Default is the "default" export.
|
||||||
|
*/
|
||||||
|
async load(
|
||||||
|
filePath: string,
|
||||||
|
exportName: string = 'default',
|
||||||
|
onlyRead?: boolean
|
||||||
|
): Promise<Command> {
|
||||||
|
const stat = await Deno.stat(filePath).catch(() => undefined)
|
||||||
|
if (stat === undefined || stat.isFile !== true)
|
||||||
|
throw new Error(`File not found on path ${filePath}`)
|
||||||
|
|
||||||
|
let seq: number | undefined
|
||||||
|
|
||||||
|
if (this.#importSeq[filePath] !== undefined) seq = this.#importSeq[filePath]
|
||||||
|
const mod = await import(
|
||||||
|
// eslint-disable-next-line @typescript-eslint/restrict-plus-operands
|
||||||
|
'file:///' +
|
||||||
|
join(Deno.cwd(), filePath) +
|
||||||
|
(seq === undefined ? '' : `#${seq}`)
|
||||||
|
)
|
||||||
|
if (this.#importSeq[filePath] === undefined) this.#importSeq[filePath] = 0
|
||||||
|
else this.#importSeq[filePath]++
|
||||||
|
|
||||||
|
const Cmd = mod[exportName]
|
||||||
|
if (Cmd === undefined)
|
||||||
|
throw new Error(`Command not exported as ${exportName} from ${filePath}`)
|
||||||
|
|
||||||
|
let cmd: Command
|
||||||
|
try {
|
||||||
|
if (Cmd instanceof Command) cmd = Cmd
|
||||||
|
else cmd = new Cmd()
|
||||||
|
if (!(cmd instanceof Command)) throw new Error('failed')
|
||||||
|
} catch (e) {
|
||||||
|
throw new Error(`Failed to load Command from ${filePath}`)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (onlyRead !== true) this.client.commands.add(cmd)
|
||||||
|
return cmd
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Load commands from a Directory.
|
||||||
|
*
|
||||||
|
* @param path Path of the directory.
|
||||||
|
* @param options Options to configure loading.
|
||||||
|
*/
|
||||||
|
async loadDirectory(
|
||||||
|
path: string,
|
||||||
|
options?: {
|
||||||
|
recursive?: boolean
|
||||||
|
exportName?: string
|
||||||
|
maxDepth?: number
|
||||||
|
exts?: string[]
|
||||||
|
onlyRead?: boolean
|
||||||
|
}
|
||||||
|
): Promise<Command[]> {
|
||||||
|
const commands: Command[] = []
|
||||||
|
|
||||||
|
for await (const entry of walk(path, {
|
||||||
|
maxDepth: options?.maxDepth,
|
||||||
|
exts: options?.exts,
|
||||||
|
includeDirs: false
|
||||||
|
})) {
|
||||||
|
if (entry.isFile !== true) continue
|
||||||
|
const cmd = await this.load(
|
||||||
|
entry.path,
|
||||||
|
options?.exportName,
|
||||||
|
options?.onlyRead
|
||||||
|
)
|
||||||
|
commands.push(cmd)
|
||||||
|
}
|
||||||
|
|
||||||
|
return commands
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export class CommandsManager {
|
export class CommandsManager {
|
||||||
client: CommandClient
|
client: CommandClient
|
||||||
list: Collection<string, Command> = new Collection()
|
list: Collection<string, Command> = new Collection()
|
||||||
disabled: Set<string> = new Set()
|
disabled: Set<string> = new Set()
|
||||||
|
loader: CommandsLoader
|
||||||
|
|
||||||
constructor(client: CommandClient) {
|
constructor(client: CommandClient) {
|
||||||
this.client = client
|
this.client = client
|
||||||
|
this.loader = new CommandsLoader(client)
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Number of loaded Commands */
|
/** Number of loaded Commands */
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
import { Message } from '../structures/message.ts'
|
import { Message } from '../structures/message.ts'
|
||||||
import { GuildTextChannel } from '../structures/textChannel.ts'
|
import { GuildTextChannel } from '../structures/textChannel.ts'
|
||||||
import { awaitSync } from '../utils/mixedPromise.ts'
|
|
||||||
import { Client, ClientOptions } from './client.ts'
|
import { Client, ClientOptions } from './client.ts'
|
||||||
import {
|
import {
|
||||||
CategoriesManager,
|
CategoriesManager,
|
||||||
|
@ -129,35 +128,29 @@ export class CommandClient extends Client implements CommandClientOptions {
|
||||||
async processMessage(msg: Message): Promise<any> {
|
async processMessage(msg: Message): Promise<any> {
|
||||||
if (!this.allowBots && msg.author.bot === true) return
|
if (!this.allowBots && msg.author.bot === true) return
|
||||||
|
|
||||||
const isUserBlacklisted = await awaitSync(
|
const isUserBlacklisted = await this.isUserBlacklisted(msg.author.id)
|
||||||
this.isUserBlacklisted(msg.author.id)
|
if (isUserBlacklisted) return
|
||||||
)
|
|
||||||
if (isUserBlacklisted === true) return
|
|
||||||
|
|
||||||
const isChannelBlacklisted = await awaitSync(
|
const isChannelBlacklisted = await this.isChannelBlacklisted(msg.channel.id)
|
||||||
this.isChannelBlacklisted(msg.channel.id)
|
if (isChannelBlacklisted) return
|
||||||
)
|
|
||||||
if (isChannelBlacklisted === true) return
|
|
||||||
|
|
||||||
if (msg.guild !== undefined) {
|
if (msg.guild !== undefined) {
|
||||||
const isGuildBlacklisted = await awaitSync(
|
const isGuildBlacklisted = await this.isGuildBlacklisted(msg.guild.id)
|
||||||
this.isGuildBlacklisted(msg.guild.id)
|
if (isGuildBlacklisted) return
|
||||||
)
|
|
||||||
if (isGuildBlacklisted === true) return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let prefix: string | string[] = []
|
let prefix: string | string[] = []
|
||||||
if (typeof this.prefix === 'string') prefix = [...prefix, this.prefix]
|
if (typeof this.prefix === 'string') prefix = [...prefix, this.prefix]
|
||||||
else prefix = [...prefix, ...this.prefix]
|
else prefix = [...prefix, ...this.prefix]
|
||||||
|
|
||||||
const userPrefix = await awaitSync(this.getUserPrefix(msg.author.id))
|
const userPrefix = await this.getUserPrefix(msg.author.id)
|
||||||
if (userPrefix !== undefined) {
|
if (userPrefix !== undefined) {
|
||||||
if (typeof userPrefix === 'string') prefix = [...prefix, userPrefix]
|
if (typeof userPrefix === 'string') prefix = [...prefix, userPrefix]
|
||||||
else prefix = [...prefix, ...userPrefix]
|
else prefix = [...prefix, ...userPrefix]
|
||||||
}
|
}
|
||||||
|
|
||||||
if (msg.guild !== undefined) {
|
if (msg.guild !== undefined) {
|
||||||
const guildPrefix = await awaitSync(this.getGuildPrefix(msg.guild.id))
|
const guildPrefix = await this.getGuildPrefix(msg.guild.id)
|
||||||
if (guildPrefix !== undefined) {
|
if (guildPrefix !== undefined) {
|
||||||
if (typeof guildPrefix === 'string') prefix = [...prefix, guildPrefix]
|
if (typeof guildPrefix === 'string') prefix = [...prefix, guildPrefix]
|
||||||
else prefix = [...prefix, ...guildPrefix]
|
else prefix = [...prefix, ...guildPrefix]
|
||||||
|
@ -361,10 +354,10 @@ export class CommandClient extends Client implements CommandClientOptions {
|
||||||
try {
|
try {
|
||||||
this.emit('commandUsed', ctx)
|
this.emit('commandUsed', ctx)
|
||||||
|
|
||||||
const beforeExecute = await awaitSync(command.beforeExecute(ctx))
|
const beforeExecute = await command.beforeExecute(ctx)
|
||||||
if (beforeExecute === false) return
|
if (beforeExecute === false) return
|
||||||
|
|
||||||
const result = await awaitSync(command.execute(ctx))
|
const result = await command.execute(ctx)
|
||||||
command.afterExecute(ctx, result)
|
command.afterExecute(ctx, result)
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
this.emit('commandError', ctx, e)
|
this.emit('commandError', ctx, e)
|
||||||
|
|
|
@ -1,3 +0,0 @@
|
||||||
export const awaitSync = async (val: any | Promise<any>): Promise<any> => {
|
|
||||||
return val instanceof Promise ? await val : val
|
|
||||||
}
|
|
Loading…
Reference in a new issue