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

userUpdate gets emitted only after first change despite partials enabled #10542

Closed
VDD2004 opened this issue Oct 7, 2024 · 3 comments
Closed

Comments

@VDD2004
Copy link

VDD2004 commented Oct 7, 2024

Which package is this bug report for?

discord.js

Issue description

  1. Initialize discord bot
  2. Set up guildMemberUpdate and userUpdate listeners
  3. Go to a discord account that is on a server the bot can see. Change the username or display name. The original display name will be "Example" and the new "Change Test". It will get emitted by guildMemberUpdate rather than updateUser and oldMember.user.displayName and newMember.user.displayName will both be the most current

Guild member updated: Change Test (exampleUsername) => Change Test (exampleUsername)

  1. Change the display name or username of that user again (Change Test will become CT2). The oldUser shows the correct previous display name and newUser shows the correct current display name as well

User updated: Change Test (exampleUsername) => CT2 (exampleUsername)

This issue is per-issue, as each user needs to make the first change to their display name or username before the userUpdate is emitted for them on the second or later changes.
It also resets every time the bot is restarted and is consistent across restarts

Code sample

import { Client, GatewayIntentBits, Partials } from "discord.js";
// use all partials just to be safe for testing
const client = new Client({intents: [
    GatewayIntentBits.Guilds,
    GatewayIntentBits.GuildMessages,
    GatewayIntentBits.DirectMessages,
    GatewayIntentBits.MessageContent,
    GatewayIntentBits.GuildMembers,
  ],
  partials: [
    Partials.User,
    Partials.GuildMember,
    Partials.Channel,
    Partials.GuildScheduledEvent,
    Partials.Message,
    Partials.Reaction,
    Partials.ThreadMember
  ]
});

client.on('guildMemberUpdate', async (oldMember, newMember) => {
    if (oldMember.partial) {
      oldMember = await oldMember.fetch();
    }
    console.log(`Guild member updated: ${oldMember.user.displayName} (${oldMember.user.username}) => `+
      `${newMember.user.displayName} (@${newMember.user.username}):`);
});

client.on('userUpdate', async (oldUser, newUser) => {
    if (oldUser.partial) {
      oldUser = await oldUser.fetch();
    }
    console.log(`User updated: ${oldUser.displayName} (${oldUser.username}) => ${newUser.displayName} (@${newUser.username})\n`);
});

Versions

-discord.js 14.16.3
-Node.js 20.11.0
-Windows 11 Pro 23H2

Issue priority

Low (slightly annoying)

Which partials do you have configured?

User, Channel, GuildMember, Message, Reaction, GuildScheduledEvent, ThreadMember

Which gateway intents are you subscribing to?

Guilds, GuildMembers, GuildMessages, DirectMessages, MessageContent

I have tested this issue on a development release

No response

@imnaiyar
Copy link
Contributor

imnaiyar commented Oct 8, 2024

userUpdate doesn’t depend on the User partial, it’s somewhat reliant on the cache. Discord only sends the event when the bot user is updated. D.js additionally emits it when the user in the cache differs from the user received in other events, like (guildMemberUpdate or presenceUpdate). So when you restart the bot, there’s no user in the cache to compare, hence no event.

And for your second issue (oldMember.user, and newMember.user being the same), for uncached members, oldMember would be a partial, and you seem to fetch the member in such cases, so you get the newMember there too, as fetching will return the latest data

@VDD2004
Copy link
Author

VDD2004 commented Oct 8, 2024

That makes sense. Although I did notice something else; if I print out the display name and username of the oldMember before I call oldMember.fetch(), I get this result (changing display name from Change Test to CT2 in this example):

oldMember partial: CT2 (undefined)

Would this be intended behavior? And if so would there be a way to get information on a user's changed display name / username from discord.js or would I need to cache that information externally so it stays across bot restarts?

@monbrey
Copy link
Member

monbrey commented Oct 8, 2024

You can't fetch the "old" state of something. The only time that state exists is if it existed in the discord.js cache. Partials exist so that you can still receive the new state even when the old one isn't in cache.

Fetching anything from Discord will always give you the current (new) state.

@VDD2004 VDD2004 closed this as completed Oct 9, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants