How to get old message reactions - javascript

What I'm trying to do is to get username for users who reacts on that message. It's working good but when the bot restarts only new reactions work.
how to make it send all users reactions
client.on('ready', () => {
client.guilds.get('guild_id').channels.get('chnl_id').fetchMessage('msg_id');
});
client.on('messageReactionAdd', (reaction, user) => {
const { message} = reaction;
if(message.channel.id == 'chnl_id'){
if(reaction.emoji.name === "✅") {
message.guild.fetchMember(user.id).then(member => {
if(user.bot) return;
else {
message.channel.send(reaction.users.map(u => u.username.toString()))
}
})
}}});

If you have the message, then you can filter the reaction of that message by emojis:
const reaction = await message.reactions.cache.filter(r=> r.emoji.name === '✅').first().fetch();
Then you can fetch all reactions with that specific emoji:
await reaction.users.fetch();
Then you can filter from that if you want to (for example your own bot), with:
const filteredReactions = reaction.users.cache.filter(r=> !r.bot);
And don't forget to put these in an async function.

Related

discord.js How do you make a reaction collector

I am trying to make it so when you get to a certain amount of reactions my bot will send a message and if somebody can help here is my code
.then(function(sentMessage) {
sentMessage.react('👍').catch(() => console.error('emoji failed to react.')).message.reactions.cache.get('👍').count;
const filter = (reaction, user) => {
return reaction.emoji.name === '👍' && user.id === message.author.id;
};
message.awaitReactions(filter, { max: 2, time: 00, errors: ['time'] })
.then(collected => console.log(collected.size))
.catch(collected => {
console.log(`After a minute, only ${collected.size} out of 4 reacted.`);
});
});
})
Instead of awaitReactions, you could also use createReactionCollector which is probably easier to use and its collector.on() listeners are more readable than awaitReactions's then() and catch() methods.
You won't need to use message.reactions.cache.get('👍').count to check the number of reactions, as the end event fires when you reached the maximum and you can send a message inside that.
Also, in your filter, you don't need to check if user.id === message.author.id as you will want to accept reactions from other users. However, you can check if !user.bot to make sure that you won't count the bot's reaction. You can also remove the time option if you don't want to limit the time your bot collects reactions.
Another error was that you called .awaitReactions() on the message itself not the sentMessage.
Check out the working code below:
// v12
client.on('message', async (message) => {
if (message.author.bot || !message.content.startsWith(prefix)) return;
const args = message.content.slice(prefix.length).split(/ +/);
const command = args.shift().toLowerCase();
const MAX_REACTIONS = 2;
if (command === 'react') {
try {
// send a message and wait for it to be sent
const sentMessage = await message.channel.send('React to this!');
// react to the sent message
await sentMessage.react('👍');
// set up a filter to only collect reactions with the 👍 emoji
// and don't count the bot's reaction
const filter = (reaction, user) => reaction.emoji.name === '👍' && !user.bot;
// set up the collecrtor with the MAX_REACTIONS
const collector = sentMessage.createReactionCollector(filter, {
max: MAX_REACTIONS,
});
collector.on('collect', (reaction) => {
// in case you want to do something when someone reacts with 👍
console.log(`Collected a new ${reaction.emoji.name} reaction`);
});
// fires when the time limit or the max is reached
collector.on('end', (collected, reason) => {
// reactions are no longer collected
// if the 👍 emoji is clicked the MAX_REACTIONS times
if (reason === 'limit')
return message.channel.send(`We've just reached the maximum of ${MAX_REACTIONS} reactions.`);
});
} catch (error) {
// "handle" errors
console.log(error);
}
}
});
If you're using discord.js v13, there are a couple of changes:
you'll need to add the GUILD_MESSAGE_REACTIONS intents
the message event is now messageCreate
the collector's filter is inside the options object
// v13
const { Client, Intents } = require('discord.js');
const client = new Client({
intents: [
Intents.FLAGS.GUILDS,
Intents.FLAGS.GUILD_MESSAGES,
Intents.FLAGS.GUILD_MESSAGE_REACTIONS,
],
});
const prefix = '!';
client.on('messageCreate', async (message) => {
if (message.author.bot || !message.content.startsWith(prefix)) return;
const args = message.content.slice(prefix.length).split(/ +/);
const command = args.shift().toLowerCase();
const MAX_REACTIONS = 2;
if (command === 'react') {
try {
// send a message and wait for it to be sent
const sentMessage = await message.channel.send('React to this!');
// react to the sent message
await sentMessage.react('👍');
// set up a filter to only collect reactions with the 👍 emoji
// and don't count the bot's reaction
const filter = (reaction, user) => reaction.emoji.name === '👍' && !user.bot;
// set up the collecrtor with the MAX_REACTIONS
const collector = sentMessage.createReactionCollector({
filter,
max: MAX_REACTIONS,
});
collector.on('collect', (reaction) => {
// in case you want to do something when someone reacts with 👍
console.log(`Collected a new ${reaction.emoji.name} reaction`);
});
// fires when the time limit or the max is reached
collector.on('end', (collected, reason) => {
// reactions are no longer collected
// if the 👍 emoji is clicked the MAX_REACTIONS times
if (reason === 'limit')
return message.channel.send(`We've just reached the maximum of ${MAX_REACTIONS} reactions.`);
});
} catch (error) {
// "handle" errors
console.log(error);
}
}
});
And the result:
You want to check the collected.size with an if statement like so:
let amount = 4; // any integer
if (collected.size /* returns an integer */ === amount) {
console.log(`Got ${amount} reactions`)
}
Hope I got the issue right.
If I understand it correctly, then you can just change the parameters for the awaitMessage method. You can remove the time: 00, errors: ['time'] arguments since they're optional and keep the max: 2. That way, the function will only finish once there are 2 reactions (in this case).
I would recommend removing the user.id === message.author.id; from the filter since it seems like you want multiple users to react to the message.
For more information, you can check the discord.js guide or the documentation for awaitReactions.
Code:
message.channel.send("Message reacting to.").then(function (sentMessage) {
sentMessage.react('👍').catch(() => console.error('emoji failed to react.'));
const filter = (reaction, user) => {
return reaction.emoji.name === '👍';
};
message.awaitReactions(filter, { max: 2 })
.then(collected => console.log(collected.size))
});

