feat(slash): add @slash decorator support
This commit is contained in:
		
							parent
							
								
									b0d6092c25
								
							
						
					
					
						commit
						e1281736ec
					
				
					 4 changed files with 134 additions and 52 deletions
				
			
		
							
								
								
									
										3
									
								
								mod.ts
									
										
									
									
									
								
							
							
						
						
									
										3
									
								
								mod.ts
									
										
									
									
									
								
							|  | @ -4,6 +4,7 @@ export { Base } from './src/structures/base.ts' | |||
| export { Gateway } from './src/gateway/index.ts' | ||||
| export type { ClientEvents } from './src/gateway/handlers/index.ts' | ||||
| export * from './src/models/client.ts' | ||||
| export * from './src/models/slashClient.ts' | ||||
| export { RESTManager } from './src/models/rest.ts' | ||||
| export * from './src/models/cacheAdapter.ts' | ||||
| export { | ||||
|  | @ -29,6 +30,8 @@ export { GatewayCache } from './src/managers/gatewayCache.ts' | |||
| export { GuildChannelsManager } from './src/managers/guildChannels.ts' | ||||
| export type { GuildChannel } from './src/managers/guildChannels.ts' | ||||
| export { GuildManager } from './src/managers/guilds.ts' | ||||
| export * from './src/structures/slash.ts' | ||||
| export * from './src/types/slash.ts' | ||||
| export { GuildEmojisManager } from './src/managers/guildEmojis.ts' | ||||
| export { MembersManager } from './src/managers/members.ts' | ||||
| export { MessageReactionsManager } from './src/managers/messageReactions.ts' | ||||
|  |  | |||
|  | @ -13,6 +13,7 @@ import { ActivityGame, ClientActivity } from '../types/presence.ts' | |||
| import { ClientEvents } from '../gateway/handlers/index.ts' | ||||
| import { Extension } from './extensions.ts' | ||||
| import { SlashClient } from './slashClient.ts' | ||||
| import { Interaction } from '../structures/slash.ts' | ||||
| 
 | ||||
| /** OS related properties sent with Gateway Identify */ | ||||
| export interface ClientProperties { | ||||
|  | @ -43,6 +44,8 @@ export interface ClientOptions { | |||
|   fetchUncachedReactions?: boolean | ||||
|   /** Client Properties */ | ||||
|   clientProperties?: ClientProperties | ||||
|   /** Enable/Disable Slash Commands Integration (enabled by default) */ | ||||
|   enableSlash?: boolean | ||||
| } | ||||
| 
 | ||||
| /** | ||||
|  | @ -86,6 +89,11 @@ export class Client extends EventEmitter { | |||
|   /** Client's presence. Startup one if set before connecting */ | ||||
|   presence: ClientPresence = new ClientPresence() | ||||
|   _decoratedEvents?: { [name: string]: (...args: any[]) => any } | ||||
|   _decoratedSlash?: Array<{ | ||||
|     name: string | ||||
|     guild?: string | ||||
|     handler: (interaction: Interaction) => any | ||||
|   }> | ||||
| 
 | ||||
|   private readonly _untypedOn = this.on | ||||
| 
 | ||||
|  | @ -137,7 +145,9 @@ export class Client extends EventEmitter { | |||
|           } | ||||
|         : options.clientProperties | ||||
| 
 | ||||
|     this.slash = new SlashClient(this) | ||||
|     this.slash = new SlashClient(this, { | ||||
|       enabled: options.enableSlash | ||||
|     }) | ||||
|   } | ||||
| 
 | ||||
|   /** | ||||
|  | @ -200,3 +210,14 @@ export function event(name?: string) { | |||
|     client._decoratedEvents[name === undefined ? prop : name] = listener | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| export function slash(name?: string, guild?: string) { | ||||
|   return function (client: Client, prop: string) { | ||||
|     if (client._decoratedSlash === undefined) client._decoratedSlash = [] | ||||
|     client._decoratedSlash.push({ | ||||
|       name: name ?? prop, | ||||
|       guild, | ||||
|       handler: (client as { [name: string]: any })[prop] | ||||
|     }) | ||||
|   } | ||||
| } | ||||
|  |  | |||
|  | @ -19,22 +19,33 @@ export interface SlashOptions { | |||
| } | ||||
| 
 | ||||
| export class SlashCommand { | ||||
|   slash: SlashCommandsManager | ||||
|   id: string | ||||
|   applicationID: string | ||||
|   name: string | ||||
|   description: string | ||||
|   options: SlashCommandOption[] | ||||
|   _guild?: string | ||||
| 
 | ||||
|   constructor(data: SlashCommandPayload) { | ||||
|   constructor(manager: SlashCommandsManager, data: SlashCommandPayload) { | ||||
|     this.slash = manager | ||||
|     this.id = data.id | ||||
|     this.applicationID = data.application_id | ||||
|     this.name = data.name | ||||
|     this.description = data.description | ||||
|     this.options = data.options | ||||
|   } | ||||
| 
 | ||||
|   async delete(): Promise<void> { | ||||
|     await this.slash.delete(this.id, this._guild) | ||||
|   } | ||||
| 
 | ||||
|   async edit(data: SlashCommandPartial): Promise<void> { | ||||
|     await this.slash.edit(this.id, data, this._guild) | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| export class SlashCommands { | ||||
| export class SlashCommandsManager { | ||||
|   client: Client | ||||
|   slash: SlashClient | ||||
| 
 | ||||
|  | @ -53,7 +64,8 @@ export class SlashCommands { | |||
|     if (!Array.isArray(res)) return col | ||||
| 
 | ||||
|     for (const raw of res) { | ||||
|       col.set(raw.id, new SlashCommand(raw)) | ||||
|       const cmd = new SlashCommand(this, raw) | ||||
|       col.set(raw.id, cmd) | ||||
|     } | ||||
| 
 | ||||
|     return col | ||||
|  | @ -74,7 +86,9 @@ export class SlashCommands { | |||
|     if (!Array.isArray(res)) return col | ||||
| 
 | ||||
|     for (const raw of res) { | ||||
|       col.set(raw.id, new SlashCommand(raw)) | ||||
|       const cmd = new SlashCommand(this, raw) | ||||
|       cmd._guild = typeof guild === 'string' ? guild : guild.id | ||||
|       col.set(raw.id, cmd) | ||||
|     } | ||||
| 
 | ||||
|     return col | ||||
|  | @ -95,14 +109,19 @@ export class SlashCommands { | |||
|       data | ||||
|     ) | ||||
| 
 | ||||
|     return new SlashCommand(payload) | ||||
|     const cmd = new SlashCommand(this, payload) | ||||
|     cmd._guild = | ||||
|       typeof guild === 'string' || guild === undefined ? guild : guild.id | ||||
| 
 | ||||
|     return cmd | ||||
|   } | ||||
| 
 | ||||
|   /** Edit a Slash Command (global or Guild) */ | ||||
|   async edit( | ||||
|     id: string, | ||||
|     data: SlashCommandPayload, | ||||
|     guild?: Guild | ||||
|   ): Promise<SlashCommands> { | ||||
|     data: SlashCommandPartial, | ||||
|     guild?: Guild | string | ||||
|   ): Promise<SlashCommandsManager> { | ||||
|     await this.client.rest.patch( | ||||
|       guild === undefined | ||||
|         ? APPLICATION_COMMAND(this.client.user?.id as string, id) | ||||
|  | @ -115,30 +134,85 @@ export class SlashCommands { | |||
|     ) | ||||
|     return this | ||||
|   } | ||||
| 
 | ||||
|   /** Delete a Slash Command (global or Guild) */ | ||||
|   async delete( | ||||
|     id: string, | ||||
|     guild?: Guild | string | ||||
|   ): Promise<SlashCommandsManager> { | ||||
|     await this.client.rest.delete( | ||||
|       guild === undefined | ||||
|         ? APPLICATION_COMMAND(this.client.user?.id as string, id) | ||||
|         : APPLICATION_GUILD_COMMAND( | ||||
|             this.client.user?.id as string, | ||||
|             typeof guild === 'string' ? guild : guild.id, | ||||
|             id | ||||
|           ) | ||||
|     ) | ||||
|     return this | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| export type SlashCommandHandlerCallback = (interaction: Interaction) => any | ||||
| export interface SlashCommandHandler { | ||||
|   name: string | ||||
|   guild?: string | ||||
|   handler: SlashCommandHandlerCallback | ||||
| } | ||||
| 
 | ||||
| export class SlashClient { | ||||
|   client: Client | ||||
|   enabled: boolean = true | ||||
|   commands: SlashCommands | ||||
|   commands: SlashCommandsManager | ||||
|   handlers: SlashCommandHandler[] = [] | ||||
| 
 | ||||
|   constructor(client: Client, options?: SlashOptions) { | ||||
|     this.client = client | ||||
|     this.commands = new SlashCommands(client) | ||||
|     this.commands = new SlashCommandsManager(client) | ||||
| 
 | ||||
|     if (options !== undefined) { | ||||
|       this.enabled = options.enabled ?? true | ||||
|     } | ||||
| 
 | ||||
|     if (this.client._decoratedSlash !== undefined) { | ||||
|       this.client._decoratedSlash.forEach((e) => { | ||||
|         this.handlers.push(e) | ||||
|       }) | ||||
|     } | ||||
| 
 | ||||
|     this.client.on('interactionCreate', (interaction) => | ||||
|       this.process(interaction) | ||||
|     ) | ||||
|   } | ||||
| 
 | ||||
|   process(interaction: Interaction): any {} | ||||
| 
 | ||||
|   handle(fn: (interaction: Interaction) => any): SlashClient { | ||||
|     this.process = fn | ||||
|   /** Adds a new Slash Command Handler */ | ||||
|   handle( | ||||
|     name: string, | ||||
|     handler: SlashCommandHandlerCallback, | ||||
|     guild?: string | ||||
|   ): SlashClient { | ||||
|     this.handlers.push({ | ||||
|       name, | ||||
|       guild, | ||||
|       handler | ||||
|     }) | ||||
|     return this | ||||
|   } | ||||
| 
 | ||||
|   process(interaction: Interaction): any { | ||||
|     if (!this.enabled) return | ||||
| 
 | ||||
|     let cmd | ||||
| 
 | ||||
|     if (interaction.guild !== undefined) | ||||
|       cmd = | ||||
|         this.handlers.find( | ||||
|           (e) => e.guild !== undefined && e.name === interaction.name | ||||
|         ) ?? this.handlers.find((e) => e.name === interaction.name) | ||||
|     else cmd = this.handlers.find((e) => e.name === interaction.name) | ||||
| 
 | ||||
|     if (cmd === undefined) return | ||||
| 
 | ||||
|     cmd.handler(interaction) | ||||
|   } | ||||
| } | ||||
|  |  | |||
|  | @ -1,33 +1,23 @@ | |||
| import { Client, Intents } from '../../mod.ts' | ||||
| import { Client, Intents, event, slash } from '../../mod.ts' | ||||
| import { Embed } from '../structures/embed.ts' | ||||
| import { SlashCommandOptionType } from '../types/slash.ts' | ||||
| import { Interaction } from '../structures/slash.ts' | ||||
| import { TOKEN } from './config.ts' | ||||
| 
 | ||||
| const client = new Client() | ||||
| export class MyClient extends Client { | ||||
|   @event() | ||||
|   ready(): void { | ||||
|     console.log(`Logged in as ${this.user?.tag}!`) | ||||
|   } | ||||
| 
 | ||||
| client.on('ready', () => { | ||||
|   console.log('Logged in!') | ||||
|   client.slash.commands | ||||
|     .create( | ||||
|       { | ||||
|         name: 'send', | ||||
|         description: 'Send a Message through Bot!', | ||||
|         options: [ | ||||
|           { | ||||
|             name: 'content', | ||||
|             description: 'Message to send', | ||||
|             type: SlashCommandOptionType.STRING, | ||||
|             required: true | ||||
|           } | ||||
|         ] | ||||
|       }, | ||||
|       '783319033205751809' | ||||
|     ) | ||||
|     .then(console.log) | ||||
| }) | ||||
|   @slash() | ||||
|   send(d: Interaction): void { | ||||
|     d.respond({ | ||||
|       content: d.data.options.find((e) => e.name === 'content')?.value | ||||
|     }) | ||||
|   } | ||||
| 
 | ||||
| client.on('interactionCreate', async (d) => { | ||||
|   if (d.name === 'eval') { | ||||
|   @slash() | ||||
|   async eval(d: Interaction): Promise<void> { | ||||
|     if (d.user.id !== '422957901716652033') { | ||||
|       d.respond({ | ||||
|         content: 'This command can only be used by owner!' | ||||
|  | @ -53,8 +43,10 @@ client.on('interactionCreate', async (d) => { | |||
|         }) | ||||
|       } | ||||
|     } | ||||
|     return | ||||
|   } else if (d.name === 'hug') { | ||||
|   } | ||||
| 
 | ||||
|   @slash() | ||||
|   async hug(d: Interaction): Promise<void> { | ||||
|     const id = d.data.options.find((e) => e.name === 'user')?.value as string | ||||
|     const user = (await client.users.get(id)) ?? (await client.users.fetch(id)) | ||||
|     const url = await fetch('https://nekos.life/api/v2/img/hug') | ||||
|  | @ -69,16 +61,8 @@ client.on('interactionCreate', async (d) => { | |||
|           .setColor(0x2f3136) | ||||
|       ] | ||||
|     }) | ||||
|     return | ||||
|   } else if (d.name === 'send') { | ||||
|     d.respond({ | ||||
|       content: d.data.options.find((e) => e.name === 'content')?.value as string | ||||
|     }) | ||||
|     return | ||||
|   } | ||||
|   await d.respond({ | ||||
|     content: `Hi, ${d.member.user.username}! You used /${d.name}` | ||||
|   }) | ||||
| }) | ||||
| } | ||||
| 
 | ||||
| const client = new MyClient() | ||||
| client.connect(TOKEN, Intents.None) | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue