feat(slash): add SlashModule and sub command support
This commit is contained in:
		
							parent
							
								
									e6be50cdc7
								
							
						
					
					
						commit
						3dcf57c658
					
				
					 6 changed files with 73 additions and 13 deletions
				
			
		|  | @ -14,6 +14,7 @@ import { ClientEvents } from '../gateway/handlers/index.ts' | ||||||
| import { Extension } from './extensions.ts' | import { Extension } from './extensions.ts' | ||||||
| import { SlashClient } from './slashClient.ts' | import { SlashClient } from './slashClient.ts' | ||||||
| import { Interaction } from '../structures/slash.ts' | import { Interaction } from '../structures/slash.ts' | ||||||
|  | import { SlashModule } from './slashModule.ts' | ||||||
| 
 | 
 | ||||||
| /** OS related properties sent with Gateway Identify */ | /** OS related properties sent with Gateway Identify */ | ||||||
| export interface ClientProperties { | export interface ClientProperties { | ||||||
|  | @ -95,6 +96,8 @@ export class Client extends EventEmitter { | ||||||
|     handler: (interaction: Interaction) => any |     handler: (interaction: Interaction) => any | ||||||
|   }> |   }> | ||||||
| 
 | 
 | ||||||
|  |   _decoratedSlashModules?: SlashModule[] | ||||||
|  | 
 | ||||||
|   private readonly _untypedOn = this.on |   private readonly _untypedOn = this.on | ||||||
| 
 | 
 | ||||||
|   private readonly _untypedEmit = this.emit |   private readonly _untypedEmit = this.emit | ||||||
|  | @ -206,18 +209,34 @@ export function event(name?: string) { | ||||||
|     const listener = ((client as unknown) as { |     const listener = ((client as unknown) as { | ||||||
|       [name: string]: (...args: any[]) => any |       [name: string]: (...args: any[]) => any | ||||||
|     })[prop] |     })[prop] | ||||||
|  |     if (typeof listener !== 'function') | ||||||
|  |       throw new Error('@event decorator requires a function') | ||||||
|     if (client._decoratedEvents === undefined) client._decoratedEvents = {} |     if (client._decoratedEvents === undefined) client._decoratedEvents = {} | ||||||
|     client._decoratedEvents[name === undefined ? prop : name] = listener |     client._decoratedEvents[name === undefined ? prop : name] = listener | ||||||
|   } |   } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| export function slash(name?: string, guild?: string) { | export function slash(name?: string, guild?: string) { | ||||||
|   return function (client: Client, prop: string) { |   return function (client: Client | SlashModule, prop: string) { | ||||||
|     if (client._decoratedSlash === undefined) client._decoratedSlash = [] |     if (client._decoratedSlash === undefined) client._decoratedSlash = [] | ||||||
|  |     const item = (client as { [name: string]: any })[prop] | ||||||
|  |     if (typeof item !== 'function') { | ||||||
|  |       client._decoratedSlash.push(item) | ||||||
|  |     } else | ||||||
|       client._decoratedSlash.push({ |       client._decoratedSlash.push({ | ||||||
|         name: name ?? prop, |         name: name ?? prop, | ||||||
|         guild, |         guild, | ||||||
|       handler: (client as { [name: string]: any })[prop] |         handler: item | ||||||
|       }) |       }) | ||||||
|   } |   } | ||||||
| } | } | ||||||
|  | 
 | ||||||
