diff --git a/packages/discord.js/src/managers/ThreadMemberManager.js b/packages/discord.js/src/managers/ThreadMemberManager.js index b7fdf62f4..054dc85d8 100644 --- a/packages/discord.js/src/managers/ThreadMemberManager.js +++ b/packages/discord.js/src/managers/ThreadMemberManager.js @@ -111,35 +111,43 @@ class ThreadMemberManager extends CachedManager { return id; } - async _fetchOne(memberId, cache, force) { + /** + * @typedef {BaseFetchOptions} FetchThreadMemberOptions + * @property {ThreadMemberResolvable} [member] The thread member to fetch + */ + + /** + * @typedef {Object} FetchThreadMembersOptions + * @property {boolean} [cache] Whether to cache the fetched thread members + */ + + /** + * Fetches thread member(s) from Discord. Requires the `GUILD_MEMBERS` gateway intent. + * @param {ThreadMemberResolvable|FetchThreadMemberOptions|FetchThreadMembersOptions} [options] + * Options for fetching thread member(s) + * @returns {Promise>} + */ + fetch(options) { + if (!options) return this._fetchMany(); + const { member, cache, force } = options; + const resolvedMember = this.resolveId(member ?? options); + if (resolvedMember) return this._fetchSingle({ member: resolvedMember, cache, force }); + return this._fetchMany(options); + } + + async _fetchSingle({ member, cache, force = false }) { if (!force) { - const existing = this.cache.get(memberId); + const existing = this.cache.get(member); if (existing) return existing; } - const data = await this.client.rest.get(Routes.threadMembers(this.thread.id, memberId)); + const data = await this.client.rest.get(Routes.threadMembers(this.thread.id, member)); return this._add(data, cache); } - async _fetchMany(cache) { - const raw = await this.client.rest.get(Routes.threadMembers(this.thread.id)); - return raw.reduce((col, member) => col.set(member.user_id, this._add(member, cache)), new Collection()); - } - - /** - * @typedef {BaseFetchOptions} ThreadMemberFetchOptions - * @property {UserResolvable} [member] The specific user to fetch from the thread - */ - - /** - * Fetches member(s) for the thread from Discord, requires access to the `GUILD_MEMBERS` gateway intent. - * @param {ThreadMemberFetchOptions|boolean} [options] Additional options for this fetch, when a `boolean` is provided - * all members are fetched with `options.cache` set to the boolean value - * @returns {Promise>} - */ - fetch({ member, cache = true, force = false } = {}) { - const id = this.resolveId(member); - return id ? this._fetchOne(id, cache, force) : this._fetchMany(member ?? cache); + async _fetchMany(options = {}) { + const data = await this.client.rest.get(Routes.threadMembers(this.thread.id)); + return data.reduce((col, member) => col.set(member.user_id, this._add(member, options.cache)), new Collection()); } } diff --git a/packages/discord.js/src/structures/ThreadChannel.js b/packages/discord.js/src/structures/ThreadChannel.js index bab761756..2f51fa313 100644 --- a/packages/discord.js/src/structures/ThreadChannel.js +++ b/packages/discord.js/src/structures/ThreadChannel.js @@ -272,7 +272,7 @@ class ThreadChannel extends Channel { } // We cannot fetch a single thread member, as of this commit's date, Discord API responds with 405 - const members = await this.members.fetch(cache); + const members = await this.members.fetch({ cache }); return members.get(this.ownerId) ?? null; } diff --git a/packages/discord.js/typings/index.d.ts b/packages/discord.js/typings/index.d.ts index 1fb7b95da..f13528dbd 100644 --- a/packages/discord.js/typings/index.d.ts +++ b/packages/discord.js/typings/index.d.ts @@ -3404,8 +3404,8 @@ export class ThreadMemberManager extends CachedManager; - public fetch(options?: ThreadMemberFetchOptions): Promise; - public fetch(cache?: boolean): Promise>; + public fetch(options?: ThreadMemberResolvable | FetchThreadMemberOptions): Promise; + public fetch(options?: FetchThreadMembersOptions): Promise>; public fetchMe(options?: BaseFetchOptions): Promise; public remove(id: Snowflake | '@me', reason?: string): Promise; } @@ -3748,10 +3748,6 @@ export interface BaseFetchOptions { force?: boolean; } -export interface ThreadMemberFetchOptions extends BaseFetchOptions { - member?: UserResolvable; -} - export type BitFieldResolvable = | RecursiveReadonlyArray>> | T @@ -4313,6 +4309,14 @@ export interface FetchReactionUsersOptions { after?: Snowflake; } +export interface FetchThreadMemberOptions extends BaseFetchOptions { + member: ThreadMemberResolvable; +} + +export interface FetchThreadMembersOptions { + cache?: boolean; +} + export interface FetchThreadsOptions { archived?: FetchArchivedThreadOptions; active?: boolean; diff --git a/packages/discord.js/typings/index.test-d.ts b/packages/discord.js/typings/index.test-d.ts index c4dbfbd03..3d1613e3b 100644 --- a/packages/discord.js/typings/index.test-d.ts +++ b/packages/discord.js/typings/index.test-d.ts @@ -127,7 +127,7 @@ import { UserContextMenuCommandInteraction, AnyThreadChannel, } from '.'; -import { expectAssignable, expectDeprecated, expectNotAssignable, expectNotType, expectType } from 'tsd'; +import { expectAssignable, expectNotAssignable, expectNotType, expectType } from 'tsd'; import { UnsafeButtonBuilder, UnsafeEmbedBuilder, UnsafeSelectMenuBuilder } from '@discordjs/builders'; // Test type transformation: @@ -561,11 +561,14 @@ client.on('guildCreate', async g => { } if (channel.isThread()) { - const fetchedMember = await channel.members.fetch({ member: '12345678' }); + const fetchedMember = await channel.members.fetch('12345678'); + const fetchedMember2 = await channel.members.fetch({ member: '12345678', cache: false, force: true }); expectType(fetchedMember); - const fetchedMemberCol = await channel.members.fetch(true); - expectDeprecated(await channel.members.fetch(true)); + expectType(fetchedMember2); + const fetchedMemberCol = await channel.members.fetch({ cache: true }); expectType>(fetchedMemberCol); + // @ts-expect-error The `force` option cannot be used alongside fetching all thread members. + const fetchedMemberCol2 = await channel.members.fetch({ cache: true, force: false }); } channel.setName('foo').then(updatedChannel => {