Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor(InteractionResponses): Deprecate ephemeral response option #10574

Merged
merged 4 commits into from
Oct 25, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions packages/discord.js/src/structures/MessagePayload.js
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@ class MessagePayload {
* Whether or not the target is an {@link BaseInteraction} or an {@link InteractionWebhook}
* @type {boolean}
* @readonly
* @deprecated This will no longer serve a purpose in the next major version.
*/
get isInteraction() {
const BaseInteraction = getBaseInteraction();
Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,16 @@
'use strict';

const process = require('node:process');
const { deprecate } = require('node:util');
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 InteractionCollector = require('../InteractionCollector');
const InteractionResponse = require('../InteractionResponse');
const MessagePayload = require('../MessagePayload');

let deprecationEmittedForEphemeralOption = false;

/**
* @typedef {Object} ModalComponentData
* @property {string} title The title of the modal
Expand All @@ -24,7 +26,10 @@ class InteractionResponses {
/**
* Options for deferring the reply to an {@link BaseInteraction}.
* @typedef {Object} InteractionDeferReplyOptions
* @property {boolean} [ephemeral] Whether the reply should be ephemeral
* @property {boolean} [ephemeral] Whether the reply should be ephemeral.
* <warn>This option is deprecated. Use `flags` instead.</warn>
* @property {MessageFlagsResolvable} [flags] Flags for the reply.
* <info>Only `MessageFlags.Ephemeral` can be set.</info>
* @property {boolean} [fetchReply] Whether to fetch the reply
*/

Expand All @@ -37,10 +42,11 @@ class InteractionResponses {
/**
* Options for a reply to a {@link BaseInteraction}.
* @typedef {BaseMessageOptionsWithPoll} InteractionReplyOptions
* @property {boolean} [ephemeral] Whether the reply should be ephemeral.
* <warn>This option is deprecated. Use `flags` instead.</warn>
* @property {boolean} [tts=false] Whether the message should be spoken aloud
* @property {boolean} [ephemeral] Whether the reply should be ephemeral
* @property {boolean} [fetchReply] Whether to fetch the reply
* @property {MessageFlags} [flags] Which flags to set for the message.
* @property {MessageFlagsResolvable} [flags] Which flags to set for the message.
* <info>Only `MessageFlags.Ephemeral`, `MessageFlags.SuppressEmbeds`, and `MessageFlags.SuppressNotifications`
* can be set.</info>
*/
Expand All @@ -62,24 +68,41 @@ class InteractionResponses {
* .catch(console.error)
* @example
* // Defer to send an ephemeral reply later
* interaction.deferReply({ ephemeral: true })
* interaction.deferReply({ flags: MessageFlags.Ephemeral })
* .then(console.log)
* .catch(console.error);
*/
async deferReply(options = {}) {
if (this.deferred || this.replied) throw new DiscordjsError(ErrorCodes.InteractionAlreadyReplied);
this.ephemeral = options.ephemeral ?? false;

if ('ephemeral' in options) {
if (!deprecationEmittedForEphemeralOption) {
process.emitWarning(
`Supplying "ephemeral" for interaction response options is deprecated. Utilize flags instead.`,
);

deprecationEmittedForEphemeralOption = true;
}
}

let { flags } = options;

if (options.ephemeral) {
flags |= MessageFlags.Ephemeral;
}

await this.client.rest.post(Routes.interactionCallback(this.id, this.token), {
body: {
type: InteractionResponseType.DeferredChannelMessageWithSource,
data: {
flags: options.ephemeral ? MessageFlags.Ephemeral : undefined,
flags,
},
},
auth: false,
});
this.deferred = true;

this.deferred = true;
this.ephemeral = Boolean(flags & MessageFlags.Ephemeral);
return options.fetchReply ? this.fetchReply() : new InteractionResponse(this);
}

Expand All @@ -97,21 +120,29 @@ class InteractionResponses {
* // Create an ephemeral reply with an embed
* const embed = new EmbedBuilder().setDescription('Pong!');
*
* interaction.reply({ embeds: [embed], ephemeral: true })
* interaction.reply({ embeds: [embed], flags: MessageFlags.Ephemeral })
* .then(() => console.log('Reply sent.'))
* .catch(console.error);
*/
async reply(options) {
if (this.deferred || this.replied) throw new DiscordjsError(ErrorCodes.InteractionAlreadyReplied);

if ('ephemeral' in options) {
if (!deprecationEmittedForEphemeralOption) {
process.emitWarning(
`Supplying "ephemeral" for interaction response options is deprecated. Utilize flags instead.`,
);

deprecationEmittedForEphemeralOption = true;
}
}

let messagePayload;
if (options instanceof MessagePayload) messagePayload = options;
else messagePayload = MessagePayload.create(this, options);

const { body: data, files } = await messagePayload.resolveBody().resolveFiles();

this.ephemeral = new MessageFlagsBitField(data.flags).has(MessageFlags.Ephemeral);

await this.client.rest.post(Routes.interactionCallback(this.id, this.token), {
body: {
type: InteractionResponseType.ChannelMessageWithSource,
Expand All @@ -120,8 +151,9 @@ class InteractionResponses {
files,
auth: false,
});
this.replied = true;

this.ephemeral = Boolean(data.flags & MessageFlags.Ephemeral);
this.replied = true;
return options.fetchReply ? this.fetchReply() : new InteractionResponse(this);
}

Expand Down
9 changes: 9 additions & 0 deletions packages/discord.js/src/util/MessageFlagsBitField.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,15 @@ class MessageFlagsBitField extends BitField {
* @param {BitFieldResolvable} [bits=0] Bit(s) to read from
*/

/**
* Data that can be resolved to give a message flags bit field. This can be:
* * A string (see {@link MessageFlagsBitField.Flags})
* * A message flag
* * An instance of {@link MessageFlagsBitField}
* * An array of `MessageFlagsResolvable`
* @typedef {string|number|MessageFlagsBitField|MessageFlagsResolvable[]} MessageFlagsResolvable
Jiralite marked this conversation as resolved.
Show resolved Hide resolved
*/

/**
* Bitfield of the packed bits
* @type {number}
Expand Down
17 changes: 14 additions & 3 deletions packages/discord.js/typings/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2389,9 +2389,11 @@ export type MessageFlagsString = keyof typeof MessageFlags;

export class MessageFlagsBitField extends BitField<MessageFlagsString> {
public static Flags: typeof MessageFlags;
public static resolve(bit?: BitFieldResolvable<MessageFlagsString, number>): number;
public static resolve(bit?: MessageFlagsResolvable): number;
}

export type MessageFlagsResolvable = BitFieldResolvable<MessageFlagsString, number>;

export class MessageMentions<InGuild extends boolean = boolean> {
private constructor(
message: Message,
Expand Down Expand Up @@ -2441,6 +2443,7 @@ export class MessagePayload {
public get isWebhook(): boolean;
public get isMessage(): boolean;
public get isMessageManager(): boolean;
/** @deprecated This will no longer serve a purpose in the next major version. */
public get isInteraction(): boolean;
public files: RawFile[] | null;
public options: MessagePayloadOption;
Expand Down Expand Up @@ -6351,15 +6354,23 @@ export interface InteractionCollectorOptions<
}

export interface InteractionDeferReplyOptions {
/** @deprecated Use {@link InteractionDeferReplyOptions.flags} instead. */
ephemeral?: boolean;
flags?: BitFieldResolvable<
Extract<MessageFlagsString, 'Ephemeral' | 'SuppressEmbeds' | 'SuppressNotifications'>,
MessageFlags.Ephemeral | MessageFlags.SuppressEmbeds | MessageFlags.SuppressNotifications
>;
Jiralite marked this conversation as resolved.
Show resolved Hide resolved
fetchReply?: boolean;
}

export interface InteractionDeferUpdateOptions extends Omit<InteractionDeferReplyOptions, 'ephemeral'> {}
export interface InteractionDeferUpdateOptions {
fetchReply?: boolean;
}

export interface InteractionReplyOptions extends BaseMessageOptionsWithPoll {
tts?: boolean;
/** @deprecated Use {@link InteractionReplyOptions.flags} instead. */
ephemeral?: boolean;
tts?: boolean;
fetchReply?: boolean;
flags?: BitFieldResolvable<
Extract<MessageFlagsString, 'Ephemeral' | 'SuppressEmbeds' | 'SuppressNotifications'>,
Expand Down