discord.js give role when react - no reply error in the discord server - javascript

I wanted do a discord bot, and wanted it to give a role when someone reacts with an emoji, but it doesn't responsed.
My code, for now, looks like this:
client.on('messageReactionAdd', async (reaction, user) => { //here the bot adds the reaction
if (reaction.partial) {
try {
await reaction.fetch()
} catch (error) {
return console.error('error');
}
}
const guild = client.guilds.cache.get("server-id");
const role = guild.roles.cache.get("role-id");
const member = reaction.message.guild.member(user);
if (reaction.message.id !== 'text-message-id') return;
else if(reaction.emoji.name === "😎") {
if (member.roles.cache.has(fem)) return;
else
member.roles.add(role)
}
})
and
client.on('messageReactionRemove', async (reaction, user) => { //here the bot removes the reaction
if (reaction.partial) {
try {
await reaction.fetch()
} catch (error) {
console.error('error')
return
}
}
const guild = client.guilds.cache.get("server-id");
const role = guild.roles.cache.get("role-id")
const member = reaction.message.guild.member(user)
if (reaction.message.id !== 'text message id') return
else if (reaction.emoji.name === "😎") {
if (member.roles.cache.has(fem))
member.roles.remove(role)
}
});
I don't know what happened, but I thing has a version error (of
discord.js) Someone can help me?
I wanted to a RPG server, when the player reacts to a emoji, a role
of Wizard or Warrior is add...

I can't say for sure if it will fix your error, but here's a few things you should apply to your code:
Make sure you enabled partials in your startup file:
const { Client } = require('discord.js');
const client = new Client({ partials: ['MESSAGE', 'CHANNEL', 'REACTION'] });
Check if user is partial:
if(user.partial) await user.fetch();
Restructure your try block:
try {
if(reaction.partial) await reaction.fetch();
if(user.partial) await user.fetch();
}
Await the role to be added:
if (reaction.message.id !== 'text-message-id') return;
else if(reaction.emoji.name === "😎") {
if (member.roles.cache.has(fem)) return;
else await member.roles.add(role);
}
You have to await this, because roles.add() returns a promise
Also...
if you're planning to add some more messages / reactions you can use a switch for this.
Example:
// Listen for messages
switch(reaction.message.id) {
case 'your message id':
if(reaction.emoji.name === '👍') {
// Your code, if the user reacted with 👍
}
break;
case 'another message id':
// if you want to listen for multiple reactions, you can add a switch for that
// too
switch(reaction.emoji.name) {
case '😂':
// your code if user reacted with 😂
break;
case '❌':
// your code if user reacted with ❌
break;
default:
break;
}
default:
break;
}
Note:
Of course you don't have to use a switch / switches because for some people it's a bit confusing / not clean. You can manage this with if / if else statements too, but if this is getting more and more I'd recommend using a switch
The rest of your code looks fine, so I hope this will fix your problem :)
You can also take a look at my code, handling this event

Related

Discord Bot in JS not reading reactions

I am currently developing a Discord bot and I am trying to add a kind of menu as the bot is supposed to be a guide for a game.
To make that work I am trying to add bot messages after reacting to the prior message.
I am testing it on a test message and the bot is supposed to send Test1 if a user reacts with 👍
After reacting, the bot simply does nothing. It doesn't crash nor does it send the intended message.
My code:
case 'Testembed': //Testembed mit Reactions
message.channel.send({embeds: [Testembed.de.data]}).then((question) => {
question.react('🙃')
question.react('👍')
const filter = (reaction, user) => {
return ['👍','🙃'].includes(reaction.emoji.name) && !user.bot;
};
const collector = question.createReactionCollector(filter, { //<-- Here it stops working
max: 1,
time: 15000
});
collector.on('end', (collected, reason) => {
if (reason === 'time') {
message.channel.send('Ran out of time...');
} else {
let userReaction = collected.array()[0];
let emoji = userReaction._emoji.name;
if (emoji === '👍'){
message.channel.send('Test1');
} else if (emoji === '🙃') {
message.channel.send('Test2');
} else {
message.channel.send("I don't understand ${emoji}...");
}
}
});
});
break;
Edit: Bot now throws new error:
throw er; // Unhandled 'error' event
^
TypeError: collected.array is not a function
In discord.js#14.x.x, the method to create a reaction collector changed. Now, the collector would only take one argument and the filter variable would have to be passed in the object. An example would look like this:
const filter = (reaction, user) => {
return ['👍','🙃'].includes(reaction.emoji.name) && !user.bot;
};
const collector = question.createReactionCollector({
max: 1,
time: 15000,
filter
});

