How to wait for a response when running a command? - javascript

Why is it not waiting for a response? it just runs the whole code
Someone told me filter is part of v13 collector options, is there anyway to do this then?
const target = message.mentions.users.first();
if (!target) return message.reply("you have to mention somebody");
await message.reply(
`you proposed to ${target}! Is it **YES** or **NO**?`
);
const filter = (m) =>
m.content.toLowerCase().startsWith("yes") &&
!m.author.bot &&
m.author.target;
const main = message.guild.channels.resolve("706263571562102835");
main.awaitMessages(filter, {
errors: ["time"],
max: 1,
time: 900000,
});
await message.reply(
`You e ${target} are now married!`
);
},
};

message.author.target does not exist. I believe what you meant to do is
const filter = (m) =>
m.content.toLowerCase().startsWith("yes") &&
!m.author.bot &&
m.author.id == target.id
This means that the filter will only detect messages which: begin with "yes", when the author is not a bot, and when the author's ID the same as the target's ID.

Related

Message collector responds to other people's messages

I'm trying to make a collector which will collect the mentioned user's message. But even with filter my bot respond to it's own message and other peoples messages! Here is my test.js file code:
const mentioned = message.mentions.users.first();
const filter1 = (msg) => {
return msg.author.id === mentioned.id
}
const collector1 = await message.channel.createMessageCollector({ filter1, max: 1, time: 120000 })
collector1.on('collect', message => {
console.log(message.content)
})
collector1.on('end', (collected) => {
if (collected.size === 0) return message.channel.send("Mentioned user did not respond in time!")
collected.forEach((message) => {
if (message.content.toLowerCase() == 'accept') {
message.channel.send(`${mentioned} accepted!`)
}
if (message.content.toLowerCase() == 'cancel') return message.channel.send(`${mentioned} declined!`)
})
})
I was changing my filter many times, but I still can't fix this problem, so what am I doing wrong?
Also I use djs v13
The problem is you're trying to use Short-Hand Property Assignment to assign the filter option. However, you pass in "filter1" which results in {filter1: filter1}. Since this does not resolve to a filter option for TextChannel#createMessageCollector() the method disregards the unknown option and therefor your collector has no filter.
Change your filter1 variable to filter
const filter = (msg) => {
return msg.author.id === mentioned.id
}
const collector1 = await message.channel.createMessageCollector({ filter, max: 1, time: 120000 })

Discord.js send message then wait until you reply

I've been trying to code a Discord bot and I can't figure out how to make it wait until you say Y or N. Right now, I'm trying to code the ban command and it works pretty well until it asks you to say Y or N. Then once it asks that and you answer, nothing happens.
Here's the code:
module.exports = {
name: 'ban',
description: 'This bans a member!',
execute (message, args){
var member = message.mentions.users.first();
if(member){
var memberTarget = message.guild.members.cache.get(member.id);
message.channel.send(`Are you sure you want to ban ${member}? (Y or N)`);
var messagethingy = message.first()
var askingBan = ('1')
do { if (messagethingy.content.toLowerCase === 'y' || messagethingy.content.toLowerCase === 'yes' || messagethingy.content.toLowerCase === 'n' || messagethingy.content.toLowerCase === 'no'); {
if (messagethingy.content.toLowerCase === 'no' || messagethingy.content.toLowerCase === 'n') {
message.channel.send('The Action has been cancelled')
var askingBan = ('0')
return
} else if (messagethingy.content.toLowerCase === 'y' || messagethingy.content.toLowerCase === 'yes') {
message.channel.send(`You have banned ${member}!`)
memberTarget.ban();
var askingBan = ('0')
}}
}
while (askingBan = '1');
} else {
message.channel.send("You couldn't ban that member!");
}
}
}
FYI these commands are in a different thingy. The main commands are in main.js and the command that senses when you say ban works perfectly fine.
Instead of a do-while loop, you can use a message collector. You can send a confirmation message and in the same channel set up a collector using createMessageCollector.
For its filter, you can check if the incoming message is coming from the same user who want to ban the member, and check if the message content is one of the accepted answers (y, yes, n, no). You can convert the message to lowercase to make it case insensitive.
You can also add some options, like the maximum number of accepted answers, and the maximum time the collector is collecting messages. I set it to one minute, and after a minute it sends a message letting the original poster know that the action is cancelled.
module.exports = {
name: 'ban',
description: 'This bans a member!',
async execute(message, args) {
const member = message.mentions.members.first();
if (!member) {
return message.channel.send('You need to mention a member you want to ban!');
}
// TODO: check if message.author can ban users
const confirmation = await message.channel.send(`Are you sure you want to ban ${member}? (Y or N)`);
const answers = ['y', 'yes', 'n', 'no'];
const filter = (m) =>
answers.includes(m.content.toLowerCase()) &&
m.author.id === message.author.id;
const collector = confirmation.channel.createMessageCollector(filter, {
max: 1,
time: 60000,
});
collector.on('collect', async (m) => {
if (
m.content.toLowerCase() === answers[2] ||
m.content.toLowerCase() === answers[3]
) {
return message.channel.send(
`The action has been cancelled, ${member} is not banned.`
);
}
try {
await member.ban();
return message.channel.send(`You have banned ${member}!`);
} catch (error) {
return message.channel.send(`Oops, error: ${error}`);
}
});
collector.on('end', (collected, reason) => {
if (reason === 'time') {
message.channel.send(
`${message.author}, it's been a minute without confirmation. The action has been cancelled, ${member} is not banned.`
);
}
});
},
};

