Reaction Collector - Get Users to post in an embed - javascript

Good Evening, I would like some help on how to get the collected users to post in the .setDescription of my embed. For some reason, everything I try to do returns an error or posts object Object or object Map in the description of the embed. As you can see I am getting the console log for the users that have reacted to the post all I want to do now is get all the users and post them in the embed.
At first, u wanted to get all the users and then randomly pair them into a 1v1 battle however I was informed I would need to use a database for them. If anyone could give me some information on that it would be appreciated.
Thank you Ukzs
.then((channel) => {
channel.send(embed).then((embedMessage) => {
embedMessage.react("👍");
embedMessage.react("👎");
const filter = (reaction, user) => {
return ["👍", "👎"].includes(reaction.emoji.name) && !user.bot;
};
const collector = embedMessage.createReactionCollector(filter, {
time: 10000,
});
const destination = guild.channels.cache.find(
(channel) => channel.name === "t5-battle-channel"
);
collector.on("collect", (reaction) => {
if (reaction.emoji.name === "👍") {
console.log(reaction.users);
}
});
collector.on("end", (collected) => {
if (destination) {
let embed6 = new Discord.MessageEmbed()
.setColor("#0099ff")
.setTitle("⚔️ Members that have joined the T5 Battles! ⚔️")
.setDescription(`${reaction.fetch("👍")} Would like to battle!`)
.setTimestamp()
.setFooter("⚔️ 1657 Battles! ⚔️ | ⚔️ Managed by Ukzs⚔️");
destination.send(embed6);
}
});
});
});

.then((channel) => {
channel.send(embed).then((embedMessage) => {
embedMessage.react("👍");
embedMessage.react("👎");
const filter = (reaction, user) => {
return ["👍", "👎"].includes(reaction.emoji.name) && !user.bot;
};
const collector = embedMessage.createReactionCollector(filter, {
time: 10000,
});
const destination = guild.channels.cache.find(
(channel) => channel.name === "t5-battle-channel"
);
collector.on("collect", (reaction) => {
if (reaction.emoji.name === "👍") {
console.log(reaction.users);
}
});
collector.on("end", (collected) => {
if (destination) {
let userArr = [];
let users = collected.first().users.cache.filter(u => !u.bot);
users.forEach(user => userArr.push(user.username));
let embed6 = new Discord.MessageEmbed()
.setColor("#0099ff")
.setTitle("⚔️ Members that have joined the T5 Battles! ⚔️")
.setDescription(`${userArr.join(", ")} Would like to battle!`)
.setTimestamp()
.setFooter("⚔️ 1657 Battles! ⚔️ | ⚔️ Managed by Ukzs⚔️");
destination.send(embed6);
}
});
});
});
I have edited your collector.on("end"..) event. I made an Array where the users get stored in. In users, all users that are no bots get stored. Then we push every username from the users we got from users, into the Array userArr. And now in the description of the embed, every value of userArr (the usernames) gets seperated by , (if there is only one there will be no comma). That is what the function join(", ") does.

Related

How do I delete a user's new message

