Making a verification system with reactions - javascript

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);
});

Related

Discord.js Message Collector not working properly, can someone recommend an other way to collect messages or how to make this work?

I made a discord bot using discord.js.
This bot should ask questions about a game when someone uses !rank [rank name]
and if the user answers correctly he/she receives the rank.
I found a way to collect messages, but this method does not want to work, it send the message multiple times and also ignores the time given to the collector, I tried multiple things but neither of them worked, I am very new to creating discord bots so can someone recommend me any other solution to make this bot work?
CODE:
client.on('messageCreate', message => {
if (message.content == '!rank r6') {
message.channel.send('Is Frost an attacker?')
const collector = new Discord.MessageCollector(message.channel, m => m.author.id == message.author.id, {max: 1, time: 8000})
collector.on('collect', message => {
if (message.content == 'no'){
message.channel.send('Role added')
message.member.roles.add('775660517053562900')
}
})
}
})
I'm not sure how you formatted your code to look like that, as the official docs & guide suggest different ways of implementing Collectors. I personally suggest following the guides carefully.
Specifically I see that you try making a new Discord.MessageCollector whereas the guide suggests using a function on message.channel to instate a message collector.
Here are some resources to help you out (assuming you're using Discord.js v12):
https://v12.discordjs.guide/popular-topics/collectors.html#message-collectors
https://v12.discordjs.guide/additional-info/async-await.html#how-do-promises-work

How do I fix DiscordAPIError: Unknown Message?

I made a bot that deletes text messages in an image channel, but when I use it it's logs this error.
client.on("message", async message => {
if (message.author.bot) return;
const users = ['853248522563485717'];
if (message.channel.id === '841260660960395287') {
if (users.includes(message.author.id)) return;
if (message.attachments.size !== 0) return;
message.member.send("You can't send text in 'images' channel")
await message.delete();
} else return;
});
(this is different from the other questions with the same topic)
how do I fix it?
The most likely problem is that you are running multiple instances of the Discord bot. Check if you have multiple command lines open, if so, check if they are running the bot. Apart from that, if users spam, Discord API tends to get confused about which messages to delete, making it try to delete the same message more than 1 time. You can try adding an if statement checking if the message is undefined.
client.on("message", async (message) => {
if (!message) return; // ADDED THIS LINE OF CODE
if (message.author.bot) return;
const users = ["853248522563485717"];
if (message.channel.id === "841260660960395287") {
if (users.includes(message.author.id)) return;
if (message.attachments.size !== 0) return;
message.member.send("You can't send text in 'images' channel");
await message.delete();
} else {
return;
}
});
From your error above, you are seemingly using a message event listener for every command or function you want your bot to perform. The maximum for this is 11 (of the same type). This is not the correct way to do this.
What is an event listener?
//the 'client.on' function is called every time a 'message' is sent
client.on("message", async (message) => {
//do code
});
How to fix this:
Instead of using 1 event listener per command, use 1 for the whole client. You could solve this a multitude of ways, with command handlers or such, however I will keep it simple.
This is the basic setup you should see in your index.js or main.js file:
// require the discord.js module
const Discord = require('discord.js');
// create a new Discord client
const client = new Discord.Client();
// on message, run this
client.on('message', (message) => {
if (!message) return;
console.log(`message sent in ${message.channel.name}. message content: ${message.content}`);
//this event will fire every time a message is sent, for example.
});
// login to Discord with your app's token
client.login('your-token-goes-here');
So what do you do if you want to do multiple functions with your bot? (for example deleting text in an images only channel and logging messages to console)
Command handling. It is the only way. I linked an official Discord.js guide above, read through it and see what you can do. I would highly recommend trying this with an entirely different bot and clean index file, as it would be easier than trying to fit in code you dont understand between your already problematic code.

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

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

Discord Bot Clear Commands Eror

I took a small break from coding my bot, and I've been playing around with adding modules to make an economy type thing. I was having some issues with that, so I went to check if the 'clear' command worked still. I originally wrote the code without the async function, but now I am using it and I think maybe that has caused a problem? Wondering if anyone knows how to fix it, thanks for checking this out.
The ban/kick commands also aren't working at all, so if anyone could take a look at those?
For the code, I've used bits and pieces of tutorials and guides from around the internet and I think some of that may have interfered with what's already been written.
ErrorCode:
(node:16360) UnhandledPromiseRejectionWarning: DiscordAPIError: You can only bulk delete messages that are under
module.exports = {
name: "clear",
description: "Clears messages",
async run (client, message, args) {
const amount = args.join(" ");
if(!amount) return message.reply('please provide an amount of messages for me to delete')
if(amount > 100) return message.reply(`you cannot clear more than 100 messages at once`)
if(amount < 1) return message.reply(`you need to delete at least one message`)
await message.channel.messages.fetch({limit: amount}).then(messages => {
message.channel.bulkDelete(messages
)});
}
}
As Tyler2P pointed out in the comments, you can only bulk-delete messages under 2 weeks old. If you'd like to keep your command running smoothly, you can filter out messages sent before that time.
// as a general tip, you don't need to use `await` and `.then()`
// use only one at a time
message.channel.messages.fetch({ limit: amount }).then(messages => {
// filter out all messages sent more than two weeks ago
messages = messages.filter((msg) => msg.createdTimestamp < new Date(Date.now() - 12096e5).getTime())
message.channel.bulkDelete(messages)
messages.size !== amount
? message.channel.send(`Unfortunately, ${amount - messages.size} messages were sent more than two weeks ago, but we deleted the other ${messages.size}.`)
: message.channel.send(`${messages.size} messages were deleted`);
});

How do I add multiple reactions?

I've looked everywhere for answers and I can't figure this out.
Here's what I want to do:
I want to run some command initially for my bot to send an embed to a specific channel only admins have access to. Done.
Then the bot will immediately react to its own message with the number emojis 1, 2, and 3. Problem.
I don't want the bot to await a reaction to the message from an admin. This embed is meant to stay there UNTIL an admin reacts to it. That could be within 1 minute, or 3 days, but if I have to reboot the bot for any reason then it will stop awaiting the reaction. So I have an event that triggers when someone reacts with a given emoji, this works. It can be improved, but it functions:
bot.on("messageReactionAdd", (messageReaction, user) => {
console.log(messageReaction);
if(reaction.emoji.name === "\u0031\u20E3") {
message.channel.send('one'); //This is temporary to test it out. There will be other code here eventually.
}
else if(reaction.emoji.name === "\u0032\u20E3") {
message.channel.send('two');
}
else if(reaction.emoji.name === "\u0033\u20E3") {
message.channel.send('three');
}
});
My problem is that when I run this code:
let cmdEmbed = new discord.RichEmbed()
.setTitle('**Command Menu Test**')
.setDescription("Type commands")
.setAuthor('InfernoBot', 'https://cdn.discordapp.com/avatars/533089334224617474/17ddec7cb178601d17964040ed8dc32d.png?size=2048')
.setColor(0xD41519);
message.channel.sendEmbed(cmdEmbed).then(function (message) {
message.react('\u0031\u20E3')
message.react('\u0032\u20E3') //This doesn't run
message.react('\u0033\u20E3') //This doesn't run
});
It only ever reacts with the '1' emoji.
How do I make it react with emoji numbers 1, 2, and 3, without awaiting for a reaction?
PS: I'm going to implement some code that will resend the exact same embed with the same reactions once the existing embed has been reacted to, to reset it.
EDIT: The bot doesn't always react with 1. However, it only ever adds one reaction. It's not consistent.
.
Found the answer about 30 mins after posting this. I'll share for anyone who was having the same issue.
My first chunk of code in the original post was causing the bot to break and reboot.
I replaced the first chunk of code with:
bot.on("messageReactionAdd", (reaction, user) => {
if(user.toString() !== '<#533089334224617474>' /*InfernoBot ID*/) {
console.log('User is not InfernoBot')
if(reaction.emoji.name === "\u0031\u20E3") {
//code here
}
}
});
And I replaced the second chunk of code with:
let cmdEmbed = new discord.RichEmbed()
.setTitle('**Command Menu Test**')
.setDescription("Type commands")
.setAuthor('InfernoBot', 'https://cdn.discordapp.com/avatars/533089334224617474/17ddec7cb178601d17964040ed8dc32d.png?size=2048')
.setColor(0xD41519);
message.channel.sendEmbed(cmdEmbed).then(function (message) {
message.react('\u0031\u20E3').then(() => message.react('\u0032\u20E3')).then(() => message.react('\u0033\u20E3'));
});

Categories