How to get GuildMember data from a User through a mention - discord.js

I am making a "user info" command that returns the user's Discord username, their ID, their server join date and whether or not they are online. I am able to display all the information through user.id, user.username, and user.presence.status. But when I try to use user.joinedAt I get undefined in the display.
I know this is because the User class and the GuildMember class are not the same, and that the GuildMember class contains a User object.
But my problem is: how I could get the .joinedAt data from my user mention?
Here is my current code:
let user = message.mentions.users.first();
let embed = new Discord.RichEmbed()
.setColor('#4286f4')
.addField("Full Username:", `${user.username}#${user.discriminator}`)
.addField("User ID:", `${user.id}`)
.addField("Server Join Date:", `${user.joinedAt}`)
.addField("Online Status:", `${user.presence.status}`)
.setThumbnail(user.avatarURL);
message.channel.send(embed);

Here's the code for my user info command:
if (msg.split(" ")[0] === prefix + "userinfo") {
//ex `member #Rinkky
let args = msg.split(" ").slice(1) // gets rid of the command
let rMember = message.guild.member(message.mentions.users.first() || message.guild.members.get(args[0])) // Takes the user mentioned, or the ID of a user
let micon = rMember.displayAvatarURL // Gets their Avatar
if(!rMember)
return message.reply("Who that user? I dunno him.") // if there is no user mentioned, or provided, it will say this
let memberembed = new Discord.RichEmbed()
.setDescription("__**Member Information**__")
.setColor(0x15f153)
.setThumbnail(micon) // Their icon
.addField("Name", `${rMember.username}#${rMember.discriminator}`) // Their name, I use a different way, this should work
.addField("ID", rMember.id) // Their ID
.addField("Joined at", rMember.joinedAt) // When they joined
await message.channel.send(memberembed)
};
This will send an embed of their user info, this is my current code and
rMember.joinedAt
does work for me.
edit:
After looking at your question again, I found out I didn't need to post everything, you can't get the joined at because it's just the mention. Try this:
let user = message.guild.member(message.mentions.users.first())
Should work

You can technically find it by fetching getting the member from the guild and then using GuildMember.joinedAt: since the User class represents the user in every guild, you will always need the GuildMember to get info about a specific guild.
let user = message.mentions.users.first(),
member;
if (user) member = message.guild.member(user);
if (member) embed.addField("Server Join Date:", `${member.joinedAt}`);
With this said, I would not suggest you to do that, since it's not really efficient. Just take the mention from the members' collection and then take the user from that.
let member = message.mentions.members.first(),
user;
if (member) user = member.user;
The downside of this is that you can't use it if you want your command to be executable from the DMs too. In that case you should use the first method.

const member = message.channel.guild.members.cache.find(member => member.user == message.mentions.users.first())

Related

Give Role when a member joins the voice channel. discord.js

Im trying to make discord.js code. When a member joins the voice channnel I want the bot to give them a role, when the member leaves, i want the role to be removed. thanks for your help.
const newChannelID = newState.channelID;
const oldChannelID = oldState.channelID;
if (oldChannelID === "835280102764838942"){
member.send('role given');
let role = message.guild.roles.cache.find(r => r.id === "835279162293747774");
member.roles.add(835279162293747774);
} else if(newChannelID === "835280102764838942"){
member.send('role removed');
member.roles.remove(835279162293747774);
}
})
There's a couple of things you need to clean up in your code. I'm going to assume you're using the voiceStateUpdate event to trigger your command.
Most importantly, (logic-wise) you actually need to flip-flop the way you add and remove roles. Currently, the general code states that if the user left the voice channel (thus oldChannelID = actual vc ID), then it would actually give the user a role. This seems to be the opposite of your intention, thus you'd simply swap out the code in each if/else if statement.
Second, the way you're assigning roles and adding them is incorrect. I'd recommend this resource for more info.
Third, you cannot access message if you were indeed using voiceStateUpdate as your event, since it only emits an oldState and a newState.
Lastly, you need to designate a text channel to send the message to. In my code, I manually grabbed the ID of the channel I wanted and plugged it into the code. You'll have to do the same by replacing the number strings I have with your own specific ones.
With that being said, here's the correct modified code:
client.on('voiceStateUpdate', (oldState, newState) => {
const txtChannel = client.channels.cache.get('803359668054786118'); //manually input your own channel
const newChannelID = newState.channelID;
const oldChannelID = oldState.channelID;
if (oldChannelID === "800743802074824747") { //manually put the voice channel ID
txtChannel.send('role removed');
let role = newState.guild.roles.cache.get("827306356842954762"); //added this
newState.member.roles.remove(role).catch(console.error);
} else if (newChannelID === "800743802074824747") {
txtChannel.send('role given');
let role = oldState.guild.roles.cache.get("827306356842954762"); //change this somewhat
oldState.member.roles.add(role).catch(console.error); //adding a catch method is always good practice
}
})

