Update Bot

This commit is contained in:
2026-03-15 11:58:43 +01:00
parent b67c111ffc
commit cd99275933
560 changed files with 23173 additions and 55113 deletions

10
node_modules/discord.js/package.json generated vendored
View File

@@ -1,7 +1,7 @@
{
"$schema": "https://json.schemastore.org/package.json",
"name": "discord.js",
"version": "14.25.1",
"version": "14.22.1",
"description": "A powerful library for interacting with the Discord API",
"main": "./src/index.js",
"types": "./typings/index.d.ts",
@@ -53,18 +53,18 @@
"homepage": "https://discord.js.org",
"funding": "https://github.com/discordjs/discord.js?sponsor",
"dependencies": {
"@discordjs/builders": "^1.11.2",
"@discordjs/collection": "1.5.3",
"@discordjs/formatters": "^0.6.1",
"@discordjs/ws": "^1.2.3",
"@sapphire/snowflake": "3.5.3",
"discord-api-types": "^0.38.33",
"discord-api-types": "^0.38.16",
"fast-deep-equal": "3.1.3",
"lodash.snakecase": "4.1.1",
"magic-bytes.js": "^1.10.0",
"tslib": "^2.6.3",
"undici": "6.21.3",
"@discordjs/builders": "^1.13.0",
"@discordjs/formatters": "^0.6.2",
"@discordjs/util": "^1.2.0",
"@discordjs/util": "^1.1.1",
"@discordjs/rest": "^2.6.0"
},
"devDependencies": {

View File

@@ -1,8 +1,6 @@
'use strict';
const { Poll } = require('../../structures/Poll.js');
const { PollAnswer } = require('../../structures/PollAnswer.js');
const Partials = require('../../util/Partials.js');
const Partials = require('../../util/Partials');
/*
@@ -65,23 +63,6 @@ class GenericAction {
);
}
getPoll(data, message, channel) {
const includePollPartial = this.client.options.partials.includes(Partials.Poll);
const includePollAnswerPartial = this.client.options.partials.includes(Partials.PollAnswer);
if (message.partial && (!includePollPartial || !includePollAnswerPartial)) return null;
if (!message.poll && includePollPartial) {
message.poll = new Poll(this.client, data, message, channel);
}
if (message.poll && !message.poll.answers.has(data.answer_id) && includePollAnswerPartial) {
const pollAnswer = new PollAnswer(this.client, data, message.poll);
message.poll.answers.set(data.answer_id, pollAnswer);
}
return message.poll;
}
getReaction(data, message, user) {
const id = data.emoji.id ?? decodeURIComponent(data.emoji.name);
return this.getPayload(

View File

@@ -11,74 +11,74 @@ class ActionsManager {
constructor(client) {
this.client = client;
this.ApplicationCommandPermissionsUpdate = this.load(require('./ApplicationCommandPermissionsUpdate.js'));
this.AutoModerationActionExecution = this.load(require('./AutoModerationActionExecution.js'));
this.AutoModerationRuleCreate = this.load(require('./AutoModerationRuleCreate.js'));
this.AutoModerationRuleDelete = this.load(require('./AutoModerationRuleDelete.js'));
this.AutoModerationRuleUpdate = this.load(require('./AutoModerationRuleUpdate.js'));
this.ChannelCreate = this.load(require('./ChannelCreate.js'));
this.ChannelDelete = this.load(require('./ChannelDelete.js'));
this.ChannelUpdate = this.load(require('./ChannelUpdate.js'));
this.EntitlementCreate = this.load(require('./EntitlementCreate.js'));
this.EntitlementDelete = this.load(require('./EntitlementDelete.js'));
this.EntitlementUpdate = this.load(require('./EntitlementUpdate.js'));
this.GuildAuditLogEntryCreate = this.load(require('./GuildAuditLogEntryCreate.js'));
this.GuildBanAdd = this.load(require('./GuildBanAdd.js'));
this.GuildBanRemove = this.load(require('./GuildBanRemove.js'));
this.GuildChannelsPositionUpdate = this.load(require('./GuildChannelsPositionUpdate.js'));
this.GuildDelete = this.load(require('./GuildDelete.js'));
this.GuildEmojiCreate = this.load(require('./GuildEmojiCreate.js'));
this.GuildEmojiDelete = this.load(require('./GuildEmojiDelete.js'));
this.GuildEmojiUpdate = this.load(require('./GuildEmojiUpdate.js'));
this.GuildEmojisUpdate = this.load(require('./GuildEmojisUpdate.js'));
this.GuildIntegrationsUpdate = this.load(require('./GuildIntegrationsUpdate.js'));
this.GuildMemberRemove = this.load(require('./GuildMemberRemove.js'));
this.GuildMemberUpdate = this.load(require('./GuildMemberUpdate.js'));
this.GuildRoleCreate = this.load(require('./GuildRoleCreate.js'));
this.GuildRoleDelete = this.load(require('./GuildRoleDelete.js'));
this.GuildRoleUpdate = this.load(require('./GuildRoleUpdate.js'));
this.GuildRolesPositionUpdate = this.load(require('./GuildRolesPositionUpdate.js'));
this.GuildScheduledEventCreate = this.load(require('./GuildScheduledEventCreate.js'));
this.GuildScheduledEventDelete = this.load(require('./GuildScheduledEventDelete.js'));
this.GuildScheduledEventUpdate = this.load(require('./GuildScheduledEventUpdate.js'));
this.GuildScheduledEventUserAdd = this.load(require('./GuildScheduledEventUserAdd.js'));
this.GuildScheduledEventUserRemove = this.load(require('./GuildScheduledEventUserRemove.js'));
this.GuildSoundboardSoundDelete = this.load(require('./GuildSoundboardSoundDelete.js'));
this.GuildStickerCreate = this.load(require('./GuildStickerCreate.js'));
this.GuildStickerDelete = this.load(require('./GuildStickerDelete.js'));
this.GuildStickerUpdate = this.load(require('./GuildStickerUpdate.js'));
this.GuildStickersUpdate = this.load(require('./GuildStickersUpdate.js'));
this.GuildUpdate = this.load(require('./GuildUpdate.js'));
this.InteractionCreate = this.load(require('./InteractionCreate.js'));
this.InviteCreate = this.load(require('./InviteCreate.js'));
this.InviteDelete = this.load(require('./InviteDelete.js'));
this.MessageCreate = this.load(require('./MessageCreate.js'));
this.MessageDelete = this.load(require('./MessageDelete.js'));
this.MessageDeleteBulk = this.load(require('./MessageDeleteBulk.js'));
this.MessagePollVoteAdd = this.load(require('./MessagePollVoteAdd.js'));
this.MessagePollVoteRemove = this.load(require('./MessagePollVoteRemove.js'));
this.MessageReactionAdd = this.load(require('./MessageReactionAdd.js'));
this.MessageReactionRemove = this.load(require('./MessageReactionRemove.js'));
this.MessageReactionRemoveAll = this.load(require('./MessageReactionRemoveAll.js'));
this.MessageReactionRemoveEmoji = this.load(require('./MessageReactionRemoveEmoji.js'));
this.MessageUpdate = this.load(require('./MessageUpdate.js'));
this.PresenceUpdate = this.load(require('./PresenceUpdate.js'));
this.StageInstanceCreate = this.load(require('./StageInstanceCreate.js'));
this.StageInstanceDelete = this.load(require('./StageInstanceDelete.js'));
this.StageInstanceUpdate = this.load(require('./StageInstanceUpdate.js'));
this.ThreadCreate = this.load(require('./ThreadCreate.js'));
this.ThreadDelete = this.load(require('./ThreadDelete.js'));
this.ThreadListSync = this.load(require('./ThreadListSync.js'));
this.ThreadMemberUpdate = this.load(require('./ThreadMemberUpdate.js'));
this.ThreadMembersUpdate = this.load(require('./ThreadMembersUpdate.js'));
this.TypingStart = this.load(require('./TypingStart.js'));
this.UserUpdate = this.load(require('./UserUpdate.js'));
this.VoiceStateUpdate = this.load(require('./VoiceStateUpdate.js'));
this.WebhooksUpdate = this.load(require('./WebhooksUpdate.js'));
this.register(require('./ApplicationCommandPermissionsUpdate'));
this.register(require('./AutoModerationActionExecution'));
this.register(require('./AutoModerationRuleCreate'));
this.register(require('./AutoModerationRuleDelete'));
this.register(require('./AutoModerationRuleUpdate'));
this.register(require('./ChannelCreate'));
this.register(require('./ChannelDelete'));
this.register(require('./ChannelUpdate'));
this.register(require('./EntitlementCreate'));
this.register(require('./EntitlementDelete'));
this.register(require('./EntitlementUpdate'));
this.register(require('./GuildAuditLogEntryCreate'));
this.register(require('./GuildBanAdd'));
this.register(require('./GuildBanRemove'));
this.register(require('./GuildChannelsPositionUpdate'));
this.register(require('./GuildDelete'));
this.register(require('./GuildEmojiCreate'));
this.register(require('./GuildEmojiDelete'));
this.register(require('./GuildEmojiUpdate'));
this.register(require('./GuildEmojisUpdate'));
this.register(require('./GuildIntegrationsUpdate'));
this.register(require('./GuildMemberRemove'));
this.register(require('./GuildMemberUpdate'));
this.register(require('./GuildRoleCreate'));
this.register(require('./GuildRoleDelete'));
this.register(require('./GuildRoleUpdate'));
this.register(require('./GuildRolesPositionUpdate'));
this.register(require('./GuildScheduledEventCreate'));
this.register(require('./GuildScheduledEventDelete'));
this.register(require('./GuildScheduledEventUpdate'));
this.register(require('./GuildScheduledEventUserAdd'));
this.register(require('./GuildScheduledEventUserRemove'));
this.register(require('./GuildSoundboardSoundDelete.js'));
this.register(require('./GuildStickerCreate'));
this.register(require('./GuildStickerDelete'));
this.register(require('./GuildStickerUpdate'));
this.register(require('./GuildStickersUpdate'));
this.register(require('./GuildUpdate'));
this.register(require('./InteractionCreate'));
this.register(require('./InviteCreate'));
this.register(require('./InviteDelete'));
this.register(require('./MessageCreate'));
this.register(require('./MessageDelete'));
this.register(require('./MessageDeleteBulk'));
this.register(require('./MessagePollVoteAdd'));
this.register(require('./MessagePollVoteRemove'));
this.register(require('./MessageReactionAdd'));
this.register(require('./MessageReactionRemove'));
this.register(require('./MessageReactionRemoveAll'));
this.register(require('./MessageReactionRemoveEmoji'));
this.register(require('./MessageUpdate'));
this.register(require('./PresenceUpdate'));
this.register(require('./StageInstanceCreate'));
this.register(require('./StageInstanceDelete'));
this.register(require('./StageInstanceUpdate'));
this.register(require('./ThreadCreate'));
this.register(require('./ThreadDelete'));
this.register(require('./ThreadListSync'));
this.register(require('./ThreadMemberUpdate'));
this.register(require('./ThreadMembersUpdate'));
this.register(require('./TypingStart'));
this.register(require('./UserUpdate'));
this.register(require('./VoiceStateUpdate'));
this.register(require('./WebhooksUpdate'));
}
load(Action) {
return new Action(this.client);
register(Action) {
this[Action.name.replace(/Action$/, '')] = new Action(this.client);
}
}

View File

@@ -11,18 +11,11 @@ class MessagePollVoteAddAction extends Action {
const message = this.getMessage(data, channel);
if (!message) return false;
const poll = this.getPoll(data, message, channel);
if (!poll) return false;
const { poll } = message;
const answer = poll.answers.get(data.answer_id);
const answer = poll?.answers.get(data.answer_id);
if (!answer) return false;
const user = this.getUser(data);
if (user) {
answer.voters._add(user);
}
answer.voteCount++;
/**

View File

@@ -11,17 +11,12 @@ class MessagePollVoteRemoveAction extends Action {
const message = this.getMessage(data, channel);
if (!message) return false;
const poll = this.getPoll(data, message, channel);
if (!poll) return false;
const { poll } = message;
const answer = poll.answers.get(data.answer_id);
const answer = poll?.answers.get(data.answer_id);
if (!answer) return false;
answer.voters.cache.delete(data.user_id);
if (answer.voteCount > 0) {
answer.voteCount--;
}
answer.voteCount--;
/**
* Emitted whenever a user removes their vote in a poll.

View File

@@ -32,10 +32,10 @@ const handlers = Object.fromEntries([
['GUILD_SCHEDULED_EVENT_UPDATE', require('./GUILD_SCHEDULED_EVENT_UPDATE')],
['GUILD_SCHEDULED_EVENT_USER_ADD', require('./GUILD_SCHEDULED_EVENT_USER_ADD')],
['GUILD_SCHEDULED_EVENT_USER_REMOVE', require('./GUILD_SCHEDULED_EVENT_USER_REMOVE')],
['GUILD_SOUNDBOARD_SOUNDS_UPDATE', require('./GUILD_SOUNDBOARD_SOUNDS_UPDATE')],
['GUILD_SOUNDBOARD_SOUND_CREATE', require('./GUILD_SOUNDBOARD_SOUND_CREATE')],
['GUILD_SOUNDBOARD_SOUND_DELETE', require('./GUILD_SOUNDBOARD_SOUND_DELETE')],
['GUILD_SOUNDBOARD_SOUND_UPDATE', require('./GUILD_SOUNDBOARD_SOUND_UPDATE')],
['GUILD_SOUNDBOARD_SOUNDS_UPDATE', require('./GUILD_SOUNDBOARD_SOUNDS_UPDATE.js')],
['GUILD_SOUNDBOARD_SOUND_CREATE', require('./GUILD_SOUNDBOARD_SOUND_CREATE.js')],
['GUILD_SOUNDBOARD_SOUND_DELETE', require('./GUILD_SOUNDBOARD_SOUND_DELETE.js')],
['GUILD_SOUNDBOARD_SOUND_UPDATE', require('./GUILD_SOUNDBOARD_SOUND_UPDATE.js')],
['GUILD_STICKERS_UPDATE', require('./GUILD_STICKERS_UPDATE')],
['GUILD_UPDATE', require('./GUILD_UPDATE')],
['INTERACTION_CREATE', require('./INTERACTION_CREATE')],
@@ -52,10 +52,9 @@ const handlers = Object.fromEntries([
['MESSAGE_REACTION_REMOVE_EMOJI', require('./MESSAGE_REACTION_REMOVE_EMOJI')],
['MESSAGE_UPDATE', require('./MESSAGE_UPDATE')],
['PRESENCE_UPDATE', require('./PRESENCE_UPDATE')],
['RATE_LIMITED', require('./RATE_LIMITED')],
['READY', require('./READY')],
['RESUMED', require('./RESUMED')],
['SOUNDBOARD_SOUNDS', require('./SOUNDBOARD_SOUNDS')],
['SOUNDBOARD_SOUNDS', require('./SOUNDBOARD_SOUNDS.js')],
['STAGE_INSTANCE_CREATE', require('./STAGE_INSTANCE_CREATE')],
['STAGE_INSTANCE_DELETE', require('./STAGE_INSTANCE_DELETE')],
['STAGE_INSTANCE_UPDATE', require('./STAGE_INSTANCE_UPDATE')],

View File

@@ -168,8 +168,6 @@
* @property {'ModalSubmitInteractionFieldNotFound'} ModalSubmitInteractionFieldNotFound
* @property {'ModalSubmitInteractionFieldType'} ModalSubmitInteractionFieldType
* @property {'ModalSubmitInteractionFieldEmpty'} ModalSubmitInteractionFieldEmpty
* @property {'ModalSubmitInteractionFieldInvalidChannelType'} ModalSubmitInteractionFieldInvalidChannelType
* @property {'InvalidMissingScopes'} InvalidMissingScopes
* @property {'InvalidScopesWithPermissions'} InvalidScopesWithPermissions
@@ -329,8 +327,6 @@ const keys = [
'ModalSubmitInteractionFieldNotFound',
'ModalSubmitInteractionFieldType',
'ModalSubmitInteractionFieldEmpty',
'ModalSubmitInteractionFieldInvalidChannelType',
'InvalidMissingScopes',
'InvalidScopesWithPermissions',

View File

@@ -115,8 +115,7 @@ const Messages = {
[DjsErrorCodes.EmojiType]: 'Emoji must be a string or GuildEmoji/ReactionEmoji',
[DjsErrorCodes.EmojiManaged]: 'Emoji is managed and has no Author.',
[DjsErrorCodes.MissingManageGuildExpressionsPermission]: guild =>
// eslint-disable-next-line max-len
`Client must have Create Guild Expressions or Manage Guild Expressions permission in guild ${guild} to see emoji authors.`,
`Client must have Manage Guild Expressions permission in guild ${guild} to see emoji authors.`,
[DjsErrorCodes.MissingManageEmojisAndStickersPermission]: guild =>
`Client must have Manage Emojis and Stickers permission in guild ${guild} to see emoji authors.`,
@@ -162,10 +161,6 @@ const Messages = {
`Required field with custom id "${customId}" not found.`,
[DjsErrorCodes.ModalSubmitInteractionFieldType]: (customId, type, expected) =>
`Field with custom id "${customId}" is of type: ${type}; expected ${expected}.`,
[DjsErrorCodes.ModalSubmitInteractionFieldEmpty]: (customId, type) =>
`Required field with custom id "${customId}" is of type: ${type}; expected a non-empty value.`,
[DjsErrorCodes.ModalSubmitInteractionFieldInvalidChannelType]: (customId, type, expected) =>
`The type of channel of the field with custom id "${customId}" is: ${type}; expected ${expected}.`,
[DjsErrorCodes.InvalidMissingScopes]: 'At least one valid scope must be provided for the invite',
[DjsErrorCodes.InvalidScopesWithPermissions]: 'Permissions cannot be set without the bot scope.',

View File

@@ -33,7 +33,6 @@ exports.Events = require('./util/Events');
exports.Formatters = require('./util/Formatters');
exports.GuildMemberFlagsBitField = require('./util/GuildMemberFlagsBitField').GuildMemberFlagsBitField;
exports.IntentsBitField = require('./util/IntentsBitField');
exports.InviteFlagsBitField = require('./util/InviteFlagsBitField.js').InviteFlagsBitField;
exports.LimitedCollection = require('./util/LimitedCollection');
exports.MessageFlagsBitField = require('./util/MessageFlagsBitField');
exports.Options = require('./util/Options');
@@ -81,7 +80,6 @@ exports.GuildStickerManager = require('./managers/GuildStickerManager');
exports.GuildTextThreadManager = require('./managers/GuildTextThreadManager');
exports.MessageManager = require('./managers/MessageManager');
exports.PermissionOverwriteManager = require('./managers/PermissionOverwriteManager');
exports.PollAnswerVoterManager = require('./managers/PollAnswerVoterManager.js').PollAnswerVoterManager;
exports.PresenceManager = require('./managers/PresenceManager');
exports.ReactionManager = require('./managers/ReactionManager');
exports.ReactionUserManager = require('./managers/ReactionUserManager');
@@ -162,7 +160,6 @@ exports.InteractionWebhook = require('./structures/InteractionWebhook');
exports.Invite = require('./structures/Invite');
exports.InviteStageInstance = require('./structures/InviteStageInstance');
exports.InviteGuild = require('./structures/InviteGuild');
exports.LabelComponent = require('./structures/LabelComponent');
exports.Message = require('./structures/Message').Message;
exports.Attachment = require('./structures/Attachment');
exports.AttachmentBuilder = require('./structures/AttachmentBuilder');

View File

@@ -120,12 +120,12 @@ class GuildBanManager extends CachedManager {
return this._add(data, cache);
}
async _fetchMany({ cache, ...apiOptions } = {}) {
async _fetchMany(options = {}) {
const data = await this.client.rest.get(Routes.guildBans(this.guild.id), {
query: makeURLSearchParams(apiOptions),
query: makeURLSearchParams(options),
});
return data.reduce((col, ban) => col.set(ban.user.id, this._add(ban, cache)), new Collection());
return data.reduce((col, ban) => col.set(ban.user.id, this._add(ban, options.cache)), new Collection());
}
/**

View File

@@ -161,7 +161,7 @@ class GuildEmojiManager extends BaseGuildEmojiManager {
const { me } = this.guild.members;
if (!me) throw new DiscordjsError(ErrorCodes.GuildUncachedMe);
if (!me.permissions.any(PermissionFlagsBits.CreateGuildExpressions | PermissionFlagsBits.ManageGuildExpressions)) {
if (!me.permissions.has(PermissionFlagsBits.ManageGuildExpressions)) {
throw new DiscordjsError(ErrorCodes.MissingManageGuildExpressionsPermission, this.guild);
}

View File

@@ -31,15 +31,7 @@ class GuildEmojiRoleManager extends DataManager {
* @readonly
*/
get cache() {
const cache = new Collection();
for (const roleId of this.emoji._roles) {
const role = this.guild.roles.cache.get(roleId);
if (role !== undefined) {
cache.set(roleId, role);
}
}
return cache;
return this.guild.roles.cache.filter(role => this.emoji._roles.includes(role.id));
}
/**

View File

@@ -163,7 +163,6 @@ class GuildManager extends CachedManager {
* Creates a guild.
* <warn>This is only available to bots in fewer than 10 guilds.</warn>
* @param {GuildCreateOptions} options Options for creating the guild
* @deprecated API related to guild ownership may no longer be used.
* @returns {Promise<Guild>} The guild that was created
*/
async create({

View File

@@ -1,24 +1,19 @@
'use strict';
const { process } = require('node:process');
const { setTimeout, clearTimeout } = require('node:timers');
const { Collection } = require('@discordjs/collection');
const { makeURLSearchParams } = require('@discordjs/rest');
const { GatewayRateLimitError } = require('@discordjs/util');
const { DiscordSnowflake } = require('@sapphire/snowflake');
const { Routes, GatewayOpcodes, GatewayDispatchEvents } = require('discord-api-types/v10');
const { Routes, GatewayOpcodes } = require('discord-api-types/v10');
const CachedManager = require('./CachedManager');
const { DiscordjsError, DiscordjsTypeError, DiscordjsRangeError, ErrorCodes } = require('../errors');
const BaseGuildVoiceChannel = require('../structures/BaseGuildVoiceChannel');
const { GuildMember } = require('../structures/GuildMember');
const { Role } = require('../structures/Role');
const { resolveImage } = require('../util/DataResolver');
const Events = require('../util/Events');
const { GuildMemberFlagsBitField } = require('../util/GuildMemberFlagsBitField');
const Partials = require('../util/Partials');
let deprecatedEmittedForEditSoleNickname = false;
/**
* Manages API methods for GuildMembers and stores their cache.
* @extends {CachedManager}
@@ -240,25 +235,19 @@ class GuildMemberManager extends CachedManager {
return new Promise((resolve, reject) => {
if (!query && !users) query = '';
this.guild.shard.send({
op: GatewayOpcodes.RequestGuildMembers,
d: {
guild_id: this.guild.id,
presences,
user_ids: users,
query,
nonce,
limit,
},
});
const fetchedMembers = new Collection();
let i = 0;
const cleanup = () => {
/* eslint-disable no-use-before-define */
clearTimeout(timeout);
this.client.removeListener(Events.Raw, rateLimitHandler);
this.client.decrementMaxListeners();
this.client.removeListener(Events.GuildMembersChunk, handler);
this.client.decrementMaxListeners();
/* eslint-enable no-use-before-define */
};
const timeout = setTimeout(() => {
cleanup();
reject(new DiscordjsError(ErrorCodes.GuildMembersTimeout));
}, time).unref();
const handler = (members, _, chunk) => {
if (chunk.nonce !== nonce) return;
timeout.refresh();
@@ -267,37 +256,19 @@ class GuildMemberManager extends CachedManager {
fetchedMembers.set(member.id, member);
}
if (members.size < 1_000 || (limit && fetchedMembers.size >= limit) || i === chunk.count) {
cleanup();
clearTimeout(timeout);
this.client.removeListener(Events.GuildMembersChunk, handler);
this.client.decrementMaxListeners();
resolve(users && !Array.isArray(users) && fetchedMembers.size ? fetchedMembers.first() : fetchedMembers);
}
};
const requestData = {
guild_id: this.guild.id,
presences,
user_ids: users,
query,
nonce,
limit,
};
const rateLimitHandler = payload => {
if (payload.t === GatewayDispatchEvents.RateLimited && payload.d.meta.nonce === nonce) {
cleanup();
reject(new GatewayRateLimitError(payload.d, requestData));
}
};
this.client.incrementMaxListeners();
this.client.on(Events.Raw, rateLimitHandler);
const timeout = setTimeout(() => {
this.client.removeListener(Events.GuildMembersChunk, handler);
this.client.decrementMaxListeners();
reject(new DiscordjsError(ErrorCodes.GuildMembersTimeout));
}, time).unref();
this.client.incrementMaxListeners();
this.client.on(Events.GuildMembersChunk, handler);
this.guild.shard.send({
op: GatewayOpcodes.RequestGuildMembers,
d: requestData,
});
});
}
@@ -365,8 +336,8 @@ class GuildMemberManager extends CachedManager {
*/
/**
* Edits a member of a guild.
*
* Edits a member of the guild.
* <info>The user must be a member of the guild</info>
* @param {UserResolvable} user The member to edit
* @param {GuildMemberEditOptions} options The options to provide
* @returns {Promise<GuildMember>}
@@ -401,30 +372,13 @@ class GuildMemberManager extends CachedManager {
}
let endpoint;
if (id === this.client.user.id) {
const keys = Object.keys(options);
if (keys.length === 1 && keys[0] === 'nick') {
// For modifying the current application's nickname only, we use the /guilds/{guild.id}/members/@me endpoint.
// This endpoint only requires the CHANGE_NICKNAME permission.
// The other endpoint would require the MANAGE_NICKNAMES permission.
// In v15, this will be split out, so emit a deprecation.
endpoint = Routes.guildMember(this.guild.id, '@me');
if (!deprecatedEmittedForEditSoleNickname) {
process.emitWarning(
// eslint-disable-next-line max-len
"You should use GuildMemberManager#editMe() when changing your nickname. Due to Discord's API changes, GuildMemberManager#edit() will end up requiring MANAGE_NICKNAMES in v15.",
'DeprecationWarning',
);
deprecatedEmittedForEditSoleNickname = true;
}
}
if (keys.length === 1 && keys[0] === 'nick') endpoint = Routes.guildMember(this.guild.id);
else endpoint = Routes.guildMember(this.guild.id, id);
} else {
endpoint = Routes.guildMember(this.guild.id, id);
}
endpoint ??= Routes.guildMember(this.guild.id, id);
const d = await this.client.rest.patch(endpoint, { body: options, reason });
const clone = this.cache.get(id)?._clone();
@@ -432,38 +386,6 @@ class GuildMemberManager extends CachedManager {
return clone ?? this._add(d, false);
}
/**
* The data for editing the current application's guild member.
*
* @typedef {Object} GuildMemberEditMeOptions
* @property {?string} [nick] The nickname to set
* @property {?(BufferResolvable|Base64Resolvable)} [banner] The banner to set
* @property {?(BufferResolvable|Base64Resolvable)} [avatar] The avatar to set
* @property {?string} [bio] The bio to set
* @property {string} [reason] The reason to use
*/
/**
* Edits the current application's guild member in a guild.
*
* @param {GuildMemberEditMeOptions} options The options to provide
* @returns {Promise<GuildMember>}
*/
async editMe({ reason, ...options }) {
const data = await this.client.rest.patch(Routes.guildMember(this.guild.id, '@me'), {
body: {
...options,
banner: options.banner && (await resolveImage(options.banner)),
avatar: options.avatar && (await resolveImage(options.avatar)),
},
reason,
});
const clone = this.me?._clone();
clone?._patch(data);
return clone ?? this._add(data, false);
}
/**
* Options used for pruning guild members.
* <info>It's recommended to set {@link GuildPruneMembersOptions#count options.count}

View File

@@ -33,17 +33,8 @@ class GuildMemberRoleManager extends DataManager {
* @readonly
*/
get cache() {
const cache = new Collection();
cache.set(this.guild.id, this.guild.roles.everyone);
for (const roleId of this.member._roles) {
const role = this.guild.roles.cache.get(roleId);
if (role !== undefined) {
cache.set(roleId, role);
}
}
return cache;
const everyone = this.guild.roles.everyone;
return this.guild.roles.cache.filter(role => this.member._roles.includes(role.id)).set(everyone.id, everyone);
}
/**

View File

@@ -111,12 +111,12 @@ class MessageManager extends CachedManager {
return this._add(data, cache);
}
async _fetchMany({ cache, ...apiOptions } = {}) {
async _fetchMany(options = {}) {
const data = await this.client.rest.get(Routes.channelMessages(this.channel.id), {
query: makeURLSearchParams(apiOptions),
query: makeURLSearchParams(options),
});
return data.reduce((_data, message) => _data.set(message.id, this._add(message, cache)), new Collection());
return data.reduce((_data, message) => _data.set(message.id, this._add(message, options.cache)), new Collection());
}
/**
@@ -146,8 +146,8 @@ class MessageManager extends CachedManager {
*/
/**
* Fetches the pinned messages of this channel, returning a paginated result.
* <info>The returned messages do not contain any reaction data.
* Fetches the pinned messages of this channel and returns a collection of them.
* <info>The returned Collection does not contain any reaction data of the messages.
* Those need to be fetched separately.</info>
*
* @param {FetchPinnedMessagesOptions} [options={}] Options for fetching pinned messages
@@ -158,11 +158,11 @@ class MessageManager extends CachedManager {
* .then(messages => console.log(`Received ${messages.items.length} messages`))
* .catch(console.error);
*/
async fetchPins({ cache, ...apiOptions } = {}) {
async fetchPins(options = {}) {
const data = await this.client.rest.get(Routes.channelMessagesPins(this.channel.id), {
query: makeURLSearchParams({
...apiOptions,
before: apiOptions.before && new Date(apiOptions.before).toISOString(),
...options,
before: options.before && new Date(options.before).toISOString(),
}),
});
@@ -172,7 +172,7 @@ class MessageManager extends CachedManager {
get pinnedAt() {
return new Date(this.pinnedTimestamp);
},
message: this._add(item.message, cache),
message: this._add(item.message, options.cache),
})),
hasMore: data.has_more,
};

