Greeting message only when a user gets a specific role - javascript

I have this verification system on my server, in which a new member must react to a message to obtain a role that gives permission to see the other channels. So, I wanted to make my bot send a message on a specific channel, greeting them, only when a member gets a specific role (verified)
The problem is: anyone can react in the message to get the verified role over and over again, causing the bot to spam, and I still haven't figured out a way to make this welcome message be sent only once per user
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(role.id));
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(role.id));
if (addedRoles.size > 0){
if (newMember.roles.cache.some(role => role.name === 'teste')) {
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}.`);
}
});

The code you have added to the guildMemberUpdate event listener is being used to send a welcome message when a verified role is added to a member. It is not running any checks to see if the member has already triggered a welcome message.
It sounds like when a member removes their reaction from the message, it also removes their verified role. You should look at where in your code you are removing roles, and change it so the verified role isn't removed after being added.
If this isn't possible, then consider saving a state in a file or database that can be checked before sending a welcome message.

Related

Discord.JS Message Edit

I want to edit the message over and over again.
So I made variable
this.msgRef = await channel.send({ embeds: [embedMessage] });
If I want to edit I use
this.msgRef.edit(...)
If the bot for some reason disconnects, he will lose msgReference.
Because of that, I saved it to DB.
How to create a message again because Message (object) in Discord.JS have a private constructor?
If you want to get the message again, you can simply fetch the channel's messages every time you bot connects (on the ready event for example) like so
client.on('ready', () =>{
const messages = await channel.messages.fetch()
client.msgRef = messages.find(msg => msg.author.id === client.user.id
&& msg.embeds[0]
// Etc.. Add as many conditions to make sure you choose the right message
);
})
This way, use client.msgRef.edit(...) whenever you want.

Discord.js || Can bot track ban list?

There are a lot of to ban a user in a server, you can do it manually or with another bot. I want my bot to scan a banlist, and if someone will get banned, it will send a message "user (id) has been banned
I started writing smt but now, I had no idea what can I do to check it.
EDIT: It's working now, but it still need to find this user id.
client.on('guildBanAdd', message => {
client.user.cache.find() //idk how to define it
const channel1 = client.channels.cache.find(channel => channel.id === "158751278127895");
channel1.send('12512');
})
You don't have to fetch bans because the guildBanAdd event parses a GuildBan object,which als includes a User object.
client.on('guildBanAdd', ban => {
console.log(ban.user.username); // Username
})
message.channel won't work because there isn't a message object.
If you want to get the executor (moderator) who performed the ban, kick etc.
There is a good guide for this Working with Audit Logs

How to work with member role update part of audit log in discord.js

I am currently making a bot to notify people by sending a message when a member role is being updated on the server. I don’t know how to set up the initial part which should be formally client.on part.
Here I have shown a bit of my code that I think should be working but unfortunately it is not working.
const Discord = require(‘discord.js’);
const client = Discord.Client();
client.on('guildMemberUpdate', (oldMember, newmember) => {
This is what I’m expecting to do:
Before I give you the code, I'll give you the steps that I took to achieve it.
Tip: ALWAYS use the documentation. The discord.js documentation helped me a lot of times.
Process:
Set up a designated text channel. In my case, I manually grabbed the channel's ID and set it as the variable txtChannel. You will have to replace my string of numbers with your own channel ID.
I cached every single role ID from the "new" member as well as from the "old" member.
Checked whether or not the length of the new member roles array was longer than the old member roles array. This signifies that the member has gained a role.
Created a filter function that "cancels" out every single role ID that both new and old role arrays have in common.
Grabbed the icon URL - I found out that if you try to get the URL of a user who has the default discord icon, it'll return NULL. To bypass this, you could just grab some sort of invisible PNG online and set it as a placeholder. Else you'll get an error saying that it wasn't able to retrieve the proper URL link.
Set up the embed, and sent it into the text channel!
Note:
At first, I couldn't figure out why the bot wasn't registering for other users who have their roles changed. Then I found this question on Stack Overflow. The link states that you have to make sure to enable Guild Members Intent. Just follow the instructions from the link and you should be all set! It's a little bit outdated (in terminology), so when it references "Guild Members Intent" it actually is "Server Members Intent" now.
Code:
It's awfully elaborate, but it gets the job done.
client.on('guildMemberUpdate', (oldMember, newMember) => {
let txtChannel = client.channels.cache.get('803359668054786118'); //my own text channel, you may want to specify your own
let oldRoleIDs = [];
oldMember.roles.cache.each(role => {
console.log(role.name, role.id);
oldRoleIDs.push(role.id);
});
let newRoleIDs = [];
newMember.roles.cache.each(role => {
console.log(role.name, role.id);
newRoleIDs.push(role.id);
});
//check if the newRoleIDs had one more role, which means it added a new role
if (newRoleIDs.length > oldRoleIDs.length) {
function filterOutOld(id) {
for (var i = 0; i < oldRoleIDs.length; i++) {
if (id === oldRoleIDs[i]) {
return false;
}
}
return true;
}
let onlyRole = newRoleIDs.filter(filterOutOld);
let IDNum = onlyRole[0];
//fetch the link of the icon name
//NOTE: only works if the user has their own icon, else it'll return null if user has standard discord icon
let icon = newMember.user.avatarURL();
const newRoleAdded = new Discord.MessageEmbed()
.setTitle('Role added')
.setAuthor(`${newMember.user.tag}`, `${icon}`)
.setDescription(`<#&${IDNum}>`)
.setFooter(`ID: ${IDNum}`)
.setTimestamp()
txtChannel.send(newRoleAdded);
}
})

