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, |   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…
	
	Add table
		Add a link
		
	
		Reference in a new issue