Trying to delete the original user command the bot reply after the bot is reacted to. For some reason, it only works every other time and when it does work it relays a DiscordAPIError: Unknown Message error
const isValidCommand = (message, cmdName) => message.content.toLowerCase().startsWith(PREFIX + cmdName)
client.on('message', function(message) {
if (message.author.bot) return;
if (isValidCommand(message, "banker"))
message.reply("Bankers are on the way to get your cash. Please be patient as Bankers are busy individuals as well. If there is a major delay you are welcome to use !HeadBanker. Bankers Please React With Money Bag When Sent/Sending!").then(r_msg =>
r_msg.react('💰'))
if (isValidCommand(message, "banker"))
message.channel.send("<#&717082379470110885> Banker Cash Needed")
.then(msg => {
msg.delete({
timeout: 0100
})
})
if (isValidCommand(message, "headbanker"))
message.reply("I see you have pinged Head Banker. If its between 14:00TCT and 5:00TCT you should get a response within a minute or two max. If no response in five minutes you have permission to ping again.").then(r_msg =>
r_msg.react('💰'))
if (isValidCommand(message, "headbanker"))
message.channel.send("<#&716843712092569640> Cash Needed")
.then(msg => {
msg.delete({
timeout: 0100
})
.catch(console.log);
})
client.on('messageReactionAdd', (reaction, user) => {
let limit = 2;
if (reaction.emoji.name == '💰' && reaction.count >= limit) reaction.message.delete()
.catch(console.log);
if (reaction.emoji.name == '💰' && reaction.count >= limit) message.delete()
.catch(console.log);
});
})
I think that's caused by the fact that you've declared your messageReactionAdd listener inside your message listener: that means that every time you get a new message your client will add a new handler, and so it will try to delete the same message multiple time, resulting in an "unknown message" error from the API.
Instead of adding a listener for the reactions on your client, you should try creating a reaction collector using either Message.awaitReactions() or Message.createReactionCollector(). Here's an example:
const isValidCommand = (message, cmdName) => message.content.toLowerCase().startsWith(PREFIX + cmdName)
client.on('message', function(message) {
if (message.author.bot) return;
if (isValidCommand(message, "banker")) { // Use single if statements where possible
message.reply("Bankers are on the way to get your cash. Please be patient as Bankers are busy individuals as well. If there is a major delay you are welcome to use !HeadBanker. Bankers Please React With Money Bag When Sent/Sending!").then(r_msg =>
r_msg.react('💰'))
message.channel.send("<#&717082379470110885> Banker Cash Needed")
.then(msg => {
msg.delete({ timeout: 0100 })
})
}
if (isValidCommand(message, "headbanker")) {
message.reply("I see you have pinged Head Banker. If its between 14:00TCT and 5:00TCT you should get a response within a minute or two max. If no response in five minutes you have permission to ping again.").then(r_msg =>
r_msg.react('💰'))
message.channel.send("<#&716843712092569640> Cash Needed")
.then(msg => {
msg.delete({ timeout: 0100 })
.catch(console.log);
})
}
message.awaitReactions(r => r.emoji.name == '💰', { max: 2 }).then(collected => {
if (collected.size >= 2)
message.delete()
})
})
Also, it's good practice not to repeat if statements, you should merge them wherever you can.
Related
I am trying to create a command where if a user reacts to a message then the bot would send a message after a certain amount of time.
This is my code. it is supposed to send the 'you have reacted to the command' when I react with the emoji, but for some reason it always sends 'its been 10 seconds and no one has reacted'. Does anyone know what I did wrong in the code?
const filter = (reaction, user) => {
return ['💌'].includes(reaction.emoji.name)
&& user.id === message.author.id;
}
message.awaitReactions(filter, { max: 1, time: 10000, errors: ['time'] })
.then(collected => {
const reaction = collected.first();
if (reaction.emoji.name === '💌') {
message.reply('you have reacted to this command');
}
})
.catch(collected => {
message.channel.send('its been 10 seconds and no one has reacted');
})
I was thinking of code like this to get the number of reactions a message has received after a set time:
if (message.content == "test") {
message.channel.send("Hi").then(msg => {
msg.react('🏠').then(r => {
const react = (reaction, user) => reaction.emoji.name === '🏠'
const collector = msg.createReactionCollector(react)
collector.on('collect', (r, u) => {
setTimeout(() => u.send(r.length), 60000 * 5);
})
})
})
}
});
But rightly .lenght is not the correct method to obtain the number of reactions, consequently the error is that the "r.length" message is empty and the bot cannot send it.
The goal is to send a message, as soon as you react to that message, a setTimeOut starts and at the end of the time it returns (in this case in private) the number of reactions that that message has received.
collected.size is the right way of getting the number of collected reactions a message has.
You can read about reaction collectors here
Here is a basic reaction collector that uses collected.size:
const filter = (reaction, user) => {
return reaction.emoji.name === '👍' && user.id === message.author.id;
};
const collector = message.createReactionCollector(filter, { time: 15000 });
collector.on('collect', (reaction, user) => {
console.log(`Collected ${reaction.emoji.name} from ${user.tag}`);
});
collector.on('end', collected => {
console.log(`Collected ${collected.size} items`);
});
So, I got my code and it works just as I want it to. the message pops up changes everything, it's perfect.
Now I want to add so the bot knows when I react to its message and then does something else. What I mean is: bot sends a message with reacts, and whenever some user clicks the reaction something happens, but I have no idea how to do that.
I've tried many things like if (reaction.emoji.name === ':bomb:'), but multiple errors popped out and I didn't know how to fix that. Here's the code:
const Discord = require('discord.js');
const { prefix, token } = require('./config.json');
var lastbuffer;
lastbuffer = 0;
const client = new Discord.Client();
client.once('ready', () => {
console.log('Ready!');
});
client.on('message', message => {
if(message.content.startsWith(`${prefix}start`)){
message.delete()
setInterval(function(){
lastbuffer++;
const Buffer = new Discord.MessageEmbed()
.setColor('#8300FF')
.setTitle("**It's time to check buffers!**")
.setDescription("**It's been **" + "`" + lastbuffer + " Hour" + "`" + "** since last buffercheck, <#&675688526460878848>**." + " **Check now!**")
.setThumbnail('https://art.pixilart.com/88534e2f28b65a4.png')
.setFooter('WEEEEEWOOOOO')
.setTimestamp();
client.channels.cache.get("700296799482675230").send(Buffer).then(msg => {
msg.react('✅');
msg.react('💣');
msg.delete({timeout: 4000})
});
}, 5000)
}
});
client.login(token);
You are going to have to use a ReactionCollector using the createReactionCollector() method.
You can follow this guide to under ReactionCollectors better
You need to use a reaction collector.
client.channels.cache.get("700296799482675230").send(Buffer).then(async msg => {
// I'm using await here so the emojis react in the right order
await msg.react('✅');
await msg.react('💣');
msg.awaitReactions(
// Discord.js v12:
/* ({emoji}, user) => ['✅', '💣'].includes(emoji.name) && user.id === message.author.id,
{max: 1, time: 4000, errors: ['time']} */
// Discord.js v13:
{
// only collect the emojis from the message author
filter: ({emoji}, user) => ['✅', '💣'].includes(emoji.name) && user.id === message.author.id,
// stop collecting when 1 reaction has been collected or throw an error after 4 seconds
max: 1,
time: 4000,
errors: ['time']
}
)
.then(collected => {
const reaction = collected.first()
// do something
})
.catch(() => {
// I'm assuming you want to delete the message if the user didn't react in time
msg.delete()
})
What this code does:
Sends the embed (Buffer) to the channel with the id 700296799482675230
Reacts with the ✅ and then the 💣 emojis on the message with the embed
Waits for a ✅ or 💣 reaction from the author of the original message
If the user reacts within 4 seconds, runs the // do something part
If the user does not react within 4 seconds, deletes the message with the embed
Is there anything remotely wrong with this code?
no errors pop up and there isn't a reaction once the bot sends the messages.
any help would be appreciated, thank you in advance!
const a = msg.guild.roles.get('666712822985654322'); //Verified User
// the role constants are in the same chronological order as below.
const filter = (reaction,user) => ['668236468384169986'].includes(reaction.emoji.name);
const embed = new Discord.RichEmbed()
.setColor(0x00FF00)
.setTitle('Rules')
.setDescription(`
In order to gain access to the rest of the server you must read and abide by these rules:
By reacting with :white_check_mark: you agree to these rules
Roles:
:white_check_mark: ${a.toString()}`)
.setThumbnail(msg.author.avatarURL)
.addField('Rule #1:You do not talk about fight club', 'Second Rule: You do not TALK about fight club')
.setFooter("Use \'!command list\' to get aquainted with Peb 3000");
msg.channel.send(embed).then(async message => {
await message.react('668236468384169986'); //white check mark
message.awaitReaction(filter, {})
.then(collected =>{
const reaction = collected.first();
switch(reaction.emoji.name) {
case('\:white_check_mark:'):
message.member.addRole(a).catch(err => {
console.log(err);
return message.channel.send(`Error adding you to this role: **${err.message}**`);
});
message.channel.send(`You have been added to the **${a.name}** role!`).then(m => m.delete(3000));
break;
}
}).catch(collected => {
return msg.collected.send(`I couldn't add you to this role!`)
})
});
I'd recommend reading both An Idiot's Guide - Using Emojis as well as Discord.js Guide - Reactions, as your current approach for Unicode emojis won't work.
In your case, :white_check_mark: should be ✅ or an equivalent.
The collected options will triggeret when collector end collect, you no provide any options to stop collector, so its will never happen.
The 1 way to give member role on react follow this code. But when bot restart, you need again use this command and create collector.
const roleToAdd = msg.guild.roles.get('666712822985654322'); //Verified Role
if(!roleToAdd) return
let embed = new Discord.RichEmbed()
.setColor(0x00FF00)
.setTitle('Rules')
.setDescription(`
In order to gain access to the rest of the server you must read and abide by these rules:
By reacting with :white_check_mark: you agree to these rules
Roles:
:white_check_mark: ${a.toString()}`)
.setThumbnail(msg.author.avatarURL)
.addField('Rule #1:You do not talk about fight club', 'Second Rule: You do not TALK about fight club')
.setFooter("Use \'!command list\' to get aquainted with Peb 3000");
msg.channel.send(embed).then(message => {
const filter = (reaction, user) => reaction.emoji.name === '✅' && user.id === msg.author.id && reaction.message.id = message.id
const collector = message.createReactionCollector(filter, {});
collector.on('collect', r => {
if(r.emoji.name === '✅') {
let member = message.guild.members.get(reaction.users.last().id)
member.addRole(roleToAdd)
.then( member => {
message.channel.send(`You have been added to the **${roleToAdd.name}** role!`).then(m => m.delete(3000));
})
.catch(console.error)
}
})
collector.on('end', collected => console.log(`Collected ${collected.size} items`));
})
The way number 2 its listen reactionadd event. After restart its will work.
bot.on('messageReactionAdd', (reaction, user) => {
if(reaction.message.id === 'YOUR MESSAGE ID' && reaction.emoji.name === 'youreactionname') {
let meber = reaction.message.guild.members.get(user.id)
member.addRole('yourRole')
}
.catch(console.error)
});
I'm trying to get the last message of a specific channel but I've couldn't do that, I want that if i write a command in another channel (Channel 1) that command gives me the last message of another channel (channel 2).
My code is:
client.on('message', (message)=>{
if(message.channel.id === '613553889433747477'){
if(message.content.startsWith('start')){
message.channel.fetchMessages({ limit: 1 }).then(messages => {
let lastMessage = messages.first();
console.log(lastMessage.content);
})
.catch(console.error);
}
}
});
I cleaned up you code a bit, and added some comments explaining what is happening.
If you have more questions, i would recommend visiting the official Discord.js Discord server.
https://discord.gg/bRCvFy9
client.on('message', message => {
// Check if the message was sent in the channel with the specified id.
// NOTE, this defines the message variable that is going to be used later.
if(message.channel.id === '613553889433747477'){
if(message.content.startsWith('start')) {
// Becuase the message varibable still refers to the command message,
// this method will fetch the last message sent in the same channel as the command message.
message.channel.fetchMessages({ limit: 1 }).then(messages => {
const lastMessage = messages.first()
console.log(lastMessage.content)
}).catch(err => {
console.error(err)
})
}
}
})
If you want to get a message from another channel, you can do something like this.
And use the command start #channel
client.on('message', message => {
// Check if the message was sent in the channel with the specified id.
if(message.channel.id === '613553889433747477'){
if(message.content.startsWith('start')) {
// Get the channel to fetch the message from.
const channelToCheck = message.mentions.channels.first()
// Fetch the last message from the mentioned channel.
channelToCheck.fetchMessages({ limit: 1 }).then(messages => {
const lastMessage = messages.first()
console.log(lastMessage.content)
}).catch(err => {
console.error(err)
})
}
}
})
More about mentioning channels in messages can be found here.
https://discord.js.org/#/docs/main/stable/class/Message?scrollTo=mentions