Reaction event discord.js

I'm trying to make a starboard code with my bot, and everything else is working good. But I'm trying to make it to where the bot ignores reactions from the author of the actual message.
This is my current code:
client.on('messageReactionAdd', (reaction_orig, message, user) => {
if (message.author.id === reaction_orig.users.id) return
manageBoard(reaction_orig)
})
It returns the following error:
if (message.author.id === reaction_orig.users.id) return;
^
TypeError: Cannot read property 'id' of undefined
The problem is that messageReactionAdd takes two parameters; the message reaction as the first one, and the user that applied the emoji as the second one. When you write reaction_orig, message, user, reaction_orig is the reaction (which is correct), but message is the user who reacted as it's the second parameter. The user variable will be undefined.
Another issue is that reaction_orig.users returns a ReactionUserManager that doesn't have an id property. Luckily, the user is already passed down to your callback so you can use its ID.
Also, reaction_orig has a message property, the original message that this reaction refers to so you can get its authors' ID from it.
You can change your code to this to work:
client.on('messageReactionAdd', (reaction_orig, user) => {
if (reaction_orig.message.author.id === user.id) {
// the reaction is coming from the same user who posted the message
return;
}
manageBoard(reaction_orig);
});
However, the code above only works on cached messages, ones posted after the bot is connected. Reacting on older messages won't fire the messageReactionAdd event. If you also want to listen to reactions on old messages you need to enable partial structures for MESSAGE, CHANNEL and REACTION when instantiating your client, like this:
const client = new Discord.Client({
partials: ['MESSAGE', 'CHANNEL', 'REACTION'],
});
You can check if the message is cached by e.g. checking if its author property is not null. If it's null, you can fetch the message. Now, you have both the message author and the user who reacted, so you can compare their IDs:
// make sure it's an async function
client.on('messageReactionAdd', async (reaction_orig, user) => {
// fetch the message if it's not cached
const message = !reaction_orig.message.author
? await reaction_orig.message.fetch()
: reaction_orig.message;
if (message.author.id === user.id) {
// the reaction is coming from the same user who posted the message
return;
}
// the reaction is coming from a different user
manageBoard(reaction_orig);
});
Try doing this :
client.on('messageReactionAdd', (reaction, user) => {
if (!reaction.message.author.id === user.id){
//Do whatever you like with it
console.log(reaction.name)
}
});
Note: The message must be cached. For that you'll need to do this
Client.channels.cache.get("ChannelID").messages.fetch("MessageID");
I'm guessing you're using discord.js v12

How to make a bot find a channel owner / compare to the author's ID

I'm making a bot where if you do d!move, the bot will move the channel where the message was sent in under a category via ID. I also want to make it so that whoever does the command has permissions such as MANAGE_CHANNELS, which I've already added. The problem is that when I want to confirm whoever created that channel is the person that activated the command, the bot says yes. I did this on an alt account, where I made the channel and my alt was the one initializing it, and the bot said "success!" I also wanted to make it so if someone else made the channel, and when I did it, it would work because I made the bot know my ID.
I've researched Google and found nothing.
I've tried using a function with fetchAuditlog but get anywhere.
if(!message.channel.client.user.id == message.author || !message.author.id == `329023088517971969`) return message.channel.send("You don't own this channel!")
else message.channel.send("success!");
message.channel.setParent(`576976244575305759`);
I expect the bot to be able to check if the author created the channel, and lead to You don't own this channel if they don't own it. But if they do then the bot moves the channel.
The actual result is the bot moving the channel anyway regardless if they own the channel or not.
As #André has pointed out, channel.client represents the client itself, not the user who created the channel. Also, the last line in your code is not part of the else statement, so that's why it's run regardless of the conditions you defined.
To reach a solution, you can make use of the guild's audit logs. You can search for entries where the user is the message author and a channel was created. Then, all you have left is to check if one of those entries is for the current channel, and run the rest of your code if so.
Sample:
message.guild.fetchAuditLogs({
user: message.author,
type: 'CHANNEL_CREATE'
}).then(logs => {
if (!logs.entries.find(e => e.target && e.target.id === message.channel.id)) return message.channel.send('You don\'t own this channel.');
else {
// rest of code
}
}).catch(err => console.error(err));
When you go <anything>.client.user it will return the bot client.
If you want to see who created the channel you would have to check the Audit Logs or save it internally.
I've checked the documents. Here's what it says for .client about the
channel. It says the person that initialized the channel, or the
person that created it.
On documentation I see this:
The client that instantiated the Channel
instantiated is different of initialized

Categories