mirror of
https://github.com/discordjs/discord.js.git
synced 2026-03-09 16:13:31 +01:00
refactor: remove djs components and use /builders components instead (#7252)
Co-authored-by: Vlad Frangu <kingdgrizzle@gmail.com>
This commit is contained in:
@@ -77,7 +77,6 @@ exports.BaseGuild = require('./structures/BaseGuild');
|
||||
exports.BaseGuildEmoji = require('./structures/BaseGuildEmoji');
|
||||
exports.BaseGuildTextChannel = require('./structures/BaseGuildTextChannel');
|
||||
exports.BaseGuildVoiceChannel = require('./structures/BaseGuildVoiceChannel');
|
||||
exports.BaseMessageComponent = require('./structures/BaseMessageComponent');
|
||||
exports.ButtonInteraction = require('./structures/ButtonInteraction');
|
||||
exports.CategoryChannel = require('./structures/CategoryChannel');
|
||||
exports.Channel = require('./structures/Channel').Channel;
|
||||
@@ -111,9 +110,7 @@ exports.Invite = require('./structures/Invite');
|
||||
exports.InviteStageInstance = require('./structures/InviteStageInstance');
|
||||
exports.InviteGuild = require('./structures/InviteGuild');
|
||||
exports.Message = require('./structures/Message').Message;
|
||||
exports.MessageActionRow = require('./structures/MessageActionRow');
|
||||
exports.MessageAttachment = require('./structures/MessageAttachment');
|
||||
exports.MessageButton = require('./structures/MessageButton');
|
||||
exports.MessageCollector = require('./structures/MessageCollector');
|
||||
exports.MessageComponentInteraction = require('./structures/MessageComponentInteraction');
|
||||
exports.MessageContextMenuCommandInteraction = require('./structures/MessageContextMenuCommandInteraction');
|
||||
@@ -121,7 +118,6 @@ exports.MessageEmbed = require('./structures/MessageEmbed');
|
||||
exports.MessageMentions = require('./structures/MessageMentions');
|
||||
exports.MessagePayload = require('./structures/MessagePayload');
|
||||
exports.MessageReaction = require('./structures/MessageReaction');
|
||||
exports.MessageSelectMenu = require('./structures/MessageSelectMenu');
|
||||
exports.NewsChannel = require('./structures/NewsChannel');
|
||||
exports.OAuth2Guild = require('./structures/OAuth2Guild');
|
||||
exports.PartialGroupDMChannel = require('./structures/PartialGroupDMChannel');
|
||||
@@ -180,3 +176,7 @@ exports.StageInstancePrivacyLevel = require('discord-api-types/v9').StageInstanc
|
||||
exports.StickerType = require('discord-api-types/v9').StickerType;
|
||||
exports.StickerFormatType = require('discord-api-types/v9').StickerFormatType;
|
||||
exports.WebhookType = require('discord-api-types/v9').WebhookType;
|
||||
exports.ActionRow = require('@discordjs/builders').ActionRow;
|
||||
exports.ButtonComponent = require('@discordjs/builders').ButtonComponent;
|
||||
exports.SelectMenuComponent = require('@discordjs/builders').SelectMenuComponent;
|
||||
exports.SelectMenuOption = require('@discordjs/builders').SelectMenuOption;
|
||||
|
||||
@@ -1,104 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
const { ComponentType } = require('discord-api-types/v9');
|
||||
const { TypeError } = require('../errors');
|
||||
const { Events } = require('../util/Constants');
|
||||
|
||||
/**
|
||||
* Represents an interactive component of a Message. It should not be necessary to construct this directly.
|
||||
* See {@link MessageComponent}
|
||||
*/
|
||||
class BaseMessageComponent {
|
||||
/**
|
||||
* Options for a BaseMessageComponent
|
||||
* @typedef {Object} BaseMessageComponentOptions
|
||||
* @property {MessageComponentTypeResolvable} type The type of this component
|
||||
*/
|
||||
|
||||
/**
|
||||
* Data that can be resolved into options for a MessageComponent. This can be:
|
||||
* * MessageActionRowOptions
|
||||
* * MessageButtonOptions
|
||||
* * MessageSelectMenuOptions
|
||||
* @typedef {MessageActionRowOptions|MessageButtonOptions|MessageSelectMenuOptions} MessageComponentOptions
|
||||
*/
|
||||
|
||||
/**
|
||||
* Components that can be sent in a message. These can be:
|
||||
* * MessageActionRow
|
||||
* * MessageButton
|
||||
* * MessageSelectMenu
|
||||
* @typedef {MessageActionRow|MessageButton|MessageSelectMenu} MessageComponent
|
||||
* @see {@link https://discord.com/developers/docs/interactions/message-components#component-object-component-types}
|
||||
*/
|
||||
|
||||
/**
|
||||
* Data that can be resolved to a MessageComponentType. This can be:
|
||||
* * MessageComponentType
|
||||
* * string
|
||||
* * number
|
||||
* @typedef {string|number|MessageComponentType} MessageComponentTypeResolvable
|
||||
*/
|
||||
|
||||
/**
|
||||
* @param {BaseMessageComponent|BaseMessageComponentOptions} [data={}] The options for this component
|
||||
*/
|
||||
constructor(data) {
|
||||
/**
|
||||
* The type of this component
|
||||
* @type {?MessageComponentType}
|
||||
*/
|
||||
this.type = 'type' in data ? BaseMessageComponent.resolveType(data.type) : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a MessageComponent based on the type of the incoming data
|
||||
* @param {MessageComponentOptions} data Data for a MessageComponent
|
||||
* @param {Client|WebhookClient} [client] Client constructing this component
|
||||
* @returns {?MessageComponent}
|
||||
* @private
|
||||
*/
|
||||
static create(data, client) {
|
||||
let component;
|
||||
let type = data.type;
|
||||
|
||||
if (typeof type === 'string') type = ComponentType[type];
|
||||
|
||||
switch (type) {
|
||||
case ComponentType.ActionRow: {
|
||||
const MessageActionRow = require('./MessageActionRow');
|
||||
component = data instanceof MessageActionRow ? data : new MessageActionRow(data, client);
|
||||
break;
|
||||
}
|
||||
case ComponentType.Button: {
|
||||
const MessageButton = require('./MessageButton');
|
||||
component = data instanceof MessageButton ? data : new MessageButton(data);
|
||||
break;
|
||||
}
|
||||
case ComponentType.SelectMenu: {
|
||||
const MessageSelectMenu = require('./MessageSelectMenu');
|
||||
component = data instanceof MessageSelectMenu ? data : new MessageSelectMenu(data);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
if (client) {
|
||||
client.emit(Events.DEBUG, `[BaseMessageComponent] Received component with unknown type: ${data.type}`);
|
||||
} else {
|
||||
throw new TypeError('INVALID_TYPE', 'data.type', 'valid MessageComponentType');
|
||||
}
|
||||
}
|
||||
return component;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolves the type of a MessageComponent
|
||||
* @param {MessageComponentTypeResolvable} type The type to resolve
|
||||
* @returns {MessageComponentType}
|
||||
* @private
|
||||
*/
|
||||
static resolveType(type) {
|
||||
return typeof type === 'string' ? type : ComponentType[type];
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = BaseMessageComponent;
|
||||
@@ -1,10 +1,10 @@
|
||||
'use strict';
|
||||
|
||||
const { createComponent } = require('@discordjs/builders');
|
||||
const { Collection } = require('@discordjs/collection');
|
||||
const { DiscordSnowflake } = require('@sapphire/snowflake');
|
||||
const { MessageType, InteractionType } = require('discord-api-types/v9');
|
||||
const Base = require('./Base');
|
||||
const BaseMessageComponent = require('./BaseMessageComponent');
|
||||
const ClientApplication = require('./ClientApplication');
|
||||
const InteractionCollector = require('./InteractionCollector');
|
||||
const MessageAttachment = require('./MessageAttachment');
|
||||
@@ -138,9 +138,9 @@ class Message extends Base {
|
||||
if ('components' in data) {
|
||||
/**
|
||||
* A list of MessageActionRows in the message
|
||||
* @type {MessageActionRow[]}
|
||||
* @type {ActionRow[]}
|
||||
*/
|
||||
this.components = data.components.map(c => BaseMessageComponent.create(c, this.client));
|
||||
this.components = data.components.map(c => createComponent(c));
|
||||
} else {
|
||||
this.components = this.components?.slice() ?? [];
|
||||
}
|
||||
|
||||
@@ -1,101 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
const { ComponentType } = require('discord-api-types/v9');
|
||||
const BaseMessageComponent = require('./BaseMessageComponent');
|
||||
|
||||
/**
|
||||
* Represents an action row containing message components.
|
||||
* @extends {BaseMessageComponent}
|
||||
*/
|
||||
class MessageActionRow extends BaseMessageComponent {
|
||||
/**
|
||||
* Components that can be placed in an action row
|
||||
* * MessageButton
|
||||
* * MessageSelectMenu
|
||||
* @typedef {MessageButton|MessageSelectMenu} MessageActionRowComponent
|
||||
*/
|
||||
|
||||
/**
|
||||
* Options for components that can be placed in an action row
|
||||
* * MessageButtonOptions
|
||||
* * MessageSelectMenuOptions
|
||||
* @typedef {MessageButtonOptions|MessageSelectMenuOptions} MessageActionRowComponentOptions
|
||||
*/
|
||||
|
||||
/**
|
||||
* Data that can be resolved into components that can be placed in an action row
|
||||
* * MessageActionRowComponent
|
||||
* * MessageActionRowComponentOptions
|
||||
* @typedef {MessageActionRowComponent|MessageActionRowComponentOptions} MessageActionRowComponentResolvable
|
||||
*/
|
||||
|
||||
/**
|
||||
* @typedef {BaseMessageComponentOptions} MessageActionRowOptions
|
||||
* @property {MessageActionRowComponentResolvable[]} [components]
|
||||
* The components to place in this action row
|
||||
*/
|
||||
|
||||
/**
|
||||
* @param {MessageActionRow|MessageActionRowOptions} [data={}] MessageActionRow to clone or raw data
|
||||
* @param {Client} [client] The client constructing this MessageActionRow, if provided
|
||||
*/
|
||||
constructor(data = {}, client = null) {
|
||||
super({ type: 'ACTION_ROW' });
|
||||
|
||||
/**
|
||||
* The components in this action row
|
||||
* @type {MessageActionRowComponent[]}
|
||||
*/
|
||||
this.components = data.components?.map(c => BaseMessageComponent.create(c, client)) ?? [];
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds components to the action row.
|
||||
* @param {...MessageActionRowComponentResolvable[]} components The components to add
|
||||
* @returns {MessageActionRow}
|
||||
*/
|
||||
addComponents(...components) {
|
||||
this.components.push(...components.flat(Infinity).map(c => BaseMessageComponent.create(c)));
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the components of the action row.
|
||||
* @param {...MessageActionRowComponentResolvable[]} components The components to set
|
||||
* @returns {MessageActionRow}
|
||||
*/
|
||||
setComponents(...components) {
|
||||
this.spliceComponents(0, this.components.length, components);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes, replaces, and inserts components in the action row.
|
||||
* @param {number} index The index to start at
|
||||
* @param {number} deleteCount The number of components to remove
|
||||
* @param {...MessageActionRowComponentResolvable[]} [components] The replacing components
|
||||
* @returns {MessageActionRow}
|
||||
*/
|
||||
spliceComponents(index, deleteCount, ...components) {
|
||||
this.components.splice(index, deleteCount, ...components.flat(Infinity).map(c => BaseMessageComponent.create(c)));
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Transforms the action row to a plain object.
|
||||
* @returns {APIMessageComponent} The raw data of this action row
|
||||
*/
|
||||
toJSON() {
|
||||
return {
|
||||
components: this.components.map(c => c.toJSON()),
|
||||
type: ComponentType[this.type],
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = MessageActionRow;
|
||||
|
||||
/**
|
||||
* @external APIMessageComponent
|
||||
* @see {@link https://discord.com/developers/docs/interactions/message-components#component-object}
|
||||
*/
|
||||
@@ -1,165 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
const { ButtonStyle, ComponentType } = require('discord-api-types/v9');
|
||||
const BaseMessageComponent = require('./BaseMessageComponent');
|
||||
const { RangeError } = require('../errors');
|
||||
const Util = require('../util/Util');
|
||||
|
||||
/**
|
||||
* Represents a button message component.
|
||||
* @extends {BaseMessageComponent}
|
||||
*/
|
||||
class MessageButton extends BaseMessageComponent {
|
||||
/**
|
||||
* @typedef {BaseMessageComponentOptions} MessageButtonOptions
|
||||
* @property {string} [label] The text to be displayed on this button
|
||||
* @property {string} [customId] A unique string to be sent in the interaction when clicked
|
||||
* @property {MessageButtonStyleResolvable} [style] The style of this button
|
||||
* @property {EmojiIdentifierResolvable} [emoji] The emoji to be displayed to the left of the text
|
||||
* @property {string} [url] Optional URL for link-style buttons
|
||||
* @property {boolean} [disabled=false] Disables the button to prevent interactions
|
||||
*/
|
||||
|
||||
/**
|
||||
* @param {MessageButton|MessageButtonOptions} [data={}] MessageButton to clone or raw data
|
||||
*/
|
||||
constructor(data = {}) {
|
||||
super({ type: 'BUTTON' });
|
||||
|
||||
this.setup(data);
|
||||
}
|
||||
|
||||
setup(data) {
|
||||
/**
|
||||
* The text to be displayed on this button
|
||||
* @type {?string}
|
||||
*/
|
||||
this.label = data.label ?? null;
|
||||
|
||||
/**
|
||||
* A unique string to be sent in the interaction when clicked
|
||||
* @type {?string}
|
||||
*/
|
||||
this.customId = data.custom_id ?? data.customId ?? null;
|
||||
|
||||
/**
|
||||
* The style of this button
|
||||
* @type {?MessageButtonStyle}
|
||||
*/
|
||||
this.style = data.style ? MessageButton.resolveStyle(data.style) : null;
|
||||
|
||||
/**
|
||||
* Emoji for this button
|
||||
* @type {?RawEmoji}
|
||||
*/
|
||||
this.emoji = data.emoji ? Util.resolvePartialEmoji(data.emoji) : null;
|
||||
|
||||
/**
|
||||
* The URL this button links to, if it is a Link style button
|
||||
* @type {?string}
|
||||
*/
|
||||
this.url = data.url ?? null;
|
||||
|
||||
/**
|
||||
* Whether this button is currently disabled
|
||||
* @type {boolean}
|
||||
*/
|
||||
this.disabled = data.disabled ?? false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the custom id for this button
|
||||
* @param {string} customId A unique string to be sent in the interaction when clicked
|
||||
* @returns {MessageButton}
|
||||
*/
|
||||
setCustomId(customId) {
|
||||
this.customId = Util.verifyString(customId, RangeError, 'BUTTON_CUSTOM_ID');
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the interactive status of the button
|
||||
* @param {boolean} [disabled=true] Whether this button should be disabled
|
||||
* @returns {MessageButton}
|
||||
*/
|
||||
setDisabled(disabled = true) {
|
||||
this.disabled = disabled;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the emoji of this button
|
||||
* @param {EmojiIdentifierResolvable} emoji The emoji to be displayed on this button
|
||||
* @returns {MessageButton}
|
||||
*/
|
||||
setEmoji(emoji) {
|
||||
this.emoji = Util.resolvePartialEmoji(emoji);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the label of this button
|
||||
* @param {string} label The text to be displayed on this button
|
||||
* @returns {MessageButton}
|
||||
*/
|
||||
setLabel(label) {
|
||||
this.label = Util.verifyString(label, RangeError, 'BUTTON_LABEL');
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the style of this button
|
||||
* @param {MessageButtonStyleResolvable} style The style of this button
|
||||
* @returns {MessageButton}
|
||||
*/
|
||||
setStyle(style) {
|
||||
this.style = MessageButton.resolveStyle(style);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the URL of this button.
|
||||
* <info>MessageButton#style must be LINK when setting a URL</info>
|
||||
* @param {string} url The URL of this button
|
||||
* @returns {MessageButton}
|
||||
*/
|
||||
setURL(url) {
|
||||
this.url = Util.verifyString(url, RangeError, 'BUTTON_URL');
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Transforms the button to a plain object.
|
||||
* @returns {APIMessageButton} The raw data of this button
|
||||
*/
|
||||
toJSON() {
|
||||
return {
|
||||
custom_id: this.customId,
|
||||
disabled: this.disabled,
|
||||
emoji: this.emoji,
|
||||
label: this.label,
|
||||
style: ButtonStyle[this.style],
|
||||
type: ComponentType[this.type],
|
||||
url: this.url,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Data that can be resolved to a MessageButtonStyle. This can be
|
||||
* * MessageButtonStyle
|
||||
* * number
|
||||
* @typedef {number|MessageButtonStyle} MessageButtonStyleResolvable
|
||||
*/
|
||||
|
||||
/**
|
||||
* Resolves the style of a button
|
||||
* @param {MessageButtonStyleResolvable} style The style to resolve
|
||||
* @returns {MessageButtonStyle}
|
||||
* @private
|
||||
*/
|
||||
static resolveStyle(style) {
|
||||
return typeof style === 'string' ? style : ButtonStyle[style];
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = MessageButton;
|
||||
@@ -1,7 +1,7 @@
|
||||
'use strict';
|
||||
|
||||
const { Buffer } = require('node:buffer');
|
||||
const BaseMessageComponent = require('./BaseMessageComponent');
|
||||
const { createComponent } = require('@discordjs/builders');
|
||||
const MessageEmbed = require('./MessageEmbed');
|
||||
const { RangeError } = require('../errors');
|
||||
const DataResolver = require('../util/DataResolver');
|
||||
@@ -138,7 +138,7 @@ class MessagePayload {
|
||||
}
|
||||
}
|
||||
|
||||
const components = this.options.components?.map(c => BaseMessageComponent.create(c).toJSON());
|
||||
const components = this.options.components?.map(c => createComponent(c).toJSON());
|
||||
|
||||
let username;
|
||||
let avatarURL;
|
||||
|
||||
@@ -1,212 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
const { ComponentType } = require('discord-api-types/v9');
|
||||
const BaseMessageComponent = require('./BaseMessageComponent');
|
||||
const Util = require('../util/Util');
|
||||
|
||||
/**
|
||||
* Represents a select menu message component
|
||||
* @extends {BaseMessageComponent}
|
||||
*/
|
||||
class MessageSelectMenu extends BaseMessageComponent {
|
||||
/**
|
||||
* @typedef {BaseMessageComponentOptions} MessageSelectMenuOptions
|
||||
* @property {string} [customId] A unique string to be sent in the interaction when clicked
|
||||
* @property {string} [placeholder] Custom placeholder text to display when nothing is selected
|
||||
* @property {number} [minValues] The minimum number of selections required
|
||||
* @property {number} [maxValues] The maximum number of selections allowed
|
||||
* @property {MessageSelectOption[]} [options] Options for the select menu
|
||||
* @property {boolean} [disabled=false] Disables the select menu to prevent interactions
|
||||
*/
|
||||
|
||||
/**
|
||||
* @typedef {Object} MessageSelectOption
|
||||
* @property {string} label The text to be displayed on this option
|
||||
* @property {string} value The value to be sent for this option
|
||||
* @property {?string} description Optional description to show for this option
|
||||
* @property {?RawEmoji} emoji Emoji to display for this option
|
||||
* @property {boolean} default Render this option as the default selection
|
||||
*/
|
||||
|
||||
/**
|
||||
* @typedef {Object} MessageSelectOptionData
|
||||
* @property {string} label The text to be displayed on this option
|
||||
* @property {string} value The value to be sent for this option
|
||||
* @property {string} [description] Optional description to show for this option
|
||||
* @property {EmojiIdentifierResolvable} [emoji] Emoji to display for this option
|
||||
* @property {boolean} [default] Render this option as the default selection
|
||||
*/
|
||||
|
||||
/**
|
||||
* @param {MessageSelectMenu|MessageSelectMenuOptions} [data={}] MessageSelectMenu to clone or raw data
|
||||
*/
|
||||
constructor(data = {}) {
|
||||
super({ type: 'SELECT_MENU' });
|
||||
|
||||
this.setup(data);
|
||||
}
|
||||
|
||||
setup(data) {
|
||||
/**
|
||||
* A unique string to be sent in the interaction when clicked
|
||||
* @type {?string}
|
||||
*/
|
||||
this.customId = data.custom_id ?? data.customId ?? null;
|
||||
|
||||
/**
|
||||
* Custom placeholder text to display when nothing is selected
|
||||
* @type {?string}
|
||||
*/
|
||||
this.placeholder = data.placeholder ?? null;
|
||||
|
||||
/**
|
||||
* The minimum number of selections required
|
||||
* @type {?number}
|
||||
*/
|
||||
this.minValues = data.min_values ?? data.minValues ?? null;
|
||||
|
||||
/**
|
||||
* The maximum number of selections allowed
|
||||
* @type {?number}
|
||||
*/
|
||||
this.maxValues = data.max_values ?? data.maxValues ?? null;
|
||||
|
||||
/**
|
||||
* Options for the select menu
|
||||
* @type {MessageSelectOption[]}
|
||||
*/
|
||||
this.options = this.constructor.normalizeOptions(data.options ?? []);
|
||||
|
||||
/**
|
||||
* Whether this select menu is currently disabled
|
||||
* @type {boolean}
|
||||
*/
|
||||
this.disabled = data.disabled ?? false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the custom id of this select menu
|
||||
* @param {string} customId A unique string to be sent in the interaction when clicked
|
||||
* @returns {MessageSelectMenu}
|
||||
*/
|
||||
setCustomId(customId) {
|
||||
this.customId = Util.verifyString(customId, RangeError, 'SELECT_MENU_CUSTOM_ID');
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the interactive status of the select menu
|
||||
* @param {boolean} [disabled=true] Whether this select menu should be disabled
|
||||
* @returns {MessageSelectMenu}
|
||||
*/
|
||||
setDisabled(disabled = true) {
|
||||
this.disabled = disabled;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the maximum number of selections allowed for this select menu
|
||||
* @param {number} maxValues Number of selections to be allowed
|
||||
* @returns {MessageSelectMenu}
|
||||
*/
|
||||
setMaxValues(maxValues) {
|
||||
this.maxValues = maxValues;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the minimum number of selections required for this select menu
|
||||
* <info>This will default the maxValues to the number of options, unless manually set</info>
|
||||
* @param {number} minValues Number of selections to be required
|
||||
* @returns {MessageSelectMenu}
|
||||
*/
|
||||
setMinValues(minValues) {
|
||||
this.minValues = minValues;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the placeholder of this select menu
|
||||
* @param {string} placeholder Custom placeholder text to display when nothing is selected
|
||||
* @returns {MessageSelectMenu}
|
||||
*/
|
||||
setPlaceholder(placeholder) {
|
||||
this.placeholder = Util.verifyString(placeholder, RangeError, 'SELECT_MENU_PLACEHOLDER');
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds options to the select menu.
|
||||
* @param {...MessageSelectOptionData|MessageSelectOptionData[]} options The options to add
|
||||
* @returns {MessageSelectMenu}
|
||||
*/
|
||||
addOptions(...options) {
|
||||
this.options.push(...this.constructor.normalizeOptions(options));
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the options of the select menu.
|
||||
* @param {...MessageSelectOptionData|MessageSelectOptionData[]} options The options to set
|
||||
* @returns {MessageSelectMenu}
|
||||
*/
|
||||
setOptions(...options) {
|
||||
this.spliceOptions(0, this.options.length, options);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes, replaces, and inserts options in the select menu.
|
||||
* @param {number} index The index to start at
|
||||
* @param {number} deleteCount The number of options to remove
|
||||
* @param {...MessageSelectOptionData|MessageSelectOptionData[]} [options] The replacing option objects
|
||||
* @returns {MessageSelectMenu}
|
||||
*/
|
||||
spliceOptions(index, deleteCount, ...options) {
|
||||
this.options.splice(index, deleteCount, ...this.constructor.normalizeOptions(...options));
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Transforms the select menu into a plain object
|
||||
* @returns {APIMessageSelectMenu} The raw data of this select menu
|
||||
*/
|
||||
toJSON() {
|
||||
return {
|
||||
custom_id: this.customId,
|
||||
disabled: this.disabled,
|
||||
placeholder: this.placeholder,
|
||||
min_values: this.minValues,
|
||||
max_values: this.maxValues ?? (this.minValues ? this.options.length : undefined),
|
||||
options: this.options,
|
||||
type: typeof this.type === 'string' ? ComponentType[this.type] : this.type,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Normalizes option input and resolves strings and emojis.
|
||||
* @param {MessageSelectOptionData} option The select menu option to normalize
|
||||
* @returns {MessageSelectOption}
|
||||
*/
|
||||
static normalizeOption(option) {
|
||||
let { label, value, description, emoji } = option;
|
||||
|
||||
label = Util.verifyString(label, RangeError, 'SELECT_OPTION_LABEL');
|
||||
value = Util.verifyString(value, RangeError, 'SELECT_OPTION_VALUE');
|
||||
emoji = emoji ? Util.resolvePartialEmoji(emoji) : null;
|
||||
description = description ? Util.verifyString(description, RangeError, 'SELECT_OPTION_DESCRIPTION', true) : null;
|
||||
|
||||
return { label, value, description, emoji, default: option.default ?? false };
|
||||
}
|
||||
|
||||
/**
|
||||
* Normalizes option input and resolves strings and emojis.
|
||||
* @param {...MessageSelectOptionData|MessageSelectOptionData[]} options The select menu options to normalize
|
||||
* @returns {MessageSelectOption[]}
|
||||
*/
|
||||
static normalizeOptions(...options) {
|
||||
return options.flat(Infinity).map(option => this.normalizeOption(option));
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = MessageSelectMenu;
|
||||
120
packages/discord.js/typings/index.d.ts
vendored
120
packages/discord.js/typings/index.d.ts
vendored
@@ -1,8 +1,12 @@
|
||||
import {
|
||||
ActionRow,
|
||||
ActionRowComponent,
|
||||
blockQuote,
|
||||
bold,
|
||||
ButtonComponent,
|
||||
channelMention,
|
||||
codeBlock,
|
||||
Component,
|
||||
formatEmoji,
|
||||
hideLinkEmbed,
|
||||
hyperlink,
|
||||
@@ -11,6 +15,7 @@ import {
|
||||
memberNicknameMention,
|
||||
quote,
|
||||
roleMention,
|
||||
SelectMenuComponent,
|
||||
spoiler,
|
||||
strikethrough,
|
||||
time,
|
||||
@@ -424,13 +429,6 @@ export class BaseGuildVoiceChannel extends GuildChannel {
|
||||
public fetchInvites(cache?: boolean): Promise<Collection<string, Invite>>;
|
||||
}
|
||||
|
||||
export class BaseMessageComponent {
|
||||
protected constructor(data?: BaseMessageComponent | BaseMessageComponentOptions);
|
||||
public type: MessageComponentTypeKey | null;
|
||||
private static create(data: MessageComponentOptions, client?: Client | WebhookClient): MessageComponent | undefined;
|
||||
private static resolveType(type: MessageComponentTypeResolvable): MessageComponentTypeKey;
|
||||
}
|
||||
|
||||
export class BitField<S extends string, N extends number | bigint = number> {
|
||||
public constructor(bits?: BitFieldResolvable<S, N>);
|
||||
public bitfield: N;
|
||||
@@ -454,10 +452,10 @@ export class ButtonInteraction<Cached extends CacheType = CacheType> extends Mes
|
||||
private constructor(client: Client, data: RawMessageButtonInteractionData);
|
||||
public readonly component: CacheTypeReducer<
|
||||
Cached,
|
||||
MessageButton,
|
||||
ButtonComponent,
|
||||
APIButtonComponent,
|
||||
MessageButton | APIButtonComponent,
|
||||
MessageButton | APIButtonComponent
|
||||
ButtonComponent | APIButtonComponent,
|
||||
ButtonComponent | APIButtonComponent
|
||||
>;
|
||||
public componentType: 'Button';
|
||||
public inGuild(): this is ButtonInteraction<'raw' | 'cached'>;
|
||||
@@ -1476,7 +1474,7 @@ export class Message<Cached extends boolean = boolean> extends Base {
|
||||
public readonly channel: If<Cached, GuildTextBasedChannel, TextBasedChannel>;
|
||||
public channelId: Snowflake;
|
||||
public readonly cleanContent: string;
|
||||
public components: MessageActionRow[];
|
||||
public components: ActionRow<ActionRowComponent>[];
|
||||
public content: string;
|
||||
public readonly createdAt: Date;
|
||||
public createdTimestamp: number;
|
||||
@@ -1527,7 +1525,7 @@ export class Message<Cached extends boolean = boolean> extends Base {
|
||||
public react(emoji: EmojiIdentifierResolvable): Promise<MessageReaction>;
|
||||
public removeAttachments(): Promise<Message>;
|
||||
public reply(options: string | MessagePayload | ReplyMessageOptions): Promise<Message>;
|
||||
public resolveComponent(customId: string): MessageActionRowComponent | null;
|
||||
public resolveComponent(customId: string): ActionRowComponent | null;
|
||||
public startThread(options: StartThreadOptions): Promise<ThreadChannel>;
|
||||
public suppressEmbeds(suppress?: boolean): Promise<Message>;
|
||||
public toJSON(): unknown;
|
||||
@@ -1536,24 +1534,6 @@ export class Message<Cached extends boolean = boolean> extends Base {
|
||||
public inGuild(): this is Message<true> & this;
|
||||
}
|
||||
|
||||
export class MessageActionRow extends BaseMessageComponent {
|
||||
public constructor(data?: MessageActionRow | MessageActionRowOptions | APIActionRowComponent);
|
||||
public type: 'ActionRow';
|
||||
public components: MessageActionRowComponent[];
|
||||
public addComponents(
|
||||
...components: MessageActionRowComponentResolvable[] | MessageActionRowComponentResolvable[][]
|
||||
): this;
|
||||
public setComponents(
|
||||
...components: MessageActionRowComponentResolvable[] | MessageActionRowComponentResolvable[][]
|
||||
): this;
|
||||
public spliceComponents(
|
||||
index: number,
|
||||
deleteCount: number,
|
||||
...components: MessageActionRowComponentResolvable[] | MessageActionRowComponentResolvable[][]
|
||||
): this;
|
||||
public toJSON(): APIActionRowComponent;
|
||||
}
|
||||
|
||||
export class MessageAttachment {
|
||||
public constructor(attachment: BufferResolvable | Stream, name?: string, data?: RawMessageAttachmentData);
|
||||
|
||||
@@ -1576,25 +1556,6 @@ export class MessageAttachment {
|
||||
public toJSON(): unknown;
|
||||
}
|
||||
|
||||
export class MessageButton extends BaseMessageComponent {
|
||||
public constructor(data?: MessageButton | MessageButtonOptions | APIButtonComponent);
|
||||
public customId: string | null;
|
||||
public disabled: boolean;
|
||||
public emoji: APIPartialEmoji | null;
|
||||
public label: string | null;
|
||||
public style: ButtonStyleKey | null;
|
||||
public type: 'Button';
|
||||
public url: string | null;
|
||||
public setCustomId(customId: string): this;
|
||||
public setDisabled(disabled?: boolean): this;
|
||||
public setEmoji(emoji: EmojiIdentifierResolvable): this;
|
||||
public setLabel(label: string): this;
|
||||
public setStyle(style: MessageButtonStyleResolvable): this;
|
||||
public setURL(url: string): this;
|
||||
public toJSON(): APIButtonComponent;
|
||||
private static resolveStyle(style: MessageButtonStyleResolvable): ButtonStyleKey;
|
||||
}
|
||||
|
||||
export class MessageCollector extends Collector<Snowflake, Message> {
|
||||
public constructor(channel: TextBasedChannel, options?: MessageCollectorOptions);
|
||||
private _handleChannelDeletion(channel: NonThreadGuildBasedChannel): void;
|
||||
@@ -1613,10 +1574,10 @@ export class MessageComponentInteraction<Cached extends CacheType = CacheType> e
|
||||
protected constructor(client: Client, data: RawMessageComponentInteractionData);
|
||||
public readonly component: CacheTypeReducer<
|
||||
Cached,
|
||||
MessageActionRowComponent,
|
||||
ActionRowComponent,
|
||||
Exclude<APIMessageComponent, APIActionRowComponent>,
|
||||
MessageActionRowComponent | Exclude<APIMessageComponent, APIActionRowComponent>,
|
||||
MessageActionRowComponent | Exclude<APIMessageComponent, APIActionRowComponent>
|
||||
ActionRowComponent | Exclude<APIMessageComponent, APIActionRowComponent>,
|
||||
ActionRowComponent | Exclude<APIMessageComponent, APIActionRowComponent>
|
||||
>;
|
||||
public componentType: Exclude<keyof typeof ComponentType, 'ActionRow'>;
|
||||
public customId: string;
|
||||
@@ -1776,30 +1737,6 @@ export class MessageReaction {
|
||||
public toJSON(): unknown;
|
||||
}
|
||||
|
||||
export class MessageSelectMenu extends BaseMessageComponent {
|
||||
public constructor(data?: MessageSelectMenu | MessageSelectMenuOptions | APISelectMenuComponent);
|
||||
public customId: string | null;
|
||||
public disabled: boolean;
|
||||
public maxValues: number | null;
|
||||
public minValues: number | null;
|
||||
public options: MessageSelectOption[];
|
||||
public placeholder: string | null;
|
||||
public type: 'SelectMenu';
|
||||
public addOptions(...options: MessageSelectOptionData[] | MessageSelectOptionData[][]): this;
|
||||
public setOptions(...options: MessageSelectOptionData[] | MessageSelectOptionData[][]): this;
|
||||
public setCustomId(customId: string): this;
|
||||
public setDisabled(disabled?: boolean): this;
|
||||
public setMaxValues(maxValues: number): this;
|
||||
public setMinValues(minValues: number): this;
|
||||
public setPlaceholder(placeholder: string): this;
|
||||
public spliceOptions(
|
||||
index: number,
|
||||
deleteCount: number,
|
||||
...options: MessageSelectOptionData[] | MessageSelectOptionData[][]
|
||||
): this;
|
||||
public toJSON(): APISelectMenuComponent;
|
||||
}
|
||||
|
||||
export class NewsChannel extends BaseGuildTextChannel {
|
||||
public threads: ThreadManager<AllowedThreadTypeForNewsChannel>;
|
||||
public type: 'GuildNews';
|
||||
@@ -1951,10 +1888,10 @@ export class SelectMenuInteraction<Cached extends CacheType = CacheType> extends
|
||||
public constructor(client: Client, data: RawMessageSelectMenuInteractionData);
|
||||
public readonly component: CacheTypeReducer<
|
||||
Cached,
|
||||
MessageSelectMenu,
|
||||
SelectMenuComponent,
|
||||
APISelectMenuComponent,
|
||||
MessageSelectMenu | APISelectMenuComponent,
|
||||
MessageSelectMenu | APISelectMenuComponent
|
||||
SelectMenuComponent | APISelectMenuComponent,
|
||||
SelectMenuComponent | APISelectMenuComponent
|
||||
>;
|
||||
public componentType: 'SelectMenu';
|
||||
public values: string[];
|
||||
@@ -4696,16 +4633,14 @@ export type MemberMention = UserMention | `<@!${Snowflake}>`;
|
||||
|
||||
export type TeamMemberMembershipStateKey = keyof typeof TeamMemberMembershipState;
|
||||
|
||||
export type MessageActionRowComponent = MessageButton | MessageSelectMenu;
|
||||
|
||||
export type MessageActionRowComponentOptions =
|
||||
export type ActionRowComponentOptions =
|
||||
| (Required<BaseMessageComponentOptions> & MessageButtonOptions)
|
||||
| (Required<BaseMessageComponentOptions> & MessageSelectMenuOptions);
|
||||
|
||||
export type MessageActionRowComponentResolvable = MessageActionRowComponent | MessageActionRowComponentOptions;
|
||||
export type MessageActionRowComponentResolvable = ActionRowComponent | ActionRowComponentOptions;
|
||||
|
||||
export interface MessageActionRowOptions extends BaseMessageComponentOptions {
|
||||
components: MessageActionRowComponentResolvable[];
|
||||
export interface ActionRowOptions extends BaseMessageComponentOptions {
|
||||
components: ActionRowComponent[];
|
||||
}
|
||||
|
||||
export interface MessageActivity {
|
||||
@@ -4740,7 +4675,7 @@ export interface MessageCollectorOptions extends CollectorOptions<[Message]> {
|
||||
maxProcessed?: number;
|
||||
}
|
||||
|
||||
export type MessageComponent = BaseMessageComponent | MessageActionRow | MessageButton | MessageSelectMenu;
|
||||
export type MessageComponent = Component | ActionRow<ActionRowComponent> | ButtonComponent | SelectMenuComponent;
|
||||
|
||||
export type MessageComponentCollectorOptions<T extends MessageComponentInteraction> = Omit<
|
||||
InteractionCollectorOptions<T>,
|
||||
@@ -4754,7 +4689,7 @@ export type MessageChannelComponentCollectorOptions<T extends MessageComponentIn
|
||||
|
||||
export type MessageComponentOptions =
|
||||
| BaseMessageComponentOptions
|
||||
| MessageActionRowOptions
|
||||
| ActionRowOptions
|
||||
| MessageButtonOptions
|
||||
| MessageSelectMenuOptions;
|
||||
|
||||
@@ -4769,7 +4704,7 @@ export interface MessageEditOptions {
|
||||
files?: (FileOptions | BufferResolvable | Stream | MessageAttachment)[];
|
||||
flags?: BitFieldResolvable<MessageFlagsString, number>;
|
||||
allowedMentions?: MessageMentionOptions;
|
||||
components?: (MessageActionRow | (Required<BaseMessageComponentOptions> & MessageActionRowOptions))[];
|
||||
components?: (ActionRow<ActionRowComponent> | (Required<BaseMessageComponentOptions> & ActionRowOptions))[];
|
||||
}
|
||||
|
||||
export interface MessageEmbedAuthor {
|
||||
@@ -4868,7 +4803,7 @@ export interface MessageOptions {
|
||||
nonce?: string | number;
|
||||
content?: string | null;
|
||||
embeds?: (MessageEmbed | MessageEmbedOptions | APIEmbed)[];
|
||||
components?: (MessageActionRow | (Required<BaseMessageComponentOptions> & MessageActionRowOptions))[];
|
||||
components?: (ActionRow<ActionRowComponent> | (Required<BaseMessageComponentOptions> & ActionRowOptions))[];
|
||||
allowedMentions?: MessageMentionOptions;
|
||||
files?: (FileOptions | BufferResolvable | Stream | MessageAttachment)[];
|
||||
reply?: ReplyOptions;
|
||||
@@ -5545,3 +5480,10 @@ export {
|
||||
StickerFormatType,
|
||||
WebhookType,
|
||||
} from 'discord-api-types/v9';
|
||||
export {
|
||||
ActionRow,
|
||||
ButtonComponent,
|
||||
SelectMenuComponent,
|
||||
SelectMenuOption,
|
||||
ActionRowComponent,
|
||||
} from '@discordjs/builders';
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import type { ChildProcess } from 'child_process';
|
||||
import type {
|
||||
import {
|
||||
APIInteractionGuildMember,
|
||||
APIMessage,
|
||||
APIPartialChannel,
|
||||
@@ -10,6 +10,7 @@ import type {
|
||||
APIButtonComponent,
|
||||
APISelectMenuComponent,
|
||||
ApplicationCommandOptionType,
|
||||
ComponentType,
|
||||
} from 'discord-api-types/v9';
|
||||
import { AuditLogEvent } from 'discord-api-types/v9';
|
||||
import {
|
||||
@@ -47,9 +48,7 @@ import {
|
||||
Interaction,
|
||||
InteractionCollector,
|
||||
Message,
|
||||
MessageActionRow,
|
||||
MessageAttachment,
|
||||
MessageButton,
|
||||
MessageCollector,
|
||||
MessageComponentInteraction,
|
||||
MessageEmbed,
|
||||
@@ -88,9 +87,11 @@ import {
|
||||
GuildAuditLogsEntry,
|
||||
GuildAuditLogs,
|
||||
StageInstance,
|
||||
MessageActionRowComponent,
|
||||
MessageSelectMenu,
|
||||
PartialDMChannel,
|
||||
ActionRow,
|
||||
ButtonComponent,
|
||||
SelectMenuComponent,
|
||||
ActionRowComponent,
|
||||
} from '.';
|
||||
import { expectAssignable, expectDeprecated, expectNotAssignable, expectNotType, expectType } from 'tsd';
|
||||
|
||||
@@ -668,11 +669,11 @@ client.on('interactionCreate', async interaction => {
|
||||
|
||||
if (!interaction.isCommand()) return;
|
||||
|
||||
void new MessageActionRow();
|
||||
void new ActionRow<ActionRowComponent>();
|
||||
|
||||
const button = new MessageButton();
|
||||
const button = new ButtonComponent();
|
||||
|
||||
const actionRow = new MessageActionRow({ components: [button] });
|
||||
const actionRow = new ActionRow({ type: ComponentType.ActionRow, components: [button] });
|
||||
|
||||
await interaction.reply({ content: 'Hi!', components: [actionRow] });
|
||||
|
||||
@@ -993,11 +994,11 @@ client.on('interactionCreate', async interaction => {
|
||||
|
||||
if (interaction.isButton()) {
|
||||
expectType<ButtonInteraction>(interaction);
|
||||
expectType<MessageButton | APIButtonComponent>(interaction.component);
|
||||
expectType<ButtonComponent | APIButtonComponent>(interaction.component);
|
||||
expectType<Message | APIMessage>(interaction.message);
|
||||
if (interaction.inCachedGuild()) {
|
||||
expectAssignable<ButtonInteraction>(interaction);
|
||||
expectType<MessageButton>(interaction.component);
|
||||
expectType<ButtonComponent>(interaction.component);
|
||||
expectType<Message<true>>(interaction.message);
|
||||
expectType<Guild>(interaction.guild);
|
||||
expectAssignable<Promise<Message>>(interaction.reply({ fetchReply: true }));
|
||||
@@ -1009,7 +1010,7 @@ client.on('interactionCreate', async interaction => {
|
||||
expectType<Promise<APIMessage>>(interaction.reply({ fetchReply: true }));
|
||||
} else if (interaction.inGuild()) {
|
||||
expectAssignable<ButtonInteraction>(interaction);
|
||||
expectType<MessageButton | APIButtonComponent>(interaction.component);
|
||||
expectType<ButtonComponent | APIButtonComponent>(interaction.component);
|
||||
expectType<Message | APIMessage>(interaction.message);
|
||||
expectAssignable<Guild | null>(interaction.guild);
|
||||
expectType<Promise<APIMessage | Message>>(interaction.reply({ fetchReply: true }));
|
||||
@@ -1018,11 +1019,11 @@ client.on('interactionCreate', async interaction => {
|
||||
|
||||
if (interaction.isMessageComponent()) {
|
||||
expectType<MessageComponentInteraction>(interaction);
|
||||
expectType<MessageActionRowComponent | APIButtonComponent | APISelectMenuComponent>(interaction.component);
|
||||
expectType<ActionRowComponent | APIButtonComponent | APISelectMenuComponent>(interaction.component);
|
||||
expectType<Message | APIMessage>(interaction.message);
|
||||
if (interaction.inCachedGuild()) {
|
||||
expectAssignable<MessageComponentInteraction>(interaction);
|
||||
expectType<MessageActionRowComponent>(interaction.component);
|
||||
expectType<ActionRowComponent>(interaction.component);
|
||||
expectType<Message<true>>(interaction.message);
|
||||
expectType<Guild>(interaction.guild);
|
||||
expectAssignable<Promise<Message>>(interaction.reply({ fetchReply: true }));
|
||||
@@ -1034,7 +1035,7 @@ client.on('interactionCreate', async interaction => {
|
||||
expectType<Promise<APIMessage>>(interaction.reply({ fetchReply: true }));
|
||||
} else if (interaction.inGuild()) {
|
||||
expectAssignable<MessageComponentInteraction>(interaction);
|
||||
expectType<MessageActionRowComponent | APIButtonComponent | APISelectMenuComponent>(interaction.component);
|
||||
expectType<ActionRowComponent | APIButtonComponent | APISelectMenuComponent>(interaction.component);
|
||||
expectType<Message | APIMessage>(interaction.message);
|
||||
expectType<Guild | null>(interaction.guild);
|
||||
expectType<Promise<APIMessage | Message>>(interaction.reply({ fetchReply: true }));
|
||||
@@ -1043,11 +1044,11 @@ client.on('interactionCreate', async interaction => {
|
||||
|
||||
if (interaction.isSelectMenu()) {
|
||||
expectType<SelectMenuInteraction>(interaction);
|
||||
expectType<MessageSelectMenu | APISelectMenuComponent>(interaction.component);
|
||||
expectType<SelectMenuComponent | APISelectMenuComponent>(interaction.component);
|
||||
expectType<Message | APIMessage>(interaction.message);
|
||||
if (interaction.inCachedGuild()) {
|
||||
expectAssignable<SelectMenuInteraction>(interaction);
|
||||
expectType<MessageSelectMenu>(interaction.component);
|
||||
expectType<SelectMenuComponent>(interaction.component);
|
||||
expectType<Message<true>>(interaction.message);
|
||||
expectType<Guild>(interaction.guild);
|
||||
expectType<Promise<Message<true>>>(interaction.reply({ fetchReply: true }));
|
||||
@@ -1059,7 +1060,7 @@ client.on('interactionCreate', async interaction => {
|
||||
expectType<Promise<APIMessage>>(interaction.reply({ fetchReply: true }));
|
||||
} else if (interaction.inGuild()) {
|
||||
expectAssignable<SelectMenuInteraction>(interaction);
|
||||
expectType<MessageSelectMenu | APISelectMenuComponent>(interaction.component);
|
||||
expectType<SelectMenuComponent | APISelectMenuComponent>(interaction.component);
|
||||
expectType<Message | APIMessage>(interaction.message);
|
||||
expectType<Guild | null>(interaction.guild);
|
||||
expectType<Promise<Message | APIMessage>>(interaction.reply({ fetchReply: true }));
|
||||
|
||||
Reference in New Issue
Block a user