Update interaction helpers (#3465)

This commit is contained in:
Fleny
2024-03-07 22:35:55 -06:00
committed by GitHub
parent 866d622eb3
commit 46c93385c1
+78 -37
View File
@@ -12,7 +12,7 @@ import {
} from '@discordeno/types'
import { Collection } from '@discordeno/utils'
import type { Bot, Channel, Component, DiscordChannel } from '../index.js'
import type { DiscordInteractionDataResolved } from '../typings.js'
import { MessageFlags, type DiscordInteractionDataResolved } from '../typings.js'
import type { Attachment } from './attachment.js'
import type { Member } from './member.js'
import type { Message } from './message.js'
@@ -78,30 +78,58 @@ export interface BaseInteraction {
* Sends a response to an interaction.
*
* @remarks
* Uses `interaction.type`, `interaction.token` and `interaction.id`
* This will send a {@link InteractionResponseTypes.ChannelMessageWithSource}, {@link InteractionResponseTypes.ApplicationCommandAutocompleteResult} or {@link InteractionResponseTypes.Modal} response based on the type of the interaction you are responding to.
*
* If the interaction has been already acknowledged, indicated by {@link Interaction.acknowledged}, it will send a followup message instead.
*
* Uses `interaction.type`, `interaction.token` and `interaction.id`, missing one of these in the desired proprieties may cause unexpected behavior.
*/
respond: (response: string | InteractionCallbackData, options?: { isPrivate?: boolean }) => Promise<Message | void>
/**
* Edit the original response of an interaction.
* Edit the original response of an interaction or a followup if the message id is provided.
*
* @remarks
* Uses `interaction.token`
* This will edit the original interaction response or, if the interaction has not yet been acknowledged and the type of the interaction is {@link InteractionTypes.MessageComponent} it will instead send a {@link InteractionResponseTypes.UpdateMessage} response instead.
*
* Uses `interaction.type`, `interaction.token` and `interaction.id`, missing one of these in the desired proprieties may cause unexpected behavior.
*/
edit: (response: string | InteractionCallbackData) => Promise<Message>
edit: (response: string | InteractionCallbackData, messageId?: BigString) => Promise<Message | void>
/**
* Defer the interaction.
* Defer the interaction for updating the referenced message at a later time with {@link edit}.
*
* @remarks
* Uses `interaction.type`, `interaction.token` and `interaction.id`
* This will send a {@link InteractionResponseTypes.DeferredUpdateMessage} response.
*
* Uses `interaction.type`, `interaction.token` and `interaction.id`, missing one of these in the desired proprieties may cause unexpected behavior.
*/
deferEdit: () => Promise<void>
/**
* Defer the interaction for updating the response at a later time with {@link edit}.
*
* @remarks
* This will send a {@link InteractionResponseTypes.DeferredChannelMessageWithSource} response.
*
* Uses `interaction.type`, `interaction.token` and `interaction.id`, missing one of these in the desired proprieties may cause unexpected behavior.
*/
defer: (isPrivate?: boolean) => Promise<void>
/**
* Delete the original interaction response or a followup message
* Delete the original interaction response or a followup if the message id is provided.
*
* @remarks
* Uses `interaction.type` and `interaction.token`
* Uses `interaction.type` and `interaction.token`, missing one of these in the desired proprieties may cause unexpected behavior.
*/
delete: (messageId?: BigString) => Promise<void>
/**
* Sends a response with an upgrade button.
*
* @remarks
* This will send a {@link InteractionResponseTypes.PremiumRequired} response.
*
* This can be used only with applications that have monetization enabled.
*
* Uses `interaction.type`, `interaction.token` and `interaction.id`, missing one of these in the desired proprieties may cause unexpected behavior.
*/
premiumRequired: () => Promise<void>
}
const baseInteraction: Partial<Interaction> & BaseInteraction = {
@@ -110,12 +138,11 @@ const baseInteraction: Partial<Interaction> & BaseInteraction = {
// If user provides a string, change it to a response object
if (typeof response === 'string') response = { content: response }
// If user provides an object, determine if it should be an autocomplete or a modal response
else if (response.title) type = InteractionResponseTypes.Modal
else if (this.type === InteractionTypes.ApplicationCommandAutocomplete) type = InteractionResponseTypes.ApplicationCommandAutocompleteResult
// If user wants to send a private message
if (type === InteractionResponseTypes.ChannelMessageWithSource && options?.isPrivate) response.flags = 64
// If user provides an object, determine if it should be an autocomplete or a modal response
if (response.title) type = InteractionResponseTypes.Modal
if (this.type === InteractionTypes.ApplicationCommandAutocomplete) type = InteractionResponseTypes.ApplicationCommandAutocompleteResult
if (type === InteractionResponseTypes.ChannelMessageWithSource && options?.isPrivate) response.flags = MessageFlags.Ephemeral
// Since this has already been given a response, any further responses must be followups.
if (this.acknowledged) return await this.bot!.helpers.sendFollowupMessage(this.token!, response)
@@ -124,43 +151,57 @@ const baseInteraction: Partial<Interaction> & BaseInteraction = {
if (this.type === InteractionTypes.ModalSubmit && type === InteractionResponseTypes.Modal)
throw new Error('Cannot respond to a modal interaction with another modal.')
// Autocomplete response can only be used for autocomplete interactions
if (this.type === InteractionTypes.ApplicationCommandAutocomplete && type !== InteractionResponseTypes.ApplicationCommandAutocompleteResult)
throw new Error('Cannot respond to an autocomplete interaction with a modal or message.')
// If user has not already responded to this interaction we need to send an original response
this.acknowledged = true
return await this.bot!.helpers.sendInteractionResponse(this.id!, this.token!, { type, data: response })
},
async edit(response) {
if (this.type === InteractionTypes.ApplicationCommandAutocomplete) throw new Error('Cannot edit an autocomplete interaction')
async edit(response, messageId) {
if (this.type === InteractionTypes.ApplicationCommandAutocomplete) throw new Error('Cannot edit an autocomplete interaction.')
// If user provides a string, change it to a response object
if (typeof response === 'string') response = { content: response }
if (messageId) {
return await this.bot?.helpers.editFollowupMessage(this.token!, messageId, response)
}
if (!this.acknowledged) {
if (this.type !== InteractionTypes.MessageComponent)
throw new Error("This interaction has not been responded to yet and this isn't a MessageComponent interaction.")
this.acknowledged = true
return await this.bot!.helpers.sendInteractionResponse(this.id!, this.token!, { type: InteractionResponseTypes.UpdateMessage, data: response })
}
return await this.bot!.helpers.editOriginalInteractionResponse(this.token!, response)
},
async deferEdit() {
if (this.type === InteractionTypes.ApplicationCommandAutocomplete) throw new Error('Cannot edit an autocomplete interaction.')
if (this.acknowledged) throw new Error('Cannot defer an already responded interaction.')
async defer(isPrivate) {
if (this.type === InteractionTypes.ApplicationCommandAutocomplete) throw new Error('Cannot defer an autocomplete interaction')
if (this.acknowledged) throw new Error('Cannot defer an already responded interaction')
// Determine the type of defer response
const type =
this.type === InteractionTypes.MessageComponent
? InteractionResponseTypes.DeferredUpdateMessage
: InteractionResponseTypes.DeferredChannelMessageWithSource
// If user wants to send a private message
const data: InteractionCallbackData = {}
if (isPrivate) data.flags = 64
if (this.type !== InteractionTypes.MessageComponent)
throw new Error("Cannot defer to then edit an interaction that isn't a MessageComponent interaction.")
this.acknowledged = true
return await this.bot!.helpers.sendInteractionResponse(this.id!, this.token!, { type, data })
return await this.bot!.helpers.sendInteractionResponse(this.id!, this.token!, { type: InteractionResponseTypes.DeferredUpdateMessage })
},
async defer(isPrivate) {
if (this.acknowledged) throw new Error('Cannot defer an already responded interaction.')
async delete(messageId?: BigString) {
this.acknowledged = true
return await this.bot!.helpers.sendInteractionResponse(this.id!, this.token!, {
type: InteractionResponseTypes.DeferredChannelMessageWithSource,
data: {
flags: isPrivate ? MessageFlags.Ephemeral : undefined,
},
})
},
async premiumRequired() {
if (this.acknowledged) throw new Error('Cannot respond to an already responded interaction.')
this.acknowledged = true
return await this.bot!.helpers.sendInteractionResponse(this.id!, this.token!, { type: InteractionResponseTypes.PremiumRequired })
},
async delete(messageId) {
if (this.type === InteractionTypes.ApplicationCommandAutocomplete) throw new Error('Cannot delete an autocomplete interaction')
if (messageId) return await this.bot?.helpers.deleteFollowupMessage(this.token!, messageId)