feat: slash commands

This commit is contained in:
DjDeveloperr 2020-12-10 10:06:36 +05:30
parent ea030deb4a
commit d14fe15d68
9 changed files with 252 additions and 76 deletions

View file

@ -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 {

View 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)
}

View file

@ -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
View 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
View 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
View 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)

View file

@ -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,

View file

@ -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
View 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
}