|  | export function slashModule() { | ||||||
|  |   return function (client: Client, prop: string) { | ||||||
|  |     if (client._decoratedSlashModules === undefined) | ||||||
|  |       client._decoratedSlashModules = [] | ||||||
|  | 
 | ||||||
|  |     const mod = ((client as unknown) as { [key: string]: any })[prop] | ||||||
|  |     client._decoratedSlashModules.push(mod) | ||||||
|  |   } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | @ -383,18 +383,26 @@ export class CommandClient extends Client implements CommandClientOptions { | ||||||
| 
 | 
 | ||||||
| export function command(options?: CommandOptions) { | export function command(options?: CommandOptions) { | ||||||
|   return function (target: CommandClient | Extension, name: string) { |   return function (target: CommandClient | Extension, name: string) { | ||||||
|  |     if (target._decoratedCommands === undefined) target._decoratedCommands = {} | ||||||
|  | 
 | ||||||
|  |     const prop = ((target as unknown) as { | ||||||
|  |       [name: string]: (ctx: CommandContext) => any | ||||||
|  |     })[name] | ||||||
|  | 
 | ||||||
|  |     if (prop instanceof Command) { | ||||||
|  |       target._decoratedCommands[prop.name] = prop | ||||||
|  |       return | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|     const command = new Command() |     const command = new Command() | ||||||
| 
 | 
 | ||||||
|     command.name = name |     command.name = name | ||||||
|     command.execute = ((target as unknown) as { |     command.execute = prop | ||||||
|       [name: string]: (ctx: CommandContext) => any |  | ||||||
|     })[name] |  | ||||||
| 
 | 
 | ||||||
|     if (options !== undefined) Object.assign(command, options) |     if (options !== undefined) Object.assign(command, options) | ||||||
| 
 | 
 | ||||||
|     if (target instanceof Extension) command.extension = target |     if (target instanceof Extension) command.extension = target | ||||||
| 
 | 
 | ||||||
|     if (target._decoratedCommands === undefined) target._decoratedCommands = {} |  | ||||||
|     target._decoratedCommands[command.name] = command |     target._decoratedCommands[command.name] = command | ||||||
|   } |   } | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -7,6 +7,7 @@ import { | ||||||
|   APPLICATION_GUILD_COMMANDS |   APPLICATION_GUILD_COMMANDS | ||||||
| } from '../types/endpoint.ts' | } from '../types/endpoint.ts' | ||||||
| import { | import { | ||||||
|  |   InteractionType, | ||||||
|   SlashCommandOption, |   SlashCommandOption, | ||||||
|   SlashCommandPartial, |   SlashCommandPartial, | ||||||
|   SlashCommandPayload |   SlashCommandPayload | ||||||
|  | @ -199,9 +200,12 @@ export class SlashClient { | ||||||
|     return this |     return this | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   process(interaction: Interaction): any { |   /** Process an incoming Slash Command (interaction) */ | ||||||
|  |   private process(interaction: Interaction): void { | ||||||
|     if (!this.enabled) return |     if (!this.enabled) return | ||||||
| 
 | 
 | ||||||
|  |     if (interaction.type !== InteractionType.APPLICATION_COMMAND) return | ||||||
|  | 
 | ||||||
|     let cmd |     let cmd | ||||||
| 
 | 
 | ||||||
|     if (interaction.guild !== undefined) |     if (interaction.guild !== undefined) | ||||||
|  |  | ||||||
							
								
								
									
										18
									
								
								src/models/slashModule.ts
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								src/models/slashModule.ts
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,18 @@ | ||||||
|  | import { SlashCommandHandler } from './slashClient.ts' | ||||||
|  | 
 | ||||||
|  | export class SlashModule { | ||||||
|  |   name: string = '' | ||||||
|  |   commands: SlashCommandHandler[] = [] | ||||||
|  |   _decoratedSlash?: SlashCommandHandler[] | ||||||
|  | 
 | ||||||
|  |   constructor() { | ||||||
|  |     if (this._decoratedSlash !== undefined) { | ||||||
|  |       this.commands = this._decoratedSlash | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   add(handler: SlashCommandHandler): SlashModule { | ||||||
|  |     this.commands.push(handler) | ||||||
|  |     return this | ||||||
|  |   } | ||||||
|  | } | ||||||
|  | @ -76,7 +76,7 @@ export class Interaction { | ||||||
|     return this.data.name |     return this.data.name | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   option(name: string): any { |   option<T = any>(name: string): T { | ||||||
|     return this.data.options.find((e) => e.name === name)?.value |     return this.data.options.find((e) => e.name === name)?.value | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|  | @ -121,6 +121,16 @@ export class Interaction { | ||||||
|     return this |     return this | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|  |   async deleteResponse(): Promise<Interaction> { | ||||||
|  |     const url = WEBHOOK_MESSAGE( | ||||||
|  |       this.client.user?.id as string, | ||||||
|  |       this.token, | ||||||
|  |       '@original' | ||||||
|  |     ) | ||||||
|  |     await this.client.rest.delete(url) | ||||||
|  |     return this | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|   get url(): string { |   get url(): string { | ||||||
|     return `https://discord.com/api/v8/webhooks/${this.client.user?.id}/${this.token}` |     return `https://discord.com/api/v8/webhooks/${this.client.user?.id}/${this.token}` | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  | @ -8,9 +8,9 @@ export interface InteractionOption { | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| export interface InteractionData { | export interface InteractionData { | ||||||
|   options: InteractionOption[] |  | ||||||
|   name: string |   name: string | ||||||
|   id: string |   id: string | ||||||
|  |   options: InteractionOption[] | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| export enum InteractionType { | export enum InteractionType { | ||||||
|  | @ -50,6 +50,7 @@ export interface SlashCommandOption { | ||||||
|   type: SlashCommandOptionType |   type: SlashCommandOptionType | ||||||
|   required: boolean |   required: boolean | ||||||
|   choices?: SlashCommandChoice[] |   choices?: SlashCommandChoice[] | ||||||
|  |   options?: SlashCommandOption[] | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| export interface SlashCommandPartial { | export interface SlashCommandPartial { | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue