Discord.js; why does this not add the role? - javascript

I'm quite new to Stack Overflow, so excuse me if I do something wrong.
I've been working on Discord bots lately, and for my server I want to make a verification bot. I've got a large piece of the code all done and dusted, but now the important part doesn't work, and I don't know why.
My code:
const Discord = require("discord.js");
const client = new Discord.Client({ partials: ["MESSAGE", "CHANNEL", "REACTION"]});
const prefix = "v!";
client.on("ready", async () => {
console.log(`Logged in as ${client.user.tag}`);
client.user.setActivity("v!verify | Verify in #πŸ”β”ƒverify-here", {type: "LISTENING"});
});
client.on("message", async(msg) => {
const args = msg.content.slice(prefix.length).trim().split(' ');
const command = args.shift().toLowerCase();
if(command === 'svm') { // svm = send verification message
if (msg.member.id !== '434239200607600651') return;
const sEmbed = new Discord.MessageEmbed()
.setTitle("Welcome to **aSpiv's Network**!")
.setDescription("aSpiv's Network is a place to hang out, talk and have fun with friends, family and strangers. Our goal is to make this community as friendly and welcoming as possible. Please, remember the human.")
.addField("πŸŽ— Community Guidelines", "TL;DR Use common sense. If you think you'll get a warning for it, don't do it!\n\nTreat everyone with respect. This is the #1 rule of this server. Absolutely no harassment, witch hunting, sexism, racism, or hate speech will be tolerated.\n\nNo spam or self-promotion (server invites, advertisements, etc) without permission from a staff member. This includes DMing fellow members.\n\nNo NSFW or obscene content. This includes text, images, or links featuring nudity, sex, hard violence, or other graphically disturbing content. (Except for the places where it's allowed; see at own risk!)\n\nTalk English. We want to make sure everyone can participate in all conversations, so no one feels left out.\n\nDon't earrape in the voice chats. It's annoying for people who actually want to talk.\n\nNo voice changers. If you don't want people to hear your voice, then don't talk at all.\n\nIf you see something against the rules or something that makes you feel unsafe, let staff know. We want this server to be a welcoming place!")
.addField("πŸ” Getting Verified", "To agree to the rules and receive permission to view all of our channels and send messages, go to <#792391986799837224> and send \`v!verify\`. You are responsible for reading the contents of this channel before agreeing. By being in this server, you agree to all our rules. These rules are subject to change.\n\naSpiv's Network or aSpiv Staff can not and will not be held responsible for any damages or losses that result from the use of our server. We will help you out the best we can, but we are only humans, too.")
.setColor(Math.floor(Math.random()*16777215))
msg.channel.send(sEmbed)
msg.delete();
}
if(command === 'verify') {
let sEmbed = new Discord.MessageEmbed()
.setTitle("Get Verified")
.setDescription("Click on the emoji below to get verified! Make sure you've read the embed in <#791281485276905492>!")
.setColor(Math.floor(Math.random()*16777215))
let m = await msg.channel.send(sEmbed)
m.react('βœ…')
}
return;
});
client.on("messageReactionAdd", async(reaction, user) => {
if(reaction.message.partial) await reaction.message.fetch();
if(reaction.partial) await reaction.fetch();
if(user.client) return;
if(!reaction.message.guild) return;
if(reaction.emoji.name === 'βœ…') {
await reaction.message.guild.members.cache.get(user.id).roles.add(r => r.id === "792395200676495371")
}
})
client.login("n0t.4-r3al_t0k3n")
Does anyone see the mistake here? It should send a message, react to that message with βœ… (That part works), but when I react with the message too, it should give me a role, but it doesn't.
Thanks in advance for your help!

