Discord.js v13.7
This commit is contained in:
@@ -65,6 +65,8 @@ class ApplicationCommandManager extends CachedManager {
|
||||
* Options used to fetch Application Commands from Discord
|
||||
* @typedef {BaseFetchOptions} FetchApplicationCommandOptions
|
||||
* @property {Snowflake} [guildId] The guild's id to fetch commands for, for when the guild is not cached
|
||||
* @property {LocaleString} [locale] The locale to use when fetching this command
|
||||
* @property {boolean} [withLocalizations] Whether to fetch all localization data
|
||||
*/
|
||||
|
||||
/**
|
||||
@@ -83,10 +85,10 @@ class ApplicationCommandManager extends CachedManager {
|
||||
* .then(commands => console.log(`Fetched ${commands.size} commands`))
|
||||
* .catch(console.error);
|
||||
*/
|
||||
async fetch(id, { guildId, cache = true, force = false } = {}) {
|
||||
async fetch(id, { guildId, cache = true, force = false, locale, withLocalizations } = {}) {
|
||||
// Change from user.createDM to opcode (risky action)
|
||||
if (typeof id === 'object') {
|
||||
({ guildId, cache = true } = id);
|
||||
({ guildId, cache = true, locale, withLocalizations } = id);
|
||||
} else if (id) {
|
||||
if (!force) {
|
||||
const existing = this.cache.get(id);
|
||||
@@ -97,7 +99,15 @@ class ApplicationCommandManager extends CachedManager {
|
||||
return this._add(command, cache);
|
||||
}
|
||||
await this.user.createDM().catch(() => {});
|
||||
const data = await this.commandPath({ guildId }).get();
|
||||
const data = await this.commandPath({ guildId }).get({
|
||||
headers: {
|
||||
'X-Discord-Locale': locale,
|
||||
},
|
||||
query:
|
||||
typeof withLocalizations === 'boolean'
|
||||
? new URLSearchParams({ with_localizations: withLocalizations })
|
||||
: undefined,
|
||||
});
|
||||
return data.reduce((coll, command) => coll.set(command.id, this._add(command, cache, guildId)), new Collection());
|
||||
}
|
||||
|
||||
@@ -213,7 +223,9 @@ class ApplicationCommandManager extends CachedManager {
|
||||
static transformCommand(command) {
|
||||
return {
|
||||
name: command.name,
|
||||
name_localizations: command.nameLocalizations ?? command.name_localizations,
|
||||
description: command.description,
|
||||
description_localizations: command.descriptionLocalizations ?? command.description_localizations,
|
||||
type: typeof command.type === 'number' ? command.type : ApplicationCommandTypes[command.type],
|
||||
options: command.options?.map(o => ApplicationCommand.transformOption(o)),
|
||||
default_permission: command.defaultPermission ?? command.default_permission,
|
||||
|
||||
@@ -54,9 +54,12 @@ class GuildBanManager extends CachedManager {
|
||||
*/
|
||||
|
||||
/**
|
||||
* Options used to fetch all bans from a guild.
|
||||
* Options used to fetch multiple bans from a guild.
|
||||
* @typedef {Object} FetchBansOptions
|
||||
* @property {boolean} cache Whether or not to cache the fetched bans
|
||||
* @property {number} [limit] The maximum number of bans to return
|
||||
* @property {Snowflake} [before] Consider only bans before this id
|
||||
* @property {Snowflake} [after] Consider only bans after this id
|
||||
* @property {boolean} [cache] Whether to cache the fetched bans
|
||||
*/
|
||||
|
||||
/**
|
||||
@@ -64,13 +67,13 @@ class GuildBanManager extends CachedManager {
|
||||
* @param {UserResolvable|FetchBanOptions|FetchBansOptions} [options] Options for fetching guild ban(s)
|
||||
* @returns {Promise<GuildBan|Collection<Snowflake, GuildBan>>}
|
||||
* @example
|
||||
* // Fetch all bans from a guild
|
||||
* // Fetch multiple bans from a guild
|
||||
* guild.bans.fetch()
|
||||
* .then(console.log)
|
||||
* .catch(console.error);
|
||||
* @example
|
||||
* // Fetch all bans from a guild without caching
|
||||
* guild.bans.fetch({ cache: false })
|
||||
* // Fetch a maximum of 5 bans from a guild without caching
|
||||
* guild.bans.fetch({ limit: 5, cache: false })
|
||||
* .then(console.log)
|
||||
* .catch(console.error);
|
||||
* @example
|
||||
@@ -91,14 +94,15 @@ class GuildBanManager extends CachedManager {
|
||||
*/
|
||||
fetch(options) {
|
||||
if (!options) return this._fetchMany();
|
||||
const user = this.client.users.resolveId(options);
|
||||
if (user) return this._fetchSingle({ user, cache: true });
|
||||
options.user &&= this.client.users.resolveId(options.user);
|
||||
if (!options.user) {
|
||||
if ('cache' in options) return this._fetchMany(options.cache);
|
||||
const { user, cache, force, limit, before, after } = options;
|
||||
const resolvedUser = this.client.users.resolveId(user ?? options);
|
||||
if (resolvedUser) return this._fetchSingle({ user: resolvedUser, cache, force });
|
||||
|
||||
if (!before && !after && !limit && typeof cache === 'undefined') {
|
||||
return Promise.reject(new Error('FETCH_BAN_RESOLVE_ID'));
|
||||
}
|
||||
return this._fetchSingle(options);
|
||||
|
||||
return this._fetchMany(options);
|
||||
}
|
||||
|
||||
async _fetchSingle({ user, cache, force = false }) {
|
||||
@@ -111,11 +115,13 @@ class GuildBanManager extends CachedManager {
|
||||
return this._add(data, cache);
|
||||
}
|
||||
|
||||
async _fetchMany(cache) {
|
||||
const data = await this.client.api.guilds(this.guild.id).bans.get();
|
||||
return data.reduce((col, ban) => col.set(ban.user.id, this._add(ban, cache)), new Collection());
|
||||
}
|
||||
async _fetchMany(options = {}) {
|
||||
const data = await this.client.api.guilds(this.guild.id).bans.get({
|
||||
query: options,
|
||||
});
|
||||
|
||||
return data.reduce((col, ban) => col.set(ban.user.id, this._add(ban, options.cache)), new Collection());
|
||||
}
|
||||
/**
|
||||
* Options used to ban a user from a guild.
|
||||
* @typedef {Object} BanOptions
|
||||
|
||||
@@ -4,11 +4,15 @@ const process = require('node:process');
|
||||
const { Collection } = require('@discordjs/collection');
|
||||
const CachedManager = require('./CachedManager');
|
||||
const ThreadManager = require('./ThreadManager');
|
||||
const { Error } = require('../errors');
|
||||
const { Error, TypeError } = require('../errors');
|
||||
const GuildChannel = require('../structures/GuildChannel');
|
||||
const PermissionOverwrites = require('../structures/PermissionOverwrites');
|
||||
const ThreadChannel = require('../structures/ThreadChannel');
|
||||
const { ChannelTypes, ThreadChannelTypes } = require('../util/Constants');
|
||||
const Webhook = require('../structures/Webhook');
|
||||
const { ThreadChannelTypes, ChannelTypes, VideoQualityModes } = require('../util/Constants');
|
||||
const DataResolver = require('../util/DataResolver');
|
||||
const Util = require('../util/Util');
|
||||
const { resolveAutoArchiveMaxLimit } = require('../util/Util');
|
||||
|
||||
let cacheWarningEmitted = false;
|
||||
let storeChannelDeprecationEmitted = false;
|
||||
@@ -169,6 +173,153 @@ class GuildChannelManager extends CachedManager {
|
||||
return this.client.actions.ChannelCreate.handle(data).channel;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a webhook for the channel.
|
||||
* @param {GuildChannelResolvable} channel The channel to create the webhook for
|
||||
* @param {string} name The name of the webhook
|
||||
* @param {ChannelWebhookCreateOptions} [options] Options for creating the webhook
|
||||
* @returns {Promise<Webhook>} Returns the created Webhook
|
||||
* @example
|
||||
* // Create a webhook for the current channel
|
||||
* guild.channels.createWebhook('222197033908436994', 'Snek', {
|
||||
* avatar: 'https://i.imgur.com/mI8XcpG.jpg',
|
||||
* reason: 'Needed a cool new Webhook'
|
||||
* })
|
||||
* .then(console.log)
|
||||
* .catch(console.error)
|
||||
*/
|
||||
async createWebhook(channel, name, { avatar, reason } = {}) {
|
||||
const id = this.resolveId(channel);
|
||||
if (!id) throw new TypeError('INVALID_TYPE', 'channel', 'GuildChannelResolvable');
|
||||
if (typeof avatar === 'string' && !avatar.startsWith('data:')) {
|
||||
avatar = await DataResolver.resolveImage(avatar);
|
||||
}
|
||||
const data = await this.client.api.channels[id].webhooks.post({
|
||||
data: {
|
||||
name,
|
||||
avatar,
|
||||
},
|
||||
reason,
|
||||
});
|
||||
return new Webhook(this.client, data);
|
||||
}
|
||||
|
||||
/**
|
||||
* The data for a guild channel.
|
||||
* @typedef {Object} ChannelData
|
||||
* @property {string} [name] The name of the channel
|
||||
* @property {ChannelType} [type] The type of the channel (only conversion between text and news is supported)
|
||||
* @property {number} [position] The position of the channel
|
||||
* @property {string} [topic] The topic of the text channel
|
||||
* @property {boolean} [nsfw] Whether the channel is NSFW
|
||||
* @property {number} [bitrate] The bitrate of the voice channel
|
||||
* @property {number} [userLimit] The user limit of the voice channel
|
||||
* @property {?CategoryChannelResolvable} [parent] The parent of the channel
|
||||
* @property {boolean} [lockPermissions]
|
||||
* Lock the permissions of the channel to what the parent's permissions are
|
||||
* @property {OverwriteResolvable[]|Collection<Snowflake, OverwriteResolvable>} [permissionOverwrites]
|
||||
* Permission overwrites for the channel
|
||||
* @property {number} [rateLimitPerUser] The rate limit per user (slowmode) for the channel in seconds
|
||||
* @property {ThreadAutoArchiveDuration} [defaultAutoArchiveDuration]
|
||||
* The default auto archive duration for all new threads in this channel
|
||||
* @property {?string} [rtcRegion] The RTC region of the channel
|
||||
* @property {?VideoQualityMode|number} [videoQualityMode] The camera video quality mode of the channel
|
||||
*/
|
||||
|
||||
/**
|
||||
* Edits the channel.
|
||||
* @param {GuildChannelResolvable} channel The channel to edit
|
||||
* @param {ChannelData} data The new data for the channel
|
||||
* @param {string} [reason] Reason for editing this channel
|
||||
* @returns {Promise<GuildChannel>}
|
||||
* @example
|
||||
* // Edit a channel
|
||||
* guild.channels.edit('222197033908436994', { name: 'new-channel' })
|
||||
* .then(console.log)
|
||||
* .catch(console.error);
|
||||
*/
|
||||
async edit(channel, data, reason) {
|
||||
channel = this.resolve(channel);
|
||||
if (!channel) throw new TypeError('INVALID_TYPE', 'channel', 'GuildChannelResolvable');
|
||||
|
||||
const parent = data.parent && this.client.channels.resolveId(data.parent);
|
||||
|
||||
if (typeof data.position !== 'undefined') await this.setPosition(channel, data.position, { reason });
|
||||
|
||||
let permission_overwrites = data.permissionOverwrites?.map(o => PermissionOverwrites.resolve(o, this.guild));
|
||||
|
||||
if (data.lockPermissions) {
|
||||
if (parent) {
|
||||
const newParent = this.guild.channels.resolve(parent);
|
||||
if (newParent?.type === 'GUILD_CATEGORY') {
|
||||
permission_overwrites = newParent.permissionOverwrites.cache.map(o =>
|
||||
PermissionOverwrites.resolve(o, this.guild),
|
||||
);
|
||||
}
|
||||
} else if (channel.parent) {
|
||||
permission_overwrites = this.parent.permissionOverwrites.cache.map(o =>
|
||||
PermissionOverwrites.resolve(o, this.guild),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
let defaultAutoArchiveDuration = data.defaultAutoArchiveDuration;
|
||||
if (defaultAutoArchiveDuration === 'MAX') defaultAutoArchiveDuration = resolveAutoArchiveMaxLimit(this.guild);
|
||||
|
||||
const newData = await this.client.api.channels(channel.id).patch({
|
||||
data: {
|
||||
name: (data.name ?? channel.name).trim(),
|
||||
type: data.type,
|
||||
topic: data.topic,
|
||||
nsfw: data.nsfw,
|
||||
bitrate: data.bitrate ?? channel.bitrate,
|
||||
user_limit: data.userLimit ?? channel.userLimit,
|
||||
rtc_region: data.rtcRegion ?? channel.rtcRegion,
|
||||
video_quality_mode:
|
||||
typeof data.videoQualityMode === 'string' ? VideoQualityModes[data.videoQualityMode] : data.videoQualityMode,
|
||||
parent_id: parent,
|
||||
lock_permissions: data.lockPermissions,
|
||||
rate_limit_per_user: data.rateLimitPerUser,
|
||||
default_auto_archive_duration: defaultAutoArchiveDuration,
|
||||
permission_overwrites,
|
||||
},
|
||||
reason,
|
||||
});
|
||||
|
||||
return this.client.actions.ChannelUpdate.handle(newData).updated;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a new position for the guild channel.
|
||||
* @param {GuildChannelResolvable} channel The channel to set the position for
|
||||
* @param {number} position The new position for the guild channel
|
||||
* @param {SetChannelPositionOptions} [options] Options for setting position
|
||||
* @returns {Promise<GuildChannel>}
|
||||
* @example
|
||||
* // Set a new channel position
|
||||
* guild.channels.setPosition('222078374472843266', 2)
|
||||
* .then(newChannel => console.log(`Channel's new position is ${newChannel.position}`))
|
||||
* .catch(console.error);
|
||||
*/
|
||||
async setPosition(channel, position, { relative, reason } = {}) {
|
||||
channel = this.resolve(channel);
|
||||
if (!channel) throw new TypeError('INVALID_TYPE', 'channel', 'GuildChannelResolvable');
|
||||
const updatedChannels = await Util.setPosition(
|
||||
channel,
|
||||
position,
|
||||
relative,
|
||||
this.guild._sortedChannels(this),
|
||||
this.client.api.guilds(this.guild.id).channels,
|
||||
reason,
|
||||
);
|
||||
|
||||
this.client.actions.GuildChannelsPositionUpdate.handle({
|
||||
guild_id: this.guild.id,
|
||||
channels: updatedChannels,
|
||||
});
|
||||
return channel;
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtains one or more guild channels from Discord, or the channel cache if they're already available.
|
||||
* @param {Snowflake} [id] The channel's id
|
||||
@@ -204,6 +355,39 @@ class GuildChannelManager extends CachedManager {
|
||||
return channels;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetches all webhooks for the channel.
|
||||
* @param {GuildChannelResolvable} channel The channel to fetch webhooks for
|
||||
* @returns {Promise<Collection<Snowflake, Webhook>>}
|
||||
* @example
|
||||
* // Fetch webhooks
|
||||
* guild.channels.fetchWebhooks('769862166131245066')
|
||||
* .then(hooks => console.log(`This channel has ${hooks.size} hooks`))
|
||||
* .catch(console.error);
|
||||
*/
|
||||
async fetchWebhooks(channel) {
|
||||
const id = this.resolveId(channel);
|
||||
if (!id) throw new TypeError('INVALID_TYPE', 'channel', 'GuildChannelResolvable');
|
||||
const data = await this.client.api.channels[id].webhooks.get();
|
||||
return data.reduce((hooks, hook) => hooks.set(hook.id, new Webhook(this.client, hook)), new Collection());
|
||||
}
|
||||
|
||||
/**
|
||||
* Data that can be resolved to give a Category Channel object. This can be:
|
||||
* * A CategoryChannel object
|
||||
* * A Snowflake
|
||||
* @typedef {CategoryChannel|Snowflake} CategoryChannelResolvable
|
||||
*/
|
||||
|
||||
/**
|
||||
* The data needed for updating a channel's position.
|
||||
* @typedef {Object} ChannelPosition
|
||||
* @property {GuildChannel|Snowflake} channel Channel to update
|
||||
* @property {number} [position] New position for the channel
|
||||
* @property {CategoryChannelResolvable} [parent] Parent channel for this channel
|
||||
* @property {boolean} [lockPermissions] If the overwrites should be locked to the parents overwrites
|
||||
*/
|
||||
|
||||
/**
|
||||
* Batch-updates the guild's channels' positions.
|
||||
* <info>Only one channel's parent can be changed at a time</info>
|
||||
@@ -243,6 +427,23 @@ class GuildChannelManager extends CachedManager {
|
||||
const raw = await this.client.api.guilds(this.guild.id).threads.active.get();
|
||||
return ThreadManager._mapThreads(raw, this.client, { guild: this.guild, cache });
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes the channel.
|
||||
* @param {GuildChannelResolvable} channel The channel to delete
|
||||
* @param {string} [reason] Reason for deleting this channel
|
||||
* @returns {Promise<void>}
|
||||
* @example
|
||||
* // Delete the channel
|
||||
* guild.channels.delete('858850993013260338', 'making room for new channels')
|
||||
* .then(console.log)
|
||||
* .catch(console.error);
|
||||
*/
|
||||
async delete(channel, reason) {
|
||||
const id = this.resolveId(channel);
|
||||
if (!id) throw new TypeError('INVALID_TYPE', 'channel', 'GuildChannelResolvable');
|
||||
await this.client.api.channels(id).delete({ reason });
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = GuildChannelManager;
|
||||
|
||||
@@ -2,8 +2,9 @@
|
||||
|
||||
const { Collection } = require('@discordjs/collection');
|
||||
const BaseGuildEmojiManager = require('./BaseGuildEmojiManager');
|
||||
const { TypeError } = require('../errors');
|
||||
const { Error, TypeError } = require('../errors');
|
||||
const DataResolver = require('../util/DataResolver');
|
||||
const Permissions = require('../util/Permissions');
|
||||
|
||||
/**
|
||||
* Manages API methods for GuildEmojis and stores their cache.
|
||||
@@ -100,6 +101,71 @@ class GuildEmojiManager extends BaseGuildEmojiManager {
|
||||
for (const emoji of data) emojis.set(emoji.id, this._add(emoji, cache));
|
||||
return emojis;
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes an emoji.
|
||||
* @param {EmojiResolvable} emoji The Emoji resolvable to delete
|
||||
* @param {string} [reason] Reason for deleting the emoji
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
async delete(emoji, reason) {
|
||||
const id = this.resolveId(emoji);
|
||||
if (!id) throw new TypeError('INVALID_TYPE', 'emoji', 'EmojiResolvable', true);
|
||||
await this.client.api.guilds(this.guild.id).emojis(id).delete({ reason });
|
||||
}
|
||||
|
||||
/**
|
||||
* Edits an emoji.
|
||||
* @param {EmojiResolvable} emoji The Emoji resolvable to edit
|
||||
* @param {GuildEmojiEditData} data The new data for the emoji
|
||||
* @param {string} [reason] Reason for editing this emoji
|
||||
* @returns {Promise<GuildEmoji>}
|
||||
*/
|
||||
async edit(emoji, data, reason) {
|
||||
const id = this.resolveId(emoji);
|
||||
if (!id) throw new TypeError('INVALID_TYPE', 'emoji', 'EmojiResolvable', true);
|
||||
const roles = data.roles?.map(r => this.guild.roles.resolveId(r));
|
||||
const newData = await this.client.api
|
||||
.guilds(this.guild.id)
|
||||
.emojis(id)
|
||||
.patch({
|
||||
data: {
|
||||
name: data.name,
|
||||
roles,
|
||||
},
|
||||
reason,
|
||||
});
|
||||
const existing = this.cache.get(id);
|
||||
if (existing) {
|
||||
const clone = existing._clone();
|
||||
clone._patch(newData);
|
||||
return clone;
|
||||
}
|
||||
return this._add(newData);
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetches the author for this emoji
|
||||
* @param {EmojiResolvable} emoji The emoji to fetch the author of
|
||||
* @returns {Promise<User>}
|
||||
*/
|
||||
async fetchAuthor(emoji) {
|
||||
emoji = this.resolve(emoji);
|
||||
if (!emoji) throw new TypeError('INVALID_TYPE', 'emoji', 'EmojiResolvable', true);
|
||||
if (emoji.managed) {
|
||||
throw new Error('EMOJI_MANAGED');
|
||||
}
|
||||
|
||||
const { me } = this.guild;
|
||||
if (!me) throw new Error('GUILD_UNCACHED_ME');
|
||||
if (!me.permissions.has(Permissions.FLAGS.MANAGE_EMOJIS_AND_STICKERS)) {
|
||||
throw new Error('MISSING_MANAGE_EMOJIS_AND_STICKERS_PERMISSION', this.guild);
|
||||
}
|
||||
|
||||
const data = await this.client.api.guilds(this.guild.id).emojis(emoji.id).get();
|
||||
emoji._patch(data);
|
||||
return emoji.author;
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = GuildEmojiManager;
|
||||
|
||||
@@ -18,6 +18,7 @@ const {
|
||||
VerificationLevels,
|
||||
DefaultMessageNotificationLevels,
|
||||
ExplicitContentFilterLevels,
|
||||
VideoQualityModes,
|
||||
} = require('../util/Constants');
|
||||
const DataResolver = require('../util/DataResolver');
|
||||
const Permissions = require('../util/Permissions');
|
||||
@@ -94,6 +95,7 @@ class GuildManager extends CachedManager {
|
||||
* @property {number} [bitrate] The bitrate of the voice channel
|
||||
* @property {number} [userLimit] The user limit of the channel
|
||||
* @property {?string} [rtcRegion] The RTC region of the channel
|
||||
* @property {VideoQualityMode|number} [videoQualityMode] The camera video quality mode of the channel
|
||||
* @property {PartialOverwriteData[]} [permissionOverwrites]
|
||||
* Overwrites of the channel
|
||||
* @property {number} [rateLimitPerUser] The rate limit per user (slowmode) of the channel in seconds
|
||||
@@ -200,6 +202,11 @@ class GuildManager extends CachedManager {
|
||||
delete channel.rateLimitPerUser;
|
||||
channel.rtc_region = channel.rtcRegion;
|
||||
delete channel.rtcRegion;
|
||||
channel.video_quality_mode =
|
||||
typeof channel.videoQualityMode === 'string'
|
||||
? VideoQualityModes[channel.videoQualityMode]
|
||||
: channel.videoQualityMode;
|
||||
delete channel.videoQualityMode;
|
||||
|
||||
if (!channel.permissionOverwrites) continue;
|
||||
for (const overwrite of channel.permissionOverwrites) {
|
||||
|
||||
@@ -353,7 +353,7 @@ class GuildMemberManager extends CachedManager {
|
||||
* @example
|
||||
* // Kick a user by id (or with a user/guild member object)
|
||||
* guild.members.kick('84484653687267328')
|
||||
* .then(banInfo => console.log(`Kicked ${banInfo.user?.tag ?? banInfo.tag ?? banInfo}`))
|
||||
* .then(kickInfo => console.log(`Kicked ${kickInfo.user?.tag ?? kickInfo.tag ?? kickInfo}`))
|
||||
* .catch(console.error);
|
||||
*/
|
||||
async kick(user, reason) {
|
||||
@@ -376,7 +376,7 @@ class GuildMemberManager extends CachedManager {
|
||||
* @example
|
||||
* // Ban a user by id (or with a user/guild member object)
|
||||
* guild.members.ban('84484653687267328')
|
||||
* .then(kickInfo => console.log(`Banned ${kickInfo.user?.tag ?? kickInfo.tag ?? kickInfo}`))
|
||||
* .then(banInfo => console.log(`Banned ${banInfo.user?.tag ?? banInfo.tag ?? banInfo}`))
|
||||
* .catch(console.error);
|
||||
*/
|
||||
ban(user, options = { days: 0 }) {
|
||||
@@ -387,7 +387,7 @@ class GuildMemberManager extends CachedManager {
|
||||
* Unbans a user from the guild. Internally calls the {@link GuildBanManager#remove} method.
|
||||
* @param {UserResolvable} user The user to unban
|
||||
* @param {string} [reason] Reason for unbanning user
|
||||
* @returns {Promise<User>} The user that was unbanned
|
||||
* @returns {Promise<?User>} The user that was unbanned
|
||||
* @example
|
||||
* // Unban a user by id (or with a user/guild member object)
|
||||
* guild.members.unban('84484653687267328')
|
||||
|
||||
@@ -5,6 +5,7 @@ const CachedManager = require('./CachedManager');
|
||||
const { TypeError, Error } = require('../errors');
|
||||
const { GuildScheduledEvent } = require('../structures/GuildScheduledEvent');
|
||||
const { PrivacyLevels, GuildScheduledEventEntityTypes, GuildScheduledEventStatuses } = require('../util/Constants');
|
||||
const DataResolver = require('../util/DataResolver');
|
||||
|
||||
/**
|
||||
* Manages API methods for GuildScheduledEvents and stores their cache.
|
||||
@@ -49,6 +50,7 @@ class GuildScheduledEventManager extends CachedManager {
|
||||
* @property {GuildScheduledEventEntityMetadataOptions} [entityMetadata] The entity metadata of the
|
||||
* guild scheduled event
|
||||
* <warn>This is required if `entityType` is 'EXTERNAL'</warn>
|
||||
* @property {?(BufferResolvable|Base64Resolvable)} [image] The cover image of the guild scheduled event
|
||||
* @property {string} [reason] The reason for creating the guild scheduled event
|
||||
*/
|
||||
|
||||
@@ -76,6 +78,7 @@ class GuildScheduledEventManager extends CachedManager {
|
||||
scheduledEndTime,
|
||||
entityMetadata,
|
||||
reason,
|
||||
image,
|
||||
} = options;
|
||||
|
||||
if (typeof privacyLevel === 'string') privacyLevel = PrivacyLevels[privacyLevel];
|
||||
@@ -99,6 +102,7 @@ class GuildScheduledEventManager extends CachedManager {
|
||||
scheduled_start_time: new Date(scheduledStartTime).toISOString(),
|
||||
scheduled_end_time: scheduledEndTime ? new Date(scheduledEndTime).toISOString() : scheduledEndTime,
|
||||
description,
|
||||
image: image && (await DataResolver.resolveImage(image)),
|
||||
entity_type: entityType,
|
||||
entity_metadata,
|
||||
},
|
||||
@@ -172,6 +176,7 @@ class GuildScheduledEventManager extends CachedManager {
|
||||
* @property {GuildScheduledEventEntityMetadataOptions} [entityMetadata] The entity metadata of the
|
||||
* guild scheduled event
|
||||
* <warn>This can be modified only if `entityType` of the `GuildScheduledEvent` to be edited is 'EXTERNAL'</warn>
|
||||
* @property {?(BufferResolvable|Base64Resolvable)} [image] The cover image of the guild scheduled event
|
||||
* @property {string} [reason] The reason for editing the guild scheduled event
|
||||
*/
|
||||
|
||||
@@ -197,6 +202,7 @@ class GuildScheduledEventManager extends CachedManager {
|
||||
scheduledEndTime,
|
||||
entityMetadata,
|
||||
reason,
|
||||
image,
|
||||
} = options;
|
||||
|
||||
if (typeof privacyLevel === 'string') privacyLevel = PrivacyLevels[privacyLevel];
|
||||
@@ -220,6 +226,7 @@ class GuildScheduledEventManager extends CachedManager {
|
||||
description,
|
||||
entity_type: entityType,
|
||||
status,
|
||||
image: image && (await DataResolver.resolveImage(image)),
|
||||
entity_metadata,
|
||||
},
|
||||
reason,
|
||||
@@ -268,7 +275,7 @@ class GuildScheduledEventManager extends CachedManager {
|
||||
const guildScheduledEventId = this.resolveId(guildScheduledEvent);
|
||||
if (!guildScheduledEventId) throw new Error('GUILD_SCHEDULED_EVENT_RESOLVE');
|
||||
|
||||
const { limit, withMember, before, after } = options;
|
||||
let { limit, withMember, before, after } = options;
|
||||
|
||||
const data = await this.client.api.guilds(this.guild.id, 'scheduled-events', guildScheduledEventId).users.get({
|
||||
query: { limit, with_member: withMember, before, after },
|
||||
|
||||
@@ -161,6 +161,19 @@ class GuildStickerManager extends CachedManager {
|
||||
const data = await this.client.api.guilds(this.guild.id).stickers.get();
|
||||
return new Collection(data.map(sticker => [sticker.id, this._add(sticker, cache)]));
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetches the user who uploaded this sticker, if this is a guild sticker.
|
||||
* @param {StickerResolvable} sticker The sticker to fetch the user for
|
||||
* @returns {Promise<?User>}
|
||||
*/
|
||||
async fetchUser(sticker) {
|
||||
sticker = this.resolve(sticker);
|
||||
if (!sticker) throw new TypeError('INVALID_TYPE', 'sticker', 'StickerResolvable');
|
||||
const data = await this.client.api.guilds(this.guildId).stickers(sticker.id).get();
|
||||
sticker._patch(data);
|
||||
return sticker.user;
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = GuildStickerManager;
|
||||
|
||||
@@ -158,25 +158,27 @@ class MessageManager extends CachedManager {
|
||||
/**
|
||||
* Pins a message to the channel's pinned messages, even if it's not cached.
|
||||
* @param {MessageResolvable} message The message to pin
|
||||
* @param {string} [reason] Reason for pinning
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
async pin(message) {
|
||||
async pin(message, reason) {
|
||||
message = this.resolveId(message);
|
||||
if (!message) throw new TypeError('INVALID_TYPE', 'message', 'MessageResolvable');
|
||||
|
||||
await this.client.api.channels(this.channel.id).pins(message).put();
|
||||
await this.client.api.channels(this.channel.id).pins(message).put({ reason });
|
||||
}
|
||||
|
||||
/**
|
||||
* Unpins a message from the channel's pinned messages, even if it's not cached.
|
||||
* @param {MessageResolvable} message The message to unpin
|
||||
* @param {string} [reason] Reason for unpinning
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
async unpin(message) {
|
||||
async unpin(message, reason) {
|
||||
message = this.resolveId(message);
|
||||
if (!message) throw new TypeError('INVALID_TYPE', 'message', 'MessageResolvable');
|
||||
|
||||
await this.client.api.channels(this.channel.id).pins(message).delete();
|
||||
await this.client.api.channels(this.channel.id).pins(message).delete({ reason });
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -7,7 +7,8 @@ const { TypeError } = require('../errors');
|
||||
const { Role } = require('../structures/Role');
|
||||
const DataResolver = require('../util/DataResolver');
|
||||
const Permissions = require('../util/Permissions');
|
||||
const { resolveColor, setPosition } = require('../util/Util');
|
||||
const { resolveColor } = require('../util/Util');
|
||||
const Util = require('../util/Util');
|
||||
|
||||
let cacheWarningEmitted = false;
|
||||
|
||||
@@ -159,7 +160,7 @@ class RoleManager extends CachedManager {
|
||||
guild_id: this.guild.id,
|
||||
role: data,
|
||||
});
|
||||
if (position) return role.setPosition(position, reason);
|
||||
if (position) return this.setPosition(role, position, { reason });
|
||||
return role;
|
||||
}
|
||||
|
||||
@@ -179,21 +180,7 @@ class RoleManager extends CachedManager {
|
||||
role = this.resolve(role);
|
||||
if (!role) throw new TypeError('INVALID_TYPE', 'role', 'RoleResolvable');
|
||||
|
||||
if (typeof data.position === 'number') {
|
||||
const updatedRoles = await setPosition(
|
||||
role,
|
||||
data.position,
|
||||
false,
|
||||
this.guild._sortedRoles(),
|
||||
this.client.api.guilds(this.guild.id).roles,
|
||||
reason,
|
||||
);
|
||||
|
||||
this.client.actions.GuildRolesPositionUpdate.handle({
|
||||
guild_id: this.guild.id,
|
||||
roles: updatedRoles,
|
||||
});
|
||||
}
|
||||
if (typeof data.position === 'number') await this.setPosition(role, data.position, { reason });
|
||||
|
||||
let icon = data.icon;
|
||||
if (icon) {
|
||||
@@ -227,7 +214,7 @@ class RoleManager extends CachedManager {
|
||||
* @example
|
||||
* // Delete a role
|
||||
* guild.roles.delete('222079219327434752', 'The role needed to go')
|
||||
* .then(deleted => console.log(`Deleted role ${deleted.name}`))
|
||||
* .then(() => console.log('Deleted the role.'))
|
||||
* .catch(console.error);
|
||||
*/
|
||||
async delete(role, reason) {
|
||||
@@ -236,6 +223,44 @@ class RoleManager extends CachedManager {
|
||||
this.client.actions.GuildRoleDelete.handle({ guild_id: this.guild.id, role_id: id });
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the new position of the role.
|
||||
* @param {RoleResolvable} role The role to change the position of
|
||||
* @param {number} position The new position for the role
|
||||
* @param {SetRolePositionOptions} [options] Options for setting the position
|
||||
* @returns {Promise<Role>}
|
||||
* @example
|
||||
* // Set the position of the role
|
||||
* guild.roles.setPosition('222197033908436994', 1)
|
||||
* .then(updated => console.log(`Role position: ${updated.position}`))
|
||||
* .catch(console.error);
|
||||
*/
|
||||
async setPosition(role, position, { relative, reason } = {}) {
|
||||
role = this.resolve(role);
|
||||
if (!role) throw new TypeError('INVALID_TYPE', 'role', 'RoleResolvable');
|
||||
const updatedRoles = await Util.setPosition(
|
||||
role,
|
||||
position,
|
||||
relative,
|
||||
this.guild._sortedRoles(),
|
||||
this.client.api.guilds(this.guild.id).roles,
|
||||
reason,
|
||||
);
|
||||
|
||||
this.client.actions.GuildRolesPositionUpdate.handle({
|
||||
guild_id: this.guild.id,
|
||||
roles: updatedRoles,
|
||||
});
|
||||
return role;
|
||||
}
|
||||
|
||||
/**
|
||||
* The data needed for updating a guild role's position
|
||||
* @typedef {Object} GuildRolePosition
|
||||
* @property {RoleResolvable} role The role's id
|
||||
* @property {number} position The position to update
|
||||
*/
|
||||
|
||||
/**
|
||||
* Batch-updates the guild's role positions
|
||||
* @param {GuildRolePosition[]} rolePositions Role positions to update
|
||||
|
||||
@@ -31,6 +31,7 @@ class StageInstanceManager extends CachedManager {
|
||||
* @typedef {Object} StageInstanceCreateOptions
|
||||
* @property {string} topic The topic of the stage instance
|
||||
* @property {PrivacyLevel|number} [privacyLevel] The privacy level of the stage instance
|
||||
* @property {boolean} [sendStartNotification] Whether to notify `@everyone` that the stage instance has started
|
||||
*/
|
||||
|
||||
/**
|
||||
@@ -58,7 +59,7 @@ class StageInstanceManager extends CachedManager {
|
||||
const channelId = this.guild.channels.resolveId(channel);
|
||||
if (!channelId) throw new Error('STAGE_CHANNEL_RESOLVE');
|
||||
if (typeof options !== 'object') throw new TypeError('INVALID_TYPE', 'options', 'object', true);
|
||||
let { topic, privacyLevel } = options;
|
||||
let { topic, privacyLevel, sendStartNotification } = options;
|
||||
|
||||
privacyLevel &&= typeof privacyLevel === 'number' ? privacyLevel : PrivacyLevels[privacyLevel];
|
||||
|
||||
@@ -67,6 +68,7 @@ class StageInstanceManager extends CachedManager {
|
||||
channel_id: channelId,
|
||||
topic,
|
||||
privacy_level: privacyLevel,
|
||||
send_start_notification: sendStartNotification,
|
||||
},
|
||||
});
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@ const CachedManager = require('./CachedManager');
|
||||
const { TypeError } = require('../errors');
|
||||
const ThreadChannel = require('../structures/ThreadChannel');
|
||||
const { ChannelTypes } = require('../util/Constants');
|
||||
const { resolveAutoArchiveMaxLimit } = require('../util/Util');
|
||||
|
||||
/**
|
||||
* Manages API methods for {@link ThreadChannel} objects and stores their cache.
|
||||
@@ -120,14 +121,8 @@ class ThreadManager extends CachedManager {
|
||||
} else if (this.channel.type !== 'GUILD_NEWS') {
|
||||
resolvedType = typeof type === 'string' ? ChannelTypes[type] : type ?? resolvedType;
|
||||
}
|
||||
if (autoArchiveDuration === 'MAX') {
|
||||
autoArchiveDuration = 1440;
|
||||
if (this.channel.guild.features.includes('SEVEN_DAY_THREAD_ARCHIVE')) {
|
||||
autoArchiveDuration = 10080;
|
||||
} else if (this.channel.guild.features.includes('THREE_DAY_THREAD_ARCHIVE')) {
|
||||
autoArchiveDuration = 4320;
|
||||
}
|
||||
}
|
||||
|
||||
if (autoArchiveDuration === 'MAX') autoArchiveDuration = resolveAutoArchiveMaxLimit(this.channel.guild);
|
||||
|
||||
const data = await path.threads.post({
|
||||
data: {
|
||||
|
||||
Reference in New Issue
Block a user