View File

@@ -73,7 +73,7 @@ class ApplicationCommand extends Base {
if ('name_localizations' in data) {
/**
* The name localizations for this command
* @type {?LocalizationMap}
* @type {?Object<Locale, string>}
*/
this.nameLocalizations = data.name_localizations;
} else {
@@ -101,7 +101,7 @@ class ApplicationCommand extends Base {
if ('description_localizations' in data) {
/**
* The description localizations for this command
* @type {?LocalizationMap}
* @type {?Object<Locale, string>}
*/
this.descriptionLocalizations = data.description_localizations;
} else {
@@ -227,11 +227,11 @@ class ApplicationCommand extends Base {
* @typedef {Object} ApplicationCommandData
* @property {string} name The name of the command, must be in all lowercase if type is
* {@link ApplicationCommandType.ChatInput}
* @property {LocalizationMap} [nameLocalizations] The localizations for the command name
* @property {Object<Locale, string>} [nameLocalizations] The localizations for the command name
* @property {string} description The description of the command,
* if type is {@link ApplicationCommandType.ChatInput} or {@link ApplicationCommandType.PrimaryEntryPoint}
* @property {boolean} [nsfw] Whether the command is age-restricted
* @property {LocalizationMap} [descriptionLocalizations] The localizations for the command description,
* @property {Object<Locale, string>} [descriptionLocalizations] The localizations for the command description,
* if type is {@link ApplicationCommandType.ChatInput} or {@link ApplicationCommandType.PrimaryEntryPoint}
* @property {ApplicationCommandType} [type=ApplicationCommandType.ChatInput] The type of the command
* @property {ApplicationCommandOptionData[]} [options] Options for the command
@@ -253,9 +253,9 @@ class ApplicationCommand extends Base {
* @typedef {Object} ApplicationCommandOptionData
* @property {ApplicationCommandOptionType} type The type of the option
* @property {string} name The name of the option
* @property {LocalizationMap} [nameLocalizations] The name localizations for the option
* @property {Object<Locale, string>} [nameLocalizations] The name localizations for the option
* @property {string} description The description of the option
* @property {LocalizationMap} [descriptionLocalizations] The description localizations for the option
* @property {Object<Locale, string>} [descriptionLocalizations] The description localizations for the option
* @property {boolean} [autocomplete] Whether the autocomplete interaction is enabled for a
* {@link ApplicationCommandOptionType.String}, {@link ApplicationCommandOptionType.Integer} or
* {@link ApplicationCommandOptionType.Number} option
@@ -277,7 +277,7 @@ class ApplicationCommand extends Base {
/**
* @typedef {Object} ApplicationCommandOptionChoiceData
* @property {string} name The name of the choice
* @property {LocalizationMap} [nameLocalizations] The localized names for this choice
* @property {Object<Locale, string>} [nameLocalizations] The localized names for this choice
* @property {string|number} value The value of the choice
*/
@@ -308,7 +308,7 @@ class ApplicationCommand extends Base {
/**
* Edits the localized names of this ApplicationCommand
* @param {LocalizationMap} nameLocalizations The new localized names for the command
* @param {Object<Locale, string>} nameLocalizations The new localized names for the command
* @returns {Promise<ApplicationCommand>}
* @example
* // Edit the name localizations of this command
@@ -334,7 +334,7 @@ class ApplicationCommand extends Base {
/**
* Edits the localized descriptions of this ApplicationCommand
* @param {LocalizationMap} descriptionLocalizations The new localized descriptions for the command
* @param {Object<Locale, string>} descriptionLocalizations The new localized descriptions for the command
* @returns {Promise<ApplicationCommand>}
* @example
* // Edit the description localizations of this command
@@ -550,10 +550,10 @@ class ApplicationCommand extends Base {
* @typedef {Object} ApplicationCommandOption
* @property {ApplicationCommandOptionType} type The type of the option
* @property {string} name The name of the option
* @property {LocalizationMap} [nameLocalizations] The localizations for the option name
* @property {Object<Locale, string>} [nameLocalizations] The localizations for the option name
* @property {string} [nameLocalized] The localized name for this option
* @property {string} description The description of the option
* @property {LocalizationMap} [descriptionLocalizations] The localizations for the option description
* @property {Object<Locale, string>} [descriptionLocalizations] The localizations for the option description
* @property {string} [descriptionLocalized] The localized description for this option
* @property {boolean} [required] Whether the option is required
* @property {boolean} [autocomplete] Whether the autocomplete interaction is enabled for a

View File

@@ -13,7 +13,7 @@ class ApplicationRoleConnectionMetadata {
/**
* The name localizations for this metadata field
* @type {?LocalizationMap}
* @type {?Object<Locale, string>}
*/
this.nameLocalizations = data.name_localizations ?? null;
@@ -25,7 +25,7 @@ class ApplicationRoleConnectionMetadata {
/**
* The description localizations for this metadata field
* @type {?LocalizationMap}
* @type {?Object<Locale, string>}
*/
this.descriptionLocalizations = data.description_localizations ?? null;

View File

@@ -375,9 +375,9 @@ class ClientApplication extends Application {
* Data for creating or editing an application role connection metadata.
* @typedef {Object} ApplicationRoleConnectionMetadataEditOptions
* @property {string} name The name of the metadata field
* @property {?LocalizationMap} [nameLocalizations] The name localizations for the metadata field
* @property {?Object<Locale, string>} [nameLocalizations] The name localizations for the metadata field
* @property {string} description The description of the metadata field
* @property {?LocalizationMap} [descriptionLocalizations] The description localizations for the metadata field
* @property {?Object<Locale, string>} [descriptionLocalizations] The description localizations for the metadata field
* @property {string} key The dictionary key of the metadata field
* @property {ApplicationRoleConnectionMetadataType} type The type of the metadata field
*/

View File

@@ -80,19 +80,14 @@ class CommandInteraction extends BaseInteraction {
}
/**
* @typedef {Object} BaseInteractionResolvedData
* Represents the resolved data of a received command interaction.
* @typedef {Object} CommandInteractionResolvedData
* @property {Collection<Snowflake, User>} [users] The resolved users
* @property {Collection<Snowflake, GuildMember|APIGuildMember>} [members] The resolved guild members
* @property {Collection<Snowflake, Role|APIRole>} [roles] The resolved roles
* @property {Collection<Snowflake, BaseChannel|APIChannel>} [channels] The resolved channels
* @property {Collection<Snowflake, Attachment>} [attachments] The resolved attachments
*/
/**
* Represents the resolved data of a received command interaction.
*
* @typedef {BaseInteractionResolvedData} CommandInteractionResolvedData
* @property {Collection<Snowflake, Message|APIMessage>} [messages] The resolved messages
* @property {Collection<Snowflake, Attachment>} [attachments] The resolved attachments
*/
/**

View File

@@ -832,7 +832,6 @@ class Guild extends AnonymousGuild {
* @property {number} [afkTimeout] The AFK timeout of the guild
* @property {?(BufferResolvable|Base64Resolvable)} [icon] The icon of the guild
* @property {GuildMemberResolvable} [owner] The owner of the guild
* <warn>This property is **deprecated** as API related to guild ownership may no longer be used.</warn>
* @property {?(BufferResolvable|Base64Resolvable)} [splash] The invite splash image of the guild
* @property {?(BufferResolvable|Base64Resolvable)} [discoverySplash] The discovery splash image of the guild
* @property {?(BufferResolvable|Base64Resolvable)} [banner] The banner of the guild
@@ -1198,7 +1197,12 @@ class Guild extends AnonymousGuild {
* @param {GuildMemberResolvable} owner The new owner of the guild
* @param {string} [reason] Reason for setting the new owner
* @returns {Promise<Guild>}
* @deprecated API related to guild ownership may no longer be used.
* @example
* // Edit the guild owner
* guild.setOwner(guild.members.cache.first())
* .then(guild => guild.fetchOwner())
* .then(owner => console.log(`Updated the guild owner to ${owner.displayName}`))
* .catch(console.error);
*/
setOwner(owner, reason) {
return this.edit({ owner, reason });
@@ -1341,7 +1345,11 @@ class Guild extends AnonymousGuild {
* @param {GuildMFALevel} level The MFA level
* @param {string} [reason] Reason for changing the guild's MFA level
* @returns {Promise<Guild>}
* @deprecated API related to guild ownership may no longer be used.
* @example
* // Set the MFA level of the guild to Elevated
* guild.setMFALevel(GuildMFALevel.Elevated)
* .then(guild => console.log("Set guild's MFA level to Elevated"))
* .catch(console.error);
*/
async setMFALevel(level, reason) {
await this.client.rest.post(Routes.guildMFA(this.id), {
@@ -1371,7 +1379,6 @@ class Guild extends AnonymousGuild {
/**
* Deletes the guild.
* @returns {Promise<Guild>}
* @deprecated API related to guild ownership may no longer be used.
* @example
* // Delete a guild
* guild.delete()

View File

@@ -24,6 +24,12 @@ class GuildMember extends Base {
*/
this.guild = guild;
/**
* The timestamp the member joined the guild at
* @type {?number}
*/
this.joinedTimestamp = null;
/**
* The last timestamp this member started boosting the guild
* @type {?number}
@@ -56,7 +62,7 @@ class GuildMember extends Base {
*/
Object.defineProperty(this, '_roles', { value: [], writable: true });
this._patch(data);
if (data) this._patch(data);
}
_patch(data) {
@@ -89,17 +95,7 @@ class GuildMember extends Base {
this.banner ??= null;
}
if ('joined_at' in data) {
/**
* The timestamp the member joined the guild at
*
* @type {?number}
*/
this.joinedTimestamp = data.joined_at && Date.parse(data.joined_at);
} else {
this.joinedTimestamp ??= null;
}
if ('joined_at' in data) this.joinedTimestamp = Date.parse(data.joined_at);
if ('premium_since' in data) {
this.premiumSinceTimestamp = data.premium_since ? Date.parse(data.premium_since) : null;
}
@@ -426,9 +422,7 @@ class GuildMember extends Base {
* .catch(console.error);
*/
setNickname(nick, reason) {
return this.user.id === this.client.user.id
? this.guild.members.editMe({ nick, reason })
: this.edit({ nick, reason });
return this.edit({ nick, reason });
}
/**

View File

@@ -120,7 +120,6 @@ class GuildTemplate extends Base {
* @param {string} name The name of the guild
* @param {BufferResolvable|Base64Resolvable} [icon] The icon for the guild
* @returns {Promise<Guild>}
* @deprecated API related to guild ownership may no longer be used.
*/
async createGuild(name, icon) {
const { client } = this;

View File

@@ -6,7 +6,6 @@ const { GuildScheduledEvent } = require('./GuildScheduledEvent');
const IntegrationApplication = require('./IntegrationApplication');
const InviteStageInstance = require('./InviteStageInstance');
const { DiscordjsError, ErrorCodes } = require('../errors');
const { InviteFlagsBitField } = require('../util/InviteFlagsBitField.js');
/**
* Represents an invitation to a guild channel.
@@ -223,17 +222,6 @@ class Invite extends Base {
} else {
this.guildScheduledEvent ??= null;
}
if ('flags' in data) {
/**
* The flags of this invite.
*
* @type {Readonly<InviteFlagsBitField>}
*/
this.flags = new InviteFlagsBitField(data.flags).freeze();
} else {
this.flags ??= new InviteFlagsBitField().freeze();
}
}
/**

View File

@@ -442,15 +442,11 @@ class Message extends Base {
}
if (data.poll) {
if (this.poll) {
this.poll._patch(data.poll);
} else {
/**
* The poll that was sent with the message
* @type {?Poll}
*/
this.poll = new Poll(this.client, data.poll, this, this.channel);
}
/**
* The poll that was sent with the message
* @type {?Poll}
*/
this.poll = new Poll(this.client, data.poll, this);
} else {
this.poll ??= null;
}
@@ -623,7 +619,7 @@ class Message extends Base {
* Similar to createReactionCollector but in promise form.
* Resolves with a collection of reactions that pass the specified filter.
* @param {AwaitReactionsOptions} [options={}] Optional options to pass to the internal collector
* @returns {Promise<Collection<string|Snowflake, MessageReaction>>}
* @returns {Promise<Collection<string | Snowflake, MessageReaction>>}
* @example
* // Create a reaction collector
* const filter = (reaction, user) => reaction.emoji.name === '👌' && user.id === 'someId'
@@ -781,16 +777,11 @@ class Message extends Base {
*/
get pinnable() {
const { channel } = this;
if (this.system) return false;
if (!this.guild) return true;
if (!channel || channel.isVoiceBased() || !channel.viewable) return false;
const permissions = channel?.permissionsFor(this.client.user);
if (!permissions) return false;
return (
permissions.has(PermissionFlagsBits.ReadMessageHistory | PermissionFlagsBits.PinMessages) ||
permissions.has(PermissionFlagsBits.ReadMessageHistory | PermissionFlagsBits.ManageMessages)
return Boolean(
!this.system &&
(!this.guild ||
(channel?.viewable &&
channel?.permissionsFor(this.client.user)?.has(PermissionFlagsBits.ManageMessages, false))),
);
}

View File

@@ -4,48 +4,23 @@ const { Collection } = require('@discordjs/collection');
const { ComponentType } = require('discord-api-types/v10');
const { DiscordjsTypeError, ErrorCodes } = require('../errors');
/**
* @typedef {Object} ModalSelectedMentionables
* @property {Collection<Snowflake, User>} users The selected users
* @property {Collection<Snowflake, GuildMember | APIGuildMember>} members The selected members
* @property {Collection<Snowflake, Role | APIRole>} roles The selected roles
*/
/**
* Represents the serialized fields from a modal submit interaction
*/
class ModalSubmitFields {
constructor(components, resolved) {
constructor(components) {
/**
* The components within the modal
*
* @type {Array<ActionRowModalData|LabelModalData|TextDisplayModalData>}
* @type {ActionRowModalData[]}
*/
this.components = components;
/**
* The interaction resolved data
*
* @name ModalSubmitFields#resolved
* @type {?Readonly<BaseInteractionResolvedData>}
*/
Object.defineProperty(this, 'resolved', { value: resolved ? Object.freeze(resolved) : null });
/**
* The extracted fields from the modal
* @type {Collection<string, ModalData>}
*/
this.fields = components.reduce((accumulator, next) => {
// For legacy support of action rows
if ('components' in next) {
for (const component of next.components) accumulator.set(component.customId, component);
}
// For label components
if ('component' in next) {
accumulator.set(next.component.customId, next.component);
}
next.components.forEach(component => accumulator.set(component.customId, component));
return accumulator;
}, new Collection());
}
@@ -67,165 +42,13 @@ class ModalSubmitFields {
return field;
}
/**
* Gets a component by custom id and property and checks its type.
*
* @param {string} customId The custom id of the component.
* @param {ComponentType[]} allowedTypes The allowed types of the component.
* @param {string[]} properties The properties to check for for `required`.
* @param {boolean} required Whether to throw an error if the component value(s) are not found.
* @returns {ModalData} The option, if found.
* @private
*/
_getTypedComponent(customId, allowedTypes, properties, required) {
const component = this.getField(customId);
if (!allowedTypes.includes(component.type)) {
throw new DiscordjsTypeError(
ErrorCodes.ModalSubmitInteractionFieldNotFound,
customId,
component.type,
allowedTypes.join(', '),
);
} else if (required && properties.every(prop => component[prop] === null || component[prop] === undefined)) {
throw new DiscordjsTypeError(ErrorCodes.ModalSubmitInteractionFieldEmpty, customId, component.type);
}
return component;
}
/**
* Gets the value of a text input component given a custom id
* @param {string} customId The custom id of the text input component
* @returns {string}
*/
getTextInputValue(customId) {
return this._getTypedComponent(customId, [ComponentType.TextInput]).value;
}
/**
* Gets the values of a string select component given a custom id
*
* @param {string} customId The custom id of the string select component
* @returns {string[]}
*/
getStringSelectValues(customId) {
return this._getTypedComponent(customId, [ComponentType.StringSelect]).values;
}
/**
* Gets users component
*
* @param {string} customId The custom id of the component
* @param {boolean} [required=false] Whether to throw an error if the component value is not found or empty
* @returns {?Collection<Snowflake, User>} The selected users, or null if none were selected and not required
*/
getSelectedUsers(customId, required = false) {
const component = this._getTypedComponent(
customId,
[ComponentType.UserSelect, ComponentType.MentionableSelect],
['users'],
required,
);
return component.users ?? null;
}
/**
* Gets roles component
*
* @param {string} customId The custom id of the component
* @param {boolean} [required=false] Whether to throw an error if the component value is not found or empty
* @returns {?Collection<Snowflake, Role|APIRole>} The selected roles, or null if none were selected and not required
*/
getSelectedRoles(customId, required = false) {
const component = this._getTypedComponent(
customId,
[ComponentType.RoleSelect, ComponentType.MentionableSelect],
['roles'],
required,
);
return component.roles ?? null;
}
/**
* Gets channels component
*
* @param {string} customId The custom id of the component
* @param {boolean} [required=false] Whether to throw an error if the component value is not found or empty
* @param {ChannelType[]} [channelTypes=[]] The allowed types of channels. If empty, all channel types are allowed.
* @returns {?Collection<Snowflake, GuildChannel|ThreadChannel|APIChannel>} The selected channels,
* or null if none were selected and not required
*/
getSelectedChannels(customId, required = false, channelTypes = []) {
const component = this._getTypedComponent(customId, [ComponentType.ChannelSelect], ['channels'], required);
const channels = component.channels;
if (channels && channelTypes.length > 0) {
for (const channel of channels.values()) {
if (!channelTypes.includes(channel.type)) {
throw new DiscordjsTypeError(
ErrorCodes.ModalSubmitInteractionComponentInvalidChannelType,
customId,
channel.type,
channelTypes.join(', '),
);
}
}
}
return channels ?? null;
}
/**
* Gets members component
*
* @param {string} customId The custom id of the component
* @returns {?Collection<Snowflake, GuildMember|APIGuildMember>} The selected members,
* or null if none were selected or the users were not present in the guild
*/
getSelectedMembers(customId) {
const component = this._getTypedComponent(
customId,
[ComponentType.UserSelect, ComponentType.MentionableSelect],
['members'],
false,
);
return component.members ?? null;
}
/**
* Gets mentionables component
*
* @param {string} customId The custom id of the component
* @param {boolean} [required=false] Whether to throw an error if the component value is not found or empty
* @returns {?ModalSelectedMentionables} The selected mentionables, or null if none were selected and not required
*/
getSelectedMentionables(customId, required = false) {
const component = this._getTypedComponent(
customId,
[ComponentType.MentionableSelect],
['users', 'members', 'roles'],
required,
);
if (component.users || component.members || component.roles) {
return {
users: component.users ?? new Collection(),
members: component.members ?? new Collection(),
roles: component.roles ?? new Collection(),
};
}
return null;
}
/**
* Gets file upload component
*
* @param {string} customId The custom id of the component
* @param {boolean} [required=false] Whether to throw an error if the component value is not found or empty
* @returns {?Collection<Snowflake, Attachment>} The uploaded files, or null if none were uploaded and not required
*/
getUploadedFiles(customId, required = false) {
return this._getTypedComponent(customId, [ComponentType.FileUpload], ['attachments'], required).attachments ?? null;
return this.getField(customId, ComponentType.TextInput).value;
}
}

View File

@@ -1,61 +1,24 @@
'use strict';
const { Collection } = require('@discordjs/collection');
const { lazy } = require('@discordjs/util');
const BaseInteraction = require('./BaseInteraction');
const InteractionWebhook = require('./InteractionWebhook');
const ModalSubmitFields = require('./ModalSubmitFields');
const InteractionResponses = require('./interfaces/InteractionResponses');
const { transformResolved } = require('../util/Util');
const getMessage = lazy(() => require('./Message').Message);
const getAttachment = lazy(() => require('./Attachment'));
/**
* @typedef {Object} BaseModalData
* @property {ComponentType} type The component type of the field
* @property {number} id The id of the field
*/
/**
* @typedef {BaseModalData} FileUploadModalData
* @property {string} customId The custom id of the file upload
* @property {Snowflake[]} values The values of the file upload
* @property {Collection<Snowflake, Attachment>} [attachments] The resolved attachments
*/
/**
* @typedef {BaseModalData} TextInputModalData
* @property {string} customId The custom id of the field
* @typedef {Object} ModalData
* @property {string} value The value of the field
*/
/**
* @typedef {BaseModalData} SelectMenuModalData
* @property {ComponentType} type The component type of the field
* @property {string} customId The custom id of the field
* @property {string[]} values The values of the field
* @property {Collection<Snowflake, GuildMember|APIGuildMember>} [members] The resolved members
* @property {Collection<Snowflake, User|APIUser>} [users] The resolved users
* @property {Collection<Snowflake, Role|APIRole>} [roles] The resolved roles
* @property {Collection<Snowflake, BaseChannel|APIChannel>} [channels] The resolved channels
*/
/**
* @typedef {BaseModalData} TextDisplayModalData
*/
/**
* @typedef {SelectMenuModalData|TextInputModalData|FileUploadModalData} ModalData
*/
/**
* @typedef {BaseModalData} LabelModalData
* @property {ModalData} component The component within the label
*/
/**
* @typedef {BaseModalData} ActionRowModalData
* @property {TextInputModalData[]} components The components of this action row
* @typedef {Object} ActionRowModalData
* @property {ModalData[]} components The components of this action row
* @property {ComponentType} type The component type of the action row
*/
/**
@@ -84,24 +47,15 @@ class ModalSubmitInteraction extends BaseInteraction {
/**
* The components within the modal
*
* @type {Array<ActionRowModalData | LabelModalData | TextDisplayModalData>}
* @type {ActionRowModalData[]}
*/
this.components = data.data.components?.map(component =>
ModalSubmitInteraction.transformComponent(component, data.data.resolved, {
client: this.client,
guild: this.guild,
}),
);
this.components = data.data.components?.map(component => ModalSubmitInteraction.transformComponent(component));
/**
* The fields within the modal
* @type {ModalSubmitFields}
*/
this.fields = new ModalSubmitFields(
this.components,
transformResolved({ client: this.client, guild: this.guild, channel: this.channel }, data.data.resolved),
);
this.fields = new ModalSubmitFields(this.components);
/**
* Whether the reply to this interaction has been deferred
@@ -131,102 +85,19 @@ class ModalSubmitInteraction extends BaseInteraction {
/**
* Transforms component data to discord.js-compatible data
* @param {*} rawComponent The data to transform
* @param {APIInteractionDataResolved} [resolved] The resolved data for the interaction
* @param {*} [extra] Extra data required for the transformation
* @returns {ModalData[]}
*/
static transformComponent(rawComponent, resolved, { client, guild } = {}) {
if ('components' in rawComponent) {
return {
type: rawComponent.type,
id: rawComponent.id,
components: rawComponent.components.map(component =>
this.transformComponent(component, resolved, { client, guild }),
),
};
}
if ('component' in rawComponent) {
return {
type: rawComponent.type,
id: rawComponent.id,
component: this.transformComponent(rawComponent.component, resolved, { client, guild }),
};
}
const data = {
type: rawComponent.type,
id: rawComponent.id,
};
// Text display components do not have custom ids.
if ('custom_id' in rawComponent) data.customId = rawComponent.custom_id;
if ('value' in rawComponent) data.value = rawComponent.value;
if (rawComponent.values) {
data.values = rawComponent.values;
/* eslint-disable max-depth */
if (resolved) {
const { members, users, channels, roles, attachments } = resolved;
const valueSet = new Set(rawComponent.values);
if (users) {
data.users = new Collection();
for (const [id, user] of Object.entries(users)) {
if (valueSet.has(id)) {
data.users.set(id, client.users._add(user));
}
}
static transformComponent(rawComponent) {
return rawComponent.components
? {
type: rawComponent.type,
components: rawComponent.components.map(component => this.transformComponent(component)),
}
if (channels) {
data.channels = new Collection();
for (const [id, apiChannel] of Object.entries(channels)) {
if (valueSet.has(id)) {
data.channels.set(id, client.channels._add(apiChannel, guild) ?? apiChannel);
}
}
}
if (members) {
data.members = new Collection();
for (const [id, member] of Object.entries(members)) {
if (valueSet.has(id)) {
const user = users?.[id];
data.members.set(id, guild?.members._add({ user, ...member }) ?? member);
}
}
}
if (roles) {
data.roles = new Collection();
for (const [id, role] of Object.entries(roles)) {
if (valueSet.has(id)) {
data.roles.set(id, guild?.roles._add(role) ?? role);
}
}
}
if (attachments) {
data.attachments = new Collection();
for (const [id, attachment] of Object.entries(attachments)) {
if (valueSet.has(id)) {
data.attachments.set(id, new (getAttachment())(attachment));
}
}
}
}
/* eslint-enable max-depth */
}
return data;
: {
value: rawComponent.value,
type: rawComponent.type,
customId: rawComponent.custom_id,
};
}
/**

View File

@@ -22,7 +22,7 @@ class PermissionOverwrites extends Base {
*/
Object.defineProperty(this, 'channel', { value: channel });
this._patch(data);
if (data) this._patch(data);
}
_patch(data) {

View File

@@ -11,30 +11,9 @@ const { ErrorCodes } = require('../errors/index');
* @extends {Base}
*/
class Poll extends Base {
constructor(client, data, message, channel) {
constructor(client, data, message) {
super(client);
/**
* The id of the channel that this poll is in
* @type {Snowflake}
*/
this.channelId = data.channel_id ?? channel.id;
/**
* The channel that this poll is in
* @name Poll#channel
* @type {TextBasedChannel}
* @readonly
*/
Object.defineProperty(this, 'channel', { value: channel });
/**
* The id of the message that started this poll
* @type {Snowflake}
*/
this.messageId = data.message_id ?? message.id;
/**
* The message that started this poll
* @name Poll#message
@@ -45,26 +24,50 @@ class Poll extends Base {
Object.defineProperty(this, 'message', { value: message });
/**
* The answers of this poll
* @type {Collection<number, PollAnswer|PartialPollAnswer>}
* The media for a poll's question
* @typedef {Object} PollQuestionMedia
* @property {string} text The text of this question
*/
this.answers = new Collection();
/**
* The media for this poll's question
* @type {PollQuestionMedia}
*/
this.question = {
text: data.question.text,
};
/**
* The answers of this poll
* @type {Collection<number, PollAnswer>}
*/
this.answers = data.answers.reduce(
(acc, answer) => acc.set(answer.answer_id, new PollAnswer(this.client, answer, this)),
new Collection(),
);
/**
* The timestamp when this poll expires
* @type {number}
*/
this.expiresTimestamp = Date.parse(data.expiry);
/**
* Whether this poll allows multiple answers
* @type {boolean}
*/
this.allowMultiselect = data.allow_multiselect;
/**
* The layout type of this poll
* @type {PollLayoutType}
*/
this.layoutType = data.layout_type;
this._patch(data);
}
_patch(data) {
if (data.answers) {
for (const answer of data.answers) {
const existing = this.answers.get(answer.answer_id);
if (existing) {
existing._patch(answer);
} else {
this.answers.set(answer.answer_id, new PollAnswer(this.client, answer, this));
}
}
}
if (data.results) {
/**
* Whether this poll's results have been precisely counted
@@ -79,84 +82,15 @@ class Poll extends Base {
} else {
this.resultsFinalized ??= false;
}
if ('allow_multiselect' in data) {
/**
* Whether this poll allows multiple answers
* @type {boolean}
*/
this.allowMultiselect = data.allow_multiselect;
} else {
this.allowMultiselect ??= null;
}
if ('layout_type' in data) {
/**
* The layout type of this poll
* @type {PollLayoutType}
*/
this.layoutType = data.layout_type;
} else {
this.layoutType ??= null;
}
if ('expiry' in data) {
/**
* The timestamp when this poll expires
* @type {?number}
*/
this.expiresTimestamp = data.expiry && Date.parse(data.expiry);
} else {
this.expiresTimestamp ??= null;
}
if (data.question) {
/**
* The media for a poll's question
* @typedef {Object} PollQuestionMedia
* @property {?string} text The text of this question
*/
/**
* The media for this poll's question
* @type {PollQuestionMedia}
*/
this.question = {
text: data.question.text,
};
} else {
this.question ??= {
text: null,
};
}
}
/**
* The date when this poll expires
* @type {?Date}
* @type {Date}
* @readonly
*/
get expiresAt() {
return this.expiresTimestamp && new Date(this.expiresTimestamp);
}
/**
* Whether this poll is a partial
* @type {boolean}
* @readonly
*/
get partial() {
return this.allowMultiselect === null;
}
/**
* Fetches the message that started this poll, then updates the poll from the fetched message.
* @returns {Promise<Poll>}
*/
async fetch() {
await this.channel.messages.fetch(this.messageId);
return this;
return new Date(this.expiresTimestamp);
}
/**
@@ -164,11 +98,11 @@ class Poll extends Base {
* @returns {Promise<Message>}
*/
async end() {
if (this.expiresTimestamp !== null && Date.now() > this.expiresTimestamp) {
if (Date.now() > this.expiresTimestamp) {
throw new DiscordjsError(ErrorCodes.PollAlreadyExpired);
}
return this.channel.messages.endPoll(this.messageId);
return this.message.channel.messages.endPoll(this.message.id);
}
}

View File

@@ -1,11 +1,7 @@
'use strict';
const process = require('node:process');
const Base = require('./Base.js');
const { Emoji } = require('./Emoji.js');
const { PollAnswerVoterManager } = require('../managers/PollAnswerVoterManager.js');
let deprecationEmittedForFetchVoters = false;
const Base = require('./Base');
const { Emoji } = require('./Emoji');
/**
* Represents an answer to a {@link Poll}
@@ -18,7 +14,7 @@ class PollAnswer extends Base {
/**
* The {@link Poll} this answer is part of
* @name PollAnswer#poll
* @type {Poll|PartialPoll}
* @type {Poll}
* @readonly
*/
Object.defineProperty(this, 'poll', { value: poll });
@@ -30,10 +26,10 @@ class PollAnswer extends Base {
this.id = data.answer_id;
/**
* The manager of the voters for this answer
* @type {PollAnswerVoterManager}
* The text of this answer
* @type {?string}
*/
this.voters = new PollAnswerVoterManager(this);
this.text = data.poll_media.text ?? null;
/**
* The raw emoji of this answer
@@ -41,7 +37,7 @@ class PollAnswer extends Base {
* @type {?APIPartialEmoji}
* @private
*/
Object.defineProperty(this, '_emoji', { value: null, writable: true });
Object.defineProperty(this, '_emoji', { value: data.poll_media.emoji ?? null });
this._patch(data);
}
@@ -55,17 +51,7 @@ class PollAnswer extends Base {
*/
this.voteCount = data.count;
} else {
this.voteCount ??= this.voters.cache.size;
}
/**
* The text of this answer
* @type {?string}
*/
this.text ??= data.poll_media?.text ?? null;
if (data.poll_media?.emoji) {
this._emoji = data.poll_media.emoji;
this.voteCount ??= 0;
}
}
@@ -78,15 +64,6 @@ class PollAnswer extends Base {
return this.client.emojis.cache.get(this._emoji.id) ?? new Emoji(this.client, this._emoji);
}
/**
* Whether this poll answer is a partial.
* @type {boolean}
* @readonly
*/
get partial() {
return this.poll.partial || (this.text === null && this.emoji === null);
}
/**
* Options used for fetching voters of a poll answer.
* @typedef {Object} BaseFetchPollAnswerVotersOptions
@@ -98,16 +75,14 @@ class PollAnswer extends Base {
* Fetches the users that voted for this answer.
* @param {BaseFetchPollAnswerVotersOptions} [options={}] The options for fetching voters
* @returns {Promise<Collection<Snowflake, User>>}
* @deprecated Use {@link PollAnswerVoterManager#fetch} instead
*/
fetchVoters({ after, limit } = {}) {
if (!deprecationEmittedForFetchVoters) {
process.emitWarning('PollAnswer#fetchVoters is deprecated. Use PollAnswer#voters#fetch instead.');
deprecationEmittedForFetchVoters = true;
}
return this.voters.fetch({ after, limit });
return this.poll.message.channel.messages.fetchPollAnswerVoters({
messageId: this.poll.message.id,
answerId: this.id,
after,
limit,
});
}
}

View File

@@ -34,7 +34,7 @@ class Role extends Base {
*/
this.unicodeEmoji = null;
this._patch(data);
if (data) this._patch(data);
}
_patch(data) {

View File

@@ -49,7 +49,7 @@ class ThreadChannel extends BaseChannel {
* @type {ThreadMemberManager}
*/
this.members = new ThreadMemberManager(this);
this._patch(data);
if (data) this._patch(data);
}
_patch(data) {

View File

@@ -267,11 +267,7 @@ class User extends Base {
* @readonly
*/
get defaultAvatarURL() {
const index =
this.discriminator === '0' || this.discriminator === '0000'
? calculateUserDefaultAvatarIndex(this.id)
: this.discriminator % 5;
const index = this.discriminator === '0' ? calculateUserDefaultAvatarIndex(this.id) : this.discriminator % 5;
return this.client.rest.cdn.defaultAvatar(index);
}
@@ -326,7 +322,7 @@ class User extends Base {
*/
get tag() {
return typeof this.username === 'string'
? this.discriminator === '0' || this.discriminator === '0000'
? this.discriminator === '0'
? this.username
: `${this.username}#${this.discriminator}`
: null;

View File

@@ -22,7 +22,7 @@ class Webhook {
* @readonly
*/
Object.defineProperty(this, 'client', { value: client });
this._patch(data);
if (data) this._patch(data);
}
_patch(data) {

View File

@@ -15,6 +15,13 @@ const MessagePayload = require('../MessagePayload');
let deprecationEmittedForEphemeralOption = false;
let deprecationEmittedForFetchReplyOption = false;
/**
* @typedef {Object} ModalComponentData
* @property {string} title The title of the modal
* @property {string} customId The custom id of the modal
* @property {ActionRow[]} components The components within this modal
*/
/**
* Interface for classes that support shared interaction response types.
* @interface

View File

@@ -245,11 +245,6 @@
* @see {@link https://discord-api-types.dev/api/discord-api-types-v10/interface/APISelectMenuOption}
*/
/**
* @external APISelectMenuDefaultValue
* @see {@link https://discord-api-types.dev/api/discord-api-types-v10/interface/APISelectMenuDefaultValue}
*/
/**
* @external APISticker
* @see {@link https://discord-api-types.dev/api/discord-api-types-v10/interface/APISticker}
@@ -520,11 +515,6 @@
* @see {@link https://discord-api-types.dev/api/discord-api-types-v10/enum/InteractionResponseType}
*/
/**
* @external InviteFlags
* @see {@link https://discord-api-types.dev/api/discord-api-types-v10/enum/InviteFlags}
*/
/**
* @external InviteType
* @see {@link https://discord-api-types.dev/api/discord-api-types-v10/enum/InviteType}
@@ -540,11 +530,6 @@
* @see {@link https://discord-api-types.dev/api/discord-api-types-v10/enum/Locale}
*/
/**
* @external LocalizationMap
* @see {@link https://discord-api-types.dev/api/discord-api-types-v10#LocalizationMap}
*/
/**
* @external MessageActivityType
* @see {@link https://discord-api-types.dev/api/discord-api-types-v10/enum/MessageActivityType}
@@ -660,11 +645,6 @@
* @see {@link https://discord-api-types.dev/api/discord-api-types-v10/enum/ThreadAutoArchiveDuration}
*/
/**
* @external ThreadMemberFlags
* @see {@link https://discord-api-types.dev/api/discord-api-types-v10/enum/ThreadMemberFlags}
*/
/**
* @external UserFlags
* @see {@link https://discord-api-types.dev/api/discord-api-types-v10/enum/UserFlags}

View File

@@ -14,26 +14,6 @@ const { ComponentType } = require('discord-api-types/v10');
* @property {ComponentData[]} components The components in this action row
*/
/**
* @typedef {Object} ModalComponentData
* @property {string} title The title of the modal
* @property {string} customId The custom id of the modal
* @property {Array<ActionRow|TextDisplayComponentData|LabelData>} components The components within this modal
*/
/**
* @typedef {StringSelectMenuComponentData|TextInputComponentData|UserSelectMenuComponentData|
* RoleSelectMenuComponentData|MentionableSelectMenuComponentData|ChannelSelectMenuComponentData|
* FileUploadComponentData} ComponentInLabelData
*/
/**
* @typedef {BaseComponentData} LabelData
* @property {string} label The label to use
* @property {string} [description] The optional description for the label
* @property {ComponentInLabelData} component The component within the label
*/
/**
* @typedef {BaseComponentData} ButtonComponentData
* @property {ButtonStyle} style The style of the button
@@ -44,50 +24,6 @@ const { ComponentType } = require('discord-api-types/v10');
* @property {string} [url] The URL of the button
*/
/**
* @typedef {BaseComponentData} FileUploadComponentData
* @property {string} customId The custom id of the file upload
* @property {number} [minValues] The minimum number of files that can be uploaded (0-10)
* @property {number} [maxValues] The maximum number of files that can be uploaded (1-10)
* @property {boolean} [required] Whether this component is required in modals
*/
/**
* @typedef {BaseComponentData} BaseSelectMenuComponentData
* @property {string} customId The custom id of the select menu
* @property {boolean} [disabled] Whether the select menu is disabled or not
* @property {number} [maxValues] The maximum amount of options that can be selected
* @property {number} [minValues] The minimum amount of options that can be selected
* @property {string} [placeholder] The placeholder of the select menu
* @property {boolean} [required] Whether this component is required in modals
*/
/**
* @typedef {BaseSelectMenuComponentData} StringSelectMenuComponentData
* @property {SelectMenuComponentOptionData[]} [options] The options in this select menu
*/
/**
* @typedef {BaseSelectMenuComponentData} UserSelectMenuComponentData
* @property {APISelectMenuDefaultValue[]} [defaultValues] The default selected values in this select menu
*/
/**
* @typedef {BaseSelectMenuComponentData} RoleSelectMenuComponentData
* @property {APISelectMenuDefaultValue[]} [defaultValues] The default selected values in this select menu
*/
/**
* @typedef {BaseSelectMenuComponentData} MentionableSelectMenuComponentData
* @property {APISelectMenuDefaultValue[]} [defaultValues] The default selected values in this select menu
*/
/**
* @typedef {BaseSelectMenuComponentData} ChannelSelectMenuComponentData
* @property {APISelectMenuDefaultValue[]} [defaultValues] The default selected values in this select menu
* @property {ChannelType[]} [channelTypes] The types of channels that can be selected
*/
/**
* @typedef {object} SelectMenuComponentOptionData
* @property {string} label The label of the option
@@ -263,7 +199,6 @@ const ChannelSelectMenuComponent = require('../structures/ChannelSelectMenuCompo
const Component = require('../structures/Component');
const ContainerComponent = require('../structures/ContainerComponent');
const FileComponent = require('../structures/FileComponent');
const LabelComponent = require('../structures/LabelComponent');
const MediaGalleryComponent = require('../structures/MediaGalleryComponent');
const MentionableSelectMenuBuilder = require('../structures/MentionableSelectMenuBuilder');
const MentionableSelectMenuComponent = require('../structures/MentionableSelectMenuComponent');
@@ -296,7 +231,6 @@ const ComponentTypeToComponent = {
[ComponentType.Section]: SectionComponent,
[ComponentType.Separator]: SeparatorComponent,
[ComponentType.Thumbnail]: ThumbnailComponent,
[ComponentType.Label]: LabelComponent,
};
const ComponentTypeToBuilder = {

View File

@@ -9,8 +9,7 @@ const BitField = require('./BitField');
*/
class GuildMemberFlagsBitField extends BitField {
/**
* Numeric guild member flags.
*
* Numeric guild guild member flags.
* @type {GuildMemberFlags}
* @memberof GuildMemberFlagsBitField
*/

View File

@@ -27,8 +27,6 @@ const { createEnum } = require('./Enums');
* @property {number} GuildScheduledEvent The partial to receive uncached guild scheduled events.
* @property {number} ThreadMember The partial to receive uncached thread members.
* @property {number} SoundboardSound The partial to receive uncached soundboard sounds.
* @property {number} Poll The partial to receive uncached polls.
* @property {number} PollAnswer The partial to receive uncached poll answers.
*/
// JSDoc for IntelliSense purposes
@@ -45,6 +43,4 @@ module.exports = createEnum([
'GuildScheduledEvent',
'ThreadMember',
'SoundboardSound',
'Poll',
'PollAnswer',
]);

View File

@@ -1,6 +1,5 @@
'use strict';
const { ThreadMemberFlags } = require('discord-api-types/v10');
const BitField = require('./BitField');
/**
@@ -10,10 +9,10 @@ const BitField = require('./BitField');
class ThreadMemberFlagsBitField extends BitField {
/**
* Numeric thread member flags. There are currently no bitflags relevant to bots for this.
* @type {ThreadMemberFlags}
* @type {Object<string, number>}
* @memberof ThreadMemberFlagsBitField
*/
static Flags = ThreadMemberFlags;
static Flags = {};
}
/**

View File

@@ -37,15 +37,7 @@ import {
} from '@discordjs/formatters';
import { Awaitable, JSONEncodable } from '@discordjs/util';
import { Collection, ReadonlyCollection } from '@discordjs/collection';
import {
BaseImageURLOptions,
EmojiURLOptions,
ImageURLOptions,
RawFile,
REST,
RESTOptions,
ImageSize,
} from '@discordjs/rest';
import { BaseImageURLOptions, EmojiURLOptions, ImageURLOptions, RawFile, REST, RESTOptions } from '@discordjs/rest';
import {
WebSocketManager as WSWebSocketManager,
IShardingStrategy,
@@ -63,7 +55,6 @@ import {
APIInteractionDataResolvedChannel,
APIInteractionDataResolvedGuildMember,
APIInteractionGuildMember,
APILabelComponent,
APIMessage,
APIMessageComponent,
APIOverwrite,
@@ -224,7 +215,6 @@ import {
APIFileComponent,
APIMessageTopLevelComponent,
EntryPointCommandHandlerType,
InviteFlags,
} from 'discord-api-types/v10';
import { ChildProcess } from 'node:child_process';
import { EventEmitter } from 'node:events';
@@ -361,22 +351,6 @@ export class ActionRowBuilder<
): ActionRowBuilder<ComponentType>;
}
export type ComponentInLabelData =
| StringSelectMenuComponentData
| TextInputComponentData
| UserSelectMenuComponentData
| ChannelSelectMenuComponentData
| RoleSelectMenuComponentData
| MentionableSelectMenuComponentData
| FileUploadComponentData;
export interface LabelComponentData extends BaseComponentData {
type: ComponentType.Label;
component: ComponentInLabelData;
description?: string;
label: string;
}
export type MessageActionRowComponent =
| ButtonComponent
| StringSelectMenuComponent
@@ -937,12 +911,6 @@ export class TextInputComponent extends Component<APITextInputComponent> {
public get value(): string;
}
export class LabelComponent extends Component<APILabelComponent> {
public component: StringSelectMenuComponent | TextInputComponent;
public get label(): string;
public get description(): string | null;
}
export class BaseSelectMenuComponent<Data extends APISelectMenuComponent> extends Component<Data> {
protected constructor(data: Data);
public get placeholder(): string | null;
@@ -1703,7 +1671,6 @@ export class Guild extends AnonymousGuild {
): Promise<Guild>;
public setIcon(icon: BufferResolvable | Base64Resolvable | null, reason?: string): Promise<Guild>;
public setName(name: string, reason?: string): Promise<Guild>;
/** @deprecated API related to guild ownership may no longer be used. */
public setOwner(owner: GuildMemberResolvable, reason?: string): Promise<Guild>;
public setPreferredLocale(preferredLocale: Locale | null, reason?: string): Promise<Guild>;
public setPublicUpdatesChannel(publicUpdatesChannel: TextChannelResolvable | null, reason?: string): Promise<Guild>;
@@ -1715,7 +1682,6 @@ export class Guild extends AnonymousGuild {
public setVerificationLevel(verificationLevel: GuildVerificationLevel | null, reason?: string): Promise<Guild>;
public setPremiumProgressBarEnabled(enabled?: boolean, reason?: string): Promise<Guild>;
public setWidgetSettings(settings: GuildWidgetSettingsData, reason?: string): Promise<Guild>;
/** @deprecated API related to guild ownership may no longer be used. */
public setMFALevel(level: GuildMFALevel, reason?: string): Promise<Guild>;
public toJSON(): unknown;
}
@@ -2054,7 +2020,6 @@ export class GuildTemplate extends Base {
public guildId: Snowflake;
public serializedGuild: APITemplateSerializedSourceGuild;
public unSynced: boolean | null;
/** @deprecated API related to guild ownership may no longer be used. */
public createGuild(name: string, icon?: BufferResolvable | Base64Resolvable): Promise<Guild>;
public delete(): Promise<GuildTemplate>;
public edit(options?: GuildTemplateEditOptions): Promise<GuildTemplate>;
@@ -2306,7 +2271,6 @@ export class Invite extends Base {
/** @deprecated Public Stage Instances don't exist anymore */
public stageInstance: InviteStageInstance | null;
public guildScheduledEvent: GuildScheduledEvent | null;
public flags: Readonly<InviteFlagsBitField>;
}
/** @deprecated Public Stage Instances don't exist anymore */
@@ -2327,13 +2291,6 @@ export class InviteGuild extends AnonymousGuild {
public welcomeScreen: WelcomeScreen | null;
}
export type InviteFlagsString = keyof typeof InviteFlags;
export class InviteFlagsBitField extends BitField<InviteFlagsString> {
public static Flags: typeof InviteFlags;
public static resolve(bit?: BitFieldResolvable<InviteFlagsString, number>): number;
}
export class LimitedCollection<Key, Value> extends Collection<Key, Value> {
public constructor(options?: LimitedCollectionOptions<Key, Value>, iterable?: Iterable<readonly [Key, Value]>);
public maxSize: number;
@@ -2788,127 +2745,33 @@ export interface ModalComponentData {
customId: string;
title: string;
components: readonly (
| JSONEncodable<APIActionRowComponent<APIComponentInModalActionRow> | APILabelComponent>
| JSONEncodable<APIActionRowComponent<APIComponentInModalActionRow>>
| ActionRowData<ModalActionRowComponentData>
| LabelComponentData
| TextDisplayComponentData
)[];
}
export interface BaseModalData<Type extends ComponentType> {
id: number;
type: Type;
export interface BaseModalData {
customId: string;
type: ComponentType;
}
export interface TextInputModalData extends BaseModalData<ComponentType.TextInput> {
customId: string;
export interface TextInputModalData extends BaseModalData {
type: ComponentType.TextInput;
value: string;
}
export interface SelectMenuModalData<Cached extends CacheType = CacheType>
extends BaseModalData<
| ComponentType.ChannelSelect
| ComponentType.MentionableSelect
| ComponentType.RoleSelect
| ComponentType.StringSelect
| ComponentType.UserSelect
> {
channels?: ReadonlyCollection<
Snowflake,
CacheTypeReducer<Cached, GuildBasedChannel, APIInteractionDataResolvedChannel>
>;
customId: string;
members?: ReadonlyCollection<Snowflake, CacheTypeReducer<Cached, GuildMember, APIInteractionDataResolvedGuildMember>>;
roles?: ReadonlyCollection<Snowflake, CacheTypeReducer<Cached, Role, APIRole>>;
users?: ReadonlyCollection<Snowflake, User>;
values: readonly string[];
}
export interface FileUploadModalData extends BaseModalData<ComponentType.FileUpload> {
customId: string;
values: readonly Snowflake[];
attachments: ReadonlyCollection<Snowflake, Attachment>;
}
export type ModalData = FileUploadModalData | SelectMenuModalData | TextInputModalData;
export interface LabelModalData extends BaseModalData<ComponentType.Label> {
component: ModalData;
}
export interface ActionRowModalData extends BaseModalData<ComponentType.ActionRow> {
export interface ActionRowModalData {
type: ComponentType.ActionRow;
components: readonly TextInputModalData[];
}
export interface TextDisplayModalData extends BaseModalData<ComponentType.TextDisplay> {}
export interface ModalSelectedMentionables<Cached extends CacheType = CacheType> {
members: NonNullable<SelectMenuModalData<Cached>['members']>;
roles: NonNullable<SelectMenuModalData<Cached>['roles']>;
users: NonNullable<SelectMenuModalData<Cached>['users']>;
}
export class ModalSubmitFields<Cached extends CacheType = CacheType> {
private constructor(
components: readonly (ActionRowModalData | LabelModalData | TextDisplayModalData)[],
resolved?: BaseInteractionResolvedData,
);
public components: (ActionRowModalData | LabelModalData | TextDisplayModalData)[];
public resolved: Readonly<BaseInteractionResolvedData<Cached>> | null;
public fields: Collection<string, ModalData>;
public getField<Type extends ComponentType>(customId: string, type: Type): Extract<ModalData, { type: Type }>;
public getField(customId: string, type?: ComponentType): ModalData;
private _getTypedComponent(
customId: string,
allowedTypes: readonly ComponentType[],
properties: string,
required: boolean,
): ModalData;
export class ModalSubmitFields {
private constructor(components: readonly (readonly ModalActionRowComponent[])[]);
public components: ActionRowModalData[];
public fields: Collection<string, TextInputModalData>;
public getField<Type extends ComponentType>(customId: string, type: Type): { type: Type } & TextInputModalData;
public getField(customId: string, type?: ComponentType): TextInputModalData;
public getTextInputValue(customId: string): string;
public getStringSelectValues(customId: string): readonly string[];
public getSelectedUsers(customId: string, required: true): ReadonlyCollection<Snowflake, User>;
public getSelectedUsers(customId: string, required?: boolean): ReadonlyCollection<Snowflake, User> | null;
public getSelectedMembers(customId: string): NonNullable<SelectMenuModalData<Cached>['members']> | null;
public getSelectedChannels<const Type extends ChannelType = ChannelType>(
customId: string,
required: true,
channelTypes?: readonly Type[],
): ReadonlyCollection<
Snowflake,
Extract<
NonNullable<CommandInteractionOption<Cached>['channel']>,
{
type: Type extends ChannelType.AnnouncementThread | ChannelType.PublicThread
? ChannelType.AnnouncementThread | ChannelType.PublicThread
: Type;
}
>
>;
public getSelectedChannels<const Type extends ChannelType = ChannelType>(
customId: string,
required?: boolean,
channelTypes?: readonly Type[],
): ReadonlyCollection<
Snowflake,
Extract<
NonNullable<CommandInteractionOption<Cached>['channel']>,
{
type: Type extends ChannelType.AnnouncementThread | ChannelType.PublicThread
? ChannelType.AnnouncementThread | ChannelType.PublicThread
: Type;
}
>
> | null;
public getSelectedRoles(customId: string, required: true): NonNullable<SelectMenuModalData<Cached>['roles']>;
public getSelectedRoles(
customId: string,
required?: boolean,
): NonNullable<SelectMenuModalData<Cached>['roles']> | null;
public getSelectedMentionables(customId: string, required: true): ModalSelectedMentionables<Cached>;
public getSelectedMentionables(customId: string, required?: boolean): ModalSelectedMentionables<Cached> | null;
public getUploadedFiles(customId: string, required: true): ReadonlyCollection<Snowflake, Attachment>;
public getUploadedFiles(customId: string, required?: boolean): ReadonlyCollection<Snowflake, Attachment> | null;
}
export interface ModalMessageModalSubmitInteraction<Cached extends CacheType = CacheType>
@@ -2932,8 +2795,8 @@ export class ModalSubmitInteraction<Cached extends CacheType = CacheType> extend
private constructor(client: Client<true>, data: APIModalSubmitInteraction);
public type: InteractionType.ModalSubmit;
public readonly customId: string;
public readonly components: (ActionRowModalData | LabelModalData)[];
public readonly fields: ModalSubmitFields<Cached>;
public readonly components: ActionRowModalData[];
public readonly fields: ModalSubmitFields;
public deferred: boolean;
public ephemeral: boolean | null;
public message: Message<BooleanCache<Cached>> | null;
@@ -3139,30 +3002,19 @@ export class Presence extends Base {
}
export interface PollQuestionMedia {
text: string | null;
}
export class PollAnswerVoterManager extends CachedManager<Snowflake, User, UserResolvable> {
private constructor(answer: PollAnswer);
public answer: PollAnswer;
public fetch(options?: BaseFetchPollAnswerVotersOptions): Promise<Collection<Snowflake, User>>;
text: string;
}
export class Poll extends Base {
private constructor(client: Client<true>, data: APIPoll, message: Message, channel: TextBasedChannel);
public readonly channel: TextBasedChannel;
public channelId: Snowflake;
private constructor(client: Client<true>, data: APIPoll, message: Message);
public readonly message: Message;
public messageId: Snowflake;
public question: PollQuestionMedia;
public answers: Collection<number, PollAnswer | PartialPollAnswer>;
public expiresTimestamp: number | null;
public get expiresAt(): Date | null;
public answers: Collection<number, PollAnswer>;
public expiresTimestamp: number;
public get expiresAt(): Date;
public allowMultiselect: boolean;
public layoutType: PollLayoutType;
public resultsFinalized: boolean;
public get partial(): false;
public fetch(): Promise<this>;
public end(): Promise<Message>;
}
@@ -3174,14 +3026,11 @@ export interface BaseFetchPollAnswerVotersOptions {
export class PollAnswer extends Base {
private constructor(client: Client<true>, data: APIPollAnswer & { count?: number }, poll: Poll);
private _emoji: APIPartialEmoji | null;
public readonly poll: Poll | PartialPoll;
public readonly poll: Poll;
public id: number;
public text: string | null;
public voteCount: number;
public voters: PollAnswerVoterManager;
public get emoji(): GuildEmoji | Emoji | null;
public get partial(): false;
/** @deprecated Use {@link PollAnswerVoterManager.fetch} instead */
public fetchVoters(options?: BaseFetchPollAnswerVotersOptions): Promise<Collection<Snowflake, User>>;
}
@@ -3841,7 +3690,7 @@ export interface PrivateThreadChannel extends ThreadChannel<false> {
export interface ThreadChannel<ThreadOnly extends boolean = boolean>
extends Omit<TextBasedChannelFields<true>, 'fetchWebhooks' | 'createWebhook' | 'setNSFW'> {}
export class ThreadChannel<ThreadOnly extends boolean = boolean> extends BaseChannel {
private constructor(guild: Guild, data: RawThreadChannelData, client?: Client<true>);
private constructor(guild: Guild, data?: RawThreadChannelData, client?: Client<true>);
public archived: boolean | null;
public get archivedAt(): Date | null;
public archiveTimestamp: number | null;
@@ -4161,8 +4010,6 @@ export class Formatters extends null {
export type ComponentData =
| MessageActionRowComponentData
| ModalActionRowComponentData
| LabelComponentData
| ComponentInLabelData
| ComponentInContainerData
| ContainerComponentData
| ThumbnailComponentData;
@@ -4234,7 +4081,7 @@ export class VoiceState extends Base {
// tslint:disable-next-line no-empty-interface
export interface Webhook<Type extends WebhookType = WebhookType> extends WebhookFields {}
export class Webhook<Type extends WebhookType = WebhookType> {
private constructor(client: Client<true>, data: RawWebhookData);
private constructor(client: Client<true>, data?: RawWebhookData);
public avatar: string | null;
public avatarURL(options?: ImageURLOptions): string | null;
public channelId: Snowflake;
@@ -4262,9 +4109,9 @@ export class Webhook<Type extends WebhookType = WebhookType> {
public editMessage(
message: MessageResolvable,
options: string | MessagePayload | WebhookMessageEditOptions,
): Promise<Message<true>>;
public fetchMessage(message: Snowflake, options?: WebhookFetchMessageOptions): Promise<Message<true>>;
public send(options: string | MessagePayload | WebhookMessageCreateOptions): Promise<Message<true>>;
): Promise<Message>;
public fetchMessage(message: Snowflake, options?: WebhookFetchMessageOptions): Promise<Message>;
public send(options: string | MessagePayload | WebhookMessageCreateOptions): Promise<Message>;
}
// tslint:disable-next-line no-empty-interface
@@ -4650,8 +4497,6 @@ export enum DiscordjsErrorCodes {
ModalSubmitInteractionFieldNotFound = 'ModalSubmitInteractionFieldNotFound',
ModalSubmitInteractionFieldType = 'ModalSubmitInteractionFieldType',
ModalSubmitInteractionFieldEmpty = 'ModalSubmitInteractionComponentEmpty',
ModalSubmitInteractionFieldInvalidChannelType = 'ModalSubmitInteractionFieldInvalidChannelType',
InvalidMissingScopes = 'InvalidMissingScopes',
InvalidScopesWithPermissions = 'InvalidScopesWithPermissions',
@@ -5000,7 +4845,6 @@ export interface FetchSoundboardSoundsOptions {
export class GuildManager extends CachedManager<Snowflake, Guild, GuildResolvable> {
private constructor(client: Client<true>, iterable?: Iterable<RawGuildData>);
/** @deprecated API related to guild ownership may no longer be used. */
public create(options: GuildCreateOptions): Promise<Guild>;
public fetch(options: Snowflake | FetchGuildOptions): Promise<Guild>;
public fetch(options?: FetchGuildsOptions): Promise<Collection<Snowflake, OAuth2Guild>>;
@@ -5035,7 +4879,6 @@ export class GuildMemberManager extends CachedManager<Snowflake, GuildMember, Gu
options?: BulkBanOptions,
): Promise<BulkBanResult>;
public edit(user: UserResolvable, options: GuildMemberEditOptions): Promise<GuildMember>;
public editMe(options: GuildMemberEditMeOptions): Promise<GuildMember>;
public fetch(
options: UserResolvable | FetchMemberOptions | (FetchMembersOptions & { user: UserResolvable }),
): Promise<GuildMember>;
@@ -5463,9 +5306,7 @@ export type AllowedPartial =
| MessageReaction
| GuildScheduledEvent
| ThreadMember
| SoundboardSound
| Poll
| PollAnswer;
| SoundboardSound;
export type AllowedThreadTypeForNewsChannel = ChannelType.AnnouncementThread;
@@ -6037,15 +5878,15 @@ export interface ClientEvents {
inviteDelete: [invite: Invite];
messageCreate: [message: OmitPartialGroupDMChannel<Message>];
messageDelete: [message: OmitPartialGroupDMChannel<Message | PartialMessage>];
messagePollVoteAdd: [pollAnswer: PollAnswer | PartialPollAnswer, userId: Snowflake];
messagePollVoteRemove: [pollAnswer: PollAnswer | PartialPollAnswer, userId: Snowflake];
messagePollVoteAdd: [pollAnswer: PollAnswer, userId: Snowflake];
messagePollVoteRemove: [pollAnswer: PollAnswer, userId: Snowflake];
messageReactionRemoveAll: [
message: OmitPartialGroupDMChannel<Message | PartialMessage>,
reactions: ReadonlyCollection<string | Snowflake, MessageReaction>,
];
messageReactionRemoveEmoji: [reaction: MessageReaction | PartialMessageReaction];
messageDeleteBulk: [
messages: ReadonlyCollection<Snowflake, Message<true> | PartialMessage<true>>,
messages: ReadonlyCollection<Snowflake, OmitPartialGroupDMChannel<Message | PartialMessage>>,
channel: GuildTextBasedChannel,
];
messageReactionAdd: [
@@ -6192,17 +6033,13 @@ export interface CommandInteractionOption<Cached extends CacheType = CacheType>
message?: Message<BooleanCache<Cached>>;
}
export interface BaseInteractionResolvedData<Cached extends CacheType = CacheType> {
attachments?: ReadonlyCollection<Snowflake, Attachment>;
channels?: ReadonlyCollection<Snowflake, CacheTypeReducer<Cached, Channel, APIInteractionDataResolvedChannel>>;
export interface CommandInteractionResolvedData<Cached extends CacheType = CacheType> {
users?: ReadonlyCollection<Snowflake, User>;
members?: ReadonlyCollection<Snowflake, CacheTypeReducer<Cached, GuildMember, APIInteractionDataResolvedGuildMember>>;
roles?: ReadonlyCollection<Snowflake, CacheTypeReducer<Cached, Role, APIRole>>;
users?: ReadonlyCollection<Snowflake, User>;
}
export interface CommandInteractionResolvedData<Cached extends CacheType = CacheType>
extends BaseInteractionResolvedData<Cached> {
channels?: ReadonlyCollection<Snowflake, CacheTypeReducer<Cached, Channel, APIInteractionDataResolvedChannel>>;
messages?: ReadonlyCollection<Snowflake, CacheTypeReducer<Cached, Message, APIMessage>>;
attachments?: ReadonlyCollection<Snowflake, Attachment>;
}
export interface AutocompleteFocusedOption extends Pick<CommandInteractionOption, 'name'> {
@@ -6808,7 +6645,6 @@ export interface GuildChannelOverwriteOptions {
type?: OverwriteType;
}
/** @deprecated API related to guild ownership may no longer be used. */
export interface GuildCreateOptions {
name: string;
icon?: BufferResolvable | Base64Resolvable | null;
@@ -6836,7 +6672,6 @@ export interface GuildEditOptions {
afkTimeout?: number;
afkChannel?: VoiceChannelResolvable | null;
icon?: BufferResolvable | Base64Resolvable | null;
/** @deprecated API related to guild ownership may no longer be used. */
owner?: GuildMemberResolvable;
splash?: BufferResolvable | Base64Resolvable | null;
discoverySplash?: BufferResolvable | Base64Resolvable | null;
@@ -6894,14 +6729,6 @@ export interface GuildMemberEditOptions {
export type GuildMemberResolvable = GuildMember | UserResolvable;
export interface GuildMemberEditMeOptions {
avatar?: Base64Resolvable | BufferResolvable | null;
banner?: Base64Resolvable | BufferResolvable | null;
bio?: string | null;
nick?: string | null;
reason?: string;
}
export type GuildResolvable = Guild | NonThreadGuildBasedChannel | GuildMember | GuildEmoji | Invite | Role | Snowflake;
export interface GuildPruneMembersOptions {
@@ -7375,7 +7202,6 @@ export interface BaseSelectMenuComponentData extends BaseComponentData {
maxValues?: number;
minValues?: number;
placeholder?: string;
required?: true;
}
export interface StringSelectMenuComponentData extends BaseSelectMenuComponentData {
@@ -7439,14 +7265,6 @@ export interface TextInputComponentData extends BaseComponentData {
placeholder?: string;
}
export interface FileUploadComponentData extends BaseComponentData {
customId: string;
maxValues?: number;
minValues?: number;
required?: boolean;
type: ComponentType.FileUpload;
}
export type MessageTarget =
| Interaction
| InteractionWebhook
@@ -7502,7 +7320,6 @@ export interface PresenceData {
export type PresenceResolvable = Presence | UserResolvable | Snowflake;
/** @deprecated API related to guild ownership may no longer be used. */
export interface PartialChannelData {
id?: Snowflake | number;
parentId?: Snowflake | number;
@@ -7549,28 +7366,11 @@ export interface PartialDMChannel extends Partialize<DMChannel, null, null, 'las
export interface PartialGuildMember extends Partialize<GuildMember, 'joinedAt' | 'joinedTimestamp' | 'pending'> {}
export interface PartialMessage<InGuild extends boolean = boolean>
extends Partialize<Message<InGuild>, 'type' | 'system' | 'pinned' | 'tts', 'content' | 'cleanContent' | 'author'> {}
export interface PartialMessage
extends Partialize<Message, 'type' | 'system' | 'pinned' | 'tts', 'content' | 'cleanContent' | 'author'> {}
export interface PartialMessageReaction extends Partialize<MessageReaction, 'count'> {}
export interface PartialPoll
extends Partialize<
Poll,
'allowMultiselect' | 'layoutType' | 'expiresTimestamp',
null,
'question' | 'message' | 'answers'
> {
question: { text: null };
message: PartialMessage;
// eslint-disable-next-line no-restricted-syntax
answers: Collection<number, PartialPollAnswer>;
}
export interface PartialPollAnswer extends Partialize<PollAnswer, 'emoji' | 'text', null, 'poll'> {
readonly poll: PartialPoll;
}
export interface PartialGuildScheduledEvent
extends Partialize<GuildScheduledEvent, 'userCount', 'status' | 'privacyLevel' | 'name' | 'entityType'> {}
@@ -7578,7 +7378,6 @@ export interface PartialThreadMember extends Partialize<ThreadMember, 'flags' |
export interface PartialSoundboardSound extends Partialize<SoundboardSound, 'available' | 'name' | 'volume'> {}
/** @deprecated API related to guild ownership may no longer be used. */
export interface PartialOverwriteData {
id: Snowflake | number;
type?: OverwriteType;
@@ -7586,7 +7385,6 @@ export interface PartialOverwriteData {
deny?: PermissionResolvable;
}
/** @deprecated API related to guild ownership may no longer be used. */
export interface PartialRoleData extends RoleData {
id?: Snowflake | number;
}
@@ -7600,8 +7398,6 @@ export enum Partials {
GuildScheduledEvent,
ThreadMember,
SoundboardSound,
Poll,
PollAnswer,
}
export interface PartialUser extends Partialize<User, 'username' | 'tag' | 'discriminator'> {}
@@ -8029,6 +7825,3 @@ export * from '@discordjs/formatters';
export * from '@discordjs/rest';
export * from '@discordjs/util';
export * from '@discordjs/ws';
// Solve TS compile error
export type { ImageSize };

View File

@@ -37,15 +37,7 @@ import {
} from '@discordjs/formatters';
import { Awaitable, JSONEncodable } from '@discordjs/util';
import { Collection, ReadonlyCollection } from '@discordjs/collection';
import {
BaseImageURLOptions,
EmojiURLOptions,
ImageURLOptions,
RawFile,
REST,
RESTOptions,
ImageSize,
} from '@discordjs/rest';
import { BaseImageURLOptions, EmojiURLOptions, ImageURLOptions, RawFile, REST, RESTOptions } from '@discordjs/rest';
import {
WebSocketManager as WSWebSocketManager,
IShardingStrategy,
@@ -63,7 +55,6 @@ import {
APIInteractionDataResolvedChannel,
APIInteractionDataResolvedGuildMember,
APIInteractionGuildMember,
APILabelComponent,
APIMessage,
APIMessageComponent,
APIOverwrite,
@@ -224,7 +215,6 @@ import {
APIFileComponent,
APIMessageTopLevelComponent,
EntryPointCommandHandlerType,
InviteFlags,
} from 'discord-api-types/v10';
import { ChildProcess } from 'node:child_process';
import { EventEmitter } from 'node:events';
@@ -361,22 +351,6 @@ export class ActionRowBuilder<
): ActionRowBuilder<ComponentType>;
}
export type ComponentInLabelData =
| StringSelectMenuComponentData
| TextInputComponentData
| UserSelectMenuComponentData
| ChannelSelectMenuComponentData
| RoleSelectMenuComponentData
| MentionableSelectMenuComponentData
| FileUploadComponentData;
export interface LabelComponentData extends BaseComponentData {
type: ComponentType.Label;
component: ComponentInLabelData;
description?: string;
label: string;
}
export type MessageActionRowComponent =
| ButtonComponent
| StringSelectMenuComponent
@@ -937,12 +911,6 @@ export class TextInputComponent extends Component<APITextInputComponent> {
public get value(): string;
}
export class LabelComponent extends Component<APILabelComponent> {
public component: StringSelectMenuComponent | TextInputComponent;
public get label(): string;
public get description(): string | null;
}
export class BaseSelectMenuComponent<Data extends APISelectMenuComponent> extends Component<Data> {
protected constructor(data: Data);
public get placeholder(): string | null;
@@ -1703,7 +1671,6 @@ export class Guild extends AnonymousGuild {
): Promise<Guild>;
public setIcon(icon: BufferResolvable | Base64Resolvable | null, reason?: string): Promise<Guild>;
public setName(name: string, reason?: string): Promise<Guild>;
/** @deprecated API related to guild ownership may no longer be used. */
public setOwner(owner: GuildMemberResolvable, reason?: string): Promise<Guild>;
public setPreferredLocale(preferredLocale: Locale | null, reason?: string): Promise<Guild>;
public setPublicUpdatesChannel(publicUpdatesChannel: TextChannelResolvable | null, reason?: string): Promise<Guild>;
@@ -1715,7 +1682,6 @@ export class Guild extends AnonymousGuild {
public setVerificationLevel(verificationLevel: GuildVerificationLevel | null, reason?: string): Promise<Guild>;
public setPremiumProgressBarEnabled(enabled?: boolean, reason?: string): Promise<Guild>;
public setWidgetSettings(settings: GuildWidgetSettingsData, reason?: string): Promise<Guild>;
/** @deprecated API related to guild ownership may no longer be used. */
public setMFALevel(level: GuildMFALevel, reason?: string): Promise<Guild>;
public toJSON(): unknown;
}
@@ -2054,7 +2020,6 @@ export class GuildTemplate extends Base {
public guildId: Snowflake;
public serializedGuild: APITemplateSerializedSourceGuild;
public unSynced: boolean | null;
/** @deprecated API related to guild ownership may no longer be used. */
public createGuild(name: string, icon?: BufferResolvable | Base64Resolvable): Promise<Guild>;
public delete(): Promise<GuildTemplate>;
public edit(options?: GuildTemplateEditOptions): Promise<GuildTemplate>;
@@ -2306,7 +2271,6 @@ export class Invite extends Base {
/** @deprecated Public Stage Instances don't exist anymore */
public stageInstance: InviteStageInstance | null;
public guildScheduledEvent: GuildScheduledEvent | null;
public flags: Readonly<InviteFlagsBitField>;
}
/** @deprecated Public Stage Instances don't exist anymore */
@@ -2327,13 +2291,6 @@ export class InviteGuild extends AnonymousGuild {
public welcomeScreen: WelcomeScreen | null;
}
export type InviteFlagsString = keyof typeof InviteFlags;
export class InviteFlagsBitField extends BitField<InviteFlagsString> {
public static Flags: typeof InviteFlags;
public static resolve(bit?: BitFieldResolvable<InviteFlagsString, number>): number;
}
export class LimitedCollection<Key, Value> extends Collection<Key, Value> {
public constructor(options?: LimitedCollectionOptions<Key, Value>, iterable?: Iterable<readonly [Key, Value]>);
public maxSize: number;
@@ -2788,127 +2745,33 @@ export interface ModalComponentData {
customId: string;
title: string;
components: readonly (
| JSONEncodable<APIActionRowComponent<APIComponentInModalActionRow> | APILabelComponent>
| JSONEncodable<APIActionRowComponent<APIComponentInModalActionRow>>
| ActionRowData<ModalActionRowComponentData>
| LabelComponentData
| TextDisplayComponentData
)[];
}
export interface BaseModalData<Type extends ComponentType> {
id: number;
type: Type;
export interface BaseModalData {
customId: string;
type: ComponentType;
}
export interface TextInputModalData extends BaseModalData<ComponentType.TextInput> {
customId: string;
export interface TextInputModalData extends BaseModalData {
type: ComponentType.TextInput;
value: string;
}
export interface SelectMenuModalData<Cached extends CacheType = CacheType>
extends BaseModalData<
| ComponentType.ChannelSelect
| ComponentType.MentionableSelect
| ComponentType.RoleSelect
| ComponentType.StringSelect
| ComponentType.UserSelect
> {
channels?: ReadonlyCollection<
Snowflake,
CacheTypeReducer<Cached, GuildBasedChannel, APIInteractionDataResolvedChannel>
>;
customId: string;
members?: ReadonlyCollection<Snowflake, CacheTypeReducer<Cached, GuildMember, APIInteractionDataResolvedGuildMember>>;
roles?: ReadonlyCollection<Snowflake, CacheTypeReducer<Cached, Role, APIRole>>;
users?: ReadonlyCollection<Snowflake, User>;
values: readonly string[];
}
export interface FileUploadModalData extends BaseModalData<ComponentType.FileUpload> {
customId: string;
values: readonly Snowflake[];
attachments: ReadonlyCollection<Snowflake, Attachment>;
}
export type ModalData = FileUploadModalData | SelectMenuModalData | TextInputModalData;
export interface LabelModalData extends BaseModalData<ComponentType.Label> {
component: ModalData;
}
export interface ActionRowModalData extends BaseModalData<ComponentType.ActionRow> {
export interface ActionRowModalData {
type: ComponentType.ActionRow;
components: readonly TextInputModalData[];
}
export interface TextDisplayModalData extends BaseModalData<ComponentType.TextDisplay> {}
export interface ModalSelectedMentionables<Cached extends CacheType = CacheType> {
members: NonNullable<SelectMenuModalData<Cached>['members']>;
roles: NonNullable<SelectMenuModalData<Cached>['roles']>;
users: NonNullable<SelectMenuModalData<Cached>['users']>;
}
export class ModalSubmitFields<Cached extends CacheType = CacheType> {
private constructor(
components: readonly (ActionRowModalData | LabelModalData | TextDisplayModalData)[],
resolved?: BaseInteractionResolvedData,
);
public components: (ActionRowModalData | LabelModalData | TextDisplayModalData)[];
public resolved: Readonly<BaseInteractionResolvedData<Cached>> | null;
public fields: Collection<string, ModalData>;
public getField<Type extends ComponentType>(customId: string, type: Type): Extract<ModalData, { type: Type }>;
public getField(customId: string, type?: ComponentType): ModalData;
private _getTypedComponent(
customId: string,
allowedTypes: readonly ComponentType[],
properties: string,
required: boolean,
): ModalData;
export class ModalSubmitFields {
private constructor(components: readonly (readonly ModalActionRowComponent[])[]);
public components: ActionRowModalData[];
public fields: Collection<string, TextInputModalData>;
public getField<Type extends ComponentType>(customId: string, type: Type): { type: Type } & TextInputModalData;
public getField(customId: string, type?: ComponentType): TextInputModalData;
public getTextInputValue(customId: string): string;
public getStringSelectValues(customId: string): readonly string[];
public getSelectedUsers(customId: string, required: true): ReadonlyCollection<Snowflake, User>;
public getSelectedUsers(customId: string, required?: boolean): ReadonlyCollection<Snowflake, User> | null;
public getSelectedMembers(customId: string): NonNullable<SelectMenuModalData<Cached>['members']> | null;
public getSelectedChannels<const Type extends ChannelType = ChannelType>(
customId: string,
required: true,
channelTypes?: readonly Type[],
): ReadonlyCollection<
Snowflake,
Extract<
NonNullable<CommandInteractionOption<Cached>['channel']>,
{
type: Type extends ChannelType.AnnouncementThread | ChannelType.PublicThread
? ChannelType.AnnouncementThread | ChannelType.PublicThread
: Type;
}
>
>;
public getSelectedChannels<const Type extends ChannelType = ChannelType>(
customId: string,
required?: boolean,
channelTypes?: readonly Type[],
): ReadonlyCollection<
Snowflake,
Extract<
NonNullable<CommandInteractionOption<Cached>['channel']>,
{
type: Type extends ChannelType.AnnouncementThread | ChannelType.PublicThread
? ChannelType.AnnouncementThread | ChannelType.PublicThread
: Type;
}
>
> | null;
public getSelectedRoles(customId: string, required: true): NonNullable<SelectMenuModalData<Cached>['roles']>;
public getSelectedRoles(
customId: string,
required?: boolean,
): NonNullable<SelectMenuModalData<Cached>['roles']> | null;
public getSelectedMentionables(customId: string, required: true): ModalSelectedMentionables<Cached>;
public getSelectedMentionables(customId: string, required?: boolean): ModalSelectedMentionables<Cached> | null;
public getUploadedFiles(customId: string, required: true): ReadonlyCollection<Snowflake, Attachment>;
public getUploadedFiles(customId: string, required?: boolean): ReadonlyCollection<Snowflake, Attachment> | null;
}
export interface ModalMessageModalSubmitInteraction<Cached extends CacheType = CacheType>
@@ -2932,8 +2795,8 @@ export class ModalSubmitInteraction<Cached extends CacheType = CacheType> extend
private constructor(client: Client<true>, data: APIModalSubmitInteraction);
public type: InteractionType.ModalSubmit;
public readonly customId: string;
public readonly components: (ActionRowModalData | LabelModalData)[];
public readonly fields: ModalSubmitFields<Cached>;
public readonly components: ActionRowModalData[];
public readonly fields: ModalSubmitFields;
public deferred: boolean;
public ephemeral: boolean | null;
public message: Message<BooleanCache<Cached>> | null;
@@ -3139,30 +3002,19 @@ export class Presence extends Base {
}
export interface PollQuestionMedia {
text: string | null;
}
export class PollAnswerVoterManager extends CachedManager<Snowflake, User, UserResolvable> {
private constructor(answer: PollAnswer);
public answer: PollAnswer;
public fetch(options?: BaseFetchPollAnswerVotersOptions): Promise<Collection<Snowflake, User>>;
text: string;
}
export class Poll extends Base {
private constructor(client: Client<true>, data: APIPoll, message: Message, channel: TextBasedChannel);
public readonly channel: TextBasedChannel;
public channelId: Snowflake;
private constructor(client: Client<true>, data: APIPoll, message: Message);
public readonly message: Message;
public messageId: Snowflake;
public question: PollQuestionMedia;
public answers: Collection<number, PollAnswer | PartialPollAnswer>;
public expiresTimestamp: number | null;
public get expiresAt(): Date | null;
public answers: Collection<number, PollAnswer>;
public expiresTimestamp: number;
public get expiresAt(): Date;
public allowMultiselect: boolean;
public layoutType: PollLayoutType;
public resultsFinalized: boolean;
public get partial(): false;
public fetch(): Promise<this>;
public end(): Promise<Message>;
}
@@ -3174,14 +3026,11 @@ export interface BaseFetchPollAnswerVotersOptions {
export class PollAnswer extends Base {
private constructor(client: Client<true>, data: APIPollAnswer & { count?: number }, poll: Poll);
private _emoji: APIPartialEmoji | null;
public readonly poll: Poll | PartialPoll;
public readonly poll: Poll;
public id: number;
public text: string | null;
public voteCount: number;
public voters: PollAnswerVoterManager;
public get emoji(): GuildEmoji | Emoji | null;
public get partial(): false;
/** @deprecated Use {@link PollAnswerVoterManager.fetch} instead */
public fetchVoters(options?: BaseFetchPollAnswerVotersOptions): Promise<Collection<Snowflake, User>>;
}
@@ -3841,7 +3690,7 @@ export interface PrivateThreadChannel extends ThreadChannel<false> {
export interface ThreadChannel<ThreadOnly extends boolean = boolean>
extends Omit<TextBasedChannelFields<true>, 'fetchWebhooks' | 'createWebhook' | 'setNSFW'> {}
export class ThreadChannel<ThreadOnly extends boolean = boolean> extends BaseChannel {
private constructor(guild: Guild, data: RawThreadChannelData, client?: Client<true>);
private constructor(guild: Guild, data?: RawThreadChannelData, client?: Client<true>);
public archived: boolean | null;
public get archivedAt(): Date | null;
public archiveTimestamp: number | null;
@@ -4161,8 +4010,6 @@ export class Formatters extends null {
export type ComponentData =
| MessageActionRowComponentData
| ModalActionRowComponentData
| LabelComponentData
| ComponentInLabelData
| ComponentInContainerData
| ContainerComponentData
| ThumbnailComponentData;
@@ -4234,7 +4081,7 @@ export class VoiceState extends Base {
// tslint:disable-next-line no-empty-interface
export interface Webhook<Type extends WebhookType = WebhookType> extends WebhookFields {}
export class Webhook<Type extends WebhookType = WebhookType> {
private constructor(client: Client<true>, data: RawWebhookData);
private constructor(client: Client<true>, data?: RawWebhookData);
public avatar: string | null;
public avatarURL(options?: ImageURLOptions): string | null;
public channelId: Snowflake;
@@ -4262,9 +4109,9 @@ export class Webhook<Type extends WebhookType = WebhookType> {
public editMessage(
message: MessageResolvable,
options: string | MessagePayload | WebhookMessageEditOptions,
): Promise<Message<true>>;
public fetchMessage(message: Snowflake, options?: WebhookFetchMessageOptions): Promise<Message<true>>;
public send(options: string | MessagePayload | WebhookMessageCreateOptions): Promise<Message<true>>;
): Promise<Message>;
public fetchMessage(message: Snowflake, options?: WebhookFetchMessageOptions): Promise<Message>;
public send(options: string | MessagePayload | WebhookMessageCreateOptions): Promise<Message>;
}
// tslint:disable-next-line no-empty-interface
@@ -4650,8 +4497,6 @@ export enum DiscordjsErrorCodes {
ModalSubmitInteractionFieldNotFound = 'ModalSubmitInteractionFieldNotFound',
ModalSubmitInteractionFieldType = 'ModalSubmitInteractionFieldType',
ModalSubmitInteractionFieldEmpty = 'ModalSubmitInteractionComponentEmpty',
ModalSubmitInteractionFieldInvalidChannelType = 'ModalSubmitInteractionFieldInvalidChannelType',
InvalidMissingScopes = 'InvalidMissingScopes',
InvalidScopesWithPermissions = 'InvalidScopesWithPermissions',
@@ -5000,7 +4845,6 @@ export interface FetchSoundboardSoundsOptions {
export class GuildManager extends CachedManager<Snowflake, Guild, GuildResolvable> {
private constructor(client: Client<true>, iterable?: Iterable<RawGuildData>);
/** @deprecated API related to guild ownership may no longer be used. */
public create(options: GuildCreateOptions): Promise<Guild>;
public fetch(options: Snowflake | FetchGuildOptions): Promise<Guild>;
public fetch(options?: FetchGuildsOptions): Promise<Collection<Snowflake, OAuth2Guild>>;
@@ -5035,7 +4879,6 @@ export class GuildMemberManager extends CachedManager<Snowflake, GuildMember, Gu
options?: BulkBanOptions,
): Promise<BulkBanResult>;
public edit(user: UserResolvable, options: GuildMemberEditOptions): Promise<GuildMember>;
public editMe(options: GuildMemberEditMeOptions): Promise<GuildMember>;
public fetch(
options: UserResolvable | FetchMemberOptions | (FetchMembersOptions & { user: UserResolvable }),
): Promise<GuildMember>;
@@ -5463,9 +5306,7 @@ export type AllowedPartial =
| MessageReaction
| GuildScheduledEvent
| ThreadMember
| SoundboardSound
| Poll
| PollAnswer;
| SoundboardSound;
export type AllowedThreadTypeForNewsChannel = ChannelType.AnnouncementThread;
@@ -6037,15 +5878,15 @@ export interface ClientEvents {
inviteDelete: [invite: Invite];
messageCreate: [message: OmitPartialGroupDMChannel<Message>];
messageDelete: [message: OmitPartialGroupDMChannel<Message | PartialMessage>];
messagePollVoteAdd: [pollAnswer: PollAnswer | PartialPollAnswer, userId: Snowflake];
messagePollVoteRemove: [pollAnswer: PollAnswer | PartialPollAnswer, userId: Snowflake];
messagePollVoteAdd: [pollAnswer: PollAnswer, userId: Snowflake];
messagePollVoteRemove: [pollAnswer: PollAnswer, userId: Snowflake];
messageReactionRemoveAll: [
message: OmitPartialGroupDMChannel<Message | PartialMessage>,
reactions: ReadonlyCollection<string | Snowflake, MessageReaction>,
];
messageReactionRemoveEmoji: [reaction: MessageReaction | PartialMessageReaction];
messageDeleteBulk: [
messages: ReadonlyCollection<Snowflake, Message<true> | PartialMessage<true>>,
messages: ReadonlyCollection<Snowflake, OmitPartialGroupDMChannel<Message | PartialMessage>>,
channel: GuildTextBasedChannel,
];
messageReactionAdd: [
@@ -6192,17 +6033,13 @@ export interface CommandInteractionOption<Cached extends CacheType = CacheType>
message?: Message<BooleanCache<Cached>>;
}
export interface BaseInteractionResolvedData<Cached extends CacheType = CacheType> {
attachments?: ReadonlyCollection<Snowflake, Attachment>;
channels?: ReadonlyCollection<Snowflake, CacheTypeReducer<Cached, Channel, APIInteractionDataResolvedChannel>>;
export interface CommandInteractionResolvedData<Cached extends CacheType = CacheType> {
users?: ReadonlyCollection<Snowflake, User>;
members?: ReadonlyCollection<Snowflake, CacheTypeReducer<Cached, GuildMember, APIInteractionDataResolvedGuildMember>>;
roles?: ReadonlyCollection<Snowflake, CacheTypeReducer<Cached, Role, APIRole>>;
users?: ReadonlyCollection<Snowflake, User>;
}
export interface CommandInteractionResolvedData<Cached extends CacheType = CacheType>
extends BaseInteractionResolvedData<Cached> {
channels?: ReadonlyCollection<Snowflake, CacheTypeReducer<Cached, Channel, APIInteractionDataResolvedChannel>>;
messages?: ReadonlyCollection<Snowflake, CacheTypeReducer<Cached, Message, APIMessage>>;
attachments?: ReadonlyCollection<Snowflake, Attachment>;
}
export interface AutocompleteFocusedOption extends Pick<CommandInteractionOption, 'name'> {
@@ -6808,7 +6645,6 @@ export interface GuildChannelOverwriteOptions {
type?: OverwriteType;
}
/** @deprecated API related to guild ownership may no longer be used. */
export interface GuildCreateOptions {
name: string;
icon?: BufferResolvable | Base64Resolvable | null;
@@ -6836,7 +6672,6 @@ export interface GuildEditOptions {
afkTimeout?: number;
afkChannel?: VoiceChannelResolvable | null;
icon?: BufferResolvable | Base64Resolvable | null;
/** @deprecated API related to guild ownership may no longer be used. */
owner?: GuildMemberResolvable;
splash?: BufferResolvable | Base64Resolvable | null;
discoverySplash?: BufferResolvable | Base64Resolvable | null;
@@ -6894,14 +6729,6 @@ export interface GuildMemberEditOptions {
export type GuildMemberResolvable = GuildMember | UserResolvable;
export interface GuildMemberEditMeOptions {
avatar?: Base64Resolvable | BufferResolvable | null;
banner?: Base64Resolvable | BufferResolvable | null;
bio?: string | null;
nick?: string | null;
reason?: string;
}
export type GuildResolvable = Guild | NonThreadGuildBasedChannel | GuildMember | GuildEmoji | Invite | Role | Snowflake;
export interface GuildPruneMembersOptions {
@@ -7375,7 +7202,6 @@ export interface BaseSelectMenuComponentData extends BaseComponentData {
maxValues?: number;
minValues?: number;
placeholder?: string;
required?: true;
}
export interface StringSelectMenuComponentData extends BaseSelectMenuComponentData {
@@ -7439,14 +7265,6 @@ export interface TextInputComponentData extends BaseComponentData {
placeholder?: string;
}
export interface FileUploadComponentData extends BaseComponentData {
customId: string;
maxValues?: number;
minValues?: number;
required?: boolean;
type: ComponentType.FileUpload;
}
export type MessageTarget =
| Interaction
| InteractionWebhook
@@ -7502,7 +7320,6 @@ export interface PresenceData {
export type PresenceResolvable = Presence | UserResolvable | Snowflake;
/** @deprecated API related to guild ownership may no longer be used. */
export interface PartialChannelData {
id?: Snowflake | number;
parentId?: Snowflake | number;
@@ -7549,28 +7366,11 @@ export interface PartialDMChannel extends Partialize<DMChannel, null, null, 'las
export interface PartialGuildMember extends Partialize<GuildMember, 'joinedAt' | 'joinedTimestamp' | 'pending'> {}
export interface PartialMessage<InGuild extends boolean = boolean>
extends Partialize<Message<InGuild>, 'type' | 'system' | 'pinned' | 'tts', 'content' | 'cleanContent' | 'author'> {}
export interface PartialMessage
extends Partialize<Message, 'type' | 'system' | 'pinned' | 'tts', 'content' | 'cleanContent' | 'author'> {}
export interface PartialMessageReaction extends Partialize<MessageReaction, 'count'> {}
export interface PartialPoll
extends Partialize<
Poll,
'allowMultiselect' | 'layoutType' | 'expiresTimestamp',
null,
'question' | 'message' | 'answers'
> {
question: { text: null };
message: PartialMessage;
// eslint-disable-next-line no-restricted-syntax
answers: Collection<number, PartialPollAnswer>;
}
export interface PartialPollAnswer extends Partialize<PollAnswer, 'emoji' | 'text', null, 'poll'> {
readonly poll: PartialPoll;
}
export interface PartialGuildScheduledEvent
extends Partialize<GuildScheduledEvent, 'userCount', 'status' | 'privacyLevel' | 'name' | 'entityType'> {}
@@ -7578,7 +7378,6 @@ export interface PartialThreadMember extends Partialize<ThreadMember, 'flags' |
export interface PartialSoundboardSound extends Partialize<SoundboardSound, 'available' | 'name' | 'volume'> {}
/** @deprecated API related to guild ownership may no longer be used. */
export interface PartialOverwriteData {
id: Snowflake | number;
type?: OverwriteType;
@@ -7586,7 +7385,6 @@ export interface PartialOverwriteData {
deny?: PermissionResolvable;
}
/** @deprecated API related to guild ownership may no longer be used. */
export interface PartialRoleData extends RoleData {
id?: Snowflake | number;
}
@@ -7600,8 +7398,6 @@ export enum Partials {
GuildScheduledEvent,
ThreadMember,
SoundboardSound,
Poll,
PollAnswer,
}
export interface PartialUser extends Partialize<User, 'username' | 'tag' | 'discriminator'> {}
@@ -8029,6 +7825,3 @@ export * from '@discordjs/formatters';
export * from '@discordjs/rest';
export * from '@discordjs/util';
export * from '@discordjs/ws';
// Solve TS compile error
export type { ImageSize };