Skip to content

Commit b222d91

Browse files
authored
Merge pull request #108 from DjDeveloperr/cmd-loader
add commands loader
2 parents 5007dc6 + 2d6f3d4 commit b222d91

File tree

4 files changed

+103
-21
lines changed

4 files changed

+103
-21
lines changed

deps.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,3 +7,5 @@ export type {
77
Redis,
88
RedisConnectOptions
99
} from 'https://deno.land/x/[email protected]/mod.ts'
10+
export { walk } from 'https://deno.land/[email protected]/fs/walk.ts'
11+
export { join } from 'https://deno.land/[email protected]/path/mod.ts'

src/models/command.ts

Lines changed: 91 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import { User } from '../structures/user.ts'
55
import { Collection } from '../utils/collection.ts'
66
import { CommandClient } from './commandClient.ts'
77
import { Extension } from './extensions.ts'
8-
import { parse } from '../../deps.ts'
8+
import { join, parse, walk } from '../../deps.ts'
99

1010
export interface CommandContext {
1111
/** The Client object */
@@ -284,13 +284,103 @@ export class CommandBuilder extends Command {
284284
}
285285
}
286286

287+
export class CommandsLoader {
288+
client: CommandClient
289+
#importSeq: { [name: string]: number } = {}
290+
291+
constructor(client: CommandClient) {
292+
this.client = client
293+
}
294+
295+
/**
296+
* Load a Command from file.
297+
*
298+
* @param filePath Path of Command file.
299+
* @param exportName Export name. Default is the "default" export.
300+
*/
301+
async load(
302+
filePath: string,
303+
exportName: string = 'default',
304+
onlyRead?: boolean
305+
): Promise<Command> {
306+
const stat = await Deno.stat(filePath).catch(() => undefined)
307+
if (stat === undefined || stat.isFile !== true)
308+
throw new Error(`File not found on path ${filePath}`)
309+
310+
let seq: number | undefined
311+
312+
if (this.#importSeq[filePath] !== undefined) seq = this.#importSeq[filePath]
313+
const mod = await import(
314+
// eslint-disable-next-line @typescript-eslint/restrict-plus-operands
315+
'file:///' +
316+
join(Deno.cwd(), filePath) +
317+
(seq === undefined ? '' : `#${seq}`)
318+
)
319+
if (this.#importSeq[filePath] === undefined) this.#importSeq[filePath] = 0
320+
else this.#importSeq[filePath]++
321+
322+
const Cmd = mod[exportName]
323+
if (Cmd === undefined)
324+
throw new Error(`Command not exported as ${exportName} from ${filePath}`)
325+
326+
let cmd: Command
327+
try {
328+
if (Cmd instanceof Command) cmd = Cmd
329+
else cmd = new Cmd()
330+
if (!(cmd instanceof Command)) throw new Error('failed')
331+
} catch (e) {
332+
throw new Error(`Failed to load Command from ${filePath}`)
333+
}
334+
335+
if (onlyRead !== true) this.client.commands.add(cmd)
336+
return cmd
337+
}
338+
339+
/**
340+
* Load commands from a Directory.
341+
*
342+
* @param path Path of the directory.
343+
* @param options Options to configure loading.
344+
*/
345+
async loadDirectory(
346+
path: string,
347+
options?: {
348+
recursive?: boolean
349+
exportName?: string
350+
maxDepth?: number
351+
exts?: string[]
352+
onlyRead?: boolean
353+
}
354+
): Promise<Command[]> {
355+
const commands: Command[] = []
356+
357+
for await (const entry of walk(path, {
358+
maxDepth: options?.maxDepth,
359+
exts: options?.exts,
360+
includeDirs: false
361+
})) {
362+
if (entry.isFile !== true) continue
363+
const cmd = await this.load(
364+
entry.path,
365+
options?.exportName,
366+
options?.onlyRead
367+
)
368+
commands.push(cmd)
369+
}
370+
371+
return commands
372+
}
373+
}
374+
287375
export class CommandsManager {
288376
client: CommandClient
289377
list: Collection<string, Command> = new Collection()
290378
disabled: Set<string> = new Set()
379+
loader: CommandsLoader
291380

292381
constructor(client: CommandClient) {
293382
this.client = client
383+
this.loader = new CommandsLoader(client)
294384
}
295385

296386
/** Number of loaded Commands */

src/models/commandClient.ts

Lines changed: 10 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
import { Message } from '../structures/message.ts'
22
import { GuildTextChannel } from '../structures/textChannel.ts'
3-
import { awaitSync } from '../utils/mixedPromise.ts'
43
import { Client, ClientOptions } from './client.ts'
54
import {
65
CategoriesManager,
@@ -129,35 +128,29 @@ export class CommandClient extends Client implements CommandClientOptions {
129128
async processMessage(msg: Message): Promise<any> {
130129
if (!this.allowBots && msg.author.bot === true) return
131130

132-
const isUserBlacklisted = await awaitSync(
133-
this.isUserBlacklisted(msg.author.id)
134-
)
135-
if (isUserBlacklisted === true) return
131+
const isUserBlacklisted = await this.isUserBlacklisted(msg.author.id)
132+
if (isUserBlacklisted) return
136133

137-
const isChannelBlacklisted = await awaitSync(
138-
this.isChannelBlacklisted(msg.channel.id)
139-
)
140-
if (isChannelBlacklisted === true) return
134+
const isChannelBlacklisted = await this.isChannelBlacklisted(msg.channel.id)
135+
if (isChannelBlacklisted) return
141136

142137
if (msg.guild !== undefined) {
143-
const isGuildBlacklisted = await awaitSync(
144-
this.isGuildBlacklisted(msg.guild.id)
145-
)
146-
if (isGuildBlacklisted === true) return
138+
const isGuildBlacklisted = await this.isGuildBlacklisted(msg.guild.id)
139+
if (isGuildBlacklisted) return
147140
}
148141

149142
let prefix: string | string[] = []
150143
if (typeof this.prefix === 'string') prefix = [...prefix, this.prefix]
151144
else prefix = [...prefix, ...this.prefix]
152145

153-
const userPrefix = await awaitSync(this.getUserPrefix(msg.author.id))
146+
const userPrefix = await this.getUserPrefix(msg.author.id)
154147
if (userPrefix !== undefined) {
155148
if (typeof userPrefix === 'string') prefix = [...prefix, userPrefix]
156149
else prefix = [...prefix, ...userPrefix]
157150
}
158151

159152
if (msg.guild !== undefined) {
160-
const guildPrefix = await awaitSync(this.getGuildPrefix(msg.guild.id))
153+
const guildPrefix = await this.getGuildPrefix(msg.guild.id)
161154
if (guildPrefix !== undefined) {
162155
if (typeof guildPrefix === 'string') prefix = [...prefix, guildPrefix]
163156
else prefix = [...prefix, ...guildPrefix]
@@ -361,10 +354,10 @@ export class CommandClient extends Client implements CommandClientOptions {
361354
try {
362355
this.emit('commandUsed', ctx)
363356

364-
const beforeExecute = await awaitSync(command.beforeExecute(ctx))
357+
const beforeExecute = await command.beforeExecute(ctx)
365358
if (beforeExecute === false) return
366359

367-
const result = await awaitSync(command.execute(ctx))
360+
const result = await command.execute(ctx)
368361
command.afterExecute(ctx, result)
369362
} catch (e) {
370363
this.emit('commandError', ctx, e)

src/utils/mixedPromise.ts

Lines changed: 0 additions & 3 deletions
This file was deleted.

0 commit comments

Comments
 (0)