How do i make discord.js list all the members in a role?

if(message.content == `${config.prefix}mods`) {
const ListEmbed = new Discord.MessageEmbed()
.setTitle('Mods:')
.setDescription(message.guild.roles.cache.get('813803673703809034').members.map(m=>m.user.tag).join('\n'));
message.channel.send(ListEmbed);
}
Hey so iam making a command which displays all the members with that role but it only seems to be sending 1 of the mods
await message.guild.roles.fetch();
let role = message.guild.roles.cache.find(role => role.id == args[0]);
if (!role) return message.channel.send('Role does not exist'); //if role cannot be found by entered ID
let roleMembers = role.members.map(m => m.user.tag).join('\n');
const ListEmbed = new Discord.MessageEmbed()
.setTitle(`Users with \`${role.name}\``)
.setDescription(roleMembers);
message.channel.send(ListEmbed);
};
Make sure your command is async, otherwise it will not run the await message.guild.roles.fetch(); - this fetches all roles in the server to make sure the command works reliably.
In Discord.jsV12 the get method was redacted and find was implemented.
Aswell as this, I would highly recommend defining variables to use in embeds and for searching since it is much more easy to error trap.
If you have many members with the role, you will encounter the maximum character limit for an embeds description. Simply split the arguments between multiple embeds.

How can i add role when member has 10 invites?

im making discord bot with discord.js v12 and im trying to give role when member has 10 invites
i found invitation code from here and modified it:
if(message.channel.type != "dm" && message.channel.id === '768475421953915093') {
message.delete();
var user = message.author;
message.guild.fetchInvites()
.then
(invites =>
{
const userInvites = invites.array().filter(o => o.inviter.id === user.id);
var userInviteCount = 0;
for(var i=0; i < userInvites.length; i++)
{
var invite = userInvites[i];
userInviteCount += invite['uses'];
}
if(userInviteCount >= 10){
const guildMember = message.member;
guildMember.addRole('767542365812886656');
message.author.send(`you have access now`)
}else {
message.author.send(`sry u have ${userInviteCount} invitations. u need at least five`)
}
}
)
}
yes, it works but you can trick the system easily. If you keep rejoining from the server, the invite counter increases. How can i stop that?
To do this, you will need an external database since Discord API doesn't provide any information about who used that invite and how many times.
ALERT: It's a simple feature but can be very hard for people that don't have any coding experience, so if it's your first project, don't give up and keep trying! :D
You can use MongoDB Atlas, which is very simples and free.
And the logic will be very simple:
1 - Create a collection to store the invites data, you can do something like in this example
2 - Create a collection (you can give any name, but in this example, I will refer to this collection as new_members) to store the new members data, it should have the fields serverId (to store the guild ID), userId (to store the user ID) and inviteCode (to store the invite code or url)
3 - When a user joins the discord server, it will trigger the "guildMemberAdd" event, and you will get the invite that was used (with the example that I give in the first step), and create a new doc in the new_members collection.
4 - After creating this new data, you will search for all the docs from the same invite, and filter them by userId (there are many ways to do this, this is one of them).
5 - With this array of docs, you can use his length to determine how many people were invited, and give the role.
VERY SIMPLE EXAMPLE, THAT SHOULDN'T BE USED:
DiscordClient.on("guildMemberAdd", async (member) => {
/**
* https://github.com/AnIdiotsGuide/discordjs-bot-guide/blob/master/coding-guides/tracking-used-invites.md
* Here you will get the invite that was used, and store in the "inviteCode" variable
*/
const inviteCode = await getInviteUsed()
await NewMemberRepository.insert({
serverId: member.guild.id,
userId: member.id,
inviteCode: inviteCode
});
const joinedMembersFromTheInvite = await NewMemberRepository.find({
inviteCode: inviteCode
});
/**
* https://stackoverflow.com/questions/43374112/filter-unique-values-from-an-array-of-objects
* Here you will filter the results by userId
*/
const invitesWithUniqueUsers = filterJoinedMembersByUserId(joinedMembers)
if (invitesWithUniqueUsers >= REQUIRED_INVITES_QTD) {
/**
* Gives the role to the creator of the invite
*/
}
});
Hope it helps, good luck! :D
OBS:
Yes, Discord API provides how many times an invite was used, but not how many a specific person used this invite.
In the examples, I used something like TypeORM, but if you are using JavaScript instead TypeScript, you can use Mongoose

