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,
|
||||
RedisConnectOptions
|
||||
} 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 { CommandClient } from './commandClient.ts'
|
||||
import { Extension } from './extensions.ts'
|
||||
import { parse } from '../../deps.ts'
|
||||
import { join, parse, walk } from '../../deps.ts'
|
||||
|
||||
export interface CommandContext {
|
||||
/** 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 {
|
||||
client: CommandClient
|
||||
list: Collection<string, Command> = new Collection()
|
||||
disabled: Set<string> = new Set()
|
||||
loader: CommandsLoader
|
||||
|
||||
constructor(client: CommandClient) {
|
||||
this.client = client
|
||||
this.loader = new CommandsLoader(client)
|
||||
}
|
||||
|
||||
/** Number of loaded Commands */
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
import { Message } from '../structures/message.ts'
|
||||
import { GuildTextChannel } from '../structures/textChannel.ts'
|
||||
import { awaitSync } from '../utils/mixedPromise.ts'
|
||||
import { Client, ClientOptions } from './client.ts'
|
||||
import {
|
||||
CategoriesManager,
|
||||
|
@ -129,35 +128,29 @@ export class CommandClient extends Client implements CommandClientOptions {
|
|||
async processMessage(msg: Message): Promise<any> {
|
||||
if (!this.allowBots && msg.author.bot === true) return
|
||||
|
||||
const isUserBlacklisted = await awaitSync(
|
||||
this.isUserBlacklisted(msg.author.id)
|
||||
)
|
||||
if (isUserBlacklisted === true) return
|
||||
const isUserBlacklisted = await this.isUserBlacklisted(msg.author.id)
|
||||
if (isUserBlacklisted) return
|
||||
|
||||
const isChannelBlacklisted = await awaitSync(
|
||||
this.isChannelBlacklisted(msg.channel.id)
|
||||
)
|
||||
if (isChannelBlacklisted === true) return
|
||||
const isChannelBlacklisted = await this.isChannelBlacklisted(msg.channel.id)
|
||||
if (isChannelBlacklisted) return
|
||||
|
||||
if (msg.guild !== undefined) {
|
||||
const isGuildBlacklisted = await awaitSync(
|
||||
this.isGuildBlacklisted(msg.guild.id)
|
||||
)
|
||||
if (isGuildBlacklisted === true) return
|
||||
const isGuildBlacklisted = await this.isGuildBlacklisted(msg.guild.id)
|
||||
if (isGuildBlacklisted) return
|
||||
}
|
||||
|
||||
let prefix: string | string[] = []
|
||||
if (typeof this.prefix === 'string') 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 (typeof userPrefix === 'string') prefix = [...prefix, userPrefix]
|
||||
else prefix = [...prefix, ...userPrefix]
|
||||
}
|
||||
|
||||
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 (typeof guildPrefix === 'string') prefix = [...prefix, guildPrefix]
|
||||
else prefix = [...prefix, ...guildPrefix]
|
||||
|
@ -361,10 +354,10 @@ export class CommandClient extends Client implements CommandClientOptions {
|
|||
try {
|
||||
this.emit('commandUsed', ctx)
|
||||
|
||||
const beforeExecute = await awaitSync(command.beforeExecute(ctx))
|
||||
const beforeExecute = await command.beforeExecute(ctx)
|
||||
if (beforeExecute === false) return
|
||||
|
||||
const result = await awaitSync(command.execute(ctx))
|
||||
const result = await command.execute(ctx)
|
||||
command.afterExecute(ctx, result)
|
||||
} catch (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