feat(slash): many new things
This commit is contained in:
		
							parent
							
								
									d14fe15d68
								
							
						
					
					
						commit
						6e014b353e
					
				
					 7 changed files with 256 additions and 7 deletions
				
			
		|  | @ -54,6 +54,7 @@ import { | |||
|   EveryTextChannelTypes | ||||
| } from '../../utils/getChannelByType.ts' | ||||
| import { interactionCreate } from './interactionCreate.ts' | ||||
| import { Interaction } from '../../structures/slash.ts' | ||||
| 
 | ||||
| export const gatewayHandlers: { | ||||
|   [eventCode in GatewayEvents]: GatewayEventHandler | undefined | ||||
|  | @ -328,4 +329,8 @@ export interface ClientEvents extends EventTypes { | |||
|    * @param channel Channel of which Webhooks were updated | ||||
|    */ | ||||
|   webhooksUpdate: (guild: Guild, channel: GuildTextChannel) => void | ||||
|   /** | ||||
|    * A Slash Command was triggered | ||||
|    */ | ||||
|   interactionCreate: (interaction: Interaction) => void | ||||
| } | ||||
|  |  | |||
|  | @ -1,4 +1,6 @@ | |||
| import { Member } from '../../structures/member.ts' | ||||
| import { Interaction } from '../../structures/slash.ts' | ||||
| import { GuildTextChannel } from '../../structures/textChannel.ts' | ||||
| import { InteractionPayload } from '../../types/slash.ts' | ||||
| import { Gateway, GatewayEventHandler } from '../index.ts' | ||||
| 
 | ||||
|  | @ -6,6 +8,22 @@ export const interactionCreate: GatewayEventHandler = async ( | |||
|   gateway: Gateway, | ||||
|   d: InteractionPayload | ||||
| ) => { | ||||
|   const interaction = new Interaction(gateway.client, d) | ||||
|   const guild = await gateway.client.guilds.get(d.guild_id) | ||||
|   if (guild === undefined) return | ||||
| 
 | ||||
|   await guild.members.set(d.member.user.id, d.member) | ||||
|   const member = ((await guild.members.get( | ||||
|     d.member.user.id | ||||
|   )) as unknown) as Member | ||||
| 
 | ||||
|   const channel = | ||||
|     (await gateway.client.channels.get<GuildTextChannel>(d.channel_id)) ?? | ||||
|     (await gateway.client.channels.fetch<GuildTextChannel>(d.channel_id)) | ||||
| 
 | ||||
|   const interaction = new Interaction(gateway.client, d, { | ||||
|     member, | ||||
|     guild, | ||||
|     channel | ||||
|   }) | ||||
|   gateway.client.emit('interactionCreate', interaction) | ||||
| } | ||||
|  |  | |||
|  | @ -12,6 +12,7 @@ import { EmojisManager } from '../managers/emojis.ts' | |||
| import { ActivityGame, ClientActivity } from '../types/presence.ts' | ||||
| import { ClientEvents } from '../gateway/handlers/index.ts' | ||||
| import { Extension } from './extensions.ts' | ||||
| import { SlashClient } from './slashClient.ts' | ||||
| 
 | ||||
| /** OS related properties sent with Gateway Identify */ | ||||
| export interface ClientProperties { | ||||
|  | @ -72,6 +73,8 @@ export class Client extends EventEmitter { | |||
|   fetchUncachedReactions: boolean = false | ||||
|   /** Client Properties */ | ||||
|   clientProperties: ClientProperties | ||||
|   /** Slash-Commands Management client */ | ||||
|   slash: SlashClient | ||||
| 
 | ||||
|   users: UsersManager = new UsersManager(this) | ||||
|   guilds: GuildManager = new GuildManager(this) | ||||
|  | @ -133,6 +136,8 @@ export class Client extends EventEmitter { | |||
|             device: 'harmony' | ||||
|           } | ||||
|         : options.clientProperties | ||||
| 
 | ||||
|     this.slash = new SlashClient(this) | ||||
|   } | ||||
| 
 | ||||
|   /** | ||||
|  |  | |||
							
								
								
									
										144
									
								
								src/models/slashClient.ts
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										144
									
								
								src/models/slashClient.ts
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,144 @@ | |||
| import { Guild } from '../structures/guild.ts' | ||||
| import { Interaction } from '../structures/slash.ts' | ||||
| import { | ||||
|   APPLICATION_COMMAND, | ||||
|   APPLICATION_COMMANDS, | ||||
|   APPLICATION_GUILD_COMMAND, | ||||
|   APPLICATION_GUILD_COMMANDS | ||||
| } from '../types/endpoint.ts' | ||||
| import { | ||||
|   SlashCommandOption, | ||||
|   SlashCommandPartial, | ||||
|   SlashCommandPayload | ||||
| } from '../types/slash.ts' | ||||
| import { Collection } from '../utils/collection.ts' | ||||
| import { Client } from './client.ts' | ||||
| 
 | ||||
| export interface SlashOptions { | ||||
|   enabled?: boolean | ||||
| } | ||||
| 
 | ||||
| export class SlashCommand { | ||||
|   id: string | ||||
|   applicationID: string | ||||
|   name: string | ||||
|   description: string | ||||
|   options: SlashCommandOption[] | ||||
| 
 | ||||
|   constructor(data: SlashCommandPayload) { | ||||
|     this.id = data.id | ||||
|     this.applicationID = data.application_id | ||||
|     this.name = data.name | ||||
|     this.description = data.description | ||||
|     this.options = data.options | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| export class SlashCommands { | ||||
|   client: Client | ||||
|   slash: SlashClient | ||||
| 
 | ||||
|   constructor(client: Client) { | ||||
|     this.client = client | ||||
|     this.slash = client.slash | ||||
|   } | ||||
| 
 | ||||
|   /** Get all Global Slash Commands */ | ||||
|   async all(): Promise<Collection<string, SlashCommand>> { | ||||
|     const col = new Collection<string, SlashCommand>() | ||||
| 
 | ||||
|     const res = (await this.client.rest.get( | ||||
|       APPLICATION_COMMANDS(this.client.user?.id as string) | ||||
|     )) as SlashCommandPayload[] | ||||
|     if (!Array.isArray(res)) return col | ||||
| 
 | ||||
|     for (const raw of res) { | ||||
|       col.set(raw.id, new SlashCommand(raw)) | ||||
|     } | ||||
| 
 | ||||
|     return col | ||||
|   } | ||||
| 
 | ||||
|   /** Get a Guild's Slash Commands */ | ||||
|   async guild( | ||||
|     guild: Guild | string | ||||
|   ): Promise<Collection<string, SlashCommand>> { | ||||
|     const col = new Collection<string, SlashCommand>() | ||||
| 
 | ||||
|     const res = (await this.client.rest.get( | ||||
|       APPLICATION_GUILD_COMMANDS( | ||||
|         this.client.user?.id as string, | ||||
|         typeof guild === 'string' ? guild : guild.id | ||||
|       ) | ||||
|     )) as SlashCommandPayload[] | ||||
|     if (!Array.isArray(res)) return col | ||||
| 
 | ||||
|     for (const raw of res) { | ||||
|       col.set(raw.id, new SlashCommand(raw)) | ||||
|     } | ||||
| 
 | ||||
|     return col | ||||
|   } | ||||
| 
 | ||||
|   /** Create a Slash Command (global or Guild) */ | ||||
|   async create( | ||||
|     data: SlashCommandPartial, | ||||
|     guild?: Guild | string | ||||
|   ): Promise<SlashCommand> { | ||||
|     const payload = await this.client.rest.post( | ||||
|       guild === undefined | ||||
|         ? APPLICATION_COMMANDS(this.client.user?.id as string) | ||||
|         : APPLICATION_GUILD_COMMANDS( | ||||
|             this.client.user?.id as string, | ||||
|             typeof guild === 'string' ? guild : guild.id | ||||
|           ), | ||||
|       data | ||||
|     ) | ||||
| 
 | ||||
|     return new SlashCommand(payload) | ||||
|   } | ||||
| 
 | ||||
|   async edit( | ||||
|     id: string, | ||||
|     data: SlashCommandPayload, | ||||
|     guild?: Guild | ||||
|   ): Promise<SlashCommands> { | ||||
|     await this.client.rest.patch( | ||||
|       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 | ||||
|           ), | ||||
|       data | ||||
|     ) | ||||
|     return this | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| export class SlashClient { | ||||
|   client: Client | ||||
|   enabled: boolean = true | ||||
|   commands: SlashCommands | ||||
| 
 | ||||
|   constructor(client: Client, options?: SlashOptions) { | ||||
|     this.client = client | ||||
|     this.commands = new SlashCommands(client) | ||||
| 
 | ||||
|     if (options !== undefined) { | ||||
|       this.enabled = options.enabled ?? true | ||||
|     } | ||||
| 
 | ||||
|     this.client.on('interactionCreate', (interaction) => | ||||
|       this.process(interaction) | ||||
|     ) | ||||
|   } | ||||
| 
 | ||||
|   process(interaction: Interaction): any {} | ||||
| 
 | ||||
|   handle(fn: (interaction: Interaction) => any): SlashClient { | ||||
|     this.process = fn | ||||
|     return this | ||||
|   } | ||||
| } | ||||
|  | @ -1,6 +1,5 @@ | |||
| import { Client } from '../models/client.ts' | ||||
| import { INTERACTION_CALLBACK } from '../types/endpoint.ts' | ||||
| import { MemberPayload } from '../types/guild.ts' | ||||
| import { | ||||
|   InteractionData, | ||||
|   InteractionPayload, | ||||
|  | @ -8,6 +7,10 @@ import { | |||
|   InteractionResponseType | ||||
| } from '../types/slash.ts' | ||||
| import { Embed } from './embed.ts' | ||||
| import { Guild } from './guild.ts' | ||||
| import { Member } from './member.ts' | ||||
| import { GuildTextChannel } from './textChannel.ts' | ||||
| import { User } from './user.ts' | ||||
| 
 | ||||
| export interface InteractionResponse { | ||||
|   type?: InteractionResponseType | ||||
|  | @ -21,17 +24,37 @@ export class Interaction { | |||
|   client: Client | ||||
|   type: number | ||||
|   token: string | ||||
|   member: MemberPayload | ||||
|   id: string | ||||
|   data: InteractionData | ||||
|   channel: GuildTextChannel | ||||
|   guild: Guild | ||||
|   member: Member | ||||
| 
 | ||||
|   constructor(client: Client, data: InteractionPayload) { | ||||
|   constructor( | ||||
|     client: Client, | ||||
|     data: InteractionPayload, | ||||
|     others: { | ||||
|       channel: GuildTextChannel | ||||
|       guild: Guild | ||||
|       member: Member | ||||
|     } | ||||
|   ) { | ||||
|     this.client = client | ||||
|     this.type = data.type | ||||
|     this.token = data.token | ||||
|     this.member = data.member | ||||
|     this.member = others.member | ||||
|     this.id = data.id | ||||
|     this.data = data.data | ||||
|     this.guild = others.guild | ||||
|     this.channel = others.channel | ||||
|   } | ||||
| 
 | ||||
|   get user(): User { | ||||
|     return this.member.user | ||||
|   } | ||||
| 
 | ||||
|   get name(): string { | ||||
|     return this.data.name | ||||
|   } | ||||
| 
 | ||||
|   async respond(data: InteractionResponse): Promise<Interaction> { | ||||
|  |  | |||
|  | @ -1,15 +1,62 @@ | |||
| import { Client, Intents } from '../../mod.ts' | ||||
| import { SlashCommandOptionType } from '../types/slash.ts' | ||||
| import { TOKEN } from './config.ts' | ||||
| 
 | ||||
| const client = new Client() | ||||
| 
 | ||||
| client.on('ready', () => { | ||||
|   console.log('Logged in!') | ||||
|   client.slash.commands | ||||
|     .create( | ||||
|       { | ||||
|         name: 'eval', | ||||
|         description: 'Run some JS code!', | ||||
|         options: [ | ||||
|           { | ||||
|             name: 'code', | ||||
|             description: 'Code to run', | ||||
|             type: SlashCommandOptionType.STRING, | ||||
|             required: true | ||||
|           } | ||||
|         ] | ||||
|       }, | ||||
|       '783319033205751809' | ||||
|     ) | ||||
|     .then(console.log) | ||||
| }) | ||||
| 
 | ||||
| client.on('interactionCreate', async (d) => { | ||||
|   if (d.name === 'eval') { | ||||
|     if (d.user.id !== '422957901716652033') { | ||||
|       d.respond({ | ||||
|         content: 'This command can only be used by owner!' | ||||
|       }) | ||||
|     } else { | ||||
|       const code = d.data.options.find((e) => e.name === 'code') | ||||
|         ?.value as string | ||||
|       try { | ||||
|         // eslint-disable-next-line no-eval
 | ||||
|         let evaled = eval(code) | ||||
|         if (evaled instanceof Promise) evaled = await evaled | ||||
|         if (typeof evaled === 'object') evaled = Deno.inspect(evaled) | ||||
|         let res = `${evaled}`.substring(0, 1990) | ||||
|         while (client.token !== undefined && res.includes(client.token)) { | ||||
|           res = res.replace(client.token, '[REMOVED]') | ||||
|         } | ||||
|         d.respond({ | ||||
|           content: '```js\n' + `${res}` + '\n```' | ||||
|         }) | ||||
|       } catch (e) { | ||||
|         d.respond({ | ||||
|           content: '```js\n' + `${e.stack}` + '\n```' | ||||
|         }) | ||||
|       } | ||||
|     } | ||||
|     return | ||||
|   } | ||||
|   await d.respond({ | ||||
|     content: `Hi, ${d.member.user.username}!` | ||||
|     content: `Hi, ${d.member.user.username}!`, | ||||
|     flags: 64 | ||||
|   }) | ||||
| }) | ||||
| 
 | ||||
|  |  | |||
|  | @ -24,6 +24,8 @@ export interface InteractionPayload { | |||
|   member: MemberPayload | ||||
|   id: string | ||||
|   data: InteractionData | ||||
|   guild_id: string | ||||
|   channel_id: string | ||||
| } | ||||
| 
 | ||||
| export interface SlashCommandChoice { | ||||
|  | @ -50,12 +52,17 @@ export interface SlashCommandOption { | |||
|   choices?: SlashCommandChoice[] | ||||
| } | ||||
| 
 | ||||
| export interface SlashCommandPayload { | ||||
| export interface SlashCommandPartial { | ||||
|   name: string | ||||
|   description: string | ||||
|   options: SlashCommandOption[] | ||||
| } | ||||
| 
 | ||||
| export interface SlashCommandPayload extends SlashCommandPartial { | ||||
|   id: string | ||||
|   application_id: string | ||||
| } | ||||
| 
 | ||||
| export enum InteractionResponseType { | ||||
|   PONG = 1, | ||||
|   ACKNOWLEDGE = 2, | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue