update
This commit is contained in:
parent
26c71d7777
commit
02fcfb881f
@ -1,16 +1,19 @@
|
||||
'use strict';
|
||||
const { Events } = require('../../../util/Constants');
|
||||
module.exports = (client, packet) => {
|
||||
/**
|
||||
* Emitted whenever a recipient is added from a group DM.
|
||||
* @event Client#channelRecipientAdd
|
||||
* @param {PartialGroupDMChannel} channel Group DM channel
|
||||
* @param {User} user User
|
||||
*/
|
||||
const { Events, Status } = require('../../../util/Constants');
|
||||
module.exports = (client, packet, shard) => {
|
||||
const channel = client.channels.cache.get(packet.d.channel_id);
|
||||
if (!channel) return;
|
||||
if (channel) {
|
||||
if (!channel._recipients) channel._recipients = [];
|
||||
channel._recipients.push(packet.d.user);
|
||||
const user = client.users._add(packet.d.user);
|
||||
if (shard.status == Status.READY) {
|
||||
/**
|
||||
* Emitted whenever a recipient is added from a group DM.
|
||||
* @event Client#channelRecipientAdd
|
||||
* @param {GroupDMChannel} channel Group DM channel
|
||||
* @param {User} user User
|
||||
*/
|
||||
client.emit(Events.CHANNEL_RECIPIENT_ADD, channel, user);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -1,16 +1,16 @@
|
||||
'use strict';
|
||||
const { Events } = require('../../../util/Constants');
|
||||
module.exports = (client, packet) => {
|
||||
const channel = client.channels.cache.get(packet.d.channel_id);
|
||||
if (channel) {
|
||||
if (!channel._recipients) channel._recipients = [];
|
||||
channel._recipients = channel._recipients.filter(u => u.id !== packet.d.user.id);
|
||||
/**
|
||||
* Emitted whenever a recipient is removed from a group DM.
|
||||
* @event Client#channelRecipientRemove
|
||||
* @param {PartialGroupDMChannel} channel Group DM channel
|
||||
* @param {GroupDMChannel} channel Group DM channel
|
||||
* @param {User} user User
|
||||
*/
|
||||
const channel = client.channels.cache.get(packet.d.channel_id);
|
||||
if (!channel) return;
|
||||
if (!channel._recipients) channel._recipients = [];
|
||||
channel._recipients = channel._recipients.filter(r => r !== packet.d.user.id);
|
||||
const user = client.users._add(packet.d.user);
|
||||
client.emit(Events.CHANNEL_RECIPIENT_REMOVE, channel, user);
|
||||
client.emit(Events.CHANNEL_RECIPIENT_REMOVE, channel, client.users._add(packet.d.user));
|
||||
}
|
||||
};
|
||||
|
@ -1,11 +0,0 @@
|
||||
'use strict';
|
||||
const { Events } = require('../../../util/Constants');
|
||||
|
||||
module.exports = (client, { d: data }) => {
|
||||
for (const command of data.application_commands) {
|
||||
const user = client.users.cache.get(command.application_id);
|
||||
if (!user || !user.bot) continue;
|
||||
user.application?.commands?._add(command, true);
|
||||
}
|
||||
client.emit(Events.GUILD_APPLICATION_COMMANDS_UPDATE, data);
|
||||
};
|
@ -1,16 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
const { Events } = require('../../../util/Constants');
|
||||
|
||||
module.exports = (client, { d: data }) => {
|
||||
const channel = client.channels.cache.get(data.channel_id);
|
||||
/**
|
||||
* Emitted whenever message is acknowledged (mark read / unread)
|
||||
* @event Client#messageAck
|
||||
* @param {TextChannel} channel Channel
|
||||
* @param {Snowflake} message_id Message ID
|
||||
* @param {boolean} isRead Whether the message is read
|
||||
* @param {Object} raw Raw data
|
||||
*/
|
||||
client.emit(Events.MESSAGE_ACK, channel, data.message_id, !data.manual, data);
|
||||
};
|
@ -1,5 +1,5 @@
|
||||
'use strict';
|
||||
|
||||
module.exports = (client, { d: data }) => {
|
||||
client.user.notes.set(data.id, data.note);
|
||||
client.notes.cache.set(data.id, data.note);
|
||||
};
|
||||
|
@ -130,7 +130,7 @@ class GuildBanManager extends CachedManager {
|
||||
* @typedef {Object} BanOptions
|
||||
* @property {number} [days=0] Number of days of messages to delete, must be between 0 and 7, inclusive
|
||||
* <warn>This property is deprecated. Use `deleteMessageSeconds` instead.</warn>
|
||||
* @property {number} [deleteMessageSeconds=0] Number of seconds of messages to delete,
|
||||
* @property {number} [deleteMessageSeconds] Number of seconds of messages to delete,
|
||||
* must be between 0 and 604800 (7 days), inclusive
|
||||
* @property {string} [reason] The reason for the ban
|
||||
*/
|
||||
|
@ -89,7 +89,7 @@ class PermissionOverwriteManager extends CachedManager {
|
||||
* @private
|
||||
*/
|
||||
async upsert(userOrRole, options, overwriteOptions = {}, existing) {
|
||||
const userOrRoleId = this.channel.guild.roles.resolveId(userOrRole) ?? this.client.users.resolveId(userOrRole);
|
||||
let userOrRoleId = this.channel.guild.roles.resolveId(userOrRole) ?? this.client.users.resolveId(userOrRole);
|
||||
let { type, reason } = overwriteOptions;
|
||||
if (typeof type !== 'number') {
|
||||
userOrRole = this.channel.guild.roles.resolve(userOrRole) ?? this.client.users.resolve(userOrRole);
|
||||
|
@ -179,7 +179,7 @@ class ThreadMemberManager extends CachedManager {
|
||||
const id = this.resolveId(member);
|
||||
return id
|
||||
? this._fetchOne(id, options)
|
||||
: this._fetchMany(typeof member !== 'boolean' ? member : { ...options, cache: member });
|
||||
: this._fetchMany(typeof member === 'boolean' ? { ...options, cache: member } : options);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2,6 +2,9 @@
|
||||
|
||||
const { ApplicationRoleConnectionMetadataTypes } = require('../util/Constants');
|
||||
|
||||
/**
|
||||
* Role connection metadata object for an application.
|
||||
*/
|
||||
class ApplicationRoleConnectionMetadata {
|
||||
constructor(data) {
|
||||
/**
|
||||
|
@ -194,7 +194,7 @@ class AutoModerationRule extends Base {
|
||||
* @returns {Promise<AutoModerationRule>}
|
||||
*/
|
||||
setKeywordFilter(keywordFilter, reason) {
|
||||
return this.edit({ triggerMetadata: { keywordFilter }, reason });
|
||||
return this.edit({ triggerMetadata: { ...this.triggerMetadata, keywordFilter }, reason });
|
||||
}
|
||||
|
||||
/**
|
||||
@ -205,7 +205,7 @@ class AutoModerationRule extends Base {
|
||||
* @returns {Promise<AutoModerationRule>}
|
||||
*/
|
||||
setRegexPatterns(regexPatterns, reason) {
|
||||
return this.edit({ triggerMetadata: { regexPatterns }, reason });
|
||||
return this.edit({ triggerMetadata: { ...this.triggerMetadata, regexPatterns }, reason });
|
||||
}
|
||||
|
||||
/**
|
||||
@ -215,7 +215,7 @@ class AutoModerationRule extends Base {
|
||||
* @returns {Promise<AutoModerationRule>}
|
||||
*/
|
||||
setPresets(presets, reason) {
|
||||
return this.edit({ triggerMetadata: { presets }, reason });
|
||||
return this.edit({ triggerMetadata: { ...this.triggerMetadata, presets }, reason });
|
||||
}
|
||||
|
||||
/**
|
||||
@ -225,7 +225,7 @@ class AutoModerationRule extends Base {
|
||||
* @returns {Promise<AutoModerationRule>}
|
||||
*/
|
||||
setAllowList(allowList, reason) {
|
||||
return this.edit({ triggerMetadata: { allowList }, reason });
|
||||
return this.edit({ triggerMetadata: { ...this.triggerMetadata, allowList }, reason });
|
||||
}
|
||||
|
||||
/**
|
||||
@ -235,7 +235,7 @@ class AutoModerationRule extends Base {
|
||||
* @returns {Promise<AutoModerationRule>}
|
||||
*/
|
||||
setMentionTotalLimit(mentionTotalLimit, reason) {
|
||||
return this.edit({ triggerMetadata: { mentionTotalLimit }, reason });
|
||||
return this.edit({ triggerMetadata: { ...this.triggerMetadata, mentionTotalLimit }, reason });
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -2,6 +2,7 @@
|
||||
|
||||
const CommandInteractionOptionResolver = require('./CommandInteractionOptionResolver');
|
||||
const Interaction = require('./Interaction');
|
||||
const { Error } = require('../errors');
|
||||
const { InteractionResponseTypes, ApplicationCommandOptionTypes } = require('../util/Constants');
|
||||
|
||||
/**
|
||||
|
@ -76,7 +76,11 @@ class BaseMessageComponent {
|
||||
component = data instanceof MessageButton ? data : new MessageButton(data);
|
||||
break;
|
||||
}
|
||||
case MessageComponentTypes.SELECT_MENU: {
|
||||
case MessageComponentTypes.STRING_SELECT:
|
||||
case MessageComponentTypes.USER_SELECT:
|
||||
case MessageComponentTypes.ROLE_SELECT:
|
||||
case MessageComponentTypes.MENTIONABLE_SELECT:
|
||||
case MessageComponentTypes.CHANNEL_SELECT: {
|
||||
const MessageSelectMenu = require('./MessageSelectMenu');
|
||||
component = data instanceof MessageSelectMenu ? data : new MessageSelectMenu(data);
|
||||
break;
|
||||
|
@ -53,7 +53,6 @@ class Channel extends Base {
|
||||
if ('flags' in data) {
|
||||
/**
|
||||
* The flags that are applied to the channel.
|
||||
* <info>This is only `null` in a {@link PartialGroupDMChannel}. In all other cases, it is not `null`.</info>
|
||||
* @type {?Readonly<ChannelFlags>}
|
||||
*/
|
||||
this.flags = new ChannelFlags(data.flags).freeze();
|
||||
@ -203,8 +202,8 @@ class Channel extends Base {
|
||||
if ((data.recipients && data.type !== ChannelTypes.GROUP_DM) || data.type === ChannelTypes.DM) {
|
||||
channel = new DMChannel(client, data);
|
||||
} else if (data.type === ChannelTypes.GROUP_DM) {
|
||||
const PartialGroupDMChannel = require('./PartialGroupDMChannel');
|
||||
channel = new PartialGroupDMChannel(client, data);
|
||||
const GroupDMChannel = require('./GroupDMChannel');
|
||||
channel = new GroupDMChannel(client, data);
|
||||
}
|
||||
} else {
|
||||
guild ??= client.guilds.cache.get(data.guild_id);
|
||||
|
@ -22,7 +22,7 @@ class ContextMenuInteraction extends BaseCommandInteraction {
|
||||
);
|
||||
|
||||
/**
|
||||
* The id of the target of the interaction
|
||||
* The id of the target of this interaction
|
||||
* @type {Snowflake}
|
||||
*/
|
||||
this.targetId = data.data.target_id;
|
||||
|
@ -3,7 +3,6 @@
|
||||
const GuildChannel = require('./GuildChannel');
|
||||
const TextBasedChannel = require('./interfaces/TextBasedChannel');
|
||||
const GuildForumThreadManager = require('../managers/GuildForumThreadManager');
|
||||
const InteractionManager = require('../managers/InteractionManager');
|
||||
const { SortOrderTypes, ForumLayoutTypes } = require('../util/Constants');
|
||||
const { transformAPIGuildForumTag, transformAPIGuildDefaultReaction } = require('../util/Util');
|
||||
|
||||
@ -46,12 +45,6 @@ class ForumChannel extends GuildChannel {
|
||||
constructor(guild, data, client) {
|
||||
super(guild, data, client, false);
|
||||
|
||||
/**
|
||||
* A manager of the interactions sent to this channel
|
||||
* @type {InteractionManager}
|
||||
*/
|
||||
this.interactions = new InteractionManager(this);
|
||||
|
||||
/**
|
||||
* A manager of the threads belonging to this channel
|
||||
* @type {GuildForumThreadManager}
|
||||
@ -260,12 +253,9 @@ TextBasedChannel.applyToClass(ForumChannel, true, [
|
||||
'send',
|
||||
'lastMessage',
|
||||
'lastPinAt',
|
||||
'bulkDelete',
|
||||
'sendTyping',
|
||||
'createMessageCollector',
|
||||
'awaitMessages',
|
||||
'createMessageComponentCollector',
|
||||
'awaitMessageComponent',
|
||||
]);
|
||||
|
||||
module.exports = ForumChannel;
|
||||
|
@ -299,8 +299,6 @@ class GroupDMChannel extends Channel {
|
||||
sendTyping() {}
|
||||
createMessageCollector() {}
|
||||
awaitMessages() {}
|
||||
createMessageComponentCollector() {}
|
||||
awaitMessageComponent() {}
|
||||
// Doesn't work on DM channels; setRateLimitPerUser() {}
|
||||
// Doesn't work on DM channels; setNSFW() {}
|
||||
}
|
||||
|
@ -269,71 +269,10 @@ class Interaction extends Base {
|
||||
* Indicates whether this interaction is a {@link SelectMenuInteraction}.
|
||||
* @returns {boolean}
|
||||
*/
|
||||
isAnySelectMenu() {
|
||||
return InteractionTypes[this.type] === InteractionTypes.MESSAGE_COMPONENT && typeof this.values !== 'undefined';
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates whether this interaction is a {@link SelectMenuInteraction} with a `STRING_SELECT` type.
|
||||
* @returns {boolean}
|
||||
* @deprecated Use {@link Interaction#isStringSelect()} instead
|
||||
*/
|
||||
isSelectMenu() {
|
||||
return this.isStringSelect();
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates whether this interaction is a {@link SelectMenuInteraction} with a `STRING_SELECT` type.
|
||||
* @returns {boolean}
|
||||
*/
|
||||
isStringSelect() {
|
||||
return (
|
||||
InteractionTypes[this.type] === InteractionTypes.MESSAGE_COMPONENT &&
|
||||
MessageComponentTypes[this.componentType] === MessageComponentTypes.STRING_SELECT
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates whether this interaction is a {@link SelectMenuInteraction} with a `USER_SELECT` type.
|
||||
* @returns {boolean}
|
||||
*/
|
||||
isUserSelect() {
|
||||
return (
|
||||
InteractionTypes[this.type] === InteractionTypes.MESSAGE_COMPONENT &&
|
||||
MessageComponentTypes[this.componentType] === MessageComponentTypes.USER_SELECT
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates whether this interaction is a {@link SelectMenuInteraction} with a `ROLE_SELECT` type.
|
||||
* @returns {boolean}
|
||||
*/
|
||||
isRoleSelect() {
|
||||
return (
|
||||
InteractionTypes[this.type] === InteractionTypes.MESSAGE_COMPONENT &&
|
||||
MessageComponentTypes[this.componentType] === MessageComponentTypes.ROLE_SELECT
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates whether this interaction is a {@link SelectMenuInteraction} with a `MENTIONABLE_SELECT` type.
|
||||
* @returns {boolean}
|
||||
*/
|
||||
isMentionableSelect() {
|
||||
return (
|
||||
InteractionTypes[this.type] === InteractionTypes.MESSAGE_COMPONENT &&
|
||||
MessageComponentTypes[this.componentType] === MessageComponentTypes.MENTIONABLE_SELECT
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates whether this interaction is a {@link SelectMenuInteraction} with a `CHANNEL_SELECT` type.
|
||||
* @returns {boolean}
|
||||
*/
|
||||
isChannelSelect() {
|
||||
return (
|
||||
InteractionTypes[this.type] === InteractionTypes.MESSAGE_COMPONENT &&
|
||||
MessageComponentTypes[this.componentType] === MessageComponentTypes.CHANNEL_SELECT
|
||||
MessageComponentTypes[this.componentType] === MessageComponentTypes.SELECT_MENU
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -1,13 +1,9 @@
|
||||
'use strict';
|
||||
|
||||
const { setTimeout } = require('node:timers');
|
||||
const BaseMessageComponent = require('./BaseMessageComponent');
|
||||
const { RangeError } = require('../errors');
|
||||
const { MessageButtonStyles, MessageComponentTypes, InteractionTypes } = require('../util/Constants');
|
||||
const SnowflakeUtil = require('../util/SnowflakeUtil');
|
||||
const { MessageButtonStyles, MessageComponentTypes } = require('../util/Constants');
|
||||
const Util = require('../util/Util');
|
||||
const { lazy } = require('../util/Util');
|
||||
const Message = lazy(() => require('../structures/Message').Message);
|
||||
|
||||
/**
|
||||
* Represents a button message component.
|
||||
@ -164,68 +160,6 @@ class MessageButton extends BaseMessageComponent {
|
||||
static resolveStyle(style) {
|
||||
return typeof style === 'string' ? style : MessageButtonStyles[style];
|
||||
}
|
||||
// Patch Click
|
||||
/**
|
||||
* Click the button
|
||||
* @param {Message} message Discord Message
|
||||
* @returns {Promise<InteractionResponse>}
|
||||
*/
|
||||
async click(message) {
|
||||
const nonce = SnowflakeUtil.generate();
|
||||
if (!(message instanceof Message())) throw new Error('[UNKNOWN_MESSAGE] Please pass a valid Message');
|
||||
if (!this.customId || this.style == MessageButtonStyles.LINK || this.disabled) return false;
|
||||
const data = {
|
||||
type: InteractionTypes.MESSAGE_COMPONENT,
|
||||
nonce,
|
||||
guild_id: message.guild?.id ?? null,
|
||||
channel_id: message.channel.id,
|
||||
message_id: message.id,
|
||||
application_id: message.applicationId ?? message.author.id,
|
||||
session_id: message.client.sessionId,
|
||||
message_flags: message.flags.bitfield,
|
||||
data: {
|
||||
component_type: MessageComponentTypes.BUTTON,
|
||||
custom_id: this.customId,
|
||||
},
|
||||
};
|
||||
await message.client.api.interactions.post({
|
||||
data,
|
||||
});
|
||||
message.client._interactionCache.set(nonce, {
|
||||
channelId: message.channelId,
|
||||
guildId: message.guildId,
|
||||
metadata: data,
|
||||
});
|
||||
return new Promise((resolve, reject) => {
|
||||
const handler = data => {
|
||||
timeout.refresh();
|
||||
if (data.metadata?.nonce !== nonce) return;
|
||||
clearTimeout(timeout);
|
||||
message.client.removeListener('interactionResponse', handler);
|
||||
message.client.decrementMaxListeners();
|
||||
if (data.status) {
|
||||
resolve(data.metadata);
|
||||
} else {
|
||||
reject(
|
||||
new Error('INTERACTION_ERROR', {
|
||||
cause: data,
|
||||
}),
|
||||
);
|
||||
}
|
||||
};
|
||||
const timeout = setTimeout(() => {
|
||||
message.client.removeListener('interactionResponse', handler);
|
||||
message.client.decrementMaxListeners();
|
||||
reject(
|
||||
new Error('INTERACTION_TIMEOUT', {
|
||||
cause: data,
|
||||
}),
|
||||
);
|
||||
}, message.client.options.interactionTimeout).unref();
|
||||
message.client.incrementMaxListeners();
|
||||
message.client.on('interactionResponse', handler);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = MessageButton;
|
||||
|
@ -1,16 +1,7 @@
|
||||
'use strict';
|
||||
|
||||
const { setTimeout } = require('node:timers');
|
||||
const BaseMessageComponent = require('./BaseMessageComponent');
|
||||
const {
|
||||
ChannelTypes,
|
||||
MessageComponentTypes,
|
||||
SelectMenuComponentTypes,
|
||||
InteractionTypes,
|
||||
} = require('../util/Constants');
|
||||
const SnowflakeUtil = require('../util/SnowflakeUtil');
|
||||
const { lazy } = require('../util/Util');
|
||||
const Message = lazy(() => require('./Message').Message);
|
||||
const { ChannelTypes, MessageComponentTypes } = require('../util/Constants');
|
||||
const Util = require('../util/Util');
|
||||
|
||||
/**
|
||||
@ -103,130 +94,6 @@ class MessageSelectMenu extends BaseMessageComponent {
|
||||
) ?? [];
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the channel types to the select menu
|
||||
* @param {...ChannelType[]} channelTypes Added channel types
|
||||
* @returns {MessageSelectMenu}
|
||||
*/
|
||||
addChannelTypes(...channelTypes) {
|
||||
if (!channelTypes.every(channelType => ChannelTypes[channelType])) {
|
||||
throw new TypeError('INVALID_TYPE', 'channelTypes', 'Rest<ChannelTypes[]>');
|
||||
}
|
||||
this.channelTypes.push(
|
||||
...channelTypes.map(channelType => (typeof channelType === 'string' ? channelType : ChannelTypes[channelType])),
|
||||
);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the channel types of the select menu
|
||||
* @param {...ChannelType[]} channelTypes An array of new channel types
|
||||
* @returns {MessageSelectMenu}
|
||||
*/
|
||||
setChannelTypes(...channelTypes) {
|
||||
if (!channelTypes.every(channelType => ChannelTypes[channelType])) {
|
||||
throw new TypeError('INVALID_TYPE', 'channelTypes', 'Rest<ChannelTypes[]>');
|
||||
}
|
||||
this.channelTypes = channelTypes.map(channelType =>
|
||||
typeof channelType === 'string' ? channelType : ChannelTypes[channelType],
|
||||
);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the type of the select menu
|
||||
* @param {SelectMenuComponentType} type Type of the select menu
|
||||
* @returns {MessageSelectMenu}
|
||||
*/
|
||||
setType(type) {
|
||||
if (!SelectMenuComponentTypes[type]) throw new TypeError('INVALID_TYPE', 'type', 'SelectMenuComponentType');
|
||||
this.type = BaseMessageComponent.resolveType(type);
|
||||
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
|
||||
@ -268,124 +135,6 @@ class MessageSelectMenu extends BaseMessageComponent {
|
||||
static normalizeOptions(...options) {
|
||||
return options.flat(Infinity).map(option => this.normalizeOption(option));
|
||||
}
|
||||
|
||||
// Add
|
||||
/**
|
||||
* Mesage select menu
|
||||
* @param {Message} message The message this select menu is for
|
||||
* @param {Array<any>} values The values of the select menu
|
||||
* @returns {Promise<InteractionResponse>}
|
||||
*/
|
||||
async select(message, values) {
|
||||
if (!(message instanceof Message())) throw new Error('[UNKNOWN_MESSAGE] Please pass a valid Message');
|
||||
if (!Array.isArray(values)) throw new TypeError('[INVALID_VALUES] Please pass an array of values');
|
||||
if (!this.customId || this.disabled) {
|
||||
throw new Error('[INVALID_MENU] Menu does not contain Id or has been disabled');
|
||||
} // Disabled or null customID
|
||||
if (values.length < this.minValues) {
|
||||
throw new RangeError(`[SELECT_MENU_MIN_VALUES] The minimum number of values is ${this.minValues}`);
|
||||
}
|
||||
if (values.length > this.maxValues) {
|
||||
throw new RangeError(`[SELECT_MENU_MAX_VALUES] The maximum number of values is ${this.maxValues}`);
|
||||
}
|
||||
const parseValues = value => {
|
||||
switch (this.type) {
|
||||
case 'SELECT_MENU':
|
||||
case 'STRING_SELECT': {
|
||||
if (typeof value !== 'string') throw new TypeError('[INVALID_VALUE] Please pass a string value');
|
||||
const value_ = this.options.find(obj => obj.value === value || obj.label === value);
|
||||
if (!value_) throw new Error('[INVALID_VALUE] Please pass a valid value');
|
||||
return value_.value;
|
||||
}
|
||||
case 'USER_SELECT': {
|
||||
const userId = this.client.users.resolveId(value);
|
||||
if (!userId) throw new Error('[INVALID_VALUE] Please pass a valid user');
|
||||
return userId;
|
||||
}
|
||||
case 'ROLE_SELECT': {
|
||||
const roleId = this.client.roles.resolveId(value);
|
||||
if (!roleId) throw new Error('[INVALID_VALUE] Please pass a valid role');
|
||||
return roleId;
|
||||
}
|
||||
case 'MENTIONABLE_SELECT': {
|
||||
const mentionableId = this.client.users.resolveId(value) || this.client.roles.resolveId(value);
|
||||
if (!mentionableId) throw new Error('[INVALID_VALUE] Please pass a valid mentionable');
|
||||
return mentionableId;
|
||||
}
|
||||
case 'CHANNEL_SELECT': {
|
||||
const channel = this.client.channels.resolve(value);
|
||||
if (!channel) throw new Error('[INVALID_VALUE] Please pass a valid channel');
|
||||
if (!this.channelTypes.includes(channel.type)) {
|
||||
throw new Error(
|
||||
`[INVALID_VALUE] Please pass a valid channel type (Got: ${channel.type}, allow: ${this.channelTypes.join(
|
||||
', ',
|
||||
)})`,
|
||||
);
|
||||
}
|
||||
return channel.id;
|
||||
}
|
||||
default: {
|
||||
throw new Error(`[INVALID_TYPE] Please pass a valid select menu type (Got ${this.type})`);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const nonce = SnowflakeUtil.generate();
|
||||
const data = {
|
||||
type: InteractionTypes.MESSAGE_COMPONENT,
|
||||
guild_id: message.guild?.id ?? null,
|
||||
channel_id: message.channel.id,
|
||||
message_id: message.id,
|
||||
application_id: message.applicationId ?? message.author.id,
|
||||
session_id: message.client.sessionId,
|
||||
message_flags: message.flags.bitfield,
|
||||
data: {
|
||||
component_type: MessageComponentTypes[this.type],
|
||||
custom_id: this.customId,
|
||||
type: MessageComponentTypes[this.type],
|
||||
values: values?.length ? values.map(parseValues) : [],
|
||||
},
|
||||
nonce,
|
||||
};
|
||||
|
||||
await message.client.api.interactions.post({
|
||||
data,
|
||||
});
|
||||
message.client._interactionCache.set(nonce, {
|
||||
channelId: message.channelId,
|
||||
guildId: message.guildId,
|
||||
metadata: data,
|
||||
});
|
||||
return new Promise((resolve, reject) => {
|
||||
const handler = data => {
|
||||
timeout.refresh();
|
||||
if (data.metadata?.nonce !== nonce) return;
|
||||
clearTimeout(timeout);
|
||||
message.client.removeListener('interactionResponse', handler);
|
||||
message.client.decrementMaxListeners();
|
||||
if (data.status) {
|
||||
resolve(data.metadata);
|
||||
} else {
|
||||
reject(
|
||||
new Error('INTERACTION_ERROR', {
|
||||
cause: data,
|
||||
}),
|
||||
);
|
||||
}
|
||||
};
|
||||
const timeout = setTimeout(() => {
|
||||
message.client.removeListener('interactionResponse', handler);
|
||||
message.client.decrementMaxListeners();
|
||||
reject(
|
||||
new Error('INTERACTION_TIMEOUT', {
|
||||
cause: data,
|
||||
}),
|
||||
);
|
||||
}, message.client.options.interactionTimeout).unref();
|
||||
message.client.incrementMaxListeners();
|
||||
message.client.on('interactionResponse', handler);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = MessageSelectMenu;
|
||||
|
@ -138,7 +138,7 @@ class Modal {
|
||||
data: postData,
|
||||
});
|
||||
return new Promise((resolve, reject) => {
|
||||
const timeoutMs = 15_000;
|
||||
const timeoutMs = 5_000;
|
||||
// Waiting for MsgCreate / ModalCreate
|
||||
const handler = data => {
|
||||
if (data.nonce !== nonce) return;
|
||||
|
@ -82,76 +82,6 @@ class TextInputComponent extends BaseMessageComponent {
|
||||
this.value = data.value ?? null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the custom id of this text input component
|
||||
* @param {string} customId A unique string to be sent in the interaction when submitted
|
||||
* @returns {TextInputComponent}
|
||||
*/
|
||||
setCustomId(customId) {
|
||||
this.customId = Util.verifyString(customId, RangeError, 'TEXT_INPUT_CUSTOM_ID');
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the label of this text input component
|
||||
* @param {string} label The text to be displayed above this text input component
|
||||
* @returns {TextInputComponent}
|
||||
*/
|
||||
setLabel(label) {
|
||||
this.label = Util.verifyString(label, RangeError, 'TEXT_INPUT_LABEL');
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the text input component to be required for modal submission
|
||||
* @param {boolean} [required=true] Whether this text input component is required
|
||||
* @returns {TextInputComponent}
|
||||
*/
|
||||
setRequired(required = true) {
|
||||
this.required = required;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the maximum length of text input required in this text input component
|
||||
* @param {number} maxLength Maximum length of text to be required
|
||||
* @returns {TextInputComponent}
|
||||
*/
|
||||
setMaxLength(maxLength) {
|
||||
this.maxLength = maxLength;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the minimum length of text input required in this text input component
|
||||
* @param {number} minLength Minimum length of text to be required
|
||||
* @returns {TextInputComponent}
|
||||
*/
|
||||
setMinLength(minLength) {
|
||||
this.minLength = minLength;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the placeholder of this text input component
|
||||
* @param {string} placeholder Custom placeholder text to display when no text is entered
|
||||
* @returns {TextInputComponent}
|
||||
*/
|
||||
setPlaceholder(placeholder) {
|
||||
this.placeholder = Util.verifyString(placeholder, RangeError, 'TEXT_INPUT_PLACEHOLDER');
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the style of this text input component
|
||||
* @param {TextInputStyleResolvable} style The style of this text input component
|
||||
* @returns {TextInputComponent}
|
||||
*/
|
||||
setStyle(style) {
|
||||
this.style = TextInputComponent.resolveStyle(style);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the value of this text input component
|
||||
* @param {string} value Value of this text input component
|
||||
|
Loading…
Reference in New Issue
Block a user