What is the difference between a User and a GuildMember in discord.js?
From Official Discord.js Guide - Common Questions:
A lot of users get confused as to what the difference between
Users
andGuildMembers
is. The simple answer is that aUser
represents a global Discord user and aGuildMember
represents a Discord user on a specific server. That means onlyGuildMembers
can have permissions, roles, and nicknames, for example, because all of these things are server-bound information that could be different on each server that user is in.
Many errors in the code in question occur because you are trying to call a guild specific function on a global user. For example, GuildMember.kick()
and GuildMember.ban()
. A very common mistake that leads to this is using the message.mentions.users
collection. As the name suggests, this returns a collection of Users
.
If you simply want, for example, the mentioned user's avatar, or maybe they're username and discriminator, it would work out fine. But it will lead to errors if you ever try to, for example, try to get the date they joined your server using GuildMember.joinedAt()
Luckily, there are many easy ways to circumvent this issue. For example, using MessageMentions.members
(returns a collection of GuildMembers
) instead of MessageMentions.users
const member = message.mentions.members.first()
member.ban() // no error here!
Another common workaround is using the Guild.member()
method, which accepts a User
object or ID!
const user = client.user // get the user object
const guild = client.guilds.cache.get('Guild ID') // get the guild object
const member = guild.member(user) // convert the User object to a GuildMember!
Other useful tricks to easily convert Users
to GuildMembers
include:
- Using
message.member
instead ofmessage.author
- Using
guild.members.cache.get()
instead ofclient.users.cache.get()
- Using
guild.members.fetch()
instead ofclient.users.fetch()
- Using
presence.member
instead ofpresence.user
It's also very useful to remember if specific event parameters provide Users
or GuildMembers
. For example, both guildMemberAdd()
and guildMemberUpdate
pass GuildMembers
, but messageReactionAdd()
, guildBanAdd()
, and typingStart()
all pass Users
.
While many GuildMember
properties and methods are not available for a User
, the same is true the other way around. For example, GuildMember.tag
does not exist. However, converting a GuildMember
to a User
is much easier than converting a User
to a GuildMember
. This is because of GuildMember.user
:
The user that this guild member instance represents
So, although GuildMember.tag
will return undefined
, GuildMember.user.tag
will not!
Is there a difference between GuildMemberManager.resolve() and Guild.member() in discord.js?
The two methods are identical.
The source for Guild#member
shows that it simply calls GuildMemberManager#resolve
:
member(user) {
return this.members.resolve(user);
}
UserResolvable
and GuildMemberResolvable
are also the same. UserResolvable
can be a User
, Snowflake
, Message
, or GuildMember
; and a GuildMemberResolvable
can be a GuildMember
or UserResolvable
. In this way, the type GuildMemberResolvable
is essentially redundant and could be substituted for UserResolvable
.
// Using TypeScript syntax to show the types
type UserResolvable = User | Snowflake | Message | GuildMember
// same as GuildMember | User | Snowflake | Message
type GuildMemberResolvable = GuildMember | UserResolvable
None of my discord.js guildmember events are emitting, my user caches are basically empty, and my functions are timing out?
Discord is now enforcing privileged intents
What are intents?
Maintaining a stateful application can be difficult when it comes to the amount of data you're expected to process, especially at scale. Gateway Intents are a system to help you lower that computational burden.
Gateway intents allow you to pick and choose what events you choose to "subscribe" to so that you don't have to use up storage on events you're not using. This feature was introduced to discord.js in v12
What are privileged intents?
Some intents are defined as "Privileged" due to the sensitive nature of the data. Those intents are:
GUILD_PRESENCES
GUILD_MEMBERS
As of October 27th, these intents have been turned off by default.
Some problems you might be facing because of this
GUILD_PRESENCES
- member and user caches are empty (or very close to it) on startup
Guild.memberCount
returns count as of ready- All events involving
Presences
do not trigger (presenceUpdate
) - Some
Presence
data returnsnull
orundefined
- All
GuildMembers
appear to the bot as offline. client.login()
times out if you specified thefetchAllMembers
option in yourClientOptions
GUILD_MEMBERS
- member and user caches are empty (or very close to it) on startup
GuildMemberManager.fetch()
andUserManager.fetch()
methods time out- All events involving
GuildMembers
do not trigger (guildMemberAdd
,guildMemberRemove
,guildMemberUpdate
,guildMemberSpeaking
, andguildMembersChunk
)
How do I enable intents?
Through the Discord Developer Portal:
Firstly, you must manually enable the intents from the Discord Developer site. Go to applications, select your app, and find the "bot" tab on the sidebar. Then you can scroll down until you see this:
As shown in the screenshot, your bot will require verification if in more than 75 guilds.
If your bot is verified:
Once your bot is verified, you won't be able to manually flip the intent switches in the Developer Portal. To request whitelisted access to an additional privileged gateway intent for a verified bot, please send our support team a ticket here!
Make sure to include your bot's ID, which intents you're requesting, a basic description of your use case for the requested intent, and screenshots or video of that use case in action (or code snippets, if not user facing!).
Through the discord.js module:
Once you have either/both intents checked off, you just have to enable them through discord.js. The discord.js intents guide thoroughly explains how to do this, but I will paraphrase it here.
You don't need to go through these steps if you want every intent. Discord enables all intents (except these two, obviously) by default. As long as you checked off both intents in the Developer Portal, you can stop here if you don't care about blocking any other intents. If you do, just remember intents are only supported by discord.js v12+, so you might have to upgrade.
One of the ClientOptions
(ClientOptions
is a typedef of potential options to pass when creating your client) is ws
(yet another typedef of potential websocket options). In there, you'll find the intents
property.
intents
accepts a IntentsResolvable
, which can be a string or an array of strings of an intent(s) (such as 'GUILD_PRESENCES'
. All available intents), a bitfield (a number corresponding to an intent(s)), an instance of the Intents
class.
Examples:
// using a string
const client = new Discord.Client({ ws: { intents: 'GUILD_PRESENCES' }});
// using an array
const client = new Discord.Client({ ws: { intents: ['GUILD_PRESENCES', 'GUILD_MEMBERS'] }});
// using a bitfield value
const client = new Discord.Client({ ws: { intents: 32509 }));
// using Intents class
const client = new Discord.Client({ ws: { intents: Discord.Intents.PRIVILEDGED }});
const client = new Discord.Client({ ws: { intents: new Discord.Intents(Discord.Intents.ALL) }});
Resources:
- Discord.js Official Guide - Gateway Intents
- Discord Developer Documentation - Gateway Intents
- Gateway Update FAQ
- Discord API Github - Issue 1363 - Privileged Intents
- Discord Blog - The Future of Bots on Discord
TL;DR
To fix this issue, go to:
Discord Developer Portal > Applications > Your Application > Bot > Check both/either intent(s) (screenshot above)
Joinedat difficulties discord.js
Message#author
is a User
. .joinedAt
only exists on GuildMember
s which you can get with Message#member
{name: 'Joined at', value: `${moment(message.member.joinedAt).format('MMMM Do YYYY, h:mm:ss a')} //remember capitalization
Additionally, .createdAt
only exists on User
s, not GuildMember
s
Comparing a message authors roles
const highest = message.author.roles.highest;
author of a message is a user and users don't have roles. That is the reason it's saying: cannot read prperty of undefined
because author.roles
is not a thing. You have to get the member, to get the roles. So do this:
const highest = message.member.roles.highest;
Here you are taking the author(user) of the message as a GuildMember(member) and then asking for the highest roles this member have.
message.member.displayAvatarURL(); is not a function
displayAvatarURL
is a function on User
, not GuildMember
.
You can either get the user from the member like this:
message.member.user.displayAvatarURL();
or just directly use the author
property:
message.author.displayAvatarURL();
How to check the role of a reacting member discord.js
You can use the second parameter of the messageReactionAdd
event, the User
that reacted, and the Guild.member()
method.
Guild.member()
can convert a global user object to a guildmember object in which you can see the roles of. To learn the difference between the two, check out What is the difference between a User and a GuildMember in discord.js?.
if (
reaction.message.guild
.member(user)
.roles.cache.some((role) => role.name == 'Goof Archivist ')
)
Related Topics
Why Is My Function Call That Should Be Scheduled by Settimeout Executed Immediately
How Is Almost Everything in JavaScript an Object
Convert Base64 String to Arraybuffer
Required Field Validations Not Working in Jquery Popup MVC 4
Check Whether a String Matches a Regex in Js
React - Uncaught Typeerror: Cannot Read Property 'Setstate' of Undefined
Convert JSON Array to an HTML Table in Jquery
How to Replace While Loops with a Functional Programming Alternative Without Tail Call Optimization
Please Explain the Use of JavaScript Closures in Loops
Differencebetween a User and a Guildmember in Discord.Js
How to Get the Scrollbar Position with JavaScript
How to Synchronize a Sequence of Promises
Is Safari on iOS 6 Caching $.Ajax Results
When to Use Es6 Class Based React Components VS. Functional Es6 React Components
How to Convert JSON to CSV Format and Store in a Variable
Pass a Parameter to a Content Script Injected Using Chrome.Tabs.Executescript()