feat: slash commands
This commit is contained in:
		
							parent
							
								
									ea030deb4a
								
							
						
					
					
						commit
						d14fe15d68
					
				
					 9 changed files with 252 additions and 76 deletions
				
			
		|  | @ -53,6 +53,7 @@ import { | ||||||
|   EveryChannelTypes, |   EveryChannelTypes, | ||||||
|   EveryTextChannelTypes |   EveryTextChannelTypes | ||||||
| } from '../../utils/getChannelByType.ts' | } from '../../utils/getChannelByType.ts' | ||||||
|  | import { interactionCreate } from './interactionCreate.ts' | ||||||
| 
 | 
 | ||||||
| export const gatewayHandlers: { | export const gatewayHandlers: { | ||||||
|   [eventCode in GatewayEvents]: GatewayEventHandler | undefined |   [eventCode in GatewayEvents]: GatewayEventHandler | undefined | ||||||
|  | @ -93,7 +94,8 @@ export const gatewayHandlers: { | ||||||
|   USER_UPDATE: userUpdate, |   USER_UPDATE: userUpdate, | ||||||
|   VOICE_STATE_UPDATE: voiceStateUpdate, |   VOICE_STATE_UPDATE: voiceStateUpdate, | ||||||
|   VOICE_SERVER_UPDATE: voiceServerUpdate, |   VOICE_SERVER_UPDATE: voiceServerUpdate, | ||||||
|   WEBHOOKS_UPDATE: webhooksUpdate |   WEBHOOKS_UPDATE: webhooksUpdate, | ||||||
|  |   INTERACTION_CREATE: interactionCreate | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| export interface EventTypes { | export interface EventTypes { | ||||||
|  |  | ||||||
							
								
								
									
										11
									
								
								src/gateway/handlers/interactionCreate.ts
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								src/gateway/handlers/interactionCreate.ts
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,11 @@ | ||||||
|  | import { Interaction } from '../../structures/slash.ts' | ||||||
|  | import { InteractionPayload } from '../../types/slash.ts' | ||||||
|  | import { Gateway, GatewayEventHandler } from '../index.ts' | ||||||
|  | 
 | ||||||
|  | export const interactionCreate: GatewayEventHandler = async ( | ||||||
|  |   gateway: Gateway, | ||||||
|  |   d: InteractionPayload | ||||||
|  | ) => { | ||||||
|  |   const interaction = new Interaction(gateway.client, d) | ||||||
|  |   gateway.client.emit('interactionCreate', interaction) | ||||||
|  | } | ||||||
|  | @ -91,7 +91,6 @@ export class ClientPresence { | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   create(): StatusPayload { |   create(): StatusPayload { | ||||||
|     console.log(this) |  | ||||||
|     return { |     return { | ||||||
|       afk: this.afk === undefined ? false : this.afk, |       afk: this.afk === undefined ? false : this.afk, | ||||||
|       activities: this.createActivity(), |       activities: this.createActivity(), | ||||||
|  |  | ||||||
							
								
								
									
										60
									
								
								src/structures/slash.ts
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										60
									
								
								src/structures/slash.ts
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,60 @@ | ||||||
|  | import { Client } from '../models/client.ts' | ||||||
|  | import { INTERACTION_CALLBACK } from '../types/endpoint.ts' | ||||||
|  | import { MemberPayload } from '../types/guild.ts' | ||||||
|  | import { | ||||||
|  |   InteractionData, | ||||||
|  |   InteractionPayload, | ||||||
|  |   InteractionResponsePayload, | ||||||
|  |   InteractionResponseType | ||||||
|  | } from '../types/slash.ts' | ||||||
|  | import { Embed } from './embed.ts' | ||||||
|  | 
 | ||||||
|  | export interface InteractionResponse { | ||||||
|  |   type?: InteractionResponseType | ||||||
|  |   content?: string | ||||||
|  |   embeds?: Embed[] | ||||||
|  |   tts?: boolean | ||||||
|  |   flags?: number | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | export class Interaction { | ||||||
|  |   client: Client | ||||||
|  |   type: number | ||||||
|  |   token: string | ||||||
|  |   member: MemberPayload | ||||||
|  |   id: string | ||||||
|  |   data: InteractionData | ||||||
|  | 
 | ||||||
|  |   constructor(client: Client, data: InteractionPayload) { | ||||||
|  |     this.client = client | ||||||
|  |     this.type = data.type | ||||||
|  |     this.token = data.token | ||||||
|  |     this.member = data.member | ||||||
|  |     this.id = data.id | ||||||
|  |     this.data = data.data | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   async respond(data: InteractionResponse): Promise<Interaction> { | ||||||
|  |     const payload: InteractionResponsePayload = { | ||||||
|  |       type: data.type ?? InteractionResponseType.CHANNEL_MESSAGE_WITH_SOURCE, | ||||||
|  |       data: | ||||||
|  |         data.type === undefined || | ||||||
|  |         data.type === InteractionResponseType.CHANNEL_MESSAGE_WITH_SOURCE || | ||||||
|  |         data.type === InteractionResponseType.CHANNEL_MESSAGE | ||||||
|  |           ? { | ||||||
|  |               content: data.content ?? '', | ||||||
|  |               embeds: data.embeds, | ||||||
|  |               tts: data.tts ?? false, | ||||||
|  |               flags: data.flags ?? undefined | ||||||
|  |             } | ||||||
|  |           : undefined | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     await this.client.rest.post( | ||||||
|  |       INTERACTION_CALLBACK(this.id, this.token), | ||||||
|  |       payload | ||||||
|  |     ) | ||||||
|  | 
 | ||||||
|  |     return this | ||||||
|  |   } | ||||||
|  | } | ||||||
							
								
								
									
										51
									
								
								src/test/slash-cmd.ts
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										51
									
								
								src/test/slash-cmd.ts
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,51 @@ | ||||||
|  | import { TOKEN } from './config.ts' | ||||||
|  | 
 | ||||||
|  | export const CMD = { | ||||||
|  |   name: 'blep', | ||||||
|  |   description: 'Send a random adorable animal photo', | ||||||
|  |   options: [ | ||||||
|  |     { | ||||||
|  |       name: 'animal', | ||||||
|  |       description: 'The type of animal', | ||||||
|  |       type: 3, | ||||||
|  |       required: true, | ||||||
|  |       choices: [ | ||||||
|  |         { | ||||||
|  |           name: 'Dog', | ||||||
|  |           value: 'animal_dog' | ||||||
|  |         }, | ||||||
|  |         { | ||||||
|  |           name: 'Cat', | ||||||
|  |           value: 'animal_dog' | ||||||
|  |         }, | ||||||
|  |         { | ||||||
|  |           name: 'Penguin', | ||||||
|  |           value: 'animal_penguin' | ||||||
|  |         } | ||||||
|  |       ] | ||||||
|  |     }, | ||||||
|  |     { | ||||||
|  |       name: 'only_smol', | ||||||
|  |       description: 'Whether to show only baby animals', | ||||||
|  |       type: 5, | ||||||
|  |       required: false | ||||||
|  |     } | ||||||
|  |   ] | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // fetch('https://discord.com/api/v8/applications/783937840752099332/commands', {
 | ||||||
|  | fetch( | ||||||
|  |   'https://discord.com/api/v8/applications/783937840752099332/guilds/783319033205751809/commands', | ||||||
|  |   { | ||||||
|  |     method: 'POST', | ||||||
|  |     body: JSON.stringify(CMD), | ||||||
|  |     headers: { | ||||||
|  |       'Content-Type': 'application/json', | ||||||
|  |       Authorization: | ||||||
|  |         // eslint-disable-next-line @typescript-eslint/restrict-plus-operands
 | ||||||
|  |         'Bot ' + TOKEN | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  | ) | ||||||
|  |   .then((r) => r.json()) | ||||||
|  |   .then(console.log) | ||||||
							
								
								
									
										16
									
								
								src/test/slash.ts
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								src/test/slash.ts
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,16 @@ | ||||||
|  | import { Client, Intents } from '../../mod.ts' | ||||||
|  | import { TOKEN } from './config.ts' | ||||||
|  | 
 | ||||||
|  | const client = new Client() | ||||||
|  | 
 | ||||||
|  | client.on('ready', () => { | ||||||
|  |   console.log('Logged in!') | ||||||
|  | }) | ||||||
|  | 
 | ||||||
|  | client.on('interactionCreate', async (d) => { | ||||||
|  |   await d.respond({ | ||||||
|  |     content: `Hi, ${d.member.user.username}!` | ||||||
|  |   }) | ||||||
|  | }) | ||||||
|  | 
 | ||||||
|  | client.connect(TOKEN, Intents.None) | ||||||
|  | @ -191,81 +191,35 @@ const VOICE_REGIONS = (guildID: string): string => | ||||||
| const CLIENT_USER = (): string => | const CLIENT_USER = (): string => | ||||||
|   `${DISCORD_API_URL}/v${DISCORD_API_VERSION}/users/@me` |   `${DISCORD_API_URL}/v${DISCORD_API_VERSION}/users/@me` | ||||||
| 
 | 
 | ||||||
| export default [ | const APPLICATION_COMMANDS = (id: string): string => | ||||||
|   GUILDS, |   `${DISCORD_API_URL}/v${DISCORD_API_VERSION}/applications/${id}/commands` | ||||||
|   GUILD, | 
 | ||||||
|   GUILD_AUDIT_LOGS, | const APPLICATION_COMMAND = (id: string, cmdID: string): string => | ||||||
|   GUILD_WIDGET, |   `${DISCORD_API_URL}/v${DISCORD_API_VERSION}/applications/${id}/commands/${cmdID}` | ||||||
|   GUILD_EMOJI, | 
 | ||||||
|   GUILD_ROLE, | const APPLICATION_GUILD_COMMANDS = (id: string, guildID: string): string => | ||||||
|   GUILD_ROLES, |   `${DISCORD_API_URL}/v${DISCORD_API_VERSION}/applications/${id}/guilds/${guildID}/commands` | ||||||
|   GUILD_INTEGRATION, | 
 | ||||||
|   GUILD_INTEGRATIONS, | const APPLICATION_GUILD_COMMAND = ( | ||||||
|   GUILD_INTEGARTION_SYNC, |   id: string, | ||||||
|   GUILD_WIDGET_IMAGE, |   guildID: string, | ||||||
|   GUILD_BAN, |   cmdID: string | ||||||
|   GUILD_BANS, | ): string => | ||||||
|   GUILD_CHANNEL, |   `${DISCORD_API_URL}/v${DISCORD_API_VERSION}/applications/${id}/guilds/${guildID}/commands/${cmdID}` | ||||||
|   GUILD_CHANNELS, | 
 | ||||||
|   GUILD_MEMBER, | const WEBHOOK_MESSAGE = (id: string, token: string, msgID: string): string => | ||||||
|   CLIENT_USER, |   `${DISCORD_API_URL}/v${DISCORD_API_VERSION}/webhooks/${id}/${token}/messages/${msgID}` | ||||||
|   GUILD_MEMBERS, | 
 | ||||||
|   GUILD_MEMBER_ROLE, | const INTERACTION_CALLBACK = (id: string, token: string): string => | ||||||
|   GUILD_INVITES, |   `${DISCORD_API_URL}/v${DISCORD_API_VERSION}/interactions/${id}/${token}/callback` | ||||||
|   GUILD_LEAVE, |  | ||||||
|   GUILD_PRUNE, |  | ||||||
|   GUILD_VANITY_URL, |  | ||||||
|   GUILD_NICK, |  | ||||||
|   GUILD_PREVIEW, |  | ||||||
|   CHANNEL, |  | ||||||
|   CHANNELS, |  | ||||||
|   CHANNEL_MESSAGE, |  | ||||||
|   CHANNEL_MESSAGES, |  | ||||||
|   CHANNEL_CROSSPOST, |  | ||||||
|   MESSAGE_REACTIONS, |  | ||||||
|   MESSAGE_REACTION, |  | ||||||
|   MESSAGE_REACTION_ME, |  | ||||||
|   MESSAGE_REACTION_USER, |  | ||||||
|   CHANNEL_BULK_DELETE, |  | ||||||
|   CHANNEL_FOLLOW, |  | ||||||
|   CHANNEL_INVITES, |  | ||||||
|   CHANNEL_PIN, |  | ||||||
|   CHANNEL_PINS, |  | ||||||
|   CHANNEL_PERMISSION, |  | ||||||
|   CHANNEL_TYPING, |  | ||||||
|   GROUP_RECIPIENT, |  | ||||||
|   CURRENT_USER, |  | ||||||
|   CURRENT_USER_GUILDS, |  | ||||||
|   USER_DM, |  | ||||||
|   USER_CONNECTIONS, |  | ||||||
|   LEAVE_GUILD, |  | ||||||
|   USER, |  | ||||||
|   CHANNEL_WEBHOOKS, |  | ||||||
|   GUILD_WEBHOOK, |  | ||||||
|   WEBHOOK, |  | ||||||
|   WEBHOOK_WITH_TOKEN, |  | ||||||
|   SLACK_WEBHOOK, |  | ||||||
|   GITHUB_WEBHOOK, |  | ||||||
|   GATEWAY, |  | ||||||
|   GATEWAY_BOT, |  | ||||||
|   CUSTOM_EMOJI, |  | ||||||
|   GUILD_ICON, |  | ||||||
|   GUILD_SPLASH, |  | ||||||
|   GUILD_DISCOVERY_SPLASH, |  | ||||||
|   GUILD_BANNER, |  | ||||||
|   DEFAULT_USER_AVATAR, |  | ||||||
|   USER_AVATAR, |  | ||||||
|   APPLICATION_ASSET, |  | ||||||
|   ACHIEVEMENT_ICON, |  | ||||||
|   TEAM_ICON, |  | ||||||
|   EMOJI, |  | ||||||
|   GUILD_EMOJIS, |  | ||||||
|   TEMPLATE, |  | ||||||
|   INVITE, |  | ||||||
|   VOICE_REGIONS |  | ||||||
| ] |  | ||||||
| 
 | 
 | ||||||
| export { | export { | ||||||
|  |   INTERACTION_CALLBACK, | ||||||
|  |   APPLICATION_COMMAND, | ||||||
|  |   APPLICATION_GUILD_COMMAND, | ||||||
|  |   WEBHOOK_MESSAGE, | ||||||
|  |   APPLICATION_COMMANDS, | ||||||
|  |   APPLICATION_GUILD_COMMANDS, | ||||||
|   GUILDS, |   GUILDS, | ||||||
|   GUILD, |   GUILD, | ||||||
|   GUILD_AUDIT_LOGS, |   GUILD_AUDIT_LOGS, | ||||||
|  |  | ||||||
|  | @ -105,7 +105,8 @@ export enum GatewayEvents { | ||||||
|   User_Update = 'USER_UPDATE', |   User_Update = 'USER_UPDATE', | ||||||
|   Voice_Server_Update = 'VOICE_SERVER_UPDATE', |   Voice_Server_Update = 'VOICE_SERVER_UPDATE', | ||||||
|   Voice_State_Update = 'VOICE_STATE_UPDATE', |   Voice_State_Update = 'VOICE_STATE_UPDATE', | ||||||
|   Webhooks_Update = 'WEBHOOKS_UPDATE' |   Webhooks_Update = 'WEBHOOKS_UPDATE', | ||||||
|  |   Interaction_Create = 'INTERACTION_CREATE' | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| export interface IdentityPayload { | export interface IdentityPayload { | ||||||
|  |  | ||||||
							
								
								
									
										82
									
								
								src/types/slash.ts
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										82
									
								
								src/types/slash.ts
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,82 @@ | ||||||
|  | import { EmbedPayload } from './channel.ts' | ||||||
|  | import { MemberPayload } from './guild.ts' | ||||||
|  | 
 | ||||||
|  | export interface InteractionOption { | ||||||
|  |   name: string | ||||||
|  |   value?: any | ||||||
|  |   options?: any[] | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | export interface InteractionData { | ||||||
|  |   options: InteractionOption[] | ||||||
|  |   name: string | ||||||
|  |   id: string | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | export enum InteractionType { | ||||||
|  |   PING = 1, | ||||||
|  |   APPLICATION_COMMAND = 2 | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | export interface InteractionPayload { | ||||||
|  |   type: InteractionType | ||||||
|  |   token: string | ||||||
|  |   member: MemberPayload | ||||||
|  |   id: string | ||||||
|  |   data: InteractionData | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | export interface SlashCommandChoice { | ||||||
|  |   name: string | ||||||
|  |   value: string | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | export enum SlashCommandOptionType { | ||||||
|  |   SUB_COMMAND = 1, | ||||||
|  |   SUB_COMMAND_GROUP = 2, | ||||||
|  |   STRING = 3, | ||||||
|  |   INTEGER = 4, | ||||||
|  |   BOOLEAN = 5, | ||||||
|  |   USER = 6, | ||||||
|  |   CHANNEL = 7, | ||||||
|  |   ROLE = 8 | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | export interface SlashCommandOption { | ||||||
|  |   name: string | ||||||
|  |   description: string | ||||||
|  |   type: SlashCommandOptionType | ||||||
|  |   required: boolean | ||||||
|  |   choices?: SlashCommandChoice[] | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | export interface SlashCommandPayload { | ||||||
|  |   name: string | ||||||
|  |   description: string | ||||||
|  |   options: SlashCommandOption[] | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | export enum InteractionResponseType { | ||||||
|  |   PONG = 1, | ||||||
|  |   ACKNOWLEDGE = 2, | ||||||
|  |   CHANNEL_MESSAGE = 3, | ||||||
|  |   CHANNEL_MESSAGE_WITH_SOURCE = 4, | ||||||
|  |   ACK_WITH_SOURCE = 5 | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | export interface InteractionResponsePayload { | ||||||
|  |   type: InteractionResponseType | ||||||
|  |   data?: InteractionResponseDataPayload | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | export interface InteractionResponseDataPayload { | ||||||
|  |   tts?: boolean | ||||||
|  |   content: string | ||||||
|  |   embeds?: EmbedPayload[] | ||||||
|  |   allowed_mentions?: { | ||||||
|  |     parse?: 'everyone' | 'users' | 'roles' | ||||||
|  |     roles?: string[] | ||||||
|  |     users?: string[] | ||||||
|  |   } | ||||||
|  |   flags?: number | ||||||
|  | } | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue