add commands loader

This commit is contained in:
DjDeveloperr 2021-02-21 18:48:18 +05:30
parent 5007dc6029
commit 2d6f3d46f3
4 changed files with 103 additions and 21 deletions

View file

@ -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'

View file

@ -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 */

View file

@ -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)

View file

@ -1,3 +0,0 @@
export const awaitSync = async (val: any | Promise<any>): Promise<any> => {
return val instanceof Promise ? await val : val
}