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, | ||||
|   EveryTextChannelTypes | ||||
| } from '../../utils/getChannelByType.ts' | ||||
| import { interactionCreate } from './interactionCreate.ts' | ||||
| 
 | ||||
| export const gatewayHandlers: { | ||||
|   [eventCode in GatewayEvents]: GatewayEventHandler | undefined | ||||
|  | @ -93,7 +94,8 @@ export const gatewayHandlers: { | |||
|   USER_UPDATE: userUpdate, | ||||
|   VOICE_STATE_UPDATE: voiceStateUpdate, | ||||
|   VOICE_SERVER_UPDATE: voiceServerUpdate, | ||||
|   WEBHOOKS_UPDATE: webhooksUpdate | ||||
|   WEBHOOKS_UPDATE: webhooksUpdate, | ||||
|   INTERACTION_CREATE: interactionCreate | ||||
| } | ||||
| 
 | ||||
| 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 { | ||||
|     console.log(this) | ||||
|     return { | ||||
|       afk: this.afk === undefined ? false : this.afk, | ||||
|       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 => | ||||
|   `${DISCORD_API_URL}/v${DISCORD_API_VERSION}/users/@me` | ||||
| 
 | ||||
| export default [ | ||||
|   GUILDS, | ||||
|   GUILD, | ||||
|   GUILD_AUDIT_LOGS, | ||||
|   GUILD_WIDGET, | ||||
|   GUILD_EMOJI, | ||||
|   GUILD_ROLE, | ||||
|   GUILD_ROLES, | ||||
|   GUILD_INTEGRATION, | ||||
|   GUILD_INTEGRATIONS, | ||||
|   GUILD_INTEGARTION_SYNC, | ||||
|   GUILD_WIDGET_IMAGE, | ||||
|   GUILD_BAN, | ||||
|   GUILD_BANS, | ||||
|   GUILD_CHANNEL, | ||||
|   GUILD_CHANNELS, | ||||
|   GUILD_MEMBER, | ||||
|   CLIENT_USER, | ||||
|   GUILD_MEMBERS, | ||||
|   GUILD_MEMBER_ROLE, | ||||
|   GUILD_INVITES, | ||||
|   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 | ||||
| ] | ||||
| const APPLICATION_COMMANDS = (id: string): string => | ||||
|   `${DISCORD_API_URL}/v${DISCORD_API_VERSION}/applications/${id}/commands` | ||||
| 
 | ||||
| const APPLICATION_COMMAND = (id: string, cmdID: string): string => | ||||
|   `${DISCORD_API_URL}/v${DISCORD_API_VERSION}/applications/${id}/commands/${cmdID}` | ||||
| 
 | ||||
| const APPLICATION_GUILD_COMMANDS = (id: string, guildID: string): string => | ||||
|   `${DISCORD_API_URL}/v${DISCORD_API_VERSION}/applications/${id}/guilds/${guildID}/commands` | ||||
| 
 | ||||
| const APPLICATION_GUILD_COMMAND = ( | ||||
|   id: string, | ||||
|   guildID: string, | ||||
|   cmdID: string | ||||
| ): string => | ||||
|   `${DISCORD_API_URL}/v${DISCORD_API_VERSION}/applications/${id}/guilds/${guildID}/commands/${cmdID}` | ||||
| 
 | ||||
| const WEBHOOK_MESSAGE = (id: string, token: string, msgID: string): string => | ||||
|   `${DISCORD_API_URL}/v${DISCORD_API_VERSION}/webhooks/${id}/${token}/messages/${msgID}` | ||||
| 
 | ||||
| const INTERACTION_CALLBACK = (id: string, token: string): string => | ||||
|   `${DISCORD_API_URL}/v${DISCORD_API_VERSION}/interactions/${id}/${token}/callback` | ||||
| 
 | ||||
| export { | ||||
|   INTERACTION_CALLBACK, | ||||
|   APPLICATION_COMMAND, | ||||
|   APPLICATION_GUILD_COMMAND, | ||||
|   WEBHOOK_MESSAGE, | ||||
|   APPLICATION_COMMANDS, | ||||
|   APPLICATION_GUILD_COMMANDS, | ||||
|   GUILDS, | ||||
|   GUILD, | ||||
|   GUILD_AUDIT_LOGS, | ||||
|  |  | |||
|  | @ -105,7 +105,8 @@ export enum GatewayEvents { | |||
|   User_Update = 'USER_UPDATE', | ||||
|   Voice_Server_Update = 'VOICE_SERVER_UPDATE', | ||||
|   Voice_State_Update = 'VOICE_STATE_UPDATE', | ||||
|   Webhooks_Update = 'WEBHOOKS_UPDATE' | ||||
|   Webhooks_Update = 'WEBHOOKS_UPDATE', | ||||
|   Interaction_Create = 'INTERACTION_CREATE' | ||||
| } | ||||
| 
 | ||||
| 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