Merge pull request #108 from DjDeveloperr/cmd-loader
add commands loader
This commit is contained in:
		
						commit
						b222d91f7c
					
				
					 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…
	
	Add table
		Add a link
		
	
		Reference in a new issue