Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(GuildMember): cache based on partials options #10785

Open
wants to merge 2 commits into
base: main
Choose a base branch
from

Conversation

Pavel-Boyazov
Copy link

Please describe the changes this PR makes and why it should be merged:
This PR based on previous PR's conversation.

Discord API's Guild Member object has isn't nullable joinedAt property.
This also confirms the partial property set to false, which depends on the nullability of joinedAt and the use of Partialize for this property to create the PartialGuildMember interface.
It's also incorrect that caching of a partial member is performed despite the provided partials options.

Status and versioning classification:

  • Code changes have been tested against the Discord API, or there are no code changes
  • I know how to update typings and have done so, or typings don't need updating

@Pavel-Boyazov Pavel-Boyazov requested a review from a team as a code owner March 1, 2025 21:12
Copy link

vercel bot commented Mar 1, 2025

The latest updates on your projects. Learn more about Vercel for Git ↗︎

2 Skipped Deployments
Name Status Preview Comments Updated (UTC)
discord-js ⬜️ Ignored (Inspect) Visit Preview Mar 1, 2025 9:13pm
discord-js-guide ⬜️ Ignored (Inspect) Visit Preview Mar 1, 2025 9:13pm

@@ -31,7 +31,7 @@ class GuildMemberManager extends CachedManager {

/**
* The cache of this Manager
* @type {Collection<Snowflake, GuildMember>}
* @type {Collection<Snowflake, GuildMember | PartialGuildMember>}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The whole idea of fixing this was that there won‘t be PartialGuildMember in the cache. And there is no PartialGuildMember in JS land anyway, so this would only make sense in the typings (but is wrong there for the above reason).
Same applies for all other JSDoc comments you added PartialGuildMember to

deaf: false,
mute: false,
},
client.options.partials.includes(Partials.GuildMember),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This needs more/better logic. The member should always be patched with that data, if cached before, but should never be newly added to cache. The guildMemberAvaliable event here should only emit if the partial is set. So add the partial check to the if conditions surrounding this block instead.

Copy link
Author

@Pavel-Boyazov Pavel-Boyazov Mar 2, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The guildMemberAvaliable event here should only emit if the partial is set.

I think it also needs to be emit if member object cached before. Didn't?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, if it's cache before then the !member condition would be false anyway.

@@ -63,7 +63,7 @@ class Presence extends Base {

/**
* The member of this presence
* @type {?GuildMember}
* @type {?(GuildMember | PartialGuildMember)}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here this.member should be turned into a property created from data passed in constructor instead of a getter. That way it could contain a partial guild member without putting that partial data into cache.

private constructor(guild: Guild, iterable?: Iterable<RawGuildMemberData>);
public guild: Guild;
public get me(): GuildMember | null;
public get me(): GuildMember | PartialGuildMember | null;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We always get the full GuildMember data for the ClientUser on GUILD_CREATE, so this can never be a PartialGuildMember to begin with.

Copy link
Author

@Pavel-Boyazov Pavel-Boyazov Mar 2, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

GUILD_CREATE not emit if Guilds intent not set

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Without Guilds intent you wouldn't have any GuildMembers cached and the whole GuildMemberManager would be inaccessible because you don't have a Guild having it as property to begin with.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What prevents us from using fetch to get and cache guilds with specific members exclude client member?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

get me() {
return (
this.cache.get(this.client.user.id) ??
(this.client.options.partials.includes(Partials.GuildMember)
? this._add({ user: { id: this.client.user.id } }, true)
: null)
);
}

And if it like you say, why exist this functionality?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Okay, that's a good catch indeed. Guess GuildMemberManager#me can be a PartialGuildMember after all, if the GuildMemberManager cache is limited to 0 without exception for the ClientUser.
But about no Guilds intent: most of the typings rely on that being present. Because several helper methods need it to work anyway.

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;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

While technically correct this degrades UX. Probably better to add a Partialized version of this manager overriding this property and overriding the roles getter on PartialGuildMember with that partial manager.

| Guild
| NonThreadGuildBasedChannel
| GuildMember
| PartialGuildMember
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think it makes much sense to resolve a Guild from a partial member, but that one's up to debate I'd say

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
Status: Review in Progress
Development

Successfully merging this pull request may close these issues.

2 participants