mirror of
https://github.com/discordeno/discordeno.git
synced 2026-09-17 08:47:22 +00:00
feat(bot): add more helper functions to BaseInteraction (#3018)
* Add more helper functions for `BaseInteraction` - Breaking changes for `respond` - `response` now takes `InteractionCallbackData` - `options` is now `ephemeral: boolean` - Added `edit`, `defer` and `delete` * Add comments and `acknowledged` check for `defer` * Update packages/bot/src/transformers/interaction.ts Co-authored-by: Skillz4Killz <23035000+Skillz4Killz@users.noreply.github.com> * Revert `respond` options, rename `ephemeral` to `private` * Fix typo * Fix arg name - Renamed `private` to `isPrivate` to prevent reserved name collision - Optional chaining for `options` * Apply suggestions from code review --------- Co-authored-by: Skillz4Killz <23035000+Skillz4Killz@users.noreply.github.com>
This commit is contained in:
@@ -1,13 +1,14 @@
|
||||
import {
|
||||
InteractionResponseTypes,
|
||||
InteractionTypes,
|
||||
type ApplicationCommandOptionTypes,
|
||||
type ApplicationCommandTypes,
|
||||
type BigString,
|
||||
type CamelizedDiscordMessage,
|
||||
type ChannelTypes,
|
||||
type DiscordInteraction,
|
||||
type DiscordInteractionDataOption,
|
||||
type InteractionResponse,
|
||||
type InteractionTypes,
|
||||
type InteractionCallbackData,
|
||||
type MessageComponentTypes,
|
||||
} from '@discordeno/types'
|
||||
import { Collection } from '@discordeno/utils'
|
||||
@@ -24,6 +25,8 @@ export interface Interaction extends BaseInteraction {
|
||||
bot: Bot
|
||||
/** Whether or not this interaction has been replied to. */
|
||||
acknowledged: boolean
|
||||
/** Whether or not a modal has been shown for this interaction. */
|
||||
shownModal: boolean
|
||||
/** Id of the interaction */
|
||||
id: bigint
|
||||
/** Id of the application this interaction is for */
|
||||
@@ -68,30 +71,79 @@ export interface Interaction extends BaseInteraction {
|
||||
|
||||
export interface BaseInteraction {
|
||||
/** Sends a response to an interaction. */
|
||||
respond: (response: string | InteractionResponse, options: { private: boolean }) => Promise<CamelizedDiscordMessage | void>
|
||||
respond: (response: string | InteractionCallbackData, options?: { isPrivate?: boolean }) => Promise<CamelizedDiscordMessage | void>
|
||||
/** Edit the original response of an interaction. */
|
||||
edit: (response: string | InteractionCallbackData) => Promise<CamelizedDiscordMessage>
|
||||
/** Defer the interaction. */
|
||||
defer: (isPrivate?: boolean) => Promise<void>
|
||||
/** Delete the original interaction response or a followup message */
|
||||
delete: (messageId?: BigString) => Promise<void>
|
||||
}
|
||||
|
||||
const baseInteraction: Partial<Interaction> & BaseInteraction = {
|
||||
async respond(response, options) {
|
||||
let type = InteractionResponseTypes.ChannelMessageWithSource
|
||||
|
||||
// If user provides a string, change it to response object
|
||||
if (typeof response === 'string') {
|
||||
response = {
|
||||
type: InteractionResponseTypes.DeferredChannelMessageWithSource,
|
||||
data: {
|
||||
content: 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
|
||||
|
||||
// Since this has already been given a response, any further responses must be followups.
|
||||
if (this.acknowledged) return await this.bot?.rest.sendFollowupMessage(this.token!, response)
|
||||
if (this.shownModal && type === InteractionResponseTypes.Modal) throw new Error('Cannot respond to a modal interaction with another modal.')
|
||||
|
||||
// If user has not already responded to this interaction we need to send an original response
|
||||
if (type === InteractionResponseTypes.Modal) this.shownModal = true
|
||||
if (type === InteractionResponseTypes.ChannelMessageWithSource) this.acknowledged = true
|
||||
|
||||
return await this.bot?.rest.sendInteractionResponse(this.id!, this.token!, { type, data: response })
|
||||
},
|
||||
|
||||
async edit(response) {
|
||||
if (this.type === InteractionTypes.ApplicationCommandAutocomplete) throw new Error('Cannot edit an autocomplete interaction')
|
||||
|
||||
// If user provides a string, change it to response object
|
||||
if (typeof response === 'string') {
|
||||
response = {
|
||||
content: response,
|
||||
}
|
||||
}
|
||||
|
||||
// If user wants to send a ephemeral message
|
||||
if (options.private && response.data) response.data.flags = 64
|
||||
// If user has not already responded to this interaction we need to send an original response
|
||||
if (!this.acknowledged) {
|
||||
this.acknowledged = true;
|
||||
return await this.bot?.rest.sendInteractionResponse(this.id!, this.token!, response)
|
||||
}
|
||||
// Since this has already been given a response, any further responses must be folloups.
|
||||
return await this.bot?.rest.sendFollowupMessage(this.token!, response.data!)
|
||||
return await this.bot?.rest.editOriginalInteractionResponse(this.token!, response)
|
||||
},
|
||||
|
||||
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
|
||||
let type: InteractionResponseTypes
|
||||
if (this.type === InteractionTypes.MessageComponent) type = InteractionResponseTypes.DeferredUpdateMessage
|
||||
else type = InteractionResponseTypes.DeferredChannelMessageWithSource
|
||||
|
||||
// If user wants to send a private message
|
||||
const data: InteractionCallbackData = {}
|
||||
if (isPrivate) data.flags = 64
|
||||
|
||||
return await this.bot?.rest.sendInteractionResponse(this.id!, this.token!, { type, data })
|
||||
},
|
||||
|
||||
async delete(messageId?: BigString) {
|
||||
if (this.type === InteractionTypes.ApplicationCommandAutocomplete) throw new Error('Cannot delete an autocomplete interaction')
|
||||
|
||||
if (messageId) return await this.bot?.rest.deleteFollowupMessage(this.token!, messageId)
|
||||
else return await this.bot?.rest.deleteOriginalInteractionResponse(this.token!)
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user