DiscordJs - Member undefined when remove reaction first

im trying to make a basic bot add/remove role when add/remove reaction from a post on discord.
The code works if i add the role first and then remove it, but lets say i already have the role and restart the script. When i remove the reaction the script gives me the error saying:
"Cannot read properties of undefined (reading 'roles')"
client.on('messageReactionRemove', async (reaction, user) => {
if (reaction.partial) {
try {
await reaction.fetch();
} catch (error) {
console.error('Something went wrong when fetching the message:', error);
return;
}
}
if (reaction.message.id != pinnedMsg) {
return;
}
var role = reaction.message.guild.roles.cache.find(role => role.name === "ROLENAME");
const guild = reaction.message.guild;
const member = await guild.members.cache.find(member => member.id === user.id);
member.roles.remove(role); }); //var member is undefined here
You need to fetch members with <Guild>.members.fetch because they are not cached. Don't forget to use await when needed, to find in cache it's not necessary.
Example for your case:
await guild.members.fetch();
const member = guild.members.cache.find(member => member.id === user.id);

Send user that got kicked the reason why they got kick

The only code I have is this:
module.exports = {
name: "kick",
description: "This command kicks a member!",
execute(message, args) {
const target = message.mentions.users.first();
if (target) {
const memberTarget = message.guild.members.cache.get(target.id);
memberTarget.kick();
message.channel.send("User has been kicked");
} else {
message.channel.send(`You coudn't kick that member!`);
}
},
};
Good Morning. So I'm trying to get it to message the person that got kicked the reason why they got kicked. (!kick user reason) I want it so the bot DMs the person what the reason was but I don't know how to do that.
You would only need to add the following:
const reason = args.splice(1).join(` `) || 'Not specified';
memberTarget.send(`You have been kicked: \nReason: ${reason}`)
module.exports = {
name: "kick",
description: "This command kicks a member!",
execute(message, args) {
const target = message.mentions.users.first();
if (target) {
const memberTarget = message.guild.members.cache.get(target.id);
const reason = args.splice(1).join(` `) || 'Not specified';
memberTarget.kick();
message.channel.send("User has been kicked");
memberTarget.send(`You have been kicked: \nReason: ${reason}`)
} else {
message.channel.send(`You coudn't kick that member!`);
}
},
};
The const reason = args.splice(1).join( ) || 'Not specified'; defines the 'reason' property, if there isn't a reason, it defaults to 'Not specified'.
memberTarget.send(You have been kicked: \nReason: ${reason})
Just sends the message to the targeted member.
Right off the bat, I see that you are getting the target using message.mentions.users and getting the memberTarget from the guild's cache. You should avoid this and use message.mentions.members.
You'll have to use the send method of GuildMember, but since it returns a Promise, you'll have to catch any errors. (e.g: the bot cannot DM the member)
// You should do some sanity checks in case you haven't. You don't want everyone to be able to kick members using the bot.
// Getting the first member in message.mentions.members.
const target = message.mentions.members.first();
// Making sure that target is defined.
if (!target) return message.channel.send('Please mention a member to kick.');
// Making sure a reason is provided. (args[0] is the mention)
if (!args[1]) return message.channel.send('Please provide a reason.');
// Making sure the bot can kick the target.
if (!target.kickable) return message.channel.send('Couldn\'t kick the target.');
// Trying to send a message to the target, notifying them that they got kicked, and catching any errors.
target.send(`You have been kicked from ${message.guild.name} for ${args.slice(1, 2000).join(' ')}`).catch(console.error).finally(() => {
// After the message was sent successfully or failed to be sent, we kick the target and catch any errors.
target.kick(`Kicked by ${message.author.tag} for ${args.slice(1, 2000).join(' ')}}.`).then(() => {
message.channel.send(`${target.user.tag} has been kicked for ${args.slice(1, 2000).join(' ')}.`);
}).catch(error => {
console.error(error)
message.channel.send(`Something went wrong...`);
});
});
This is working kick command with reason made by me (you can try it):-
It has every validation you should have in a kick command
const Discord = require('discord.js')
exports.kick = async(message , prefix , client) => {
if(!message.member.hasPermission("KICK_MEMBERS")) return message.channel.send('Missing Permission! You need to have `KICK_MEMBERS` permissions in order kick this member.')
if(!message.guild.me.hasPermission("KICK_MEMBERS")) return message.channel.send('Missing Permission! I need to have `KICK_MEMBERS` permissions to kick this member.')
const args = message.content.slice(prefix.length).trim().split(' ');
const command = args.shift().toLowerCase();
let member = message.mentions.members.first();
if(!member){
let err = "```css\n[ Agrument Error : You Have not mentioned the user on first args. ]\n```\n\n"
let embed = new Discord.MessageEmbed()
.setAuthor(`${client.user.username} Help Manual` , client.user.displayAvatarURL({format : "png"}))
.setTitle(`${message.guild.name}`)
.setDescription(err)
.addField('Help Command:' , `\`\`\`\n${prefix}kick #user#0001 Reason\n\`\`\``)
.setTimestamp()
.setColor('RED')
return message.channel.send(embed)
}
if(args[0] != `<#!${member.id}>`){
let err = "```css\n[ Agrument Error : You Have not mentioned the user on first args. ]\n```"
let embed = new Discord.MessageEmbed()
.setAuthor(`${client.user.username} Help Manual` , client.user.displayAvatarURL({format : "png"}))
.setTitle(`${message.guild.name}`)
.setDescription(err)
.addField('Help Command:' , `\`\`\`\n${prefix}kick #user#0001 Reason\n\`\`\``)
.setTimestamp()
.setColor('RED')
return message.channel.send(embed)
}
if(member.id === message.author.id) return message.channel.send(`Why? No Just Say Why Do you want to kick yourself?`)
let reason = args.slice(1).join(' ');
if(!reason || reason.length <= 1){
reason = "No Reason Was Provided."
}
if(!member.kickable){
return message.channel.send(`I Don't Have Permissions to Kick ${member.user.username}`)
}
member.kick().then(() => {
return message.channel.send(`Successfully Kicked ${member.user.username} for Reason ==> \`${reason}\``)
}).catch(() => {
return message.channel.send(`I Don't Have Permissions to Kick ${member.user.username}`)
})
}

