mirror of
https://github.com/discordjs/discord.js.git
synced 2026-03-10 00:23:30 +01:00
feat(MessageSelectMenu): droppybois (#5692)
Co-authored-by: Antonio Román <kyradiscord@gmail.com>
This commit is contained in:
@@ -21,6 +21,9 @@ class InteractionCreateAction extends Action {
|
||||
case MessageComponentTypes.BUTTON:
|
||||
InteractionType = Structures.get('ButtonInteraction');
|
||||
break;
|
||||
case MessageComponentTypes.SELECT_MENU:
|
||||
InteractionType = Structures.get('SelectMenuInteraction');
|
||||
break;
|
||||
default:
|
||||
client.emit(
|
||||
Events.DEBUG,
|
||||
|
||||
@@ -50,6 +50,12 @@ const Messages = {
|
||||
BUTTON_URL: 'MessageButton url must be a string',
|
||||
BUTTON_CUSTOM_ID: 'MessageButton customID must be a string',
|
||||
|
||||
SELECT_MENU_CUSTOM_ID: 'MessageSelectMenu customID must be a string',
|
||||
SELECT_MENU_PLACEHOLDER: 'MessageSelectMenu placeholder must be a string',
|
||||
SELECT_OPTION_LABEL: 'MessageSelectOption label must be a string',
|
||||
SELECT_OPTION_VALUE: 'MessageSelectOption value must be a string',
|
||||
SELECT_OPTION_DESCRIPTION: 'MessageSelectOption description must be a string',
|
||||
|
||||
INTERACTION_COLLECTOR_ERROR: reason => `Collector received no interactions before ending with reason: ${reason}`,
|
||||
|
||||
FILE_NOT_FOUND: file => `File could not be found: ${file}`,
|
||||
|
||||
@@ -97,6 +97,7 @@ module.exports = {
|
||||
MessageEmbed: require('./structures/MessageEmbed'),
|
||||
MessageMentions: require('./structures/MessageMentions'),
|
||||
MessageReaction: require('./structures/MessageReaction'),
|
||||
MessageSelectMenu: require('./structures/MessageSelectMenu'),
|
||||
NewsChannel: require('./structures/NewsChannel'),
|
||||
OAuth2Guild: require('./structures/OAuth2Guild'),
|
||||
PermissionOverwrites: require('./structures/PermissionOverwrites'),
|
||||
@@ -106,6 +107,7 @@ module.exports = {
|
||||
ReactionEmoji: require('./structures/ReactionEmoji'),
|
||||
RichPresenceAssets: require('./structures/Presence').RichPresenceAssets,
|
||||
Role: require('./structures/Role'),
|
||||
SelectMenuInteraction: require('./structures/SelectMenuInteraction'),
|
||||
Sticker: require('./structures/Sticker'),
|
||||
StoreChannel: require('./structures/StoreChannel'),
|
||||
StageChannel: require('./structures/StageChannel'),
|
||||
|
||||
@@ -18,14 +18,16 @@ class BaseMessageComponent {
|
||||
* Data that can be resolved into options for a MessageComponent. This can be:
|
||||
* * MessageActionRowOptions
|
||||
* * MessageButtonOptions
|
||||
* @typedef {MessageActionRowOptions|MessageButtonOptions} MessageComponentOptions
|
||||
* * MessageSelectMenuOptions
|
||||
* @typedef {MessageActionRowOptions|MessageButtonOptions|MessageSelectMenuOptions} MessageComponentOptions
|
||||
*/
|
||||
|
||||
/**
|
||||
* Components that can be sent in a message. This can be:
|
||||
* * MessageActionRow
|
||||
* * MessageButton
|
||||
* @typedef {MessageActionRow|MessageButton} MessageComponent
|
||||
* * MessageSelectMenu
|
||||
* @typedef {MessageActionRow|MessageButton|MessageSelectMenu} MessageComponent
|
||||
*/
|
||||
|
||||
/**
|
||||
@@ -72,6 +74,11 @@ class BaseMessageComponent {
|
||||
component = new MessageButton(data);
|
||||
break;
|
||||
}
|
||||
case MessageComponentTypes.SELECT_MENU: {
|
||||
const MessageSelectMenu = require('./MessageSelectMenu');
|
||||
component = new MessageSelectMenu(data);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
if (client) {
|
||||
client.emit(Events.DEBUG, `[BaseMessageComponent] Received component with unknown type: ${data.type}`);
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
'use strict';
|
||||
|
||||
const Base = require('./Base');
|
||||
const { InteractionTypes } = require('../util/Constants');
|
||||
const { InteractionTypes, MessageComponentTypes } = require('../util/Constants');
|
||||
const SnowflakeUtil = require('../util/SnowflakeUtil');
|
||||
|
||||
/**
|
||||
@@ -114,7 +114,7 @@ class Interaction extends Base {
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates whether this interaction is a component interaction.
|
||||
* Indicates whether this interaction is a message component interaction.
|
||||
* @returns {boolean}
|
||||
*/
|
||||
isMessageComponent() {
|
||||
@@ -126,7 +126,21 @@ class Interaction extends Base {
|
||||
* @returns {boolean}
|
||||
*/
|
||||
isButton() {
|
||||
return InteractionTypes[this.type] === InteractionTypes.MESSAGE_COMPONENT && this.componentType === 'BUTTON';
|
||||
return (
|
||||
InteractionTypes[this.type] === InteractionTypes.MESSAGE_COMPONENT &&
|
||||
MessageComponentTypes[this.componentType] === MessageComponentTypes.BUTTON
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates whether this interaction is a select menu interaction.
|
||||
* @returns {boolean}
|
||||
*/
|
||||
isSelectMenu() {
|
||||
return (
|
||||
InteractionTypes[this.type] === InteractionTypes.MESSAGE_COMPONENT &&
|
||||
MessageComponentTypes[this.componentType] === MessageComponentTypes.SELECT_MENU
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -11,17 +11,19 @@ class MessageActionRow extends BaseMessageComponent {
|
||||
/**
|
||||
* Components that can be placed in an action row
|
||||
* * MessageButton
|
||||
* @typedef {MessageButton} MessageActionRowComponent
|
||||
* * MessageSelectMenu
|
||||
* @typedef {MessageButton|MessageSelectMenu} MessageActionRowComponent
|
||||
*/
|
||||
|
||||
/**
|
||||
* Options for components that can be placed in an action row
|
||||
* * MessageButtonOptions
|
||||
* @typedef {MessageButtonOptions} MessageActionRowComponentOptions
|
||||
* * MessageSelectMenuOptions
|
||||
* @typedef {MessageButtonOptions|MessageSelectMenuOptions} MessageActionRowComponentOptions
|
||||
*/
|
||||
|
||||
/**
|
||||
* Data that can be resolved into a components that can be placed in an action row
|
||||
* Data that can be resolved into components that can be placed in an action row
|
||||
* * MessageActionRowComponent
|
||||
* * MessageActionRowComponentOptions
|
||||
* @typedef {MessageActionRowComponent|MessageActionRowComponentOptions} MessageActionRowComponentResolvable
|
||||
@@ -61,7 +63,7 @@ class MessageActionRow extends BaseMessageComponent {
|
||||
* @param {number} index The index to start at
|
||||
* @param {number} deleteCount The number of components to remove
|
||||
* @param {...MessageActionRowComponentResolvable[]} [components] The replacing components
|
||||
* @returns {MessageSelectMenu}
|
||||
* @returns {MessageActionRow}
|
||||
*/
|
||||
spliceComponents(index, deleteCount, ...components) {
|
||||
this.components.splice(
|
||||
|
||||
202
src/structures/MessageSelectMenu.js
Normal file
202
src/structures/MessageSelectMenu.js
Normal file
@@ -0,0 +1,202 @@
|
||||
'use strict';
|
||||
|
||||
const BaseMessageComponent = require('./BaseMessageComponent');
|
||||
const { MessageComponentTypes } = require('../util/Constants');
|
||||
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 Whether this select menu should be disabled
|
||||
* @returns {MessageSelectMenu}
|
||||
*/
|
||||
setDisabled(disabled) {
|
||||
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 {...(MessageSelectOption[]|MessageSelectOption[])} options The options to add
|
||||
* @returns {MessageSelectMenu}
|
||||
*/
|
||||
addOptions(...options) {
|
||||
this.options.push(...this.constructor.normalizeOptions(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 {...MessageSelectOption|MessageSelectOption[]} [options] The replacing option objects
|
||||
* @returns {MessageSelectMenu}
|
||||
*/
|
||||
spliceOptions(index, deleteCount, ...options) {
|
||||
this.options.splice(index, deleteCount, ...this.constructor.normalizeOptions(...options));
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Transforms this select menu to a plain object
|
||||
* @returns {Object} 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' ? MessageComponentTypes[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|MessageSelectOption[]} options The select menu options to normalize
|
||||
* @returns {MessageSelectOption[]}
|
||||
*/
|
||||
static normalizeOptions(...options) {
|
||||
return options.flat(Infinity).map(option => this.normalizeOption(option));
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = MessageSelectMenu;
|
||||
21
src/structures/SelectMenuInteraction.js
Normal file
21
src/structures/SelectMenuInteraction.js
Normal file
@@ -0,0 +1,21 @@
|
||||
'use strict';
|
||||
|
||||
const MessageComponentInteraction = require('./MessageComponentInteraction');
|
||||
|
||||
/**
|
||||
* Represents a select menu interaction.
|
||||
* @extends {MessageComponentInteraction}
|
||||
*/
|
||||
class SelectMenuInteraction extends MessageComponentInteraction {
|
||||
constructor(client, data) {
|
||||
super(client, data);
|
||||
|
||||
/**
|
||||
* The values selected, if the component which was interacted with was a select menu
|
||||
* @type {string[]}
|
||||
*/
|
||||
this.values = this.componentType === 'SELECT_MENU' ? data.data.values : null;
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = SelectMenuInteraction;
|
||||
@@ -944,9 +944,10 @@ exports.InteractionResponseTypes = createEnum([
|
||||
* The type of a message component
|
||||
* * ACTION_ROW
|
||||
* * BUTTON
|
||||
* * SELECT_MENU
|
||||
* @typedef {string} MessageComponentType
|
||||
*/
|
||||
exports.MessageComponentTypes = createEnum([null, 'ACTION_ROW', 'BUTTON']);
|
||||
exports.MessageComponentTypes = createEnum([null, 'ACTION_ROW', 'BUTTON', 'SELECT_MENU']);
|
||||
|
||||
/**
|
||||
* The style of a message button
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
* * **`CommandInteraction`**
|
||||
* * **`ButtonInteraction`**
|
||||
* * **`StageInstance`**
|
||||
* * **`SelectMenuInteraction`**
|
||||
* @typedef {string} ExtendableStructure
|
||||
*/
|
||||
|
||||
@@ -118,6 +119,7 @@ const structures = {
|
||||
User: require('../structures/User'),
|
||||
CommandInteraction: require('../structures/CommandInteraction'),
|
||||
ButtonInteraction: require('../structures/ButtonInteraction'),
|
||||
SelectMenuInteraction: require('../structures/SelectMenuInteraction'),
|
||||
StageInstance: require('../structures/StageInstance'),
|
||||
};
|
||||
|
||||
|
||||
70
typings/index.d.ts
vendored
70
typings/index.d.ts
vendored
@@ -82,6 +82,7 @@ declare enum MessageButtonStyles {
|
||||
declare enum MessageComponentTypes {
|
||||
ACTION_ROW = 1,
|
||||
BUTTON = 2,
|
||||
SELECT_MENU = 3,
|
||||
}
|
||||
|
||||
declare enum MFALevels {
|
||||
@@ -1176,6 +1177,7 @@ declare module 'discord.js' {
|
||||
public isButton(): this is ButtonInteraction;
|
||||
public isCommand(): this is CommandInteraction;
|
||||
public isMessageComponent(): this is MessageComponentInteraction;
|
||||
public isSelectMenu(): this is SelectMenuInteraction;
|
||||
}
|
||||
|
||||
export class InteractionWebhook extends PartialWebhookMixin() {
|
||||
@@ -1531,6 +1533,29 @@ declare module 'discord.js' {
|
||||
public toJSON(): unknown;
|
||||
}
|
||||
|
||||
class MessageSelectMenu extends BaseMessageComponent {
|
||||
constructor(data?: MessageSelectMenu | MessageSelectMenuOptions);
|
||||
public customID: string | null;
|
||||
public disabled: boolean;
|
||||
public maxValues: number | null;
|
||||
public minValues: number | null;
|
||||
public options: MessageSelectOption[];
|
||||
public placeholder: string | null;
|
||||
public type: 'SELECT_MENU';
|
||||
public addOptions(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(): unknown;
|
||||
}
|
||||
|
||||
export class NewsChannel extends TextBasedChannel(GuildChannel) {
|
||||
constructor(guild: Guild, data?: unknown);
|
||||
public defaultAutoArchiveDuration?: ThreadAutoArchiveDuration;
|
||||
@@ -1693,6 +1718,11 @@ declare module 'discord.js' {
|
||||
public static comparePositions(role1: Role, role2: Role): number;
|
||||
}
|
||||
|
||||
export class SelectMenuInteraction extends MessageComponentInteraction {
|
||||
public componentType: 'SELECT_MENU';
|
||||
public values: string[] | null;
|
||||
}
|
||||
|
||||
export class Shard extends EventEmitter {
|
||||
constructor(manager: ShardingManager, id: number);
|
||||
private _evals: Map<string, Promise<any>>;
|
||||
@@ -3182,6 +3212,7 @@ declare module 'discord.js' {
|
||||
User: typeof User;
|
||||
CommandInteraction: typeof CommandInteraction;
|
||||
ButtonInteraction: typeof ButtonInteraction;
|
||||
SelectMenuInteraction: typeof SelectMenuInteraction;
|
||||
}
|
||||
|
||||
interface FetchApplicationCommandOptions extends BaseFetchOptions {
|
||||
@@ -3572,9 +3603,9 @@ declare module 'discord.js' {
|
||||
|
||||
type MembershipState = keyof typeof MembershipStates;
|
||||
|
||||
type MessageActionRowComponent = MessageButton;
|
||||
type MessageActionRowComponent = MessageButton | MessageSelectMenu;
|
||||
|
||||
type MessageActionRowComponentOptions = MessageButtonOptions;
|
||||
type MessageActionRowComponentOptions = MessageButtonOptions | MessageSelectMenuOptions;
|
||||
|
||||
type MessageActionRowComponentResolvable = MessageActionRowComponent | MessageActionRowComponentOptions;
|
||||
|
||||
@@ -3587,6 +3618,8 @@ declare module 'discord.js' {
|
||||
type: number;
|
||||
}
|
||||
|
||||
type MessageAdditions = MessageEmbed | MessageAttachment | (MessageEmbed | MessageAttachment)[];
|
||||
|
||||
interface MessageButtonOptions extends BaseMessageComponentOptions {
|
||||
customID?: string;
|
||||
disabled?: boolean;
|
||||
@@ -3605,7 +3638,7 @@ declare module 'discord.js' {
|
||||
maxProcessed?: number;
|
||||
}
|
||||
|
||||
type MessageComponent = BaseMessageComponent | MessageActionRow | MessageButton;
|
||||
type MessageComponent = BaseMessageComponent | MessageActionRow | MessageButton | MessageSelectMenu;
|
||||
|
||||
interface MessageComponentInteractionCollectorOptions extends CollectorOptions {
|
||||
max?: number;
|
||||
@@ -3613,7 +3646,11 @@ declare module 'discord.js' {
|
||||
maxUsers?: number;
|
||||
}
|
||||
|
||||
type MessageComponentOptions = BaseMessageComponentOptions | MessageActionRowOptions | MessageButtonOptions;
|
||||
type MessageComponentOptions =
|
||||
| BaseMessageComponentOptions
|
||||
| MessageActionRowOptions
|
||||
| MessageButtonOptions
|
||||
| MessageSelectMenuOptions;
|
||||
|
||||
type MessageComponentType = keyof typeof MessageComponentTypes;
|
||||
|
||||
@@ -3750,6 +3787,31 @@ declare module 'discord.js' {
|
||||
|
||||
type MessageResolvable = Message | Snowflake;
|
||||
|
||||
interface MessageSelectMenuOptions extends BaseMessageComponentOptions {
|
||||
customID?: string;
|
||||
disabled?: boolean;
|
||||
maxValues?: number;
|
||||
minValues?: number;
|
||||
options?: MessageSelectOptionData[];
|
||||
placeholder?: string;
|
||||
}
|
||||
|
||||
interface MessageSelectOption {
|
||||
default: boolean;
|
||||
description: string | null;
|
||||
emoji: RawEmoji | null;
|
||||
label: string;
|
||||
value: string;
|
||||
}
|
||||
|
||||
interface MessageSelectOptionData {
|
||||
default?: boolean;
|
||||
description?: string;
|
||||
emoji?: EmojiIdentifierResolvable;
|
||||
label: string;
|
||||
value: string;
|
||||
}
|
||||
|
||||
type MessageTarget =
|
||||
| Interaction
|
||||
| InteractionWebhook
|
||||
|
||||
Reference in New Issue
Block a user