Bot confirmation after user reacts not displaying in Discord.js

I want the user to answer a "yes or no" question using reactions. However, there is a bug in which when the tagged user reacts to the question, the bot is not sending a message on whether or not the tagged user wants to negotiate. Here is my code below.
const yesEmoji = '✅';
const noEmoji = '❌';
client.on('message', (negotiate) => {
const listen = negotiate.content;
const userID = negotiate.author.id;
var prefix = '!';
var negotiating = false;
let mention = negotiate.mentions.users.first();
if(listen.toUpperCase().startsWith(prefix + 'negotiate with '.toUpperCase()) && (mention)) {
negotiate.channel.send(`<#${mention.id}>, do you want to negotiate with ` + `<#${userID}>`)
.then(async (m) => {
await m.react(yesEmoji);
await m.react(noEmoji);
//get an answer from the mentioned user
const filter = (reaction, user) => user.id === mention.id;
const collector = negotiate.createReactionCollector(filter);
collector.on('collect', (reaction) => {
if (reaction.emoji.name === yesEmoji) {
negotiate.channel.send('The mentioned user is okay to negotiate with you!');
}
else {
negotiate.channel.send('The mentioned user is not okay to negotiate with you...')
}
})
})
negotiating = true;
}
})
So far, the code displays the reaction but it does not make the bot send a message whether the tagged user is ok or not ok to negotiate with the user that tagged them.
UPDATE:
I managed to get the bot to send a message whether the tagged user is ok or not ok to negotiate with the user that tagged them. Now there is an error in which is shown after 10 seconds (specified time). Here is the updated code below:
const yesEmoji = '✅';
const noEmoji = '❌';
client.on("message", async negotiate => {
const listen = negotiate.content;
let mention = negotiate.mentions.users.first();
if(listen.toUpperCase().startsWith(prefix + 'negotiate with '.toUpperCase()) && (mention)) {
let mention = negotiate.mentions.users.first();
let msg = await negotiate.channel.send(`${mention} do you want to negotiate with ${negotiate.author}`);
var negotiating = false;
await msg.react(yesEmoji);
await msg.react(noEmoji);
const filter = (reaction, member) => {
return reaction.emoji.name === yesEmoji || reaction.emoji.name === noEmoji && member.id === mention.id;
};
msg.awaitReactions(filter, { max: 1, time: 10000, errors: ['time'] })
.then(collected => {
const reaction = collected.first();
if (reaction.emoji.name === yesEmoji) {
negotiating = true;
negotiate.reply('The mentioned user agreed to negotiate with you!');
}
else return negotiate.reply('The mentioned user did not agree to negotiate with you.')
})
}
})
I have a much easier solution to your problem:
const yesEmoji = '✅';
const noEmoji = '❌';
let mention = negotiate.mentions.users.first();
if(mention.id === negotiate.author.id) return message.channel.send("You cannot tag yourself!");
let msg = await negotiate.channel.send(`${mention} do you want to negotiate with ${negotiate.author}`);
var negotiating = false;
await msg.react(yesEmoji);
await msg.react(noEmoji);
const filter = (reaction, member) => {
return (member.id === mention.id && reaction.emoji.name === yesEmoji) || (member.id === mention.id && reaction.emoji.name === noEmoji);
};
msg.awaitReactions(filter, { max: 1, time: 10000, errors: ['time'] })
.then(collected => {
const reaction = collected.first();
if (reaction.emoji.name === yesEmoji) {
negotiating = true;
negotiate.channel.send('The mentioned user is okay to negotiate with you!');
}
else if (reaction.emoji.name === noEmoji) return negotiate.channel.send('The mentioned user is not okay to negotiate with you...')
}).catch(err => {
if(err) return message.channel.send(`${mention} did not react within the 10 seconds!`);
})
So first we got the two emojis, we want the user to react with. mention is our mentioned user, msg is the "yes or no" question and negotiating is set to false by default. At first we react to the question with our emojis. In this example I am using awaitReactions, because it is very simple to use. For this we need a filter. In this case I named the variable also filter. filter checks if the reaction wether is yesEmoji or noEmoji and if the user who reacted is mention (our mentioned user). Then in awaitReactions we want only 1 reaction (yes or no), and I set the time to 10 seconds, but you can change it if you want. After awaitReactions is set up we want to collect our reaction. This is done in .then(). collected gives us the reactions, and we only want the first one, so we store collected.first() in reaction. Now we have a really simple if-else statement. If the reacted emoji is yesEmoji, negotiating will be set to true and a message gets sent into the channel, otherwise it will only sent a message and return.
It is important to set negotiating only to true if the user reacted with yesEmoji. In your code it is true even if nothing happens, because as you run the command everything in that command code will be executed. and your last line there was negotiating = true;. And I think that is not what you wanted to do.

