diff --git a/src/managers/GuildChannelManager.js b/src/managers/GuildChannelManager.js index 9b794ccda523..0d3eedff4c2b 100644 --- a/src/managers/GuildChannelManager.js +++ b/src/managers/GuildChannelManager.js @@ -3,6 +3,7 @@ const BaseManager = require('./BaseManager'); const GuildChannel = require('../structures/GuildChannel'); const PermissionOverwrites = require('../structures/PermissionOverwrites'); +const ThreadChannel = require('../structures/ThreadChannel'); const Collection = require('../util/Collection'); const { ChannelTypes, ThreadChannelTypes } = require('../util/Constants'); @@ -36,7 +37,7 @@ class GuildChannelManager extends BaseManager { /** * The cache of this Manager - * @type {Collection} + * @type {Collection} * @name GuildChannelManager#cache */ @@ -50,27 +51,30 @@ class GuildChannelManager extends BaseManager { /** * Data that can be resolved to give a Guild Channel object. This can be: * * A GuildChannel object + * * A ThreadChannel object * * A Snowflake - * @typedef {GuildChannel|Snowflake} GuildChannelResolvable + * @typedef {GuildChannel|ThreadChannel|Snowflake} GuildChannelResolvable */ /** * Resolves a GuildChannelResolvable to a Channel object. - * @method resolve - * @memberof GuildChannelManager - * @instance * @param {GuildChannelResolvable} channel The GuildChannel resolvable to resolve - * @returns {?GuildChannel} + * @returns {?(GuildChannel|ThreadChannel)} */ + resolve(channel) { + if (channel instanceof ThreadChannel) return super.resolve(channel.id); + return super.resolve(channel); + } /** * Resolves a GuildChannelResolvable to a channel ID string. - * @method resolveID - * @memberof GuildChannelManager - * @instance * @param {GuildChannelResolvable} channel The GuildChannel resolvable to resolve * @returns {?Snowflake} */ + resolveID(channel) { + if (channel instanceof ThreadChannel) return super.resolveID(channel.id); + return super.resolveID(channel); + } /** * Options used to create a new channel in a guild. diff --git a/src/managers/ThreadManager.js b/src/managers/ThreadManager.js index f8112d87c8b0..afded97cbf9d 100644 --- a/src/managers/ThreadManager.js +++ b/src/managers/ThreadManager.js @@ -63,8 +63,8 @@ class ThreadManager extends BaseManager { * A number that is allowed to be the duration in minutes before a thread is automatically archived. This can be: * * `60` (1 hour) * * `1440` (1 day) - * * `4320` (3 days) - * * `10080` (7 days) + * * `4320` (3 days) This is only available when the guild has the `THREE_DAY_THREAD_ARCHIVE` feature. + * * `10080` (7 days) This is only available when the guild has the `SEVEN_DAY_THREAD_ARCHIVE` feature. * @typedef {number} ThreadAutoArchiveDuration */ @@ -76,8 +76,8 @@ class ThreadManager extends BaseManager { * @property {ThreadAutoArchiveDuration} autoArchiveDuration How long before the thread is automatically archived * @property {MessageResolvable} [startMessage] The message to start a public or news thread from, * creates a private thread if not provided - * @property {ThreadChannelType|number} [type] The type of thread to create - * When creating threads in a `news` channel this is always `news_thread` + * @property {ThreadChannelType|number} [type='public_thread'] The type of thread to create + * When creating threads in a `news` channel this is ignored and is always `news_thread` * @param {string} [reason] Reason for creating the thread */ @@ -89,16 +89,21 @@ class ThreadManager extends BaseManager { * // Create a new public thread * channel.threads * .create({ - * name: 'food-talk' + * name: 'food-talk', * autoArchiveDuration: 60, - * startMessage: channel.lastMessageID, * reason: 'Needed a separate thread for food', * }) * .then(console.log) * .catch(console.error); + * @example * // Create a new private thread * channel.threads - * .create({ name: 'mod-talk', autoArchiveDuration: 60, reason: 'Needed a separate thread for moderation' }) + * .create({ + * name: 'mod-talk', + * autoArchiveDuration: 60, + * type: 'private_thread', + * reason: 'Needed a separate thread for moderation', + * }) * .then(console.log) * .catch(console.error); */ @@ -113,7 +118,7 @@ class ThreadManager extends BaseManager { if (!startMessageID) throw new TypeError('INVALID_TYPE', 'startMessage', 'MessageResolvable'); path = path.messages(startMessageID); } else if (this.channel.type !== 'news') { - resolvedType = typeof type === 'string' ? ChannelTypes[type.toUpperCase()] : type; + resolvedType = typeof type === 'string' ? ChannelTypes[type.toUpperCase()] : type ?? resolvedType; } const data = await path.threads.post({ diff --git a/src/structures/Guild.js b/src/structures/Guild.js index ba5a444e1838..685d422e8243 100644 --- a/src/structures/Guild.js +++ b/src/structures/Guild.js @@ -170,7 +170,10 @@ class Guild extends AnonymousGuild { * * NEWS * * PARTNERED * * PREVIEW_ENABLED + * * PRIVATE_THREADS * * RELAY_ENABLED + * * SEVEN_DAY_THREAD_ARCHIVE + * * THREE_DAY_THREAD_ARCHIVE * * TICKETED_EVENTS_ENABLED * * VANITY_URL * * VERIFIED diff --git a/src/structures/GuildMember.js b/src/structures/GuildMember.js index 0bc84414f5ba..0f5082621996 100644 --- a/src/structures/GuildMember.js +++ b/src/structures/GuildMember.js @@ -256,13 +256,13 @@ class GuildMember extends Base { /** * Returns `channel.permissionsFor(guildMember)`. Returns permissions for a member in a guild channel, * taking into account roles and permission overwrites. - * @param {ChannelResolvable} channel The guild channel to use as context + * @param {GuildChannelResolvable} channel The guild channel to use as context * @returns {Readonly} */ permissionsIn(channel) { channel = this.guild.channels.resolve(channel); if (!channel) throw new Error('GUILD_CHANNEL_RESOLVE'); - return channel.memberPermissions(this); + return channel.permissionsFor(this); } /** diff --git a/src/util/Constants.js b/src/util/Constants.js index e4e158bc0ea7..49e48b01776b 100644 --- a/src/util/Constants.js +++ b/src/util/Constants.js @@ -764,6 +764,7 @@ exports.APIErrors = { ANNOUNCEMENT_EDIT_LIMIT_EXCEEDED: 20022, CHANNEL_HIT_WRITE_RATELIMIT: 20028, CONTENT_NOT_ALLOWED: 20031, + GUILD_PREMIUM_LEVEL_TOO_LOW: 20035, MAXIMUM_GUILDS: 30001, MAXIMUM_FRIENDS: 30002, MAXIMUM_PINS: 30003, diff --git a/typings/index.d.ts b/typings/index.d.ts index bf3ee5cd6cea..9b1cfd8eb736 100644 --- a/typings/index.d.ts +++ b/typings/index.d.ts @@ -1082,7 +1082,7 @@ declare module 'discord.js' { public deleteDM(): Promise; public edit(data: GuildMemberEditData, reason?: string): Promise; public kick(reason?: string): Promise; - public permissionsIn(channel: ChannelResolvable): Readonly; + public permissionsIn(channel: GuildChannelResolvable): Readonly; public setNickname(nickname: string | null, reason?: string): Promise; public toJSON(): unknown; public toString(): string; @@ -2400,7 +2400,11 @@ declare module 'discord.js' { ): Promise>; } - export class GuildChannelManager extends BaseManager { + export class GuildChannelManager extends BaseManager< + Snowflake, + GuildChannel | ThreadChannel, + GuildChannelResolvable + > { constructor(guild: Guild, iterable?: Iterable); public readonly channelCountWithoutThreads: number; public guild: Guild; @@ -2740,6 +2744,7 @@ declare module 'discord.js' { ANNOUNCEMENT_EDIT_LIMIT_EXCEEDED: 20022; CHANNEL_HIT_WRITE_RATELIMIT: 20028; CONTENT_NOT_ALLOWED: 20031; + GUILD_PREMIUM_LEVEL_TOO_LOW: 20035; MAXIMUM_GUILDS: 30001; MAXIMUM_FRIENDS: 30002; MAXIMUM_PINS: 30003; @@ -3372,7 +3377,7 @@ declare module 'discord.js' { type?: number; } - type GuildChannelResolvable = Snowflake | GuildChannel; + type GuildChannelResolvable = Snowflake | GuildChannel | ThreadChannel; interface GuildChannelCreateOptions { permissionOverwrites?: OverwriteResolvable[] | Collection; @@ -3466,7 +3471,10 @@ declare module 'discord.js' { | 'NEWS' | 'PARTNERED' | 'PREVIEW_ENABLED' + | 'PRIVATE_THREADS' | 'RELAY_ENABLED' + | 'SEVEN_DAY_THREAD_ARCHIVE' + | 'THREE_DAY_THREAD_ARCHIVE' | 'TICKETED_EVENTS_ENABLED' | 'VANITY_URL' | 'VERIFIED'