Discord, Mention someone when gets a role - javascript

Is there a way to mention someone immediately after getting a specific role in a specific channel?
For example when I, or any other admin, give someone a specific role the bot mentions them in a specific channel.
Here is my code:
client.on("guildMemberUpdate", (oldMember, newMember) => {
const channel = client.channels.cache.get("channelid");
// If the role(s) are present on the old member object but no longer on the new one (i.e role(s) were removed)
const removedRoles = oldMember.roles.cache.filter((role) => !newMember.roles.cache.has("roleid"));
if (removedRoles.size > 0) console.log(`The roles ${removedRoles.map((r) => r.name)} were removed from ${oldMember.displayName}.`);
// If the role(s) are present on the new member object but are not on the old one (i.e role(s) were added)
const addedRoles = newMember.roles.cache.filter((role) => !oldMember.roles.cache.has("roleid"));
if (addedRoles.size > 0) {
if (newMember.roles.cache.some((role) => role.name === "testing")) {
let embed = new Discord.MessageEmbed().setTitle("♡﹕welcome!").setDescription("lalalala").setColor("#FFB6C1").setThumbnail("https://cdn.discordapp.com/attachments/806974794461216813/817737054745526304/giffy_2.gif");
channel.send(`Welcome ${oldMember.user}`, embed);
}
console.log(`The roles ${addedRoles.map((r) => r.name)} were added to ${oldMember.displayName}.`);
}
});

This is assuming your code is exactly as shown in the question, and not using placeholder strings.
Firstly, "roleid" should be role.id without the "" when you're filtering. This will filter it properly, as should channelId where channel is defined, which I'm guessing are placeholders, but just in case.
Secondly, you'll probably want to check using addedRoles.has("roleIdToSend") as opposed to newMember.roles.cache.some(). This will DM them every time they're updated if they have the role, not if they only just got the role on that update.
Lastly, assuming you're using discord.js v13, you'll need to correct your send() method. It should look something like
channel.send({
content: `Welcome, ${oldMember.toString()}`,
embeds: [embed]
});

Related

Is there any way I can get who gave the role to the log system I'm doing?

I was wanting to make a logging system for roles for my roleplay server but I need to make the bot get the name of who gave the role to that person.
client.on("guildMemberUpdate", (oldMember, newMember) => {
// Old roles Collection is higher in size than the new one. A role has been removed.
if (oldMember.roles.cache.size > newMember.roles.cache.size) {
// Creating an embed message.
const Embed = new Discord.MessageEmbed();
Embed.setColor("RED");
Embed.setAuthor(newMember.user.tag, newMember.user.avatarURL());
// Looping through the role and checking which role was removed.
oldMember.roles.cache.forEach(role => {
if (!newMember.roles.cache.has(role.id)) {
Embed.addField("Role Removed", role);
}
});
client.channels.cache.get("872558074290896908").send(Embed);
} else if (oldMember.roles.cache.size < newMember.roles.cache.size) {
const Embed = new Discord.MessageEmbed();
Embed.setColor("GREEN");
Embed.setAuthor(newMember.user.tag, newMember.user.avatarURL());
// Looping through the role and checking which role was added.
newMember.roles.cache.forEach(role => {
if (!oldMember.roles.cache.has(role.id)) {
Embed.addField("Role Added", role);
}
});
client.channels.cache.get("872558074290896908").send(Embed);
}
});
For this, you will need to use audit logs as it isn't included in the arguments provided with the event. Working with audit logs can be a bit difficult but the documentation has some great resources like this one to help you get started: https://discordjs.guide/popular-topics/audit-logs.html

I'm trying to make a discord bot give roles base on the time since somebody has joined the server

