From 04a7cf349e121355b8658de807c602c09060877d Mon Sep 17 00:00:00 2001 From: Pavel-Boyazov <65123753+Pavel-Boyazov@users.noreply.github.com> Date: Sun, 2 Mar 2025 00:01:40 +0300 Subject: [PATCH 1/2] types(GuildMember): use PartialGuildMember interface --- .../src/managers/GuildMemberManager.js | 6 +- .../src/managers/GuildMemberRoleManager.js | 2 +- .../src/structures/BaseGuildVoiceChannel.js | 2 +- .../discord.js/src/structures/GuildChannel.js | 2 +- packages/discord.js/src/structures/Message.js | 2 +- .../src/structures/MessageMentions.js | 4 +- .../discord.js/src/structures/Presence.js | 2 +- packages/discord.js/src/structures/Role.js | 2 +- packages/discord.js/src/structures/Typing.js | 2 +- .../discord.js/src/structures/VoiceState.js | 2 +- packages/discord.js/typings/index.d.ts | 57 ++++++++++++------- 11 files changed, 50 insertions(+), 33 deletions(-) diff --git a/packages/discord.js/src/managers/GuildMemberManager.js b/packages/discord.js/src/managers/GuildMemberManager.js index 383dda8a2cfc..f293f00e96a0 100644 --- a/packages/discord.js/src/managers/GuildMemberManager.js +++ b/packages/discord.js/src/managers/GuildMemberManager.js @@ -31,7 +31,7 @@ class GuildMemberManager extends CachedManager { /** * The cache of this Manager - * @type {Collection} + * @type {Collection} * @name GuildMemberManager#cache */ @@ -42,7 +42,7 @@ class GuildMemberManager extends CachedManager { /** * Resolves a {@link UserResolvable} to a {@link GuildMember} object. * @param {UserResolvable} member The user that is part of the guild - * @returns {?GuildMember} + * @returns {?(GuildMember | PartialGuildMember)} */ resolve(member) { const memberResolvable = super.resolve(member); @@ -132,7 +132,7 @@ class GuildMemberManager extends CachedManager { /** * The client user as a GuildMember of this guild - * @type {?GuildMember} + * @type {?(GuildMember | PartialGuildMember)} * @readonly */ get me() { diff --git a/packages/discord.js/src/managers/GuildMemberRoleManager.js b/packages/discord.js/src/managers/GuildMemberRoleManager.js index f784955e45d2..10f5e7bf7e82 100644 --- a/packages/discord.js/src/managers/GuildMemberRoleManager.js +++ b/packages/discord.js/src/managers/GuildMemberRoleManager.js @@ -16,7 +16,7 @@ class GuildMemberRoleManager extends DataManager { /** * The GuildMember this manager belongs to - * @type {GuildMember} + * @type {GuildMember | PartialGuildMember} */ this.member = member; diff --git a/packages/discord.js/src/structures/BaseGuildVoiceChannel.js b/packages/discord.js/src/structures/BaseGuildVoiceChannel.js index c42df6476c3d..ced1e8d8b05c 100644 --- a/packages/discord.js/src/structures/BaseGuildVoiceChannel.js +++ b/packages/discord.js/src/structures/BaseGuildVoiceChannel.js @@ -93,7 +93,7 @@ class BaseGuildVoiceChannel extends GuildChannel { /** * The members in this voice-based channel - * @type {Collection} + * @type {Collection} * @readonly */ get members() { diff --git a/packages/discord.js/src/structures/GuildChannel.js b/packages/discord.js/src/structures/GuildChannel.js index 5ef409e89d2a..bd601c8a63c5 100644 --- a/packages/discord.js/src/structures/GuildChannel.js +++ b/packages/discord.js/src/structures/GuildChannel.js @@ -275,7 +275,7 @@ class GuildChannel extends BaseChannel { * A collection of cached members of this channel, mapped by their ids. * Members that can view this channel, if the channel is text-based. * Members in the channel, if the channel is voice-based. - * @type {Collection} + * @type {Collection} * @readonly */ get members() { diff --git a/packages/discord.js/src/structures/Message.js b/packages/discord.js/src/structures/Message.js index b77ba32b7abd..31e1174b5125 100644 --- a/packages/discord.js/src/structures/Message.js +++ b/packages/discord.js/src/structures/Message.js @@ -497,7 +497,7 @@ class Message extends Base { /** * Represents the author of the message as a guild member. * Only available if the message comes from a guild where the author is still a member - * @type {?GuildMember} + * @type {?(GuildMember | PartialGuildMember)} * @readonly */ get member() { diff --git a/packages/discord.js/src/structures/MessageMentions.js b/packages/discord.js/src/structures/MessageMentions.js index 5df93a75c472..c992f7ee0cb2 100644 --- a/packages/discord.js/src/structures/MessageMentions.js +++ b/packages/discord.js/src/structures/MessageMentions.js @@ -129,7 +129,7 @@ class MessageMentions { /** * Cached members for {@link MessageMentions#members} - * @type {?Collection} + * @type {?Collection} * @private */ this._members = null; @@ -190,7 +190,7 @@ class MessageMentions { /** * Any members that were mentioned (only in {@link Guild}s) * Order as received from the API, not as they appear in the message content - * @type {?Collection} + * @type {?Collection} * @readonly */ get members() { diff --git a/packages/discord.js/src/structures/Presence.js b/packages/discord.js/src/structures/Presence.js index a86d1f37c3ab..a63685cb1946 100644 --- a/packages/discord.js/src/structures/Presence.js +++ b/packages/discord.js/src/structures/Presence.js @@ -63,7 +63,7 @@ class Presence extends Base { /** * The member of this presence - * @type {?GuildMember} + * @type {?(GuildMember | PartialGuildMember)} * @readonly */ get member() { diff --git a/packages/discord.js/src/structures/Role.js b/packages/discord.js/src/structures/Role.js index d58a0143b998..e4bbf536f4e2 100644 --- a/packages/discord.js/src/structures/Role.js +++ b/packages/discord.js/src/structures/Role.js @@ -175,7 +175,7 @@ class Role extends Base { /** * The cached guild members that have this role - * @type {Collection} + * @type {Collection} * @readonly */ get members() { diff --git a/packages/discord.js/src/structures/Typing.js b/packages/discord.js/src/structures/Typing.js index 6fdc0c865b11..93c434f64ba0 100644 --- a/packages/discord.js/src/structures/Typing.js +++ b/packages/discord.js/src/structures/Typing.js @@ -63,7 +63,7 @@ class Typing extends Base { /** * The member who is typing - * @type {?GuildMember} + * @type {?(GuildMember | PartialGuildMember)} * @readonly */ get member() { diff --git a/packages/discord.js/src/structures/VoiceState.js b/packages/discord.js/src/structures/VoiceState.js index 31fc37b832b4..b98c281d08d0 100644 --- a/packages/discord.js/src/structures/VoiceState.js +++ b/packages/discord.js/src/structures/VoiceState.js @@ -132,7 +132,7 @@ class VoiceState extends Base { /** * The member that this voice state belongs to - * @type {?GuildMember} + * @type {?(GuildMember | PartialGuildMember)} * @readonly */ get member() { diff --git a/packages/discord.js/typings/index.d.ts b/packages/discord.js/typings/index.d.ts index 93a828f29af3..26836b5b0e0d 100644 --- a/packages/discord.js/typings/index.d.ts +++ b/packages/discord.js/typings/index.d.ts @@ -677,7 +677,7 @@ export class BaseGuildVoiceChannel extends GuildChannel { public bitrate: number; public get full(): boolean; public get joinable(): boolean; - public get members(): Collection; + public get members(): Collection; public nsfw: boolean; public rateLimitPerUser: number | null; public rtcRegion: string | null; @@ -1541,7 +1541,10 @@ export class GuildBan extends Base { export abstract class GuildChannel extends BaseChannel { public constructor(guild: Guild, data?: RawGuildChannelData, client?: Client, immediatePatch?: boolean); - private memberPermissions(member: GuildMember, checkAdmin: boolean): Readonly; + private memberPermissions( + member: GuildMember | PartialGuildMember, + checkAdmin: boolean, + ): Readonly; private rolePermissions(role: Role, checkAdmin: boolean): Readonly; public get createdAt(): Date; public get createdTimestamp(): number; @@ -1550,7 +1553,7 @@ export abstract class GuildChannel extends BaseChannel { public guild: Guild; public guildId: Snowflake; public get manageable(): boolean; - public get members(): Collection; + public get members(): Collection; public name: string; public get parent(): CategoryChannel | null; public parentId: Snowflake | null; @@ -1565,7 +1568,10 @@ export abstract class GuildChannel extends BaseChannel { public edit(options: GuildChannelEditOptions): Promise; public equals(channel: GuildChannel): boolean; public lockPermissions(): Promise; - public permissionsFor(memberOrRole: GuildMember | Role, checkAdmin?: boolean): Readonly; + public permissionsFor( + memberOrRole: GuildMember | PartialGuildMember | Role, + checkAdmin?: boolean, + ): Readonly; public permissionsFor( memberOrRole: UserResolvable | RoleResolvable, checkAdmin?: boolean, @@ -1618,8 +1624,8 @@ export class GuildMember extends Base { public get communicationDisabledUntil(): Date | null; public communicationDisabledUntilTimestamp: number | null; public flags: Readonly; - public get joinedAt(): Date | null; - public joinedTimestamp: number | null; + public get joinedAt(): Date; + public joinedTimestamp: number; public get kickable(): boolean; public get manageable(): boolean; public get moderatable(): boolean; @@ -2135,7 +2141,7 @@ export class Message extends Base { public get hasThread(): boolean; public id: Snowflake; public interactionMetadata: MessageInteractionMetadata | null; - public get member(): GuildMember | null; + public get member(): GuildMember | PartialGuildMember | null; public mentions: MessageMentions; public nonce: string | number | null; public get partial(): false; @@ -2370,7 +2376,7 @@ export class MessageMentions { ); private _channels: Collection | null; private readonly _content: string; - private _members: Collection | null; + private _members: Collection | null; private _parsedUsers: Collection | null; public get channels(): Collection; @@ -2378,7 +2384,7 @@ export class MessageMentions { public everyone: boolean; public readonly guild: If; public has(data: UserResolvable | RoleResolvable | ChannelResolvable, options?: MessageMentionsHasOptions): boolean; - public get members(): If>; + public get members(): If>; public get parsedUsers(): Collection; public repliedUser: User | null; public roles: Collection; @@ -2693,7 +2699,7 @@ export class Presence extends Base { public activities: Activity[]; public clientStatus: ClientPresenceStatusData | null; public guild: Guild | null; - public get member(): GuildMember | null; + public get member(): GuildMember | PartialGuildMember | null; public status: PresenceStatus; public get user(): User | null; public userId: Snowflake; @@ -2803,7 +2809,7 @@ export class Role extends Base { public hoist: boolean; public id: Snowflake; public managed: boolean; - public get members(): Collection; + public get members(): Collection; public mentionable: boolean; public name: string; public permissions: Readonly; @@ -3355,7 +3361,10 @@ export class ThreadChannel extends BaseCha public edit(options: ThreadEditOptions): Promise; public join(): Promise; public leave(): Promise; - public permissionsFor(memberOrRole: GuildMember | Role, checkAdmin?: boolean): Readonly; + public permissionsFor( + memberOrRole: GuildMember | PartialGuildMember | Role, + checkAdmin?: boolean, + ): Readonly; public permissionsFor( memberOrRole: UserResolvable | RoleResolvable, checkAdmin?: boolean, @@ -3403,7 +3412,7 @@ export class Typing extends Base { public startedTimestamp: number; public get startedAt(): Date; public get guild(): Guild | null; - public get member(): GuildMember | null; + public get member(): GuildMember | PartialGuildMember | null; public inGuild(): this is this & { channel: TextChannel | AnnouncementChannel | ThreadChannel; get guild(): Guild; @@ -3586,7 +3595,7 @@ export class VoiceState extends Base { public get deaf(): boolean | null; public guild: Guild; public id: Snowflake; - public get member(): GuildMember | null; + public get member(): GuildMember | PartialGuildMember | null; public get mute(): boolean | null; public selfDeaf: boolean | null; public selfMute: boolean | null; @@ -4224,10 +4233,10 @@ export interface AddOrRemoveGuildMemberRoleOptions { reason?: string; } -export class GuildMemberManager extends CachedManager { +export class GuildMemberManager extends CachedManager { private constructor(guild: Guild, iterable?: Iterable); public guild: Guild; - public get me(): GuildMember | null; + public get me(): GuildMember | PartialGuildMember | null; public add( user: UserResolvable, options: AddGuildMemberOptions & { fetchWhenExisting: false }, @@ -4314,14 +4323,14 @@ export class GuildStickerManager extends CachedManager { - private constructor(member: GuildMember); + private constructor(member: GuildMember | PartialGuildMember); public get hoist(): Role | null; public get icon(): Role | null; public get color(): Role | null; public get highest(): Role; public get premiumSubscriberRole(): Role | null; public get botRole(): Role | null; - public member: GuildMember; + public member: GuildMember | PartialGuildMember; public guild: Guild; public add( @@ -5959,7 +5968,15 @@ export interface GuildMemberEditOptions { reason?: string; } -export type GuildResolvable = Guild | NonThreadGuildBasedChannel | GuildMember | GuildEmoji | Invite | Role | Snowflake; +export type GuildResolvable = + | Guild + | NonThreadGuildBasedChannel + | GuildMember + | PartialGuildMember + | GuildEmoji + | Invite + | Role + | Snowflake; export interface GuildPruneMembersOptions { count?: boolean; @@ -6864,7 +6881,7 @@ export type ThreadMemberResolvable = ThreadMember | UserResolvable; export type UserMention = `<@${Snowflake}>`; -export type UserResolvable = User | Snowflake | Message | GuildMember | ThreadMember; +export type UserResolvable = User | Snowflake | Message | GuildMember | PartialGuildMember | ThreadMember; export interface Vanity { code: string | null; From a30a749599382ba02554d1baa7f2e10bcf26e96e Mon Sep 17 00:00:00 2001 From: Pavel-Boyazov <65123753+Pavel-Boyazov@users.noreply.github.com> Date: Sun, 2 Mar 2025 00:03:46 +0300 Subject: [PATCH 2/2] fix(PresenceUpdate): cache member based on partials --- .../client/websocket/handlers/PRESENCE_UPDATE.js | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/packages/discord.js/src/client/websocket/handlers/PRESENCE_UPDATE.js b/packages/discord.js/src/client/websocket/handlers/PRESENCE_UPDATE.js index a4db8a43ea30..875a1c07aacf 100644 --- a/packages/discord.js/src/client/websocket/handlers/PRESENCE_UPDATE.js +++ b/packages/discord.js/src/client/websocket/handlers/PRESENCE_UPDATE.js @@ -21,11 +21,14 @@ module.exports = (client, { d: data }) => { let member = guild.members.cache.get(user.id); if (!member && data.status !== 'offline') { - member = guild.members._add({ - user, - deaf: false, - mute: false, - }); + member = guild.members._add( + { + user, + deaf: false, + mute: false, + }, + client.options.partials.includes(Partials.GuildMember), + ); client.emit(Events.GuildMemberAvailable, member); }