Add / Remove user from role by ID [DISCORD.JS]

Hey today I'd like give and remove roles from a user by their ID
First try:
const user = '5454654687868768'
const role = '451079228381724672'
user.roles.remove(role)
Second Try:
const user = '5454654687868768'
const role = '451079228381724672'
user.removeRole(role)
Neither one of these methods seems to work, however.
const user = '5454654687868768'
const role = '451079228381724672'
These are just numbers which happen to be the id of your user and role object. They are nothing on their own and you can't call any Discordjs methods on them. To get the user and role object you will first have to get them using their respective ID.
Let's assume you want to add a role when someone joins the server, you can do the same thing in any type of event but we will use guildMemberAdd event for example:
bot.on('guildMemberAdd', async member => {
const memberID = '5454654687868768'; // you want to add/remove roles. Only members have roles not users. So, that's why I named the variable memberID for keeping it clear.
const roleID = '451079228381724672';
const guild = bot.guilds.cache.get('guild-ID'); // copy the id of the server your bot is in and paste it in place of guild-ID.
const role = guild.roles.cache.get(roleID); // here we are getting the role object using the id of that role.
const member = await guild.members.fetch(memberID); // here we are getting the member object using the id of that member. This is the member we will add the role to.
member.roles.add(role); // here we just added the role to the member we got.
}
See these methods are only working because they are real discordjs objects and not some numbers like you were trying to do. Also the async/await thing is there because we need to wait for the bot to get the member object from the API before we can add role to it.
Your first try was actually not that far off. The only problem is that roles.remove() is a guildMember function.
So first we need to define the member.
const member = message.guild.members.cache.get("member ID here");
Now we can remove or add a role. Source
member.roles.remove("role ID here");

How can i get mentioned user's username in discord.js

Read the title and will be glad if anyone can help me guys
For an example messages.mentions.first(). Like that, is there anything for mentioned user's username?
The best way would be to use the message.mentions.users.first(), as this will actually give you the first user mentioned in a message. (message.mentions is not a collection). If there are no users mentioned, the first will result in undefined, so you will probably want to check for that. Once you have a user, you will want to access the username property.
Example:
// Assuming we just need a message event
client.on('message', (message) => {
const user = message.mentions.users.first();
if (user === undefined) {
return; // Do not proceed, there is no user.
}
const name = user.username;
// Do stuff with the username
})
Sources:
message.mentions
message.mentions.users
message.mentions.members.first().user.username;
This would give you the username of the first mention.
You could also do message.mentions.users.first().username;

Resources