I'm pretty new to discord.js but I'm trying to make a bot give roles based on time elapsed since the user joined (the bot's role is above the needed roles and the bot itself has admin permissions)
client.on("guildMemberAdd", (member) => {
member.roles.add(801917861110874122);
});
client.on("message", (message) => {
if(Date.now() - message.member.joinedAt < 1000*60*60*24*1) {
message.member.roles.add(801917434558808074);
}
});
Basically, the bot doesn't give the role neither when the user joins nor when the wanted amount of time passes.
You need to pass a role to .add(), which can be done by looking up the ID from the cache.
Here is an example:
let role = message.guild.roles.cache.get("801917861110874122");
member.roles.add(role);
You can also search through roles using the name instead of the ID like this:
let role = message.guild.roles.cache.find(r => r.name == "Role name");
member.roles.add(role);
Edit:
To make your time function work, you need to use message.member.joinedTimestamp instead of message.member.joinedAt, like this:
client.on("message", (message) => {
if(Date.now() - message.member.joinedTimestamp < 1000*60*60*24*1) {
message.member.roles.add(801917434558808074);
}
});

How Can My Discord.js Bot welcome new people to the server?

I'm trying to make it so the bot Will Auto Welcome new members on multiple servers, this is the code I have currently and it doesn't come up with an error but it doesn't work
client.on("guildMemberAdd", (member) => {
const guild = member.guild;
if (!newUsers[guild.id]) newUsers[guild.id] = new Discord.Collection();
newUsers[guild.id].set(member.id, member.user);
if (newUsers[guild.id].size > 10) {
const userlist = newUsers[guild.id].map(u => u.toString()).join(" ");
guild.channels.find(channel => channel.name === "general").send("Welcome our new users!\n" + userlist);
newUsers[guild.id].clear();
}
});
client.on("guildMemberRemove", (member) => {
const guild = member.guild;
if (newUsers[guild.id].has(member.id)) newUsers.delete(member.id);
});```
Your problem lies within your third line of code. What you do here is create a new Collection everytime someone joins. This means that the collection can never be > 10 because it's always 1.
To fix this simply create the Collection at the top of your index file and not inside a listener.
On a sidenote, I assume you want to create the collection to keep track of who is in your discord server. Thats not really a good idea because it will be newly created every time the bot restarts and since it only gets updated when someone joins or leaves it won't be accurate. A lot easier to use is the guild.members collection.
EDIT: This is how you would do something like that
client.on('guildMemberAdd', member => {
const guild = member.guild;
const userlist = guild.members.cache.map(u => `\n${u.user.username}: ${u.user.id}`);
guild.channels.find(channel => channel.name === "general").send("Welcome our new user!\n Users" + userlist);
})
Please keep in mind that this will return all members of the guild. You can only use the guildMembersChunk listener to welcome multiple members and all of those need to come from the same guild which is rather unlikely.

Discord.js v12 role.delete() doesn't work

So, i was testing this out, and that when I use this code, it doesn't actually delete the roles, is this a bug?
On the code:
client.on('message', async message => {
message.guild.roles.fetch()
.then(r => r.forEach(s =>
s.delete()
));
})
I tried other variants as well such as:
client.on('message', async message => {
message.guild.roles.cache.forEach(r => r.delete());
});
client.on('message', async message => {
message.guild.roles.cache
.map(r => r.id)
.forEach(s =>
message.guild.roles.cache.find(l => l.id === s)
.delete()
);
});
client.on('message', async message => {
const roles = message.guild.roles.cache
.map(r => r.id);
for (m=0;m<roles.length;m++) {
message.guild.roles.cache.find(s => s.id === roles[m])
.delete();
}
});
I even tried to not mass delete and just delete one:
message.guild.roles.cache.find(s => s.id === 'ROLE_ID')
.delete();
None seemed to have worked, and they all return the same error:
TypeError: Cannot read property 'delete' of undefined
or
DiscordAPIError: Invalid Role
Though I'm 100% sure that the role does exist and is valid. This error only happens when I try to delete roles. When I tried checking the roles in the server using
message.guild.roles.cache.map(r => r.id);
it sometimes returns a blank array, though there are roles in the server.
It seems that the reason for this is because Discord Guilds have default roles, mainly, #everyone, and one with the bots name, which you can't delete.
I don't know exactly how to differentiate these "default" roles from created ones, but it seems like #everyone role seems to be always Role.rawPosition= 0 and the bots roles likes to take the last position of this same index. Also throughout my testing, seems like bot roles have Role.editable = false. Created ones, but also #everyone, has it = true. Which makes things a little confusing.
With that in mind, it's up to you to create the best algorithm for what you're trying to achieve. But I can promise it's unsafe.
If you can if yourself to roles that can be deleted, Node shouldn't crash.
(CURA GAMER BOT is my test bot, so the first role was not manually created)
I'd recommend you to log all your roles cache, at least for testing, and check the roles properties in other to find out what will suit you better. Whatever if your doubt was if role.delete() was reliable, yes it seems like. But I'd recommend deleting a single role at time, having the reference to its objects anyway.
Here are some tests that worked for me (screenshot scenario) which may or may not work for you (use at your own risk):
const roles = message.guild.roles.cache;
roles.forEach(role => {
// -1 because I have only on bot role
if(role.rawPosition > 0 && role.rawPosition < (roles.size - 1)) {
role.delete();
}
});
const roles = message.guild.roles.cache;
roles.forEach(role => {
if(role.editable && role.name !== '#everyone') {
role.delete();
}
});
The safest for me, delete based on timestamp:
const roles = message.guild.roles.cache;
roles.forEach(role => {
// Created after Tue Sep 08 2020 15:55:00 GMT-0500
if(role.createdTimestamp > 1599598514000) {
role.delete();
}
});
That's because Collection.delete() requires a key, not an object. Instead of passing the role object as an argument, you should be passing the role snowflake.
message.guild.roles.cache.delete('<Role ID>')
Also, to delete all roles, you can use the Collection.clear() method, which removes all elements from the collection.
message.guild.roles.cache.clear()

Discord JS // Trying to add role by reacting to the message

bot.on('messageReactionAdd', async (reaction, user) => {
// Define the emoji user add
let role = message.guild.roles.find(role => role.name === 'Alerts');
if (message.channel.name !== 'alerts') return message.reply(':x: You must go to the channel #alerts');
message.member.addRole(role);
});
Thats the part of my bot.js. I want the user to react in a certain channel and receive role Alerts
You haven't really stated what the problem is, what works and what doesn't work but I'll take a wild stab at some parts which catch my eye.
For starters you are calling properties on the variable message whilst in the code you supplied, you didn't create/set a variable named message. My guess is that you want the message to which a reaction has been added. To do that you have to use the MessageReaction parameter which is supplied in the messageReactionAdd event as reaction.
From there you can replace message.<something> with reaction.message.<something> everywhere in the code you supplied.
Something also to note is that you add the role Alerts to message.member. This won't work how you want it to, since it will give the Alerts role to the author of the original message.
What (I think) you want to do, is fetch the user who just reacted with the emoji and assign them the Alerts role. You'll have to find the member in the guild first and then assign them the Alerts role. To do this you'll have to use the User parameter and find the correct Member because you can't add a role to a User object but you can to a Member object. Below is some code which should hopefully put you on the right track.
// Fetch and store the guild (the server) in which the message was send.
const guild = reaction.message.guild;
const memberWhoReacted = guild.members.find(member => member.id === user.id);
memberWhoReacted.addRole(role);
You are using message.member variable despite not defining message.
Any of these methods won't really work in v12 so I updated it for someone else searching.
If you find any mistakes be sure to make me aware of it.
const Discord = require('discord.js');
const client = new Discord.Client({ partials: ['MESSAGE', 'CHANNEL', 'REACTION'] }); //partials arent really needed but I woudld reccomend using them because not every reaction is stored in the cache (it's new in v12)
const prefix = "-";
client.on('messageReactionAdd', async (reaction, user) => {
if (reaction.partial) { //this whole section just checks if the reaction is partial
try {
await reaction.fetch(); //fetches reaction because not every reaction is stored in the cache
} catch (error) {
console.error('Fetching message failed: ', error);
return;
}
}
if (!user.bot) {
if (reaction.emoji.id == yourEmojID) { //if the user reacted with the right emoji
const role = reaction.message.guild.roles.cache.find(r => r.id === yourRoleID); //finds role you want to assign (you could also user .name instead of .id)
const { guild } = reaction.message //store the guild of the reaction in variable
const member = guild.members.cache.find(member => member.id === user.id); //find the member who reacted (because user and member are seperate things)
member.roles.add(role); //assign selected role to member
}
}
})
Here's a quick answer, though way too late. So I'll be updating the answer with Discord.js v.12.x (or the same as Discord.js Master)
bot.on('messageReactionAdd', async (reaction, user) => {
//Filter the reaction
if (reaction.id === '<The ID of the Reaction>') {
// Define the emoji user add
let role = message.guild.roles.cache.find((role) => role.name === 'Alerts');
if (message.channel.name !== 'alerts') {
message.reply(':x: You must go to the channel #alerts');
} else {
message.member.addRole(role.id);
}
}
});

Categories