The Problem
The issue is in your messageReactionAdd event handler, which I assume you must already know given the only part of your code that isn't working is the code's response to your reaction. In that part of your code, you are doing if (user.client) return;. This line is incorrect, and will always return (because user.client is always true).
I'm guessing you want to return if the user that reacted is a bot. But user.client doesn't return whether or not the user is a bot; it returns the Client that created the user variable. Essentially, it returns your client variable. And since the User object stored in the user variable is always created by your client, that if statement will always return and prevent your actual role-adding code from occurring (just like what if (true) return; would do).
The Solution
Here's how to fix it, such that it actually checks if the user is a bot or not instead of trying to check if the client exists or not:
client.on("messageReactionAdd", async(reaction, user) => {
if(reaction.message.partial) await reaction.message.fetch();
if(reaction.partial) await reaction.fetch();
if(user.bot) return;
if(!reaction.message.guild) return;
if(reaction.emoji.name === 'βœ…') {
await reaction.message.guild.members.cache.get(user.id).roles.add(r => r.id === "792395200676495371")
}
})
Simply changing user.client to user.bot will solve your issue, or will at the very least allow your role-adding code to actually run and allow you to see if there are any additional errors.
Relevant Resources
https://discord.js.org/#/docs/main/stable/class/User?scrollTo=bot
https://discord.js.org/#/docs/main/stable/class/User?scrollTo=client

Related

I have a question with my discord bot Kick system

I need to make that not everyone can kick members, but only who have permissions
Here is my kick system-
client.on('message', message => {
if (!message.guild) return;
if (message.content.startsWith('+kick')) {
const user = message.mentions.users.first();
if (user) {
const member = message.guild.members.resolve(user);
if (member) {
member
.kick({
reason: 'They were bad!',
})
.then(() => {
message.channel.send(`Successfully kicked ${user.tag}`);
})
.catch(err => {
message.channel.send('I was unable to kick the member');
console.error(err);
});
} else {
message.channel.send("That user isn't in this guild!");
}
} else {
message.channel.send("You didn't mention the user to kick!");
}
}
});
Welcome to StackOverflow! And, from the look of things, the beginning of your bot-making journey.
You can use message.mentions.members.first() to skip a step and simplify your code somewhat.
As mentioned above, you'll want to use member.permissions.has() to check if a member has the MANAGE_MEMBERS permission, or whatever other permission you want to check for. (See Permissions.FLAGS)
Also, consider moving away from using message-based commands, if possible. For a small personal bot, it's not really an issue, but Discord is really pushing the new Interactions (aka slash commands) system, which you can read more about here (discord.js guide) and here (official, discord.com).
in order to make only mods use a command I recommend you using message.member.permissions.has() which allows the bot to check if the person who ran the command has a certain permission in the guild or not. Then to return, if the person doesn't have permission, you can use it in an if statement like that:
if (!message.member.permissions.has("KICK_MEMBERS")) {
return message.reply({content: `You need permissions to use command`})
}
And of course you can always add in your messageCreate event a userPermissions to add on the top of your command.
So the event file would have:
if (!message.member.permissions.has(<command>.userPermissions || [])) return message.channel.send({content: 'You need permissions to run this command'})
then you can just add in your command under name or description userPermissions: ['KICK_MEMBERS'],
This is the easiest way to handle user permissions

How do i make reactions working after restart?

