From fb02e8a9eff67276c73eedc4f102961d028644ed Mon Sep 17 00:00:00 2001 From: monbrey Date: Thu, 12 Sep 2024 13:55:50 +1000 Subject: [PATCH 01/12] feat(InteractionResponses): support with_response query parameter --- .../src/structures/InteractionCallback.js | 104 +++++++ .../structures/InteractionCallbackResource.js | 51 ++++ .../structures/InteractionCallbackResponse.js | 32 +++ .../interfaces/InteractionResponses.js | 73 +++-- packages/discord.js/typings/index.d.ts | 269 +++++++++++------- 5 files changed, 402 insertions(+), 127 deletions(-) create mode 100644 packages/discord.js/src/structures/InteractionCallback.js create mode 100644 packages/discord.js/src/structures/InteractionCallbackResource.js create mode 100644 packages/discord.js/src/structures/InteractionCallbackResponse.js diff --git a/packages/discord.js/src/structures/InteractionCallback.js b/packages/discord.js/src/structures/InteractionCallback.js new file mode 100644 index 000000000000..41ba380097cc --- /dev/null +++ b/packages/discord.js/src/structures/InteractionCallback.js @@ -0,0 +1,104 @@ +'use strict'; + +const { DiscordSnowflake } = require('@sapphire/snowflake'); + +/** + * Represents an interaction callback response from Discord + */ +class InteractionCallback { + constructor(client, data) { + /** + * The client that instantiated this. + * @name InteractionCallback#client + * @type {Client} + * @readonly + */ + Object.defineProperty(this, 'client', { value: client }); + + /** + * The id of the original interaction response + * @type {Snowflake} + */ + this.id = data.id; + + /** + * The type of the original interaction + * @type {InteractionType} + */ + this.type = data.type; + + /** + * The id of the channel the original interaction was sent in + * @type {?Snowflake} + */ + this.channelId = data.channel_id ?? null; + + /** + * The id of the guild the original interaction was sent in + * @type {Snowflake} + */ + this.guildId = data.guild_id ?? null; + + /** + * The instance id of the Activity if one was launched or joined + * @type {string} + */ + this.activityInstanceId = data.activity_instance_id ?? null; + + /** + * The id of the message that was created by the interaction + * @type {Snowflake} + */ + this.responseMessageId = data.response_message_id ?? null; + + /** + * Whether or not the message is in a loading state + * @type {boolean} + */ + this.responseMessageLoading = data.response_message_loading ?? null; + + /** + * Whether or not the response message was ephemeral + * @type {boolean} + */ + this.responseMessageEphemeral = data.response_message_ephemeral ?? null; + } + + /** + * The timestamp the original interaction was created at + * @type {number} + * @readonly + */ + get createdTimestamp() { + return DiscordSnowflake.timestampFrom(this.id); + } + + /** + * The time the original interaction was created at + * @type {Date} + * @readonly + */ + get createdAt() { + return new Date(this.createdTimestamp); + } + + /** + * The channel the original interaction was sent in + * @type {?TextBasedChannels} + * @readonly + */ + get channel() { + return this.client.channels.cache.get(this.channelId) ?? null; + } + + /** + * The guild the original interaction was sent in + * @type {?Guild} + * @readonly + */ + get guild() { + return this.client.guilds.cache.get(this.guildId) ?? null; + } +} + +exports.InteractionCallback = InteractionCallback; diff --git a/packages/discord.js/src/structures/InteractionCallbackResource.js b/packages/discord.js/src/structures/InteractionCallbackResource.js new file mode 100644 index 000000000000..1e21103d1041 --- /dev/null +++ b/packages/discord.js/src/structures/InteractionCallbackResource.js @@ -0,0 +1,51 @@ +'use strict'; +const { lazy } = require('@discordjs/util'); + +const getMessage = lazy(() => require('./Message').Message); + +/** + * Represents the resource that was created by the interaction response. + */ +class InteractionCallbackResource { + constructor(client, data) { + /** + * The client that instantiated this + * @name InteractionCallbackResource#client + * @type {Client} + * @readonly + */ + Object.defineProperty(this, 'client', { value: client }); + + /** + * The interaction callback type + * @type {InteractionResponseType} + */ + this.type = data.type; + + /** + * The Activity launched by an interaction + * @typedef {Object} ActivityInstance + * @property {string} id The instance id of the Activity + */ + + /** + * Represents the Activity launched by this interaction + * @type {?ActivityInstance} + */ + this.activityInstance = data.activity_instance ?? null; + + if ('message' in data) { + /** + * The message created by the interaction + * @type {?Message} + */ + this.message = + this.client.channels.cache.get(data.message.channel_id)?.messages._add(data.message) ?? + new (getMessage())(client, data.message); + } else { + this.message = null; + } + } +} + +exports.InteractionCallbackResource = InteractionCallbackResource; diff --git a/packages/discord.js/src/structures/InteractionCallbackResponse.js b/packages/discord.js/src/structures/InteractionCallbackResponse.js new file mode 100644 index 000000000000..9f35555676a6 --- /dev/null +++ b/packages/discord.js/src/structures/InteractionCallbackResponse.js @@ -0,0 +1,32 @@ +'use strict'; + +const { InteractionCallback } = require('./InteractionCallback'); +const { InteractionCallbackResource } = require('./InteractionCallbackResource'); +/** + * Represents an interaction's response + */ +class InteractionCallbackResponse { + constructor(client, data) { + /** + * The client that instantiated this + * @name InteractionCallbackResponse#client + * @type {Client} + * @readonly + */ + Object.defineProperty(this, 'client', { value: client }); + + /** + * The interaction object associated with the interaction callback response + * @type {InteractionCallback} + */ + this.interaction = new InteractionCallback(client, data.interaction); + + /** + * The resource that was created by the interaction response + * @type {?InteractionCallbackResource} + */ + this.resource = new InteractionCallbackResource(client, data.resource) ?? null; + } +} + +exports.InteractionCallbackResponse = InteractionCallbackResponse; diff --git a/packages/discord.js/src/structures/interfaces/InteractionResponses.js b/packages/discord.js/src/structures/interfaces/InteractionResponses.js index e448e19fd17e..b6117ab82bb6 100644 --- a/packages/discord.js/src/structures/interfaces/InteractionResponses.js +++ b/packages/discord.js/src/structures/interfaces/InteractionResponses.js @@ -1,8 +1,11 @@ 'use strict'; +const { makeURLSearchParams } = require('@discordjs/rest'); const { isJSONEncodable } = require('@discordjs/util'); const { InteractionResponseType, MessageFlags, Routes, InteractionType } = require('discord-api-types/v10'); const { DiscordjsError, ErrorCodes } = require('../../errors'); +const MessageFlagsBitField = require('../../util/MessageFlagsBitField'); +const { InteractionCallbackResponse } = require('../InteractionCallbackResponse'); const InteractionCollector = require('../InteractionCollector'); const InteractionResponse = require('../InteractionResponse'); const MessagePayload = require('../MessagePayload'); @@ -19,9 +22,15 @@ const MessagePayload = require('../MessagePayload'); * @interface */ class InteractionResponses { + /** + * Shared options for responses to a {@link BaseInteraction}. + * @typedef {Object} SharedInteractionResponseOptions + * @property {boolean} [withResponse] Whether to include an {@link InteractionCallbackResponse} as the response + */ + /** * Options for deferring the reply to an {@link BaseInteraction}. - * @typedef {Object} InteractionDeferReplyOptions + * @typedef {SharedInteractionResponseOptions} InteractionDeferReplyOptions * @property {MessageFlagsResolvable} [flags] Flags for the reply. * Only `MessageFlags.Ephemeral` can be set. * @property {boolean} [fetchReply] Whether to fetch the reply @@ -29,13 +38,13 @@ class InteractionResponses { /** * Options for deferring and updating the reply to a {@link MessageComponentInteraction}. - * @typedef {Object} InteractionDeferUpdateOptions + * @typedef {SharedInteractionResponseOptions} InteractionDeferUpdateOptions * @property {boolean} [fetchReply] Whether to fetch the reply */ /** * Options for a reply to a {@link BaseInteraction}. - * @typedef {BaseMessageOptionsWithPoll} InteractionReplyOptions + * @typedef {BaseMessageOptionsWithPoll|SharedInteractionResponseOptions} InteractionReplyOptions * @property {boolean} [tts=false] Whether the message should be spoken aloud * @property {boolean} [fetchReply] Whether to fetch the reply * @property {MessageFlagsResolvable} [flags] Which flags to set for the message. @@ -45,14 +54,19 @@ class InteractionResponses { /** * Options for updating the message received from a {@link MessageComponentInteraction}. - * @typedef {MessageEditOptions} InteractionUpdateOptions + * @typedef {MessageEditOptions|SharedInteractionResponseOptions} InteractionUpdateOptions * @property {boolean} [fetchReply] Whether to fetch the reply */ + /** + * Options for showing a modal in response to a {@link BaseInteraction} + * @typedef {SharedInteractionResponseOptions} ShowModalOptions + */ + /** * Defers the reply to this interaction. * @param {InteractionDeferReplyOptions} [options] Options for deferring the reply to this interaction - * @returns {Promise} + * @returns {Promise} * @example * // Defer the reply to this interaction * interaction.deferReply() @@ -67,7 +81,7 @@ class InteractionResponses { async deferReply(options = {}) { if (this.deferred || this.replied) throw new DiscordjsError(ErrorCodes.InteractionAlreadyReplied); - await this.client.rest.post(Routes.interactionCallback(this.id, this.token), { + const response = await this.client.rest.post(Routes.interactionCallback(this.id, this.token), { body: { type: InteractionResponseType.DeferredChannelMessageWithSource, data: { @@ -75,10 +89,15 @@ class InteractionResponses { }, }, auth: false, + query: makeURLSearchParams({ with_response: options.withResponse ?? false }), }); this.deferred = true; this.ephemeral = Boolean(options.flags & MessageFlags.Ephemeral); + + if (options.withResponse) { + return new InteractionCallbackResponse(this.client, response); + } return options.fetchReply ? this.fetchReply() : new InteractionResponse(this); } @@ -86,7 +105,7 @@ class InteractionResponses { * Creates a reply to this interaction. * Use the `fetchReply` option to get the bot's reply message. * @param {string|MessagePayload|InteractionReplyOptions} options The options for the reply - * @returns {Promise} + * @returns {Promise} * @example * // Reply to the interaction and fetch the response * interaction.reply({ content: 'Pong!', fetchReply: true }) @@ -109,17 +128,23 @@ class InteractionResponses { const { body: data, files } = await messagePayload.resolveBody().resolveFiles(); - await this.client.rest.post(Routes.interactionCallback(this.id, this.token), { + const response = await this.client.rest.post(Routes.interactionCallback(this.id, this.token), { body: { type: InteractionResponseType.ChannelMessageWithSource, data, }, files, auth: false, + query: makeURLSearchParams({ with_response: options.withResponse ?? false }), }); this.ephemeral = Boolean(options.flags & MessageFlags.Ephemeral); this.replied = true; + + if (options.withResponse) { + return new InteractionCallbackResponse(this.client, response); + } + return options.fetchReply ? this.fetchReply() : new InteractionResponse(this); } @@ -192,7 +217,7 @@ class InteractionResponses { /** * Defers an update to the message to which the component was attached. * @param {InteractionDeferUpdateOptions} [options] Options for deferring the update to this interaction - * @returns {Promise} + * @returns {Promise} * @example * // Defer updating and reset the component's loading state * interaction.deferUpdate() @@ -201,21 +226,26 @@ class InteractionResponses { */ async deferUpdate(options = {}) { if (this.deferred || this.replied) throw new DiscordjsError(ErrorCodes.InteractionAlreadyReplied); - await this.client.rest.post(Routes.interactionCallback(this.id, this.token), { + const response = await this.client.rest.post(Routes.interactionCallback(this.id, this.token), { body: { type: InteractionResponseType.DeferredMessageUpdate, }, auth: false, + query: makeURLSearchParams({ with_response: options.withResponse ?? false }), }); this.deferred = true; - return options.fetchReply ? this.fetchReply() : new InteractionResponse(this, this.message?.interaction?.id); + if (options.withResponse) { + return new InteractionCallbackResponse(this.client, response); + } else { + return options.fetchReply ? this.fetchReply() : new InteractionResponse(this, this.message?.interaction?.id); + } } /** * Updates the original message of the component on which the interaction was received on. * @param {string|MessagePayload|InteractionUpdateOptions} options The options for the updated message - * @returns {Promise} + * @returns {Promise} * @example * // Remove the components from the message * interaction.update({ @@ -234,34 +264,43 @@ class InteractionResponses { const { body: data, files } = await messagePayload.resolveBody().resolveFiles(); - await this.client.rest.post(Routes.interactionCallback(this.id, this.token), { + const response = await this.client.rest.post(Routes.interactionCallback(this.id, this.token), { body: { type: InteractionResponseType.UpdateMessage, data, }, files, auth: false, + query: makeURLSearchParams({ with_response: options.withResponse ?? false }), }); this.replied = true; - return options.fetchReply ? this.fetchReply() : new InteractionResponse(this, this.message.interaction?.id); + if (options.withResponse) { + return new InteractionCallbackResponse(this.client, response); + } else { + return options.fetchReply ? this.fetchReply() : new InteractionResponse(this, this.message.interaction?.id); + } } /** * Shows a modal component * @param {ModalBuilder|ModalComponentData|APIModalInteractionResponseCallbackData} modal The modal to show - * @returns {Promise} + * @param {ShowModalOptions} options The options for sending this interaction response + * @returns {Promise} */ - async showModal(modal) { + async showModal(modal, options = {}) { if (this.deferred || this.replied) throw new DiscordjsError(ErrorCodes.InteractionAlreadyReplied); - await this.client.rest.post(Routes.interactionCallback(this.id, this.token), { + const response = await this.client.rest.post(Routes.interactionCallback(this.id, this.token), { body: { type: InteractionResponseType.Modal, data: isJSONEncodable(modal) ? modal.toJSON() : this.client.options.jsonTransformer(modal), }, auth: false, + query: makeURLSearchParams({ with_response: options.withResponse ?? false }), }); this.replied = true; + + return options.withResponse ? new InteractionCallbackResponse(this.client, response) : undefined; } /** diff --git a/packages/discord.js/typings/index.d.ts b/packages/discord.js/typings/index.d.ts index afb73b20a91b..79b166034ca1 100644 --- a/packages/discord.js/typings/index.d.ts +++ b/packages/discord.js/typings/index.d.ts @@ -166,6 +166,10 @@ import { GuildScheduledEventRecurrenceRuleFrequency, GatewaySendPayload, GatewayDispatchPayload, + RESTPostAPIInteractionCallbackWithResponseResult, + RESTAPIInteractionCallbackObject, + RESTAPIInteractionCallbackResourceObject, + InteractionResponseType, } from 'discord-api-types/v10'; import { ChildProcess } from 'node:child_process'; import { EventEmitter } from 'node:events'; @@ -258,6 +262,10 @@ export class Activity { public toString(): string; } +export interface ActivityInstance { + id: string; +} + export type ActivityFlagsString = keyof typeof ActivityFlags; export interface BaseComponentData { @@ -558,6 +566,9 @@ export abstract class CommandInteraction e public inGuild(): this is CommandInteraction<'raw' | 'cached'>; public inCachedGuild(): this is CommandInteraction<'cached'>; public inRawGuild(): this is CommandInteraction<'raw'>; + public deferReply( + options: InteractionDeferReplyOptions & { withResponse: true }, + ): Promise; public deferReply( options: InteractionDeferReplyOptions & { fetchReply: true }, ): Promise>>; @@ -635,7 +646,7 @@ export class BaseGuildEmoji extends Emoji { } // tslint:disable-next-line no-empty-interface -export interface BaseGuildTextChannel extends TextBasedChannelFields {} +export interface BaseGuildTextChannel extends TextBasedChannelFields { } export class BaseGuildTextChannel extends GuildChannel { protected constructor(guild: Guild, data?: RawGuildChannelData, client?: Client, immediatePatch?: boolean); public defaultAutoArchiveDuration?: ThreadAutoArchiveDuration; @@ -656,7 +667,7 @@ export class BaseGuildTextChannel extends GuildChannel { } // tslint:disable-next-line no-empty-interface -export interface BaseGuildVoiceChannel extends Omit, 'lastPinTimestamp' | 'lastPinAt'> {} +export interface BaseGuildVoiceChannel extends Omit, 'lastPinTimestamp' | 'lastPinAt'> { } export class BaseGuildVoiceChannel extends GuildChannel { public constructor(guild: Guild, data?: RawGuildChannelData); public bitrate: number; @@ -818,11 +829,11 @@ export class StringSelectMenuComponent extends BaseSelectMenuComponent {} +export class UserSelectMenuComponent extends BaseSelectMenuComponent { } -export class RoleSelectMenuComponent extends BaseSelectMenuComponent {} +export class RoleSelectMenuComponent extends BaseSelectMenuComponent { } -export class MentionableSelectMenuComponent extends BaseSelectMenuComponent {} +export class MentionableSelectMenuComponent extends BaseSelectMenuComponent { } export class ChannelSelectMenuComponent extends BaseSelectMenuComponent { public getChannelTypes(): ChannelType[] | null; @@ -849,9 +860,9 @@ export interface IconData { proxyIconURL?: string; } -export interface EmbedAuthorData extends Omit, IconData {} +export interface EmbedAuthorData extends Omit, IconData { } -export interface EmbedFooterData extends Omit, IconData {} +export interface EmbedFooterData extends Omit, IconData { } export interface EmbedAssetData extends Omit { proxyURL?: string; @@ -946,8 +957,8 @@ export abstract class BaseChannel extends Base { export type If = Value extends true ? TrueResult : Value extends false - ? FalseResult - : TrueResult | FalseResult; + ? FalseResult + : TrueResult | FalseResult; export class Client extends BaseClient { public constructor(options: ClientOptions); @@ -1236,8 +1247,8 @@ export class CommandInteractionOptionResolver['channel']>, { type: Type extends ChannelType.PublicThread | ChannelType.AnnouncementThread - ? ChannelType.PublicThread | ChannelType.AnnouncementThread - : Type; + ? ChannelType.PublicThread | ChannelType.AnnouncementThread + : Type; } >; /** @@ -1254,8 +1265,8 @@ export class CommandInteractionOptionResolver['channel']>, { type: Type extends ChannelType.PublicThread | ChannelType.AnnouncementThread - ? ChannelType.PublicThread | ChannelType.AnnouncementThread - : Type; + ? ChannelType.PublicThread | ChannelType.AnnouncementThread + : Type; } > | null; public getString(name: string, required: true): string; @@ -1307,7 +1318,7 @@ export interface DMChannel extends Omit< TextBasedChannelFields, 'bulkDelete' | 'fetchWebhooks' | 'createWebhook' | 'setRateLimitPerUser' | 'setNSFW' - > {} + > { } export class DMChannel extends BaseChannel { private constructor(client: Client, data?: RawDMChannelData); public flags: Readonly; @@ -1527,11 +1538,11 @@ export class GuildAuditLogs { private constructor(guild: Guild, data: RawGuildAuditLogEntryData, logs?: GuildAuditLogs); @@ -1629,7 +1640,7 @@ export class GuildMemberFlagsBitField extends BitField { public static resolve(bit?: BitFieldResolvable): number; } -export interface GuildMember extends PartialTextBasedChannelFields {} +export interface GuildMember extends PartialTextBasedChannelFields { } export class GuildMember extends Base { private constructor(client: Client, data: RawGuildMemberData, guild: Guild); private _roles: Snowflake[]; @@ -1903,10 +1914,10 @@ export type CacheTypeReducer< > = [State] extends ['cached'] ? CachedType : [State] extends ['raw'] - ? RawType - : [State] extends ['raw' | 'cached'] - ? PresentType - : Fallback; + ? RawType + : [State] extends ['raw' | 'cached'] + ? PresentType + : Fallback; export type Interaction = | ChatInputCommandInteraction @@ -1973,6 +1984,37 @@ export class BaseInteraction extends Base public isRepliable(): this is RepliableInteraction; } +export class InteractionCallback { + public constructor(client: Client, data: RESTAPIInteractionCallbackObject); + public activityInstanceId: string | null; + public readonly client: Client; + public get channel(): TextBasedChannel | null; + public channelId: Snowflake | null; + public get createdAt(): Date; + public get createdTimestamp(): number; + public get guild(): Guild | null; + public guildId: Snowflake | null; + public id: Snowflake; + public responseMessageEphemeral: boolean | null; + public responseMessageId: Snowflake | null; + public responseMessageLoading: boolean | null; + public type: InteractionType; +} + +export class InteractionCallbackResponse { + public constructor(client: Client, data: RESTPostAPIInteractionCallbackWithResponseResult); + public readonly client: Client; + public interaction: InteractionCallback; + public resource: InteractionCallbackResource | null; +} + +export class InteractionCallbackResource { + public constructor(client: Client, data: RESTAPIInteractionCallbackResourceObject); + public activityInstance: ActivityInstance | null; + public message: Message | null; + public type: InteractionResponseType; +} + export class InteractionCollector extends Collector< Snowflake, Interaction, @@ -2012,7 +2054,7 @@ export class InteractionCollector exte } // tslint:disable-next-line no-empty-interface -export interface InteractionWebhook extends PartialWebhookFields {} +export interface InteractionWebhook extends PartialWebhookFields { } export class InteractionWebhook { public constructor(client: Client, id: Snowflake, token: string); public readonly client: Client; @@ -2099,9 +2141,9 @@ export interface AwaitMessageCollectorOptionsParams< ComponentType extends MessageComponentType, Cached extends boolean = boolean, > extends Pick< - InteractionCollectorOptions[ComponentType]>, - keyof AwaitMessageComponentOptions - > { + InteractionCollectorOptions[ComponentType]>, + keyof AwaitMessageComponentOptions +> { componentType?: ComponentType; } @@ -2584,7 +2626,7 @@ export interface ThreadOnlyChannel | 'awaitMessages' | 'createMessageComponentCollector' | 'awaitMessageComponent' - > {} + > { } export abstract class ThreadOnlyChannel extends GuildChannel { public type: ChannelType.GuildForum | ChannelType.GuildMedia; public threads: GuildForumThreadManager; @@ -3275,7 +3317,7 @@ export interface PrivateThreadChannel extends ThreadChannel { // tslint:disable-next-line no-empty-interface export interface ThreadChannel - extends Omit, 'fetchWebhooks' | 'createWebhook' | 'setNSFW'> {} + extends Omit, 'fetchWebhooks' | 'createWebhook' | 'setNSFW'> { } export class ThreadChannel extends BaseChannel { private constructor(guild: Guild, data?: RawThreadChannelData, client?: Client); public archived: boolean | null; @@ -3374,7 +3416,7 @@ export interface AvatarDecorationData { } // tslint:disable-next-line no-empty-interface -export interface User extends PartialTextBasedChannelFields {} +export interface User extends PartialTextBasedChannelFields { } export class User extends Base { protected constructor(client: Client, data: RawUserData); private _equals(user: APIUser): boolean; @@ -3597,7 +3639,7 @@ export class VoiceState extends Base { } // tslint:disable-next-line no-empty-interface -export interface Webhook extends WebhookFields {} +export interface Webhook extends WebhookFields { } export class Webhook { private constructor(client: Client, data?: RawWebhookData); public avatar: string | null; @@ -3612,8 +3654,8 @@ export class Webhook { public token: Type extends WebhookType.Incoming ? string : Type extends WebhookType.ChannelFollower - ? null - : string | null; + ? null + : string | null; public type: Type; public applicationId: Type extends WebhookType.Application ? Snowflake : null; public get channel(): @@ -3640,7 +3682,7 @@ export class Webhook { } // tslint:disable-next-line no-empty-interface -export interface WebhookClient extends WebhookFields, BaseClient {} +export interface WebhookClient extends WebhookFields, BaseClient { } export class WebhookClient extends BaseClient { public constructor(data: WebhookClientData, options?: WebhookClientOptions); public readonly client: this; @@ -3985,23 +4027,23 @@ export class ApplicationCommandPermissionsManager< public remove( options: | (FetchSingleOptions & { - token: string; - channels?: readonly (GuildChannelResolvable | ChannelPermissionConstant)[]; - roles?: readonly (RoleResolvable | RolePermissionConstant)[]; - users: readonly UserResolvable[]; - }) + token: string; + channels?: readonly (GuildChannelResolvable | ChannelPermissionConstant)[]; + roles?: readonly (RoleResolvable | RolePermissionConstant)[]; + users: readonly UserResolvable[]; + }) | (FetchSingleOptions & { - token: string; - channels?: readonly (GuildChannelResolvable | ChannelPermissionConstant)[]; - roles: readonly (RoleResolvable | RolePermissionConstant)[]; - users?: readonly UserResolvable[]; - }) + token: string; + channels?: readonly (GuildChannelResolvable | ChannelPermissionConstant)[]; + roles: readonly (RoleResolvable | RolePermissionConstant)[]; + users?: readonly UserResolvable[]; + }) | (FetchSingleOptions & { - token: string; - channels: readonly (GuildChannelResolvable | ChannelPermissionConstant)[]; - roles?: readonly (RoleResolvable | RolePermissionConstant)[]; - users?: readonly UserResolvable[]; - }), + token: string; + channels: readonly (GuildChannelResolvable | ChannelPermissionConstant)[]; + roles?: readonly (RoleResolvable | RolePermissionConstant)[]; + users?: readonly UserResolvable[]; + }), ): Promise; public set( options: FetchSingleOptions & EditApplicationCommandPermissionsMixin, @@ -4079,7 +4121,7 @@ export class EntitlementManager extends CachedManager; } -export interface FetchGuildApplicationCommandFetchOptions extends Omit {} +export interface FetchGuildApplicationCommandFetchOptions extends Omit { } export class GuildApplicationCommandManager extends ApplicationCommandManager { private constructor(guild: Guild, iterable?: Iterable); @@ -4541,7 +4583,7 @@ export interface WebhookFields extends PartialWebhookFields { //#region Typedefs -export interface ActivitiesOptions extends Omit {} +export interface ActivitiesOptions extends Omit { } export interface ActivityOptions { name: string; @@ -4901,10 +4943,10 @@ export interface AutoModerationTriggerMetadata { } export interface AwaitMessageComponentOptions - extends Omit, 'max' | 'maxComponents' | 'maxUsers'> {} + extends Omit, 'max' | 'maxComponents' | 'maxUsers'> { } export interface ModalSubmitInteractionCollectorOptions - extends Omit, 'channel' | 'message' | 'guild' | 'interactionType'> {} + extends Omit, 'channel' | 'message' | 'guild' | 'interactionType'> { } export interface AwaitModalSubmitOptions extends Omit, 'max' | 'maxComponents' | 'maxUsers'> { @@ -5012,8 +5054,8 @@ export type CacheFactory = ( export type CacheWithLimitsOptions = { [K in keyof Caches]?: Caches[K][0]['prototype'] extends DataManager - ? LimitedCollectionOptions | number - : never; + ? LimitedCollectionOptions | number + : never; }; export interface CategoryCreateChannelOptions { @@ -5264,9 +5306,9 @@ export interface CommandInteractionResolvedData { focused: true; type: - | ApplicationCommandOptionType.String - | ApplicationCommandOptionType.Integer - | ApplicationCommandOptionType.Number; + | ApplicationCommandOptionType.String + | ApplicationCommandOptionType.Integer + | ApplicationCommandOptionType.Number; value: string; } @@ -5674,20 +5716,20 @@ export interface GuildAuditLogsEntryExtraField { [AuditLogEvent.MessageUnpin]: { channel: GuildTextBasedChannel | { id: Snowflake }; messageId: Snowflake }; [AuditLogEvent.MemberDisconnect]: { count: number }; [AuditLogEvent.ChannelOverwriteCreate]: - | Role - | GuildMember - | { id: Snowflake; name: string; type: AuditLogOptionsType.Role } - | { id: Snowflake; type: AuditLogOptionsType.Member }; + | Role + | GuildMember + | { id: Snowflake; name: string; type: AuditLogOptionsType.Role } + | { id: Snowflake; type: AuditLogOptionsType.Member }; [AuditLogEvent.ChannelOverwriteUpdate]: - | Role - | GuildMember - | { id: Snowflake; name: string; type: AuditLogOptionsType.Role } - | { id: Snowflake; type: AuditLogOptionsType.Member }; + | Role + | GuildMember + | { id: Snowflake; name: string; type: AuditLogOptionsType.Role } + | { id: Snowflake; type: AuditLogOptionsType.Member }; [AuditLogEvent.ChannelOverwriteDelete]: - | Role - | GuildMember - | { id: Snowflake; name: string; type: AuditLogOptionsType.Role } - | { id: Snowflake; type: AuditLogOptionsType.Member }; + | Role + | GuildMember + | { id: Snowflake; name: string; type: AuditLogOptionsType.Role } + | { id: Snowflake; type: AuditLogOptionsType.Member }; [AuditLogEvent.StageInstanceCreate]: StageChannel | { id: Snowflake }; [AuditLogEvent.StageInstanceDelete]: StageChannel | { id: Snowflake }; [AuditLogEvent.StageInstanceUpdate]: StageChannel | { id: Snowflake }; @@ -5716,8 +5758,8 @@ export interface GuildAuditLogsEntryTargetField> {} +export interface AutoModerationRuleEditOptions extends Partial> { } -export interface AutoModerationTriggerMetadataOptions extends Partial {} +export interface AutoModerationTriggerMetadataOptions extends Partial { } export interface AutoModerationActionOptions { type: AutoModerationActionType; @@ -5988,10 +6030,10 @@ export type GuildScheduledEventResolvable = Snowflake | GuildScheduledEvent; export type GuildScheduledEventSetStatusArg = Status extends GuildScheduledEventStatus.Scheduled - ? GuildScheduledEventStatus.Active | GuildScheduledEventStatus.Canceled - : Status extends GuildScheduledEventStatus.Active - ? GuildScheduledEventStatus.Completed - : never; + ? GuildScheduledEventStatus.Active | GuildScheduledEventStatus.Canceled + : Status extends GuildScheduledEventStatus.Active + ? GuildScheduledEventStatus.Completed + : never; export interface GuildScheduledEventUser { guildScheduledEventId: Snowflake; @@ -6073,7 +6115,7 @@ export interface InteractionCollectorOptions< interactionResponse?: InteractionResponse>; } -export interface InteractionDeferReplyOptions { +export interface InteractionDeferReplyOptions extends SharedInteractionResponseOptions { flags?: BitFieldResolvable< Extract, MessageFlags.Ephemeral | MessageFlags.SuppressEmbeds | MessageFlags.SuppressNotifications @@ -6085,7 +6127,8 @@ export interface InteractionDeferUpdateOptions { fetchReply?: boolean; } -export interface InteractionReplyOptions extends BaseMessageOptionsWithPoll { + +export interface InteractionReplyOptions extends BaseMessageOptionsWithPoll, SharedInteractionResponseOptions { tts?: boolean; fetchReply?: boolean; flags?: BitFieldResolvable< @@ -6094,7 +6137,7 @@ export interface InteractionReplyOptions extends BaseMessageOptionsWithPoll { >; } -export interface InteractionUpdateOptions extends MessageEditOptions { +export interface InteractionUpdateOptions extends MessageEditOptions, SharedInteractionResponseOptions { fetchReply?: boolean; } @@ -6196,10 +6239,10 @@ export type CollectedMessageInteraction = >; export interface MessageComponentCollectorOptions - extends Omit, 'channel' | 'message' | 'guild' | 'interactionType'> {} + extends Omit, 'channel' | 'message' | 'guild' | 'interactionType'> { } export interface MessageChannelComponentCollectorOptions - extends Omit, 'channel' | 'guild' | 'interactionType'> {} + extends Omit, 'channel' | 'guild' | 'interactionType'> { } export interface MessageInteractionMetadata { id: Snowflake; @@ -6253,7 +6296,7 @@ export interface MessageSnapshot | 'stickers' | 'type' > - > {} + > { } export interface BaseMessageOptions { content?: string; @@ -6292,7 +6335,7 @@ export interface MessageCreateOptions extends BaseMessageOptionsWithPoll { export interface GuildForumThreadMessageCreateOptions extends BaseMessageOptions, - Pick {} + Pick { } export interface MessageEditAttachmentData { id: Snowflake; @@ -6424,7 +6467,7 @@ export type PermissionResolvable = BitFieldResolvable extends ReadonlyArray> {} +export interface RecursiveReadonlyArray extends ReadonlyArray> { } export interface PartialRecipient { username: string; @@ -6470,30 +6513,30 @@ export type Partialize< NullableKeys extends keyof PartialType | null = null, OverridableKeys extends keyof PartialType | '' = '', > = { - [K in keyof Omit]: K extends 'partial' + [K in keyof Omit]: K extends 'partial' ? true : K extends NulledKeys - ? null - : K extends NullableKeys - ? PartialType[K] | null - : PartialType[K]; -}; + ? null + : K extends NullableKeys + ? PartialType[K] | null + : PartialType[K]; + }; export interface PartialDMChannel extends Partialize { lastMessageId: undefined; } -export interface PartialGuildMember extends Partialize {} +export interface PartialGuildMember extends Partialize { } export interface PartialMessage - extends Partialize {} + extends Partialize { } -export interface PartialMessageReaction extends Partialize {} +export interface PartialMessageReaction extends Partialize { } export interface PartialGuildScheduledEvent - extends Partialize {} + extends Partialize { } -export interface PartialThreadMember extends Partialize {} +export interface PartialThreadMember extends Partialize { } export interface PartialOverwriteData { id: Snowflake | number; @@ -6516,7 +6559,7 @@ export enum Partials { ThreadMember, } -export interface PartialUser extends Partialize {} +export interface PartialUser extends Partialize { } export type PresenceStatusData = ClientPresenceStatus | 'invisible'; @@ -6606,6 +6649,12 @@ export interface ShardingManagerOptions { execArgv?: readonly string[]; } +export interface SharedInteractionResponseOptions { + withResponse?: boolean; +} + +export interface ShowModalOptions extends SharedInteractionResponseOptions { } + export { Snowflake }; export type StageInstanceResolvable = StageInstance | Snowflake; @@ -6673,8 +6722,8 @@ export interface SweeperDefinitions { export type SweeperOptions = { [Key in keyof SweeperDefinitions]?: SweeperDefinitions[Key][2] extends true - ? SweepOptions | LifetimeSweepOptions - : SweepOptions; + ? SweepOptions | LifetimeSweepOptions + : SweepOptions; }; export interface LimitedCollectionOptions { @@ -6780,7 +6829,7 @@ export interface WebhookClientDataURL { url: string; } -export interface WebhookClientOptions extends Pick {} +export interface WebhookClientOptions extends Pick { } export interface WebhookDeleteOptions { token?: string; @@ -6800,7 +6849,7 @@ export interface WebhookMessageEditOptions extends Omit { + Pick { message?: MessageResolvable | '@original'; } @@ -6858,14 +6907,14 @@ export interface ClientApplicationInstallParams { export type Serialized = Value extends symbol | bigint | (() => any) ? never : Value extends number | string | boolean | undefined - ? Value - : Value extends JSONEncodable - ? JSONResult - : Value extends ReadonlyArray - ? Serialized[] - : Value extends ReadonlyMap | ReadonlySet - ? {} - : { [K in keyof Value]: Serialized }; + ? Value + : Value extends JSONEncodable + ? JSONResult + : Value extends ReadonlyArray + ? Serialized[] + : Value extends ReadonlyMap | ReadonlySet + ? {} + : { [K in keyof Value]: Serialized }; //#endregion From a9a5872612f471933f15dba6862c44e2b882b345 Mon Sep 17 00:00:00 2001 From: monbrey Date: Thu, 12 Sep 2024 13:58:47 +1000 Subject: [PATCH 02/12] fix: export new files from index --- packages/discord.js/src/index.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/packages/discord.js/src/index.js b/packages/discord.js/src/index.js index cdedc8aa45c0..aad3b506f36b 100644 --- a/packages/discord.js/src/index.js +++ b/packages/discord.js/src/index.js @@ -142,6 +142,9 @@ exports.GuildScheduledEvent = require('./structures/GuildScheduledEvent').GuildS exports.GuildTemplate = require('./structures/GuildTemplate'); exports.Integration = require('./structures/Integration'); exports.IntegrationApplication = require('./structures/IntegrationApplication'); +exports.InteractionCallback = require('./structures/InteractionCallback'); +exports.InteractionCallbackResource = require('./structures/InteractionCallbackResource'); +exports.InteractionCallbackResponse = require('./structures/InteractionCallbackResponse'); exports.BaseInteraction = require('./structures/BaseInteraction'); exports.InteractionCollector = require('./structures/InteractionCollector'); exports.InteractionResponse = require('./structures/InteractionResponse'); From bd6d5b02f7f45c50d829df9bf677af5fee2dec9e Mon Sep 17 00:00:00 2001 From: Ryan Munro Date: Thu, 12 Sep 2024 18:03:37 +1000 Subject: [PATCH 03/12] Apply suggestions from code review Co-authored-by: Jiralite <33201955+Jiralite@users.noreply.github.com> --- packages/discord.js/src/structures/InteractionCallback.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/discord.js/src/structures/InteractionCallback.js b/packages/discord.js/src/structures/InteractionCallback.js index 41ba380097cc..75778235d1b4 100644 --- a/packages/discord.js/src/structures/InteractionCallback.js +++ b/packages/discord.js/src/structures/InteractionCallback.js @@ -52,13 +52,13 @@ class InteractionCallback { this.responseMessageId = data.response_message_id ?? null; /** - * Whether or not the message is in a loading state + * Whether the message is in a loading state * @type {boolean} */ this.responseMessageLoading = data.response_message_loading ?? null; /** - * Whether or not the response message was ephemeral + * Whether the response message was ephemeral * @type {boolean} */ this.responseMessageEphemeral = data.response_message_ephemeral ?? null; From dd642d7faf638b6f6a761e8a6a40eefb832ef4fe Mon Sep 17 00:00:00 2001 From: monbrey Date: Thu, 12 Sep 2024 18:29:05 +1000 Subject: [PATCH 04/12] fix: correct assignment of nullable property, types --- .../discord.js/src/structures/InteractionCallbackResponse.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/discord.js/src/structures/InteractionCallbackResponse.js b/packages/discord.js/src/structures/InteractionCallbackResponse.js index 9f35555676a6..3479a8378878 100644 --- a/packages/discord.js/src/structures/InteractionCallbackResponse.js +++ b/packages/discord.js/src/structures/InteractionCallbackResponse.js @@ -25,7 +25,7 @@ class InteractionCallbackResponse { * The resource that was created by the interaction response * @type {?InteractionCallbackResource} */ - this.resource = new InteractionCallbackResource(client, data.resource) ?? null; + this.resource = data.resource ? new InteractionCallbackResource(client, data.resource) : null; } } From c5a4696cf11ba95b0887d7bf528e135e1807f114 Mon Sep 17 00:00:00 2001 From: monbrey Date: Thu, 12 Sep 2024 18:44:30 +1000 Subject: [PATCH 05/12] fix: exports --- packages/discord.js/src/structures/InteractionCallback.js | 2 +- .../src/structures/InteractionCallbackResource.js | 2 +- .../src/structures/InteractionCallbackResponse.js | 6 +++--- .../src/structures/interfaces/InteractionResponses.js | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/packages/discord.js/src/structures/InteractionCallback.js b/packages/discord.js/src/structures/InteractionCallback.js index 75778235d1b4..72d35eb6528f 100644 --- a/packages/discord.js/src/structures/InteractionCallback.js +++ b/packages/discord.js/src/structures/InteractionCallback.js @@ -101,4 +101,4 @@ class InteractionCallback { } } -exports.InteractionCallback = InteractionCallback; +module.exports = InteractionCallback; diff --git a/packages/discord.js/src/structures/InteractionCallbackResource.js b/packages/discord.js/src/structures/InteractionCallbackResource.js index 1e21103d1041..bb0bca5756ed 100644 --- a/packages/discord.js/src/structures/InteractionCallbackResource.js +++ b/packages/discord.js/src/structures/InteractionCallbackResource.js @@ -48,4 +48,4 @@ class InteractionCallbackResource { } } -exports.InteractionCallbackResource = InteractionCallbackResource; +module.exports = InteractionCallbackResource; diff --git a/packages/discord.js/src/structures/InteractionCallbackResponse.js b/packages/discord.js/src/structures/InteractionCallbackResponse.js index 3479a8378878..7211ce6bcd1b 100644 --- a/packages/discord.js/src/structures/InteractionCallbackResponse.js +++ b/packages/discord.js/src/structures/InteractionCallbackResponse.js @@ -1,7 +1,7 @@ 'use strict'; -const { InteractionCallback } = require('./InteractionCallback'); -const { InteractionCallbackResource } = require('./InteractionCallbackResource'); +const InteractionCallback = require('./InteractionCallback'); +const InteractionCallbackResource = require('./InteractionCallbackResource'); /** * Represents an interaction's response */ @@ -29,4 +29,4 @@ class InteractionCallbackResponse { } } -exports.InteractionCallbackResponse = InteractionCallbackResponse; +module.exports = InteractionCallbackResponse; diff --git a/packages/discord.js/src/structures/interfaces/InteractionResponses.js b/packages/discord.js/src/structures/interfaces/InteractionResponses.js index b6117ab82bb6..2c974c341657 100644 --- a/packages/discord.js/src/structures/interfaces/InteractionResponses.js +++ b/packages/discord.js/src/structures/interfaces/InteractionResponses.js @@ -5,7 +5,7 @@ const { isJSONEncodable } = require('@discordjs/util'); const { InteractionResponseType, MessageFlags, Routes, InteractionType } = require('discord-api-types/v10'); const { DiscordjsError, ErrorCodes } = require('../../errors'); const MessageFlagsBitField = require('../../util/MessageFlagsBitField'); -const { InteractionCallbackResponse } = require('../InteractionCallbackResponse'); +const InteractionCallbackResponse = require('../InteractionCallbackResponse'); const InteractionCollector = require('../InteractionCollector'); const InteractionResponse = require('../InteractionResponse'); const MessagePayload = require('../MessagePayload'); From 111b3ddde9bca7f5a0df8f096991ba6ef68d4bd0 Mon Sep 17 00:00:00 2001 From: monbrey Date: Thu, 14 Nov 2024 09:58:32 +1100 Subject: [PATCH 06/12] fix: suggestions from code review --- .../src/structures/InteractionCallback.js | 20 ++++--------------- .../structures/InteractionCallbackResource.js | 1 + .../structures/InteractionCallbackResponse.js | 3 ++- .../interfaces/InteractionResponses.js | 9 +++++---- 4 files changed, 12 insertions(+), 21 deletions(-) diff --git a/packages/discord.js/src/structures/InteractionCallback.js b/packages/discord.js/src/structures/InteractionCallback.js index 72d35eb6528f..e2d2cf9b3c5b 100644 --- a/packages/discord.js/src/structures/InteractionCallback.js +++ b/packages/discord.js/src/structures/InteractionCallback.js @@ -27,39 +27,27 @@ class InteractionCallback { */ this.type = data.type; - /** - * The id of the channel the original interaction was sent in - * @type {?Snowflake} - */ - this.channelId = data.channel_id ?? null; - - /** - * The id of the guild the original interaction was sent in - * @type {Snowflake} - */ - this.guildId = data.guild_id ?? null; - /** * The instance id of the Activity if one was launched or joined - * @type {string} + * @type {?string} */ this.activityInstanceId = data.activity_instance_id ?? null; /** * The id of the message that was created by the interaction - * @type {Snowflake} + * @type {?Snowflake} */ this.responseMessageId = data.response_message_id ?? null; /** * Whether the message is in a loading state - * @type {boolean} + * @type {?boolean} */ this.responseMessageLoading = data.response_message_loading ?? null; /** * Whether the response message was ephemeral - * @type {boolean} + * @type {?boolean} */ this.responseMessageEphemeral = data.response_message_ephemeral ?? null; } diff --git a/packages/discord.js/src/structures/InteractionCallbackResource.js b/packages/discord.js/src/structures/InteractionCallbackResource.js index bb0bca5756ed..ffb088d8100e 100644 --- a/packages/discord.js/src/structures/InteractionCallbackResource.js +++ b/packages/discord.js/src/structures/InteractionCallbackResource.js @@ -1,4 +1,5 @@ 'use strict'; + const { lazy } = require('@discordjs/util'); const getMessage = lazy(() => require('./Message').Message); diff --git a/packages/discord.js/src/structures/InteractionCallbackResponse.js b/packages/discord.js/src/structures/InteractionCallbackResponse.js index 7211ce6bcd1b..c114648398ae 100644 --- a/packages/discord.js/src/structures/InteractionCallbackResponse.js +++ b/packages/discord.js/src/structures/InteractionCallbackResponse.js @@ -2,6 +2,7 @@ const InteractionCallback = require('./InteractionCallback'); const InteractionCallbackResource = require('./InteractionCallbackResource'); + /** * Represents an interaction's response */ @@ -22,7 +23,7 @@ class InteractionCallbackResponse { this.interaction = new InteractionCallback(client, data.interaction); /** - * The resource that was created by the interaction response + * The resource that was created by the interaction response * @type {?InteractionCallbackResource} */ this.resource = data.resource ? new InteractionCallbackResource(client, data.resource) : null; diff --git a/packages/discord.js/src/structures/interfaces/InteractionResponses.js b/packages/discord.js/src/structures/interfaces/InteractionResponses.js index 2c974c341657..23541b16aeb9 100644 --- a/packages/discord.js/src/structures/interfaces/InteractionResponses.js +++ b/packages/discord.js/src/structures/interfaces/InteractionResponses.js @@ -98,6 +98,7 @@ class InteractionResponses { if (options.withResponse) { return new InteractionCallbackResponse(this.client, response); } + return options.fetchReply ? this.fetchReply() : new InteractionResponse(this); } @@ -237,9 +238,9 @@ class InteractionResponses { if (options.withResponse) { return new InteractionCallbackResponse(this.client, response); - } else { - return options.fetchReply ? this.fetchReply() : new InteractionResponse(this, this.message?.interaction?.id); } + + return options.fetchReply ? this.fetchReply() : new InteractionResponse(this, this.message?.interaction?.id); } /** @@ -277,9 +278,9 @@ class InteractionResponses { if (options.withResponse) { return new InteractionCallbackResponse(this.client, response); - } else { - return options.fetchReply ? this.fetchReply() : new InteractionResponse(this, this.message.interaction?.id); } + + return options.fetchReply ? this.fetchReply() : new InteractionResponse(this, this.message.interaction?.id); } /** From 80986bcadec03e93468f7e7921ef687502380976 Mon Sep 17 00:00:00 2001 From: monbrey Date: Thu, 14 Nov 2024 10:25:08 +1100 Subject: [PATCH 07/12] fix: formatting --- packages/discord.js/typings/index.d.ts | 217 ++++++++++++------------- 1 file changed, 108 insertions(+), 109 deletions(-) diff --git a/packages/discord.js/typings/index.d.ts b/packages/discord.js/typings/index.d.ts index 79b166034ca1..3798ead67d78 100644 --- a/packages/discord.js/typings/index.d.ts +++ b/packages/discord.js/typings/index.d.ts @@ -646,7 +646,7 @@ export class BaseGuildEmoji extends Emoji { } // tslint:disable-next-line no-empty-interface -export interface BaseGuildTextChannel extends TextBasedChannelFields { } +export interface BaseGuildTextChannel extends TextBasedChannelFields {} export class BaseGuildTextChannel extends GuildChannel { protected constructor(guild: Guild, data?: RawGuildChannelData, client?: Client, immediatePatch?: boolean); public defaultAutoArchiveDuration?: ThreadAutoArchiveDuration; @@ -667,7 +667,7 @@ export class BaseGuildTextChannel extends GuildChannel { } // tslint:disable-next-line no-empty-interface -export interface BaseGuildVoiceChannel extends Omit, 'lastPinTimestamp' | 'lastPinAt'> { } +export interface BaseGuildVoiceChannel extends Omit, 'lastPinTimestamp' | 'lastPinAt'> {} export class BaseGuildVoiceChannel extends GuildChannel { public constructor(guild: Guild, data?: RawGuildChannelData); public bitrate: number; @@ -829,11 +829,11 @@ export class StringSelectMenuComponent extends BaseSelectMenuComponent { } +export class UserSelectMenuComponent extends BaseSelectMenuComponent {} -export class RoleSelectMenuComponent extends BaseSelectMenuComponent { } +export class RoleSelectMenuComponent extends BaseSelectMenuComponent {} -export class MentionableSelectMenuComponent extends BaseSelectMenuComponent { } +export class MentionableSelectMenuComponent extends BaseSelectMenuComponent {} export class ChannelSelectMenuComponent extends BaseSelectMenuComponent { public getChannelTypes(): ChannelType[] | null; @@ -860,9 +860,9 @@ export interface IconData { proxyIconURL?: string; } -export interface EmbedAuthorData extends Omit, IconData { } +export interface EmbedAuthorData extends Omit, IconData {} -export interface EmbedFooterData extends Omit, IconData { } +export interface EmbedFooterData extends Omit, IconData {} export interface EmbedAssetData extends Omit { proxyURL?: string; @@ -957,8 +957,8 @@ export abstract class BaseChannel extends Base { export type If = Value extends true ? TrueResult : Value extends false - ? FalseResult - : TrueResult | FalseResult; + ? FalseResult + : TrueResult | FalseResult; export class Client extends BaseClient { public constructor(options: ClientOptions); @@ -1247,8 +1247,8 @@ export class CommandInteractionOptionResolver['channel']>, { type: Type extends ChannelType.PublicThread | ChannelType.AnnouncementThread - ? ChannelType.PublicThread | ChannelType.AnnouncementThread - : Type; + ? ChannelType.PublicThread | ChannelType.AnnouncementThread + : Type; } >; /** @@ -1265,8 +1265,8 @@ export class CommandInteractionOptionResolver['channel']>, { type: Type extends ChannelType.PublicThread | ChannelType.AnnouncementThread - ? ChannelType.PublicThread | ChannelType.AnnouncementThread - : Type; + ? ChannelType.PublicThread | ChannelType.AnnouncementThread + : Type; } > | null; public getString(name: string, required: true): string; @@ -1318,7 +1318,7 @@ export interface DMChannel extends Omit< TextBasedChannelFields, 'bulkDelete' | 'fetchWebhooks' | 'createWebhook' | 'setRateLimitPerUser' | 'setNSFW' - > { } + > {} export class DMChannel extends BaseChannel { private constructor(client: Client, data?: RawDMChannelData); public flags: Readonly; @@ -1538,11 +1538,11 @@ export class GuildAuditLogs { private constructor(guild: Guild, data: RawGuildAuditLogEntryData, logs?: GuildAuditLogs); @@ -1640,7 +1640,7 @@ export class GuildMemberFlagsBitField extends BitField { public static resolve(bit?: BitFieldResolvable): number; } -export interface GuildMember extends PartialTextBasedChannelFields { } +export interface GuildMember extends PartialTextBasedChannelFields {} export class GuildMember extends Base { private constructor(client: Client, data: RawGuildMemberData, guild: Guild); private _roles: Snowflake[]; @@ -1914,10 +1914,10 @@ export type CacheTypeReducer< > = [State] extends ['cached'] ? CachedType : [State] extends ['raw'] - ? RawType - : [State] extends ['raw' | 'cached'] - ? PresentType - : Fallback; + ? RawType + : [State] extends ['raw' | 'cached'] + ? PresentType + : Fallback; export type Interaction = | ChatInputCommandInteraction @@ -2054,7 +2054,7 @@ export class InteractionCollector exte } // tslint:disable-next-line no-empty-interface -export interface InteractionWebhook extends PartialWebhookFields { } +export interface InteractionWebhook extends PartialWebhookFields {} export class InteractionWebhook { public constructor(client: Client, id: Snowflake, token: string); public readonly client: Client; @@ -2141,9 +2141,9 @@ export interface AwaitMessageCollectorOptionsParams< ComponentType extends MessageComponentType, Cached extends boolean = boolean, > extends Pick< - InteractionCollectorOptions[ComponentType]>, - keyof AwaitMessageComponentOptions -> { + InteractionCollectorOptions[ComponentType]>, + keyof AwaitMessageComponentOptions + > { componentType?: ComponentType; } @@ -2626,7 +2626,7 @@ export interface ThreadOnlyChannel | 'awaitMessages' | 'createMessageComponentCollector' | 'awaitMessageComponent' - > { } + > {} export abstract class ThreadOnlyChannel extends GuildChannel { public type: ChannelType.GuildForum | ChannelType.GuildMedia; public threads: GuildForumThreadManager; @@ -3317,7 +3317,7 @@ export interface PrivateThreadChannel extends ThreadChannel { // tslint:disable-next-line no-empty-interface export interface ThreadChannel - extends Omit, 'fetchWebhooks' | 'createWebhook' | 'setNSFW'> { } + extends Omit, 'fetchWebhooks' | 'createWebhook' | 'setNSFW'> {} export class ThreadChannel extends BaseChannel { private constructor(guild: Guild, data?: RawThreadChannelData, client?: Client); public archived: boolean | null; @@ -3416,7 +3416,7 @@ export interface AvatarDecorationData { } // tslint:disable-next-line no-empty-interface -export interface User extends PartialTextBasedChannelFields { } +export interface User extends PartialTextBasedChannelFields {} export class User extends Base { protected constructor(client: Client, data: RawUserData); private _equals(user: APIUser): boolean; @@ -3639,7 +3639,7 @@ export class VoiceState extends Base { } // tslint:disable-next-line no-empty-interface -export interface Webhook extends WebhookFields { } +export interface Webhook extends WebhookFields {} export class Webhook { private constructor(client: Client, data?: RawWebhookData); public avatar: string | null; @@ -3654,8 +3654,8 @@ export class Webhook { public token: Type extends WebhookType.Incoming ? string : Type extends WebhookType.ChannelFollower - ? null - : string | null; + ? null + : string | null; public type: Type; public applicationId: Type extends WebhookType.Application ? Snowflake : null; public get channel(): @@ -3682,7 +3682,7 @@ export class Webhook { } // tslint:disable-next-line no-empty-interface -export interface WebhookClient extends WebhookFields, BaseClient { } +export interface WebhookClient extends WebhookFields, BaseClient {} export class WebhookClient extends BaseClient { public constructor(data: WebhookClientData, options?: WebhookClientOptions); public readonly client: this; @@ -4027,23 +4027,23 @@ export class ApplicationCommandPermissionsManager< public remove( options: | (FetchSingleOptions & { - token: string; - channels?: readonly (GuildChannelResolvable | ChannelPermissionConstant)[]; - roles?: readonly (RoleResolvable | RolePermissionConstant)[]; - users: readonly UserResolvable[]; - }) + token: string; + channels?: readonly (GuildChannelResolvable | ChannelPermissionConstant)[]; + roles?: readonly (RoleResolvable | RolePermissionConstant)[]; + users: readonly UserResolvable[]; + }) | (FetchSingleOptions & { - token: string; - channels?: readonly (GuildChannelResolvable | ChannelPermissionConstant)[]; - roles: readonly (RoleResolvable | RolePermissionConstant)[]; - users?: readonly UserResolvable[]; - }) + token: string; + channels?: readonly (GuildChannelResolvable | ChannelPermissionConstant)[]; + roles: readonly (RoleResolvable | RolePermissionConstant)[]; + users?: readonly UserResolvable[]; + }) | (FetchSingleOptions & { - token: string; - channels: readonly (GuildChannelResolvable | ChannelPermissionConstant)[]; - roles?: readonly (RoleResolvable | RolePermissionConstant)[]; - users?: readonly UserResolvable[]; - }), + token: string; + channels: readonly (GuildChannelResolvable | ChannelPermissionConstant)[]; + roles?: readonly (RoleResolvable | RolePermissionConstant)[]; + users?: readonly UserResolvable[]; + }), ): Promise; public set( options: FetchSingleOptions & EditApplicationCommandPermissionsMixin, @@ -4121,7 +4121,7 @@ export class EntitlementManager extends CachedManager; } -export interface FetchGuildApplicationCommandFetchOptions extends Omit { } +export interface FetchGuildApplicationCommandFetchOptions extends Omit {} export class GuildApplicationCommandManager extends ApplicationCommandManager { private constructor(guild: Guild, iterable?: Iterable); @@ -4583,7 +4583,7 @@ export interface WebhookFields extends PartialWebhookFields { //#region Typedefs -export interface ActivitiesOptions extends Omit { } +export interface ActivitiesOptions extends Omit {} export interface ActivityOptions { name: string; @@ -4943,10 +4943,10 @@ export interface AutoModerationTriggerMetadata { } export interface AwaitMessageComponentOptions - extends Omit, 'max' | 'maxComponents' | 'maxUsers'> { } + extends Omit, 'max' | 'maxComponents' | 'maxUsers'> {} export interface ModalSubmitInteractionCollectorOptions - extends Omit, 'channel' | 'message' | 'guild' | 'interactionType'> { } + extends Omit, 'channel' | 'message' | 'guild' | 'interactionType'> {} export interface AwaitModalSubmitOptions extends Omit, 'max' | 'maxComponents' | 'maxUsers'> { @@ -5054,8 +5054,8 @@ export type CacheFactory = ( export type CacheWithLimitsOptions = { [K in keyof Caches]?: Caches[K][0]['prototype'] extends DataManager - ? LimitedCollectionOptions | number - : never; + ? LimitedCollectionOptions | number + : never; }; export interface CategoryCreateChannelOptions { @@ -5306,9 +5306,9 @@ export interface CommandInteractionResolvedData { focused: true; type: - | ApplicationCommandOptionType.String - | ApplicationCommandOptionType.Integer - | ApplicationCommandOptionType.Number; + | ApplicationCommandOptionType.String + | ApplicationCommandOptionType.Integer + | ApplicationCommandOptionType.Number; value: string; } @@ -5716,20 +5716,20 @@ export interface GuildAuditLogsEntryExtraField { [AuditLogEvent.MessageUnpin]: { channel: GuildTextBasedChannel | { id: Snowflake }; messageId: Snowflake }; [AuditLogEvent.MemberDisconnect]: { count: number }; [AuditLogEvent.ChannelOverwriteCreate]: - | Role - | GuildMember - | { id: Snowflake; name: string; type: AuditLogOptionsType.Role } - | { id: Snowflake; type: AuditLogOptionsType.Member }; + | Role + | GuildMember + | { id: Snowflake; name: string; type: AuditLogOptionsType.Role } + | { id: Snowflake; type: AuditLogOptionsType.Member }; [AuditLogEvent.ChannelOverwriteUpdate]: - | Role - | GuildMember - | { id: Snowflake; name: string; type: AuditLogOptionsType.Role } - | { id: Snowflake; type: AuditLogOptionsType.Member }; + | Role + | GuildMember + | { id: Snowflake; name: string; type: AuditLogOptionsType.Role } + | { id: Snowflake; type: AuditLogOptionsType.Member }; [AuditLogEvent.ChannelOverwriteDelete]: - | Role - | GuildMember - | { id: Snowflake; name: string; type: AuditLogOptionsType.Role } - | { id: Snowflake; type: AuditLogOptionsType.Member }; + | Role + | GuildMember + | { id: Snowflake; name: string; type: AuditLogOptionsType.Role } + | { id: Snowflake; type: AuditLogOptionsType.Member }; [AuditLogEvent.StageInstanceCreate]: StageChannel | { id: Snowflake }; [AuditLogEvent.StageInstanceDelete]: StageChannel | { id: Snowflake }; [AuditLogEvent.StageInstanceUpdate]: StageChannel | { id: Snowflake }; @@ -5758,8 +5758,8 @@ export interface GuildAuditLogsEntryTargetField> { } +export interface AutoModerationRuleEditOptions extends Partial> {} -export interface AutoModerationTriggerMetadataOptions extends Partial { } +export interface AutoModerationTriggerMetadataOptions extends Partial {} export interface AutoModerationActionOptions { type: AutoModerationActionType; @@ -6030,10 +6030,10 @@ export type GuildScheduledEventResolvable = Snowflake | GuildScheduledEvent; export type GuildScheduledEventSetStatusArg = Status extends GuildScheduledEventStatus.Scheduled - ? GuildScheduledEventStatus.Active | GuildScheduledEventStatus.Canceled - : Status extends GuildScheduledEventStatus.Active - ? GuildScheduledEventStatus.Completed - : never; + ? GuildScheduledEventStatus.Active | GuildScheduledEventStatus.Canceled + : Status extends GuildScheduledEventStatus.Active + ? GuildScheduledEventStatus.Completed + : never; export interface GuildScheduledEventUser { guildScheduledEventId: Snowflake; @@ -6127,7 +6127,6 @@ export interface InteractionDeferUpdateOptions { fetchReply?: boolean; } - export interface InteractionReplyOptions extends BaseMessageOptionsWithPoll, SharedInteractionResponseOptions { tts?: boolean; fetchReply?: boolean; @@ -6239,10 +6238,10 @@ export type CollectedMessageInteraction = >; export interface MessageComponentCollectorOptions - extends Omit, 'channel' | 'message' | 'guild' | 'interactionType'> { } + extends Omit, 'channel' | 'message' | 'guild' | 'interactionType'> {} export interface MessageChannelComponentCollectorOptions - extends Omit, 'channel' | 'guild' | 'interactionType'> { } + extends Omit, 'channel' | 'guild' | 'interactionType'> {} export interface MessageInteractionMetadata { id: Snowflake; @@ -6296,7 +6295,7 @@ export interface MessageSnapshot | 'stickers' | 'type' > - > { } + > {} export interface BaseMessageOptions { content?: string; @@ -6335,7 +6334,7 @@ export interface MessageCreateOptions extends BaseMessageOptionsWithPoll { export interface GuildForumThreadMessageCreateOptions extends BaseMessageOptions, - Pick { } + Pick {} export interface MessageEditAttachmentData { id: Snowflake; @@ -6467,7 +6466,7 @@ export type PermissionResolvable = BitFieldResolvable extends ReadonlyArray> { } +export interface RecursiveReadonlyArray extends ReadonlyArray> {} export interface PartialRecipient { username: string; @@ -6513,30 +6512,30 @@ export type Partialize< NullableKeys extends keyof PartialType | null = null, OverridableKeys extends keyof PartialType | '' = '', > = { - [K in keyof Omit]: K extends 'partial' + [K in keyof Omit]: K extends 'partial' ? true : K extends NulledKeys - ? null - : K extends NullableKeys - ? PartialType[K] | null - : PartialType[K]; - }; + ? null + : K extends NullableKeys + ? PartialType[K] | null + : PartialType[K]; +}; export interface PartialDMChannel extends Partialize { lastMessageId: undefined; } -export interface PartialGuildMember extends Partialize { } +export interface PartialGuildMember extends Partialize {} export interface PartialMessage - extends Partialize { } + extends Partialize {} -export interface PartialMessageReaction extends Partialize { } +export interface PartialMessageReaction extends Partialize {} export interface PartialGuildScheduledEvent - extends Partialize { } + extends Partialize {} -export interface PartialThreadMember extends Partialize { } +export interface PartialThreadMember extends Partialize {} export interface PartialOverwriteData { id: Snowflake | number; @@ -6559,7 +6558,7 @@ export enum Partials { ThreadMember, } -export interface PartialUser extends Partialize { } +export interface PartialUser extends Partialize {} export type PresenceStatusData = ClientPresenceStatus | 'invisible'; @@ -6653,7 +6652,7 @@ export interface SharedInteractionResponseOptions { withResponse?: boolean; } -export interface ShowModalOptions extends SharedInteractionResponseOptions { } +export interface ShowModalOptions extends SharedInteractionResponseOptions {} export { Snowflake }; @@ -6722,8 +6721,8 @@ export interface SweeperDefinitions { export type SweeperOptions = { [Key in keyof SweeperDefinitions]?: SweeperDefinitions[Key][2] extends true - ? SweepOptions | LifetimeSweepOptions - : SweepOptions; + ? SweepOptions | LifetimeSweepOptions + : SweepOptions; }; export interface LimitedCollectionOptions { @@ -6829,7 +6828,7 @@ export interface WebhookClientDataURL { url: string; } -export interface WebhookClientOptions extends Pick { } +export interface WebhookClientOptions extends Pick {} export interface WebhookDeleteOptions { token?: string; @@ -6849,7 +6848,7 @@ export interface WebhookMessageEditOptions extends Omit { + Pick { message?: MessageResolvable | '@original'; } @@ -6907,14 +6906,14 @@ export interface ClientApplicationInstallParams { export type Serialized = Value extends symbol | bigint | (() => any) ? never : Value extends number | string | boolean | undefined - ? Value - : Value extends JSONEncodable - ? JSONResult - : Value extends ReadonlyArray - ? Serialized[] - : Value extends ReadonlyMap | ReadonlySet - ? {} - : { [K in keyof Value]: Serialized }; + ? Value + : Value extends JSONEncodable + ? JSONResult + : Value extends ReadonlyArray + ? Serialized[] + : Value extends ReadonlyMap | ReadonlySet + ? {} + : { [K in keyof Value]: Serialized }; //#endregion From 1d82b3de3d664036d20d7eac38d940d2e48380f0 Mon Sep 17 00:00:00 2001 From: monbrey Date: Thu, 14 Nov 2024 10:25:40 +1100 Subject: [PATCH 08/12] fix: more formatting --- .../discord.js/src/structures/interfaces/InteractionResponses.js | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/discord.js/src/structures/interfaces/InteractionResponses.js b/packages/discord.js/src/structures/interfaces/InteractionResponses.js index 23541b16aeb9..3dd4e85fe3c7 100644 --- a/packages/discord.js/src/structures/interfaces/InteractionResponses.js +++ b/packages/discord.js/src/structures/interfaces/InteractionResponses.js @@ -4,7 +4,6 @@ const { makeURLSearchParams } = require('@discordjs/rest'); const { isJSONEncodable } = require('@discordjs/util'); const { InteractionResponseType, MessageFlags, Routes, InteractionType } = require('discord-api-types/v10'); const { DiscordjsError, ErrorCodes } = require('../../errors'); -const MessageFlagsBitField = require('../../util/MessageFlagsBitField'); const InteractionCallbackResponse = require('../InteractionCallbackResponse'); const InteractionCollector = require('../InteractionCollector'); const InteractionResponse = require('../InteractionResponse'); From dac5a9d8b7b6aef5265a12e3f36cb5d771835ddf Mon Sep 17 00:00:00 2001 From: Ryan Munro Date: Thu, 14 Nov 2024 14:35:29 +1100 Subject: [PATCH 09/12] fix: apply suggestions from code review Co-authored-by: Jiralite <33201955+Jiralite@users.noreply.github.com> --- .../src/structures/interfaces/InteractionResponses.js | 2 +- packages/discord.js/typings/index.d.ts | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/packages/discord.js/src/structures/interfaces/InteractionResponses.js b/packages/discord.js/src/structures/interfaces/InteractionResponses.js index 3dd4e85fe3c7..47167097ac0e 100644 --- a/packages/discord.js/src/structures/interfaces/InteractionResponses.js +++ b/packages/discord.js/src/structures/interfaces/InteractionResponses.js @@ -286,7 +286,7 @@ class InteractionResponses { * Shows a modal component * @param {ModalBuilder|ModalComponentData|APIModalInteractionResponseCallbackData} modal The modal to show * @param {ShowModalOptions} options The options for sending this interaction response - * @returns {Promise} + * @returns {Promise} */ async showModal(modal, options = {}) { if (this.deferred || this.replied) throw new DiscordjsError(ErrorCodes.InteractionAlreadyReplied); diff --git a/packages/discord.js/typings/index.d.ts b/packages/discord.js/typings/index.d.ts index 3798ead67d78..936859c48053 100644 --- a/packages/discord.js/typings/index.d.ts +++ b/packages/discord.js/typings/index.d.ts @@ -2002,14 +2002,14 @@ export class InteractionCallback { } export class InteractionCallbackResponse { - public constructor(client: Client, data: RESTPostAPIInteractionCallbackWithResponseResult); + private constructor(client: Client, data: RESTPostAPIInteractionCallbackWithResponseResult); public readonly client: Client; public interaction: InteractionCallback; public resource: InteractionCallbackResource | null; } export class InteractionCallbackResource { - public constructor(client: Client, data: RESTAPIInteractionCallbackResourceObject); + private constructor(client: Client, data: RESTAPIInteractionCallbackResourceObject); public activityInstance: ActivityInstance | null; public message: Message | null; public type: InteractionResponseType; @@ -6652,6 +6652,7 @@ export interface SharedInteractionResponseOptions { withResponse?: boolean; } +// tslint:disable-next-line no-empty-interface export interface ShowModalOptions extends SharedInteractionResponseOptions {} export { Snowflake }; From 93f4aa8026ebd849570922900bff1309be32250b Mon Sep 17 00:00:00 2001 From: monbrey Date: Sun, 17 Nov 2024 09:35:32 +1100 Subject: [PATCH 10/12] feat: remove fetchReply option completely --- .../interfaces/InteractionResponses.js | 72 +++++++---------- packages/discord.js/typings/index.d.ts | 66 ++++++++------- packages/discord.js/typings/index.test-d.ts | 81 +++++++++---------- 3 files changed, 102 insertions(+), 117 deletions(-) diff --git a/packages/discord.js/src/structures/interfaces/InteractionResponses.js b/packages/discord.js/src/structures/interfaces/InteractionResponses.js index 47167097ac0e..6c6ce830b747 100644 --- a/packages/discord.js/src/structures/interfaces/InteractionResponses.js +++ b/packages/discord.js/src/structures/interfaces/InteractionResponses.js @@ -21,31 +21,24 @@ const MessagePayload = require('../MessagePayload'); * @interface */ class InteractionResponses { - /** - * Shared options for responses to a {@link BaseInteraction}. - * @typedef {Object} SharedInteractionResponseOptions - * @property {boolean} [withResponse] Whether to include an {@link InteractionCallbackResponse} as the response - */ - /** * Options for deferring the reply to an {@link BaseInteraction}. - * @typedef {SharedInteractionResponseOptions} InteractionDeferReplyOptions + * @typedef {Object} InteractionDeferReplyOptions * @property {MessageFlagsResolvable} [flags] Flags for the reply. * Only `MessageFlags.Ephemeral` can be set. - * @property {boolean} [fetchReply] Whether to fetch the reply */ /** * Options for deferring and updating the reply to a {@link MessageComponentInteraction}. - * @typedef {SharedInteractionResponseOptions} InteractionDeferUpdateOptions - * @property {boolean} [fetchReply] Whether to fetch the reply + * @typedef {Object} InteractionDeferUpdateOptions + * @property {boolean} [withResponse] Whether to return an {@link InteractionCallbackResponse} as the response */ /** * Options for a reply to a {@link BaseInteraction}. - * @typedef {BaseMessageOptionsWithPoll|SharedInteractionResponseOptions} InteractionReplyOptions + * @typedef {BaseMessageOptionsWithPoll} InteractionReplyOptions * @property {boolean} [tts=false] Whether the message should be spoken aloud - * @property {boolean} [fetchReply] Whether to fetch the reply + * @property {boolean} [withResponse] Whether to return an {@link InteractionCallbackResponse} as the response * @property {MessageFlagsResolvable} [flags] Which flags to set for the message. * Only `MessageFlags.Ephemeral`, `MessageFlags.SuppressEmbeds`, and `MessageFlags.SuppressNotifications` * can be set. @@ -53,19 +46,20 @@ class InteractionResponses { /** * Options for updating the message received from a {@link MessageComponentInteraction}. - * @typedef {MessageEditOptions|SharedInteractionResponseOptions} InteractionUpdateOptions - * @property {boolean} [fetchReply] Whether to fetch the reply + * @typedef {MessageEditOptions} InteractionUpdateOptions + * @property {boolean} [withResponse] Whether to return an {@link InteractionCallbackResponse} as the response */ /** * Options for showing a modal in response to a {@link BaseInteraction} - * @typedef {SharedInteractionResponseOptions} ShowModalOptions + * @typedef {Object} ShowModalOptions + * @property {boolean} [withResponse] Whether to return an {@link InteractionCallbackResponse} as the response */ /** * Defers the reply to this interaction. * @param {InteractionDeferReplyOptions} [options] Options for deferring the reply to this interaction - * @returns {Promise} + * @returns {Promise} * @example * // Defer the reply to this interaction * interaction.deferReply() @@ -94,22 +88,20 @@ class InteractionResponses { this.deferred = true; this.ephemeral = Boolean(options.flags & MessageFlags.Ephemeral); - if (options.withResponse) { - return new InteractionCallbackResponse(this.client, response); - } - - return options.fetchReply ? this.fetchReply() : new InteractionResponse(this); + return options.withResponse + ? new InteractionCallbackResponse(this.client, response) + : new InteractionResponse(this); } /** * Creates a reply to this interaction. - * Use the `fetchReply` option to get the bot's reply message. + * Use the `withResponse` option to get the interaction callback response. * @param {string|MessagePayload|InteractionReplyOptions} options The options for the reply - * @returns {Promise} + * @returns {Promise} * @example * // Reply to the interaction and fetch the response - * interaction.reply({ content: 'Pong!', fetchReply: true }) - * .then((message) => console.log(`Reply sent with content ${message.content}`)) + * interaction.reply({ content: 'Pong!', withResponse: true }) + * .then((response) => console.log(`Reply sent with content ${response.resource.message.content}`)) * .catch(console.error); * @example * // Create an ephemeral reply with an embed @@ -141,11 +133,9 @@ class InteractionResponses { this.ephemeral = Boolean(options.flags & MessageFlags.Ephemeral); this.replied = true; - if (options.withResponse) { - return new InteractionCallbackResponse(this.client, response); - } - - return options.fetchReply ? this.fetchReply() : new InteractionResponse(this); + return options.withResponse + ? new InteractionCallbackResponse(this.client, response) + : new InteractionResponse(this); } /** @@ -217,7 +207,7 @@ class InteractionResponses { /** * Defers an update to the message to which the component was attached. * @param {InteractionDeferUpdateOptions} [options] Options for deferring the update to this interaction - * @returns {Promise} + * @returns {Promise} * @example * // Defer updating and reset the component's loading state * interaction.deferUpdate() @@ -235,17 +225,15 @@ class InteractionResponses { }); this.deferred = true; - if (options.withResponse) { - return new InteractionCallbackResponse(this.client, response); - } - - return options.fetchReply ? this.fetchReply() : new InteractionResponse(this, this.message?.interaction?.id); + return options.withResponse + ? new InteractionCallbackResponse(this.client, response) + : new InteractionResponse(this, this.message?.interaction?.id); } /** * Updates the original message of the component on which the interaction was received on. * @param {string|MessagePayload|InteractionUpdateOptions} options The options for the updated message - * @returns {Promise} + * @returns {Promise} * @example * // Remove the components from the message * interaction.update({ @@ -275,17 +263,15 @@ class InteractionResponses { }); this.replied = true; - if (options.withResponse) { - return new InteractionCallbackResponse(this.client, response); - } - - return options.fetchReply ? this.fetchReply() : new InteractionResponse(this, this.message.interaction?.id); + return options.withResponse + ? new InteractionCallbackResponse(this.client, response) + : new InteractionResponse(this, this.message.interaction?.id); } /** * Shows a modal component * @param {ModalBuilder|ModalComponentData|APIModalInteractionResponseCallbackData} modal The modal to show - * @param {ShowModalOptions} options The options for sending this interaction response + * @param {ShowModalOptions} [options={}] The options for sending this interaction response * @returns {Promise} */ async showModal(modal, options = {}) { diff --git a/packages/discord.js/typings/index.d.ts b/packages/discord.js/typings/index.d.ts index 936859c48053..641cf27c1e45 100644 --- a/packages/discord.js/typings/index.d.ts +++ b/packages/discord.js/typings/index.d.ts @@ -170,6 +170,7 @@ import { RESTAPIInteractionCallbackObject, RESTAPIInteractionCallbackResourceObject, InteractionResponseType, + RESTAPIInteractionCallbackActivityInstanceResource, } from 'discord-api-types/v10'; import { ChildProcess } from 'node:child_process'; import { EventEmitter } from 'node:events'; @@ -262,10 +263,6 @@ export class Activity { public toString(): string; } -export interface ActivityInstance { - id: string; -} - export type ActivityFlagsString = keyof typeof ActivityFlags; export interface BaseComponentData { @@ -570,8 +567,8 @@ export abstract class CommandInteraction e options: InteractionDeferReplyOptions & { withResponse: true }, ): Promise; public deferReply( - options: InteractionDeferReplyOptions & { fetchReply: true }, - ): Promise>>; + options: InteractionDeferReplyOptions & { withResponse: true }, + ): Promise; public deferReply(options?: InteractionDeferReplyOptions): Promise>>; public deleteReply(message?: MessageResolvable | '@original'): Promise; public editReply( @@ -579,7 +576,7 @@ export abstract class CommandInteraction e ): Promise>>; public fetchReply(message?: Snowflake | '@original'): Promise>>; public followUp(options: string | MessagePayload | InteractionReplyOptions): Promise>>; - public reply(options: InteractionReplyOptions & { fetchReply: true }): Promise>>; + public reply(options: InteractionReplyOptions & { withResponse: true }): Promise; public reply( options: string | MessagePayload | InteractionReplyOptions, ): Promise>>; @@ -2010,7 +2007,7 @@ export class InteractionCallbackResponse { export class InteractionCallbackResource { private constructor(client: Client, data: RESTAPIInteractionCallbackResourceObject); - public activityInstance: ActivityInstance | null; + public activityInstance: RESTAPIInteractionCallbackActivityInstanceResource | null; public message: Message | null; public type: InteractionResponseType; } @@ -2330,12 +2327,12 @@ export class MessageComponentInteraction e public inCachedGuild(): this is MessageComponentInteraction<'cached'>; public inRawGuild(): this is MessageComponentInteraction<'raw'>; public deferReply( - options: InteractionDeferReplyOptions & { fetchReply: true }, - ): Promise>>; + options: InteractionDeferReplyOptions & { withResponse: true }, + ): Promise; public deferReply(options?: InteractionDeferReplyOptions): Promise>>; public deferUpdate( - options: InteractionDeferUpdateOptions & { fetchReply: true }, - ): Promise>>; + options: InteractionDeferUpdateOptions & { withResponse: true }, + ): Promise; public deferUpdate(options?: InteractionDeferUpdateOptions): Promise>>; public deleteReply(message?: MessageResolvable | '@original'): Promise; public editReply( @@ -2343,11 +2340,11 @@ export class MessageComponentInteraction e ): Promise>>; public fetchReply(message?: Snowflake | '@original'): Promise>>; public followUp(options: string | MessagePayload | InteractionReplyOptions): Promise>>; - public reply(options: InteractionReplyOptions & { fetchReply: true }): Promise>>; + public reply(options: InteractionReplyOptions & { withResponse: true }): Promise; public reply( options: string | MessagePayload | InteractionReplyOptions, ): Promise>>; - public update(options: InteractionUpdateOptions & { fetchReply: true }): Promise>>; + public update(options: InteractionUpdateOptions & { withResponse: true }): Promise; public update( options: string | MessagePayload | InteractionUpdateOptions, ): Promise>>; @@ -2356,7 +2353,15 @@ export class MessageComponentInteraction e | JSONEncodable | ModalComponentData | APIModalInteractionResponseCallbackData, + options?: ShowModalOptions, ): Promise; + public showModal( + modal: + | JSONEncodable + | ModalComponentData + | APIModalInteractionResponseCallbackData, + options: ShowModalOptions & { withResponse: true }, + ): Promise; public awaitModalSubmit( options: AwaitModalSubmitOptions, ): Promise>; @@ -2523,7 +2528,7 @@ export interface ModalMessageModalSubmitInteraction { message: Message>; channelId: Snowflake; - update(options: InteractionUpdateOptions & { fetchReply: true }): Promise; + update(options: InteractionUpdateOptions & { withResponse: true }): Promise; update( options: string | MessagePayload | InteractionUpdateOptions, ): Promise>>; @@ -2543,7 +2548,7 @@ export class ModalSubmitInteraction extend public message: Message> | null; public replied: boolean; public readonly webhook: InteractionWebhook; - public reply(options: InteractionReplyOptions & { fetchReply: true }): Promise>>; + public reply(options: InteractionReplyOptions & { withResponse: true }): Promise; public reply( options: string | MessagePayload | InteractionReplyOptions, ): Promise>>; @@ -2552,14 +2557,14 @@ export class ModalSubmitInteraction extend options: string | MessagePayload | InteractionEditReplyOptions, ): Promise>>; public deferReply( - options: InteractionDeferReplyOptions & { fetchReply: true }, - ): Promise>>; + options: InteractionDeferReplyOptions & { withResponse: true }, + ): Promise; public deferReply(options?: InteractionDeferReplyOptions): Promise>>; public fetchReply(message?: Snowflake | '@original'): Promise>>; public followUp(options: string | MessagePayload | InteractionReplyOptions): Promise>>; public deferUpdate( - options: InteractionDeferUpdateOptions & { fetchReply: true }, - ): Promise>>; + options: InteractionDeferUpdateOptions & { withResponse: true }, + ): Promise; public deferUpdate(options?: InteractionDeferUpdateOptions): Promise>>; public inGuild(): this is ModalSubmitInteraction<'raw' | 'cached'>; public inCachedGuild(): this is ModalSubmitInteraction<'cached'>; @@ -6115,29 +6120,30 @@ export interface InteractionCollectorOptions< interactionResponse?: InteractionResponse>; } -export interface InteractionDeferReplyOptions extends SharedInteractionResponseOptions { +export interface InteractionDeferReplyOptions { flags?: BitFieldResolvable< Extract, MessageFlags.Ephemeral | MessageFlags.SuppressEmbeds | MessageFlags.SuppressNotifications >; - fetchReply?: boolean; + withResponse?: boolean; } export interface InteractionDeferUpdateOptions { - fetchReply?: boolean; + /** @deprecated Use {@link SharedInteractionResponseOptions.withResponse} instead */ + withResponse?: boolean; } -export interface InteractionReplyOptions extends BaseMessageOptionsWithPoll, SharedInteractionResponseOptions { +export interface InteractionReplyOptions extends BaseMessageOptionsWithPoll { tts?: boolean; - fetchReply?: boolean; flags?: BitFieldResolvable< Extract, MessageFlags.Ephemeral | MessageFlags.SuppressEmbeds | MessageFlags.SuppressNotifications >; } -export interface InteractionUpdateOptions extends MessageEditOptions, SharedInteractionResponseOptions { - fetchReply?: boolean; +export interface InteractionUpdateOptions extends MessageEditOptions { + /** @deprecated Use {@link SharedInteractionResponseOptions.withResponse} instead */ + withResponse?: boolean; } export interface InviteGenerationOptions { @@ -6648,13 +6654,11 @@ export interface ShardingManagerOptions { execArgv?: readonly string[]; } -export interface SharedInteractionResponseOptions { +// tslint:disable-next-line no-empty-interface +export interface ShowModalOptions { withResponse?: boolean; } -// tslint:disable-next-line no-empty-interface -export interface ShowModalOptions extends SharedInteractionResponseOptions {} - export { Snowflake }; export type StageInstanceResolvable = StageInstance | Snowflake; diff --git a/packages/discord.js/typings/index.test-d.ts b/packages/discord.js/typings/index.test-d.ts index 390d698223f6..8812a3c5f492 100644 --- a/packages/discord.js/typings/index.test-d.ts +++ b/packages/discord.js/typings/index.test-d.ts @@ -208,6 +208,7 @@ import { GuildScheduledEventManager, SendableChannels, PollData, + InteractionCallbackResponse, } from '.'; import { expectAssignable, expectNotAssignable, expectNotType, expectType } from 'tsd'; import type { ContextMenuCommandBuilder, SlashCommandBuilder } from '@discordjs/builders'; @@ -432,7 +433,7 @@ client.on('messageCreate', async message => { expectAssignable>(message); const component = await message.awaitMessageComponent({ componentType: ComponentType.Button }); expectType>(component); - expectType>(await component.reply({ fetchReply: true })); + expectType(await component.reply({ withResponse: true })); const buttonCollector = message.createMessageComponentCollector({ componentType: ComponentType.Button }); expectType>>(buttonCollector); @@ -1785,36 +1786,36 @@ client.on('interactionCreate', async interaction => { expectType(interaction.component); expectType>(interaction.message); expectType(interaction.guild); - expectType>>(interaction.reply({ content: 'a', fetchReply: true })); - expectType>>(interaction.deferReply({ fetchReply: true })); + expectType>(interaction.reply({ content: 'a', withResponse: true })); + expectType>(interaction.deferReply({ withResponse: true })); expectType>>(interaction.editReply({ content: 'a' })); expectType>>(interaction.fetchReply()); - expectType>>(interaction.update({ content: 'a', fetchReply: true })); - expectType>>(interaction.deferUpdate({ fetchReply: true })); + expectType>(interaction.update({ content: 'a', withResponse: true })); + expectType>(interaction.deferUpdate({ withResponse: true })); expectType>>(interaction.followUp({ content: 'a' })); } else if (interaction.inRawGuild()) { expectAssignable(interaction); expectType(interaction.component); expectType>(interaction.message); expectType(interaction.guild); - expectType>>(interaction.reply({ content: 'a', fetchReply: true })); - expectType>>(interaction.deferReply({ fetchReply: true })); + expectType>(interaction.reply({ content: 'a', withResponse: true })); + expectType>(interaction.deferReply({ withResponse: true })); expectType>>(interaction.editReply({ content: 'a' })); expectType>>(interaction.fetchReply()); - expectType>>(interaction.update({ content: 'a', fetchReply: true })); - expectType>>(interaction.deferUpdate({ fetchReply: true })); + expectType>(interaction.update({ content: 'a', withResponse: true })); + expectType>(interaction.deferUpdate({ withResponse: true })); expectType>>(interaction.followUp({ content: 'a' })); } else if (interaction.inGuild()) { expectAssignable(interaction); expectType(interaction.component); expectType(interaction.message); expectType(interaction.guild); - expectType>(interaction.reply({ content: 'a', fetchReply: true })); - expectType>(interaction.deferReply({ fetchReply: true })); + expectType>(interaction.reply({ content: 'a', withResponse: true })); + expectType>(interaction.deferReply({ withResponse: true })); expectType>(interaction.editReply({ content: 'a' })); expectType>(interaction.fetchReply()); - expectType>(interaction.update({ content: 'a', fetchReply: true })); - expectType>(interaction.deferUpdate({ fetchReply: true })); + expectType>(interaction.update({ content: 'a', withResponse: true })); + expectType>(interaction.deferUpdate({ withResponse: true })); expectType>(interaction.followUp({ content: 'a' })); } } @@ -1848,24 +1849,24 @@ client.on('interactionCreate', async interaction => { expectAssignable(interaction); expectAssignable(interaction.guild); expectAssignable>(interaction); - expectType>>(interaction.reply({ content: 'a', fetchReply: true })); - expectType>>(interaction.deferReply({ fetchReply: true })); + expectType>(interaction.reply({ content: 'a', withResponse: true })); + expectType>(interaction.deferReply({ withResponse: true })); expectType>>(interaction.editReply({ content: 'a' })); expectType>>(interaction.fetchReply()); expectType>>(interaction.followUp({ content: 'a' })); } else if (interaction.inRawGuild()) { expectAssignable(interaction); expectType(interaction.guild); - expectType>>(interaction.reply({ content: 'a', fetchReply: true })); - expectType>>(interaction.deferReply({ fetchReply: true })); + expectType>(interaction.reply({ content: 'a', withResponse: true })); + expectType>(interaction.deferReply({ withResponse: true })); expectType>>(interaction.editReply({ content: 'a' })); expectType>>(interaction.fetchReply()); expectType>>(interaction.followUp({ content: 'a' })); } else if (interaction.inGuild()) { expectAssignable(interaction); expectType(interaction.guild); - expectType>(interaction.reply({ content: 'a', fetchReply: true })); - expectType>(interaction.deferReply({ fetchReply: true })); + expectType>(interaction.reply({ content: 'a', withResponse: true })); + expectType>(interaction.deferReply({ withResponse: true })); expectType>(interaction.editReply({ content: 'a' })); expectType>(interaction.fetchReply()); expectType>(interaction.followUp({ content: 'a' })); @@ -1919,19 +1920,19 @@ client.on('interactionCreate', async interaction => { expectType(interaction.component); expectType>(interaction.message); expectType(interaction.guild); - expectType>>(interaction.reply({ fetchReply: true })); + expectType>(interaction.reply({ withResponse: true })); } else if (interaction.inRawGuild()) { expectAssignable(interaction); expectType(interaction.component); expectType>(interaction.message); expectType(interaction.guild); - expectType>>(interaction.reply({ fetchReply: true })); + expectType>(interaction.reply({ withResponse: true })); } else if (interaction.inGuild()) { expectAssignable(interaction); expectType(interaction.component); expectType(interaction.message); expectAssignable(interaction.guild); - expectType>(interaction.reply({ fetchReply: true })); + expectType>(interaction.reply({ withResponse: true })); } } @@ -1947,19 +1948,19 @@ client.on('interactionCreate', async interaction => { expectType(interaction.component); expectType>(interaction.message); expectType(interaction.guild); - expectType>>(interaction.reply({ fetchReply: true })); + expectType>(interaction.reply({ withResponse: true })); } else if (interaction.inRawGuild()) { expectAssignable(interaction); expectType(interaction.component); expectType>(interaction.message); expectType(interaction.guild); - expectType>>(interaction.reply({ fetchReply: true })); + expectType>(interaction.reply({ withResponse: true })); } else if (interaction.inGuild()) { expectAssignable(interaction); expectType(interaction.component); expectType(interaction.message); expectType(interaction.guild); - expectType>(interaction.reply({ fetchReply: true })); + expectType>(interaction.reply({ withResponse: true })); } } @@ -1970,21 +1971,15 @@ client.on('interactionCreate', async interaction => { if (interaction.inRawGuild()) { expectNotAssignable>(interaction); expectAssignable(interaction); - expectType>>(interaction.reply({ fetchReply: true })); + expectType>(interaction.reply({ withResponse: true })); expectType(interaction.options.getMember('test')); expectType(interaction.options.getChannel('test', true)); expectType(interaction.options.getRole('test', true)); } else if (interaction.inCachedGuild()) { - const msg = await interaction.reply({ fetchReply: true }); - const btn = await msg.awaitMessageComponent({ componentType: ComponentType.Button }); - - expectType>(msg); - expectType>(btn); - expectType(interaction.options.getMember('test')); expectAssignable(interaction); - expectType>>(interaction.reply({ fetchReply: true })); + expectType>(interaction.reply({ withResponse: true })); expectType(interaction.options.getChannel('test', true)); expectType(interaction.options.getRole('test', true)); @@ -2010,7 +2005,7 @@ client.on('interactionCreate', async interaction => { // @ts-expect-error consumeCachedCommand(interaction); expectType(interaction); - expectType>(interaction.reply({ fetchReply: true })); + expectType>(interaction.reply({ withResponse: true })); expectType(interaction.options.getMember('test')); expectType(interaction.options.getChannel('test', true)); @@ -2064,29 +2059,29 @@ client.on('interactionCreate', async interaction => { if (interaction.inCachedGuild()) { expectAssignable(interaction); expectType(interaction.guild); - expectType>>(interaction.reply({ content: 'a', fetchReply: true })); - expectType>>(interaction.deferReply({ fetchReply: true })); + expectType>(interaction.reply({ content: 'a', withResponse: true })); + expectType>(interaction.deferReply({ withResponse: true })); expectType>>(interaction.editReply({ content: 'a' })); expectType>>(interaction.fetchReply()); - expectType>>(interaction.deferUpdate({ fetchReply: true })); + expectType>(interaction.deferUpdate({ withResponse: true })); expectType>>(interaction.followUp({ content: 'a' })); } else if (interaction.inRawGuild()) { expectAssignable(interaction); expectType(interaction.guild); - expectType>>(interaction.reply({ content: 'a', fetchReply: true })); - expectType>>(interaction.deferReply({ fetchReply: true })); + expectType>(interaction.reply({ content: 'a', withResponse: true })); + expectType>(interaction.deferReply({ withResponse: true })); expectType>>(interaction.editReply({ content: 'a' })); expectType>>(interaction.fetchReply()); - expectType>>(interaction.deferUpdate({ fetchReply: true })); + expectType>(interaction.deferUpdate({ withResponse: true })); expectType>>(interaction.followUp({ content: 'a' })); } else if (interaction.inGuild()) { expectAssignable(interaction); expectType(interaction.guild); - expectType>(interaction.reply({ content: 'a', fetchReply: true })); - expectType>(interaction.deferReply({ fetchReply: true })); + expectType>(interaction.reply({ content: 'a', withResponse: true })); + expectType>(interaction.deferReply({ withResponse: true })); expectType>(interaction.editReply({ content: 'a' })); expectType>(interaction.fetchReply()); - expectType>(interaction.deferUpdate({ fetchReply: true })); + expectType>(interaction.deferUpdate({ withResponse: true })); expectType>(interaction.followUp({ content: 'a' })); } } From 2637c17f61a0e204af0a1dfff218a25c48f1ab7a Mon Sep 17 00:00:00 2001 From: Ryan Munro Date: Sun, 17 Nov 2024 13:53:53 +1100 Subject: [PATCH 11/12] fix: apply suggestions from code review Co-authored-by: Jiralite <33201955+Jiralite@users.noreply.github.com> --- packages/discord.js/typings/index.d.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/packages/discord.js/typings/index.d.ts b/packages/discord.js/typings/index.d.ts index 9ad60333de1f..653a2244261f 100644 --- a/packages/discord.js/typings/index.d.ts +++ b/packages/discord.js/typings/index.d.ts @@ -6152,7 +6152,6 @@ export interface InteractionDeferReplyOptions { } export interface InteractionDeferUpdateOptions { - /** @deprecated Use {@link SharedInteractionResponseOptions.withResponse} instead */ withResponse?: boolean; } @@ -6677,7 +6676,6 @@ export interface ShardingManagerOptions { execArgv?: readonly string[]; } -// tslint:disable-next-line no-empty-interface export interface ShowModalOptions { withResponse?: boolean; } From 00bae08798126547bd2c5e54d58518ec098b4a26 Mon Sep 17 00:00:00 2001 From: monbrey Date: Mon, 18 Nov 2024 06:20:29 +1100 Subject: [PATCH 12/12] fix: types and docs --- .../src/structures/interfaces/InteractionResponses.js | 1 + packages/discord.js/typings/index.d.ts | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/packages/discord.js/src/structures/interfaces/InteractionResponses.js b/packages/discord.js/src/structures/interfaces/InteractionResponses.js index 6c6ce830b747..3610b2e47bdd 100644 --- a/packages/discord.js/src/structures/interfaces/InteractionResponses.js +++ b/packages/discord.js/src/structures/interfaces/InteractionResponses.js @@ -25,6 +25,7 @@ class InteractionResponses { * Options for deferring the reply to an {@link BaseInteraction}. * @typedef {Object} InteractionDeferReplyOptions * @property {MessageFlagsResolvable} [flags] Flags for the reply. + * @property {boolean} [withResponse] Whether to return an {@link InteractionCallbackResponse} as the response * Only `MessageFlags.Ephemeral` can be set. */ diff --git a/packages/discord.js/typings/index.d.ts b/packages/discord.js/typings/index.d.ts index 641cf27c1e45..bf1d02689954 100644 --- a/packages/discord.js/typings/index.d.ts +++ b/packages/discord.js/typings/index.d.ts @@ -585,7 +585,7 @@ export abstract class CommandInteraction e | JSONEncodable | ModalComponentData | APIModalInteractionResponseCallbackData, - ): Promise; + ): Promise; public awaitModalSubmit( options: AwaitModalSubmitOptions, ): Promise>; @@ -2354,7 +2354,7 @@ export class MessageComponentInteraction e | ModalComponentData | APIModalInteractionResponseCallbackData, options?: ShowModalOptions, - ): Promise; + ): Promise; public showModal( modal: | JSONEncodable