I'm pretty trash at coding so I need a little bit of help. I'm trying to code my discord bot to delete someone's messages for one minute after they click a react emoji. It sounds simple but for my tiny pea brain, it's not. This is what I have got so far. It deletes all messages from different users and guilds it's in, forever. I want it so it only delete messages in one channel for one minute.
client.once('message', async userMessage => {
if (userMessage.content.startsWith(''))
{
botMessage = await userMessage.channel.send('Who here likes goats?')
await botMessage.react("👍")
await botMessage.react("👎")
const filter = (reaction, user) => {
return (
["👍", "👎"].includes(reaction.emoji.name) && user.id === userMessage.author.id
);
};
botMessage
.awaitReactions(filter, { max: 1, time: 60000, errors: ["time"] })
.then((collected) => {
const reaction = collected.first();
if (reaction.emoji.name === "👎") {
userMessage.channel.send(`${userMessage.author}, how dare you. I guess no on here likes me. Hmmm, because of that I shall now eat all your messages! BAAAAAHAHAHHAHAHA!`)
setTimeout(() => {
client.on("message", async msg => {
if (author.msg.content.startsWith("")) {
userMessage.channel = await msg.delete();
}
});
}, 2000);
} else {
userMessage.reply("Thanks!");
}
})
.catch((_collected) => {
userMessage.channel.send("Hehe")
});
}
});
Btw, the code is in discord.js!
Your problem is this chunk of code
setTimeout(() => {
client.on("message", async msg => {
if (author.msg.content.startsWith("")) {
userMessage.channel = await msg.delete();
}
});
}, 2000);
This is not how you use events.
A) Your message event is nested within another which could cause memory leaks.
B) To get the content you need to use msg.content, author.msg Is not a thing.
C) I assume your intention here: msg.content.startsWith("") is to always fire the if statement, in that case why not do if (true).
Here's how I would do it:
Create a Set in the namespace which will hold id's of users who's messages should be deleted
const toDelete = new Set();
If they react with a 👎 add them to the set.
if (reaction.emoji.name === "👎") {
userMessage.channel.send('Your message here');
if (!toDelete.has(userMessage.author.id)) {
toDelete.add(userMessage.author.id);
}
}
On each message event check if the author of the message has their id in the set, If so delete their message
client.once('message', async userMessage => {
if (toDelete.has(userMessage.author.id)) {
return userMessage.delete()
.catch(console.error);
}
if (userMessage.content.startsWith('')) {
// Rest of your code
I think your problem in understanding how everything works.
I took everything from discord.js documentation.
Type reaction command to see how it works.
const Discord = require("discord.js");
require("dotenv").config();
const TOKEN = process.env.TOKEN||"YOUR TOKEN";
const PREFIX = process.env.PREFIX||"YOUR PREFIX";
const bot = new Discord.Client();
bot.on("ready", async function(e) {
console.log("Loaded!");
})
bot.on("message", async function(message) {
if (message.author.bot) return;
if (!message.content.startsWith(PREFIX)) return;
let args = message.content.slice(PREFIX.length).trim().split(/\s+/);
let command = args.splice(0, 1).toString().toLowerCase();
if (command == "reaction") {
message.delete();
let msg = await message.channel.send("Click on the reaction");
await msg.react("👍");
await msg.react("👎");
let filter = (reaction, user) => {
return ["👍", "👎"].includes(reaction.emoji.name) && user.id == message.author.id;
}
msg.awaitReactions(filter, {max: 1, time: 10000, errors: ["time"]}).then(collected => {
let reaction = collected.first();
if (reaction.emoji.name == "👎") {
return message.channel.send("downvote");
}
return message.channel.send("upvote");
}).catch(e => {
message.channel.send("user didn't vote");
})
}
})
bot.login(TOKEN);

"TypeError [EMOJI_TYPE]: Emoji must be a string or GuildEmoji/ReactionEmoji" while coding Reaction Roles for a Discord Bot

I have been following the Worn Off Keys Discord.JS guide to get to know discord.js better, even though I understand JS fairly well. I got to a problem though when coding the reaction roles. I cloned the code for a special file from the WOK Discord JS repository. I usually clone the files and then adapt them to my liking, adding and removing some parts. But this time when I ran the code to test the basic clone out, I got an error saying TypeError [EMOJI_TYPE]: Emoji must be a string or GuildEmoji/ReactionEmoji I couldn't find any place where I could fix this, as it worked in the tutorial video with the exact same code.
Here is my code for the special reaction roles file:
const firstMessage = require('./first-message')
module.exports = (client) => {
const channelId = '870818745109585920'
const getEmoji = (emojiName) => client.emojis.cache.find((emoji) => emoji.name === emojiName)
const emojis = {
red_circle: 'CrackShot / Sniper',
orange_circle: 'Scrambler / Shotgun',
yellow_circle: 'Whipper / P90',
green_circle: 'RPEGG / RPG',
blue_circle: 'Free Ranger / Semi-Auto',
purple_circle: 'EGG-K / AK-47',
white_circle: 'TriHard / AUG',
black_circle: 'Cluck-9mm / Pistol'
}
const reactions = []
let emojiText = '**GUN ROLES**\n\n'
for (const key in emojis) {
const emoji = getEmoji(key)
reactions.push(emoji)
const role = emojis[key]
emojiText += `${emoji} = ${role}\n`
}
firstMessage(client, channelId, emojiText, reactions)
const handleReaction = (reaction, user, add) => {
if (user.id === '869698265698947102') {
return
}
const emoji = reaction._emoji.name
const { guild } = reaction.message
const roleName = emojis[emoji]
if(!roleName) {
return
}
const role = guild.roles.cache.find((role) => role.name === roleName)
const member = guild.members.cache.find((member) => member.id === user.id)
if (add) {
member.roles.add(role)
} else {
member.roles.remove(role)
}
}
client.on('messageReactionAdd', (reaction, user) => {
if (reaction.message.channel.id === channelId) {
handleReaction(reaction, user, true)
}
})
client.on('messageReactionRemove', (reaction, user) => {
if (reaction.message.channel.id === channelId) {
handleReaction(reaction, user, false)
}
})
}
The first-message file that you see there is:
const addReactions = (message, reactions) => {
message.react(reactions[0])
reactions.shift()
if (reactions.length > 0) {
setTimeout(() => addReactions(message, reactions), 750)
}
}
module.exports = async (client, id, text, reactions = []) => {
const channel = await client.channels.fetch(id)
channel.messages.fetch().then((messages) => {
if (messages.size === 0) {
channel.send(text).then((message) => {
addReactions(message, reactions)
})
} else {
for (const message of messages) {
message[1].edit(text)
addReactions(message[1], reactions)
}
}
})
}
And all I added from those files to the main index.js file is const roleClaim = require('./role-claim') and later inside the client.on(ready)etc. part I added roleClaim(client) to run the bot code. Any suggestions? Sorry for the giant amounts of text. Please help.
The problem is that you don't have emojis with names like red_circle, orange_circle, etc. client.emojis.cache only contains custom emojis the bot has access to.
So, when you use getEmoji() to get the emoji you'll receive undefined. You don't check the emoji value inside that function and just add it to an array (reactions.push(emoji)). Later, when you try to add the reaction (addReactions()), you try to react with undefined. As it's not an emoji, you receive the error.
A solution would be to use emojis available, and you could also simplify the for loop
let emojis = {
'🔴': 'CrackShot / Sniper',
'🟠': 'Scrambler / Shotgun',
'🟡': 'Whipper / P90',
'🟢': 'RPEGG / RPG',
'🔵': 'Free Ranger / Semi-Auto',
'🟣': 'EGG-K / AK-47',
};
let emojiText = '**GUN ROLES**\n\n';
let reactions = [];
Object.entries(emojis).forEach(([emoji, role]) => {
reactions.push(emoji);
emojiText += `${emoji} = ${role}\n`;
});
console.log(emojiText)
console.log(reactions)
module.exports = (client) => {
let channelId = '870818745109585920';
let emojis = {
'🔴': 'CrackShot / Sniper',
'🟠': 'Scrambler / Shotgun',
'🟡': 'Whipper / P90',
'🟢': 'RPEGG / RPG',
'🔵': 'Free Ranger / Semi-Auto',
'🟣': 'EGG-K / AK-47',
};
let reactions = [];
let emojiText = '**GUN ROLES**\n\n';
Object.entries(emojis).forEach(([emoji, role]) => {
reactions.push(emoji);
emojiText += `${emoji} = ${role}\n`;
});
firstMessage(client, channelId, emojiText, reactions);
function handleReaction(reaction, user, add) {
if (user.id === '869698265698947102') return;
let emoji = reaction._emoji.name;
let { guild } = reaction.message;
let roleName = emojis[emoji];
if (!roleName) return;
let role = guild.roles.cache.find((role) => role.name === roleName);
let member = guild.members.cache.find((member) => member.id === user.id);
// TODO: check if role and member exist
if (add) {
member.roles.add(role);
} else {
member.roles.remove(role);
}
}
client.on('messageReactionAdd', (reaction, user) => {
if (reaction.message.channel.id === channelId) {
handleReaction(reaction, user, true);
}
});
client.on('messageReactionRemove', (reaction, user) => {
if (reaction.message.channel.id === channelId) {
handleReaction(reaction, user, false);
}
});
};

How does a bot create a category with channels in it?

if(!args[0]) return message.channel.send("Missing Parameter: `guild`")
if(args[0] === "guild") {
const loggingChannel = message.guild.channels.cache.find(ch => ch.name === "katsu-member-logs");
const katsuCategory = "Chika Logs";
if(!loggingChannel) {
const channelName = "katsu-member-logs";
message.guild.channels.create(channelName, { parent: katsuCategory.id, topic: "Katsu Member Logs" }).then(c => {
const allUsers = message.guild.roles.cache.find(r => r.name === "#everyone")
c.updateOverwrite(allUsers, {
SEND_MESSAGES: false
})
});
} else {
await message.channel.send("Oops, it looks like `katsu-member-logs` channel already exist in this server");
}
}
}
I have this piece of code. It is working fine as it creates the channel, however, it's not creating the text category where the channel should go. I am not quite sure on how to fix this issue. Discord.JS v12.2.0
You'd need to replace this statement with the following :
const katsuCategory = "Chika Logs";
Should be :
const katsuCategory = message.guild.channels.cache.find(c => c.name === 'Chika Logs' && c.type === 'category');
You should now be able to access it's ID and create a channel using this one as a parent :)

How to detect when a reaction has occured?

I currently have a Discord bot which reads information of a API that deals with a game server panel.
In this Bot there is tasks that are to start/restart/stop/kill the server. i want to give the option for the end user to react to a embed posted by a bot with a certain reaction to trigger these tasks.
The Command and embed that are posted by the bot are:
The code which currently checks which reaction has been triggered looks like this:
message.channel.send(embed).then(async (sentEmbed) => {
sentEmbed.react("🟩")
sentEmbed.react("🔁")
sentEmbed.react("🟥")
sentEmbed.react("❌")
const filter = (reaction, user) => {
console.log(reaction.emoji.name)
return reaction.emoji.name === '🟩' && user.id === message.author.id;
};
const collector = sentEmbed.createReactionCollector(filter, {time: 20000});
collector.on('collect', (reaction, user) => {
Client.startServer(args[0]).then((response) => {
const start_embed = new Discord.MessageEmbed()
.setTitle(response)
.setColor(settings.embed.color.default)
.setFooter(settings.embed.footer);
message.channel.send(start_embed);
}).catch((error) => {
message.channel.send(client.embederror(error))
});
});
const filter2 = (reaction, user) => {
return reaction.emoji.name === '🔁' && user.id === message.author.id;
};
const collector2 = sentEmbed.createReactionCollector(filter2, {time: 20000});
collector.on('collect', (reaction, user) => {
Client.restartServer(args[0]).then((response) => {
const restart_embed = new Discord.MessageEmbed()
.setTitle(response)
.setColor(settings.embed.color.default)
.setFooter(settings.embed.footer);
message.channel.send(restart_embed);
}).catch((error) => {
message.channel.send(client.embederror(error))
});
});
const filter3 = (reaction, user) => {
return reaction.emoji.name === '🟥' && user.id === message.author.id;
};
const collector3 = sentEmbed.createReactionCollector(filter3, {time: 30000});
collector.on('collect', (reaction, user) => {
console.log(`User Stopped There Server`);
});
const filter4 = (reaction, user) => {
return reaction.emoji.name === '❌' && user.id === message.author.id;
};
const collector4 = sentEmbed.createReactionCollector(filter4, {time: 30000});
collector.on('collect', (reaction, user) => {
console.log(`User Killed There Server`);
});
})
This code works for detecting the reactions onto the message, however when a user reacts with any reaction it runs all of the trigger code, so the bot posts two embeds which i have defined as what the bot should output when a reaction is triggered.
I just want the user to click one reaction, then the bot does something, then the use can click another and the bot does something else.
Thanks in advance
The issue was you used collector.on("collect") 4 times instead of using collector2, collector3 and collector4
It's best not to have variables like that since like it shows you might get confused
Plus you should not have 4 different filters and collectors, especially since you repeat a lot of the code
const validEmojis = ['🟩', '🔁', '🟥', '❌'];
const filter = (reaction, user) => {
return validEmojis.includes(reaction.emoji.name) && user.id === message.author.id;
};
const collector = sentEmbed.createReactionCollector(filter, { time: 20000, maxEmojis: 1 });
collector.on('collect', (reaction, user) => {
const name = reaction.emoji.name;
//you only use it in two cases but I assume you will use it for all later on
const embed = new Discord.MessageEmbed()
.setColor(settings.embed.color.default)
.setFooter(settings.embed.footer);
if (name === '🟩' || name === '🔁') {
const method = name === '🟩' ? "startServer" : "restartServer";
Client[method](args[0])
.then(response => {
embed.setTitle(response);
message.channel.send(start_embed);
}).catch((error) => {
message.channel.send(client.embederror(error))
});
} else if (name === '🟥') {
console.log(`User Stopped There Server`);
} else if (name === '❌') {
console.log(`User Killed There Server`);
}
});

Discord JS - Await Messages - Multiple Questions

I am making my first Discord Bot, using Discord.js - I can make it read a command !makeraid and the bot will ask the first question, and store the response into an array.
I want to be able to ask multiple questions like raid name, description, date, and time. I have not yet got this far, after the first question is asked, as a test i want the bot to create the embed message.
However, i cannot make it trigger/fire the next question.
client.on('message', message => {
if (message.content.toLowerCase().startsWith("!makeraid")) {
const filter = m => m.author.id === message.author.id;
var raid = {};
var color = ((1 << 24) * Math.random() | 0).toString(16);
var raidImages = {'DDS':'https://i.imgur.com/izsm8ri.jpg','GR':'https://i.imgur.com/4S9NKtF.jpg','CR':'https://i.imgur.com/EnYiWka.jpg','OR':'https://i.imgur.com/VOYDUlO.jpg'};
message.reply('Raid Name?').then(r => r.delete(10000));
message.channel.awaitMessages(filter, {
max: 1,
time: 10000,
errors: ['time'],
})
.then((collected) => {
raid.title = collected.first().content;
console.log(raid);
collected.first().delete(5000);
})
.catch(() => {
message.channel.send('Raid Cancelled - Too Slow!').then(r => r.delete(5000));
});
while ( Object.keys(raid).length > 0 ) {
message.reply('Do you want to create the raid? Yes or No.').then(r => r.delete(10000));
message.channel.awaitMessages(filter, {
max: 1,
time: 10000,
errors: ['time'],
})
.then((collected) => {
if (collected.first().content.toLowerCase() === "yes") {
collected.first().delete();
var raidEmbed = new Discord.RichEmbed()
.setColor('#'+color)
.setAuthor('Raid Bot', client.user.avatarURL)
.setTitle(':star::star: '+raid.title+' :star::star:')
.setThumbnail(client.user.avatarURL)
.setDescription('Some description here')
.addField('Date', 'Some value here', true)
.addField('Time', 'Some value here', true)
.setTimestamp()
.setFooter('Raid created by: '+ message.member.user.tag, message.member.user.avatarURL);
message.channel.send(raidEmbed).then(async embedMessage => {
await embedMessage.react('✅');
await embedMessage.react('❓');
await embedMessage.react('🇽');
});
} else {
collected.first().delete();
message.channel.send('Raid Cancelled').then(r => r.delete(5000));
}
})
.catch(() => {
message.channel.send('Raid Cancelled - Too Slow! (Make)').then(r => r.delete(5000));
});
}
message.delete();
} else if (message.content.toLowerCase().startsWith("!help")) {
message.reply('You Suck 😃').then(r => r.delete(10000));
message.delete();
}
});
No errors are coming up in the terminal, it just does nothing after the first response has been collected and push into the array.

Categories

Resources