How to find out if the message author is an element of my mongo database

EDIT: THIS IS FIXED!
I apparently forgot to reroute my mongoose connection to my Atlas!
I'm making a premium feature in my bot, that allows users to play music. Only thing wrong is that I can't find out how to find the message author's id in the database!
.findOne() returns promise that will resolve to the document if it's found, otherwise null. This means you can simply check if it's not null, you don't need to check if the IDs are the same. That's already checked by Mongoose.
Don't forget that you need to await the results if you're using promises.
try {
const premiumMember = await premiumSchema
.findOne({ userID: message.author.id })
.exec();
if (!premiumMember) {
return message.reply('You are not a premium user!');
}
const VC = message.member.voice.channel;
if (!VC)
return message.reply(
'You are not in a VC! Please join one and redo the command!',
);
const connection = await VC.join();
const dispatcher = connection
.play(ytdl(args[0]))
.on('finish', () => {
VC.leave();
message.channel.send(`${message.author}, your song has ended!`);
})
.on('error', (error) => {
console.log(error);
message.channel.send('There was an error playing this song');
});
dispatcher.setVolumeLogarithmic(5 / 5);
} catch (err) {
console.log(err);
}
use await before query like this:
const id = await premiumSchema.findOne({
userID: message.author.id
})
after that implement the business logic with == if you want to check the type ===
if(id.userID == message.author.id) {
return message.reply('You are not a premium user!')
}

My kick command lets anyone in the server kick someone

I need my kick command for my discord bot only be able to work for moderators and admins. Does anyone have any more coding that could make it so only mods or admins could kick?
My coding for the kick command:
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.member(user);
if (member) {
member
.kick('Optional reason that will display in the audit logs')
.then(() => {
message.reply(`Successfully kicked ${user.tag}`);
})
.catch((err) => {
message.reply('I was unable to kick the member');
console.error(err);
});
} else {
message.reply("That user isn't in this guild!");
}
} else {
message.reply("You didn't mention the user to kick!");
}
}
});
You can use GuildMember.hasPermission to check if a user has a certain permission. You can see the valid permission flags here, although I think you'll want to use KICK_MEMBERS in this case.
if (!message.member.hasPermission('KICK_MEMBERS'))
return message.channel.send('Insufficient Permissions');
You can also restrict access via the roles someone has, for which I urge you to read this existing answer

Categories