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…
Reference in a new issue