Discord Bot, Discord.js | Get bot to send message after clicking reaction

I'm trying to get my first discord bot to send a message after clicking a reaction,
One for yes reaction, one for no
I have my code already send an embed with the reactions
I created a Reaction collector but
the only thing now its that it instantly reacts with (reacted no) twice, even before I click the reaction
Help is greatly appreciated!
My Code so far:
const {Client, RichEmbed } = require('discord.js');
const client = new Client();
const a =
client.once('ready', () => {
console.log('boogie time!');
});
client.on('message', message => {
if(message.author.bot)
{
if(message.embeds)
{
const embedMsg = message.embeds.find(msg=> msg.title ==='Boogie Time!?');
if(embedMsg)
{
embedMsg.message.react('✅')
.then(reaction => reaction.message.react('❌'))
// This is filter, this specified which reactions it should capture, you can use filter to make sure you're only catching specific reactions by specific user
const filter = (reaction, user) => (reaction.emoji.name === '✅' || reaction.emoji.name === '❌') && user.id === message.author.id;
// Here, we're defining a collector that will be active for 30 seconds and collect reactions that pass the above filter
const collector = embedMsg.message.createReactionCollector(filter, {time: 10000});
// This event is emitted when a reaction passes through the filter
collector.on('collect', r => r.name === '✅' ?
console.log('Reacted Yes') : console.log('Reacted No'));
}
}
return;
}
if(message.content.toLowerCase() === 'boogie')
{
const embed = new RichEmbed();
embed.setTitle("Boogie Time!?")
embed.setColor("GREEN")
embed.setDescription("Are you sure?")
message.channel.send(embed);
};
});
You have a several problems here. The first issue is you are only looking at messages sent by a bot if(message.author.bot) and then later trying to filter by that message author which will always be a bot, not you or anyone else user.id === message.author.id. I think your intention may have been to not collect bot reactions.
The second issue you have is that the asynchronous execution is causing the collector to get created before the bot adds the initial reaction.
embedMsg.message.react('✅')
.then(reaction => reaction.message.react('❌'))
After this call to .react, the code below it starts immediate async execution, before the reactions complete. If you aren't listening to the bots reaction this shouldn't be an issue, but if you enclose the collector creating in a second .then statement it will ensure it doesn't create it until the second reaction is complete and you won't need to filter the user.id because the bot shouldn't react after that, thus eliminating both problems.
So the cause of the problem is the bot is collecting it's own two reactions. Why is it always saying 'React No' then?
This is the third issue:
collector.on('collect', r => r.name === '✅' ?
console.log('Reacted Yes') : console.log('Reacted No'));
Here you have forgotten to call out the reactions emoji. This line should be:
collector.on('collect', r => r.emoji.name === '✅' ?
console.log('Reacted Yes') : console.log('Reacted No'));
In conclusion, this should be the changes described above:
if(embedMsg)
{
embedMsg.message.react('✅')
.then(reaction => reaction.message.react('❌')
.then(() => {
// This is filter, this specified which reactions it should capture, you can use filter to make sure you're only catching specific reactions by specific user
const filter = (reaction, user) => (reaction.emoji.name === '✅' || reaction.emoji.name === '❌');
// Here, we're defining a collector that will be active for 30 seconds and collect reactions that pass the above filter
const collector = embedMsg.message.createReactionCollector(filter, {time: 10000});
// This event is emitted when a reaction passes through the filter
collector.on('collect', r => r.emoji.name === '✅' ?
console.log('Reacted Yes') : console.log('Reacted No'));
}));
}

Await reaction by a different user

I'm making a verification system that if you send a message. In a different channel, an embed shows up with 2 emoji's: 1 to accept, and 1 to deny. The .awaitReaction has to be triggered by a different user then the author. But when I change the filter. It triggers the message if the bot reacts to it. How can I fix this?
Here is my code:
let register = args.join(" ").slice(7)
const filter = (reaction, user) => ["✅", "❌"].includes(reaction.emoji.name) && !bot.user;
let test = new Discord.RichEmbed()
.addField("User:", message.author.username && message.author.tag, true)
.addField("Requested nickname:", register)
.setColor("#ed0c75")
.setImage(message.author.displayAvatarURL)
let acceptordeny = message.guild.channels.find(`name`, "accept-or-deny");
if(!acceptordeny) return message.channel.send("Can't find accept or deny channel.");
acceptordeny.send(test).then(async message => {
await message.react("✅")
await message.react("❌")
message.awaitReactions(filter, {
max: 1,
time: 60000,
errors: ["time"]
}).then(collected => {
const reaction = collected.first();
switch (reaction.emoji.name) {
case "✅":
console.log("Accepted")
break;
case '❌':
console.log("Denied")
break;
}
}).catch(collected => {
return acceptordeny.send("Failed")
})
})
Hope someone can help me with this.
Update the filter with this one:
const filter = (reaction, user) => ["✅", "❌"].includes(reaction.emoji.name) && user.id !== message.client.user.id;
It will check if the id of the user who reacted to the message is the same as the id and if, cancel.

Categories

Resources