So i am trying to make an ticket bot, using discord.js . By clicking on an reaction, users will be added to an ticket channel, where they can get help. The ticket system itself works perfectly fine, exactly like i want it to work. But the problem is, after i restart the bot, nothing happens anymore when you click on the reaction. Here is the relevant code:
let helpdeskmessageEmbed = await message.channel.send(helpdeskticketEmbed)
helpdeskmessageEmbed.react("1️⃣")
helpdeskmessageEmbed.react("2️⃣")
helpdeskmessageEmbed.react("3️⃣")
client.on('messageReactionAdd', async (reaction, user) => {
const categoryID = "820920950114615318"
if (reaction.message.partial) await reaction.message.fetch()
if (reaction.partial) await reaction.fetch()
if (user.bot) return;
if (!reaction.message.guild) return;
if (reaction.message.channel.id == channel ) {
if(reaction.emoji.name === "1️⃣") {
reaction.users.remove(user)
message.guild.channels.create(`report-${user.username}`).then(
The rest of the code isn't relevant to my question. Could anyone tell me how to fix this.
Note: I am using an command handler, if that is relevant
I've had this exact issue some time ago. Long story short, you need to use partials.
Be aware, that:
"Partials do not have all the information necessary to make them fully functional discord.js structures, so it would not be a good idea to enable the functionality by default. Users should know how to handle them before opting into this feature."
I see that you have tried to use them, but you need to add the ability to handle partials in your code. Change const client = new Discord.Client(); into:
const client = new Discord.Client({
partials: [`MESSAGE`, `CHANNEL`, `REACTION`], //unsure if message and channel are needed, feel free to test it out
});
This basically allows handling all messages, even those posted before your bot started. Without the change above, your code will not detect partials.
client.on("messageReactionAdd", async (reaction, user) => {
let msg = reaction.message;
if (msg.partial) {
await msg.fetch().catch(() => {});
}
//your code goes here
});
Answering your comment:
I have read your replit code and it looks fine, I can only suggest to change this:
const Discord = require ('discord.js');
const client = new Discord.Client({ partials: [`MESSAGE`, `CHANNEL`, `REACTION` ]});
into this:
const { Discord } = require('discord.js');
const client = new Discord({ partials: ['MESSAGE', 'CHANNEL', 'REACTION'] });

How do I track the number of reactions on a message?

So I wanted to implement report&ban system and I decided to use an embedded message with reactions added to it. Moderator can either agree or disagree. For example once 10 moderators agree with the complaint the user mentioned in this message should be banned or kicked.
I thought of using client.on('messageReactionAdd', (messageReaction, user) => {}), but it only checks cached messages. Then I found discordjs.guide about reactions and they showed how to use client.on('raw', (event) => {}), but it's was abandoned long time ago and I didn't even found any mentions about this official Discord.js documentation. Message has .awaitReactions(filter, [options]), but I have to mark voting messages somehow and then searching them in a some kind client of method which is super complicated.
Here's what I have:
const service = client.channels.get('id');
let user = msg.mentions.users.first();
if (!user) {
msg.reply('Couldn\'t find the user!')
return 1;
}
args.shift();
let reason = args.join(' ').trim();
if (!reason) {
msg.reply('No reason to create a complaint!')
return 1;
}
msg.channel.send(`I've created and sent a user complaint about ${user.tag}!)`)
.catch((e) => console.log(e));
msg.delete();
const emb = new Discord.RichEmbed()
.setTitle('User complaint')
.addField('Who?', `**User: ${user.tag}**`)
.addField('Reason?', `**Reson: ${reason}**`)
.setColor('#ff7b00')
.setFooter('Please take action');
service.send(emb)
.then(async msg => {
await msg.react('βœ…')
msg.react('❌')
})
.catch(e => {
console.error()
msg.reply('Couldn\'t send a user complaint!');
return 1;
})
Is it even possible? I explained my previous plan earlier, but is there a way to make is simpler?
1. Database
You should use either message.awaitReactions(); or client.on('messageReactionAdd', ...); and fetch the message on the bot ready event.
It's a very simple process. You'd require a database to store the message ID's, channel ID and of course, server ID. After that make a small algorithm inyour ready event to go through all the messages collected from the database and use either message.awaitReactions(); or client.on('messageReactionAdd', ...); on them.
I'd suggest using message.awaitReactions(); if you decide to go with the database method.
2. Global Array (Less Recommended)
If you have a really simple bot and you can't use a database then I'd recommend having a global array storing all the message IDs and using those for the client.on('messageReactionAdd', ...); event.
You'd have to check if the ID from the message array matches the ID of the message collected in the event and then act accordingly.
This method would work well for the smaller bots, but if you have a bigger, multi-server bot, then I'd highly recommend going with the database version because this version would not work after the bot restarts.

Strings/Arguments for a new person

I need help with a command, for example, if someone writes
" !report #user Spamming " How can I do so my discord account gets a message from the bot about =
Who reports who and for what reason
I've tried watching videos and posts but I can't get my head around it
client.on('message', async function(message) {
if (message.content.startsWith(prefix + "report")) {
const user = await client.fetchUser(args[1].match(/^<#!?(\d+)>$/)[1]);
if (!user) return message.channel.send('Oops! Please mention a valid user.');
const reason = args.slice(2).join(' ');
const me = await client.fetchUser('123456890'); //My id
me.send(`${message.author} reported ${user} for: \`${reason}\``)
.catch(err => console.error(err));
}
}
)
I want for example
In channel = !report #patrick#4245 He is spamming
Then The bot sends a message to me
#fadssa#2556 Reported #patrick#4245 Reason = He is spamming
Before just copying this code, let's actually think this through...
So, let's start by first getting everything we need for the message. First, we should retrieve a User from the argument provided. We do this by comparing the string to that of a mention and picking out the ID. If one doesn't exist, we return an error telling the user to mention someone.
Now, assuming you already have your arguments declared (if not, see this guide to help), we can simply put together the arguments used for the reason. To do so, we should use Array.slice() and then join those words with Array.join().
Then, since we want the bot to send you a DM, we'll have to find you in the Discord world. For this, we can use client.fetchUser().
Now, we can just send you the DM and you'll be alerted of all reports.
/*
* Should be placed within your command's code, after checking required arguments exist
* Assuming 'client' is the Discord Client and 'args' is the array of arguments
* Must be within an async function to use 'await'
*/
const user = await client.fetchUser(args[1].match(/^<#!?(\d+)>$/)[1]); // see below
if (!user) return message.channel.send('Oops! Please mention a valid user.');
const reason = args.slice(2).join(' ');
const me = await client.fetchUser('189855563893571595'); // replace with your ID
me.send(`${message.author} reported ${user} for: \`${reason}\``))
.catch(err => console.error(err));
Although it may look confusing, using regex is a much better option than message.mentions. There's plenty of whack examples where seemingly perfect code will not return the expected user, so this is why I would definitely choose retrieving the ID from a mention myself.

Making a verification system with reactions

I have spotted some posts regarding the same topic, but not the exact problem.
I have also referred to javascript discords, where they were unable to assist me with my problem.
So to inform you,
The purpose of this verification system is to make sure the user understood the rules and can proceed to have the rest of the discord unlocked after he adds a checkmark reaction.
I have made a bot that has the command |message and it works fine and all, but I then want the bot to react to its own message once sent, and then wait for a user to also add a reaction, which will trigger a function, in this case. Triggering the bot to send a PM to the user and giving him a rank.
The bot adds his reaction fine, and upon reacting from me as an example it sends me a PM, but in the PM between me and the bot, the bot reacts once again to his message. And this might be because of the code checking if the message author is the bot.
I was told in the JS Discord that the messageReactionAdd function has a Message Property, however upon searching I couldn't find a way to implement this into my code. How would I do so? Also trying to give the user a rank also spits out an error, and I am simply stuck between understanding and making stuff work. I am getting confused with my own code, and I have minimal understanding of what I am doing, so with that said, Can anyone assist me doing this change, so I can get it in my head? Giving me links to the discord.js documentation is just making me more confused, and the only way for me to learn is by creating, and successfully making it work. Any help is appreciated of course.
So, here is the code for the messageReactionAdd:
bot.on('messageReactionAdd', (reaction, user) => {
if(reaction.emoji.name === "βœ…") {
if(user === bot.user) return;
// if(bot.channel === "dm") return;
// let role = bot.guild.roles.find("name", "C - Verified");
// let role1 = bot.guild.roles.find("name", "C - Unverified");
//if(user.roles.has(role.id));
//await(user.addRole(role.id) && user.removeRole(role1.id));
user.send("Thank you for being apart of the community! As a thanks for accepting the rules, you have been awarded the verified role!");
return;
}
});
And here is the code for the react function itself:
513769507907567628 is the bots' ID.
bot.on("message", async message => {
if(message.author.id != "513769507907567628") return;
message.react("βœ…");
});
So, if you have any input that'd be great! If you can join a Discord Call please message me, That'd be the easiest and quickest.
Regards, Marius.
If your problem occured here:
await(user.addRole(role.id) && user.removeRole(role1.id));
then it is because:
1) await only exists inside async functions.
2) you cannot just chain promises with &&, a && b will result in b and that gets then awaited, so in your case you only wait for the removal.
bot.on('messageReactionAdd', async (reaction, user) => {
if(reaction.emoji.name === "βœ…") return;
if(user === bot.user) return;
let role = bot.guild.roles.find("name", "C - Verified");
let role1 = bot.guild.roles.find("name", "C - Unverified");
await user.addRole(role.id);
await user.removeRole(role1.id);
});

Categories