How send DM message to the author of the reaction?

How can I make the bot to send a DM message to the users who clicked the reaction?
client.on("message", (msg) => {
if (msg.guild && msg.content.startsWith("!test")) {
client.channels.cache.get("813782841187631126").send("Test-1")
.then((sentMessage) => {
sentMessage.react('811140592762486805')
const filter = (r) => r.emoji.id == '811140592762486805';
const collector = sentMessage.createReactionCollector(filter, {time: 60000});
collector.on('collect', (r) => {
reaction.author.send("Test-2");
});
});
}
});
The collect event on ReactionCollector takes two parameters; reaction and user. You can simply use the send() method on the user to send them a DM.
Also, you should not collect the bot's reaction. You'll need to update your filter and add && !user.bot, so you won't try to send the bot a message.
const filter = (reaction, user) =>
reaction.emoji.id === '811140592762486805' && !user.bot;
const collector = sentMessage.createReactionCollector(filter, {
time: 60000,
});
collector.on('collect', (reaction, user) => {
user.send('Test-2');
});

reactions counted multiple times? discord.js

I made a bot where if you type a command it will send a message and if you react to that message it will send another message but if i run the command again and react to the first message it will send the message two times how can i fix that?
client.on('messageReactionAdd', async (reaction, user)=>{
if(user.bot) return;
if (reaction.emoji.name === '⛔') {
clearInterval(my_interval);
clearTimeout(my_timeout);
const exampleEmbed1 = new Discord.MessageEmbed()
.setColor('#fefefe')
.setTitle(`Your record was ${index}s!`)
.setAuthor(message.author.tag, message.author.avatarURL())
.setDescription('Bot made by tempacc')
if(run){
message.channel.send(exampleEmbed1);
index = 0;
message.member.voice.channel.leave();
run = false;
}else if(!run){
message.channel.send('You must start a speedrun before running this command!');
}
}
})
I suggested that you should use a reaction collector instead, but I will include an example here along with docs for anyone else wondering.
const filter = (reaction, user) => {
return reaction.emoji.name === '👍'; // Check reaction was a 👍 and not anything else
};
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`);
});
However where time is, you can also pass max, maxUsers or maxEmojis into this data object, for example:
const collector = message.createReactionCollector(filter, { maxUsers: 1 });
You can find more about the reaction collector here and more about the options here

How to make bot send message to another channel after reaction | Discord.js

How do I make it so that when someone reacts with the first emoji in this command, the bot deletes the message and sends it to another channel?
Current Code:
const Discord = require("discord.js");
module.exports.run = async (bot, message, args) => {
if (!message.member.hasPermission("MANAGE_MESSAGES"))
return message.channel.send("You are not allowed to run this command.");
let botmessage = args.join(" ");
let pollchannel = bot.channels.cache.get("716348362219323443");
let avatar = message.author.avatarURL({ size: 2048 });
let helpembed = new Discord.MessageEmbed()
.setAuthor(message.author.tag, avatar)
.setColor("#8c52ff")
.setDescription(botmessage);
pollchannel.send(helpembed).then(async msg => {
await msg.react("715383579059945512");
await msg.react("715383579059683349");
});
};
module.exports.help = {
name: "poll"
};
You can use awaitReactions, createReactionCollector or messageReactionAdd event, I think awaitReactions is the best option here since the other two are for more global purposes,
const emojis = ["715383579059945512", "715383579059683349"];
pollchannel.send(helpembed).then(async msg => {
await msg.react(emojis[0]);
await msg.react(emojis[1]);
//generic filter customize to your own wants
const filter = (reaction, user) => emojis.includes(reaction.emoji.id) && user.id === message.author.id;
const options = { errors: ["time"], time: 5000, max: 1 };
msg.awaitReactions(filter, options)
.then(collected => {
const first = collected.first();
if(emojis.indexOf(first.emoji.id) === 0) {
msg.delete();
// certainChannel = <TextChannel>
certainChannel.send(helpembed);
} else {
//case you wanted to do something if they reacted with the second one
}
})
.catch(err => {
//time up, no reactions
});
});

How to delete all user inputs except one command in specific channel?

I was working on a discord bot and for a verification channel. I want users to type only the /verify command: every message or command except /verify they type should get deleted automatically. How can I do this?
Current code:
if (command === "verify") {
if (message.channel.id !== "ChannelID") return;
let role = message.guild.roles.find(rol => rol.name === 'Member')
const reactmessage = await message.channel.send('React with 👌 to verify yourself!');
await reactmessage.react('👌');
const filter = (reaction, user) => reaction.emoji.name === '👌' && !user.bot;
const collector = reactmessage.createReactionCollector(filter, {
time: 15000
});
collector.on('collect', async reaction => {
const user = reaction.users.last();
const guild = reaction.message.guild;
const member = guild.member(user) || await guild.fetchMember(user);
member.addRole(role);
message.channel.send(`Verification Complete.. ${member.displayName}. You have got access to server. `)
});
message.delete();
}
You can add a check at the top of your client.on('message') listener:
client.on('message', message => {
let verified = !!message.member.roles.find(role => role.name == 'Member');
// ... command parsing ect...
if (!verified && command == 'verify') {...}
else if (verified) {
// other commands...
}
});

Categories