Similar to these questions:
How to use remove event with ReactionCollector?
DiscordJS reactionCollector 'remove' is never emitted
But none of the solutions listed in either solve my problem:
//Message filter and collector
const reactionFilter = (reaction, user) => {
return ['✅', '▶️'].includes(reaction.emoji.name);
}
//Create reaction collector
const reactionCollector = sent.createReactionCollector(reactionFilter, { dispose: true, max: 1, time: 100000 });
//Message filter and collector
const messageFilter = m => m.member.id == this.player.id && m.content;
const messageCollector = sent.channel.createMessageCollector(messageFilter, { dispose: true, time: 100000 });
//Await message collector collect
messageCollector.on('collect', m => {
//Emits fine
});
//Await reaction
reactionCollector.on('collect', (reaction, user) => {
//Emits fine
});
//Await remove
reactionCollector.on('remove', (reaction, user) => {
//Never emits
});
//Await end
reactionCollector.on('end', r => {
//Emits fine
});
No matter what I do, the remove event is never emitted.
I am using Discord.js V12.5.3
I have dispose: true and it still doesn't work
The collector ends on the first reaction
The collector ends on the first reaction because you set the max to 1. For the remove event to be fired, the max must be 2 or above.
sent.createReactionCollector(reactionFilter, { dispose: true, max: 2, time: 100000 })
This can emit the remove event because the max is more than 1.
Related
I am stuck on a problem. When "Player 2" (player[1]) types !yes in the channel then reason it times out. I'm not sure what I am doing wrong. player[1] is defined as msg.mentions.members.first();
let answer = true;
if (players[1].user.bot) {
return;
} else {
answer = await msg.channel.awaitMessages((msg) => {
console.log(msg.author.id === players[1].id && msg.content === `!yes`) // returns true
if (msg.author.id === players[1].id && msg.content === `!yes`) {
console.log("Player has accepted") // The console does print "Player has accepted"
return true;
}
return false;
}, {maxMatches: 1, time: 30000, errors: ['time']})
.catch(() => {
console.log("Timed out!") // The console does print "Timed Out as well"
return false;
});
}
// if user refuses to play
if (!answer) {
return channel.send(`${players[1]} preferred to run away.`);
}
You have incorrect syntax for awaitMessages() - the first argument should be a CollectorFilter (see here), not a callback.
Consider using createMessageCollector() instead. It reads much more nicely than awaitMessages() and makes more sense than forcing async/await into a collector. Should look something like this:
const filter = m => (m.author.id===players[1].id && m.content==="!yes");
const collector = msg.channel.createMessageCollector(filter, {max: 1, time: 30000});
collector.on("collect", (m) => {
// Player has accepted... do whatever
});
collector.on("end", (reason) => {
if(reason === "time") {
// Ran out of time
}
});
I am trying to make a poll command for a discord bot in which the user chooses a number of options in the first command (ie '!poll 4') and then chooses the questions and the options. I am having some issues getting the bot to wait for a response before it moves on to the next option in the loop. When I try and use await in the loop it says I cannot use await because it's not an async function, but it is an async function I think. I am very inexperienced with this so I am sure it is a simple error or probably multiple. If anyone can give me advice on a way to make the loop work as intended and ask for each option I would appreciate it. Also is there a way to add if statements to do addFields to an embed? Here is my code:
const Discord = module.require('discord.js');
module.exports = {
name: 'poll',
async execute(message, args) {
function isNumber(n) { return !isNaN(parseFloat(n)) && !isNaN(n - 0) }
if(isNumber(args[1])){
if(args[1]<2) return message.channel.send('Please choose a higher number of options for the poll :)');
if(args[1]>10) return message.channel.send('Please choose a lower number of options for the poll :)');
const filter = response => {
if(!response.author.bot) return response;
};
var question;
var options;
message.channel.send('What question would you like to ask?').then(() => {
message.channel.awaitMessages(filter, { max: 1, time: 15000})
.then(collected => {
question = `${collected.first()}?`;
message.channel.send('Question: ' + question);
for (var i = 0; i < args[1]; i++) {
message.channel.send('What is option ' + (i + 1) + '?').then(() => {
message.channel.awaitMessages(filter, { max: 1, time: 15000})
.then(collected => {
options[i] = collected.first;
message.channel.send(`Option ${i}: ${options[i]}`);
})
.catch(collected => {
message.channel.send('Poll has timed out.');
});
})
}
})
.catch(collected => {
message.channel.send('Poll has timed out.');
});
const embed = new Discord.MessageEmbed()
.setColor(3447003)
.setTitle(question)
.setDescription('choose an option')
/*
if (options[0]) .addField('1️⃣:' + option[0])
if (options[1]) .addField('2️⃣:' + option[1])
if (options[2]) .addField('3️⃣:' + option[2])
if (options[3]) .addField('4️⃣:' + option[3])
if (options[4]) .addField('5️⃣:' + option[4])
if (options[5]) .addField('6️⃣:' + option[5])
if (options[6]) .addField('7️⃣:' + option[6])
if (options[7]) .addField('8️⃣:' + option[7])
if (options[8]) .addField('9️⃣:' + option[8])
if (options[9]) .addField('🔟:' + option[9])
*/
message.channel.send(embed).then(embedMessage => {
if (options[0]) embedMessage.react('1️⃣');
if (options[1]) embedMessage.react('2️⃣');
if (options[2]) embedMessage.react('3️⃣');
if (options[3]) embedMessage.react('4️⃣');
if (options[4]) embedMessage.react('5️⃣');
if (options[5]) embedMessage.react('6️⃣');
if (options[6]) embedMessage.react('7️⃣');
if (options[7]) embedMessage.react('8️⃣');
if (options[8]) embedMessage.react('9️⃣');
if (options[9]) embedMessage.react('🔟');
});
});
}
}
}
Since you say you are trying to use await in your loop, let me take the function it is contained in out from your snippet, format it a little, and try to do some explaining. Disclaimer: I am no expert, so I am learning as well.
.then(collected => {
question = `${collected.first()}?`;
message.channel.send(`Question: ${question}`);
for (var i = 0; i < args[1]; i++) {
message.channel.send(
`What is option ${i + 1}?`
).then(() => {
message.channel.awaitMessages(filter, {
"max": 1,
"time": 15000,
}).then(collected => {
options[i] = collected.first;
message.channel.send(`Option ${i}: ${options[i]}`);
}).catch(collected => {
message.channel.send("Poll has timed out.");
});
});
}
});
But before that, as the first inner .then() still returns a Promise, you can chain the second inner .then() in the outer scope to avoid nesting them too deep, and leave a single .catch() at the end. On that note, it would probably be more accurate to call the catch's parameter something like error. So here's the new snippet:
.then(collected => {
question = `${collected.first()}?`;
message.channel.send('Question: ' + question);
for (var i = 0; i < args[1]; i++) {
message.channel.send(
`What is option ${i + 1}?`
).then(() => {
message.channel.awaitMessages(filter, {
"max": 1,
"time": 15000,
});
}).then(collected => { // Change .then() chaining
options[i] = collected.first;
message.channel.send(`Option ${i}: ${options[i]}`);
}).catch(error => { // Change parameter name
message.channel.send("Poll has timed out.");
});
}
})
What's happening now is that each iteration is running one after the other immediately. You .send() a whole bunch of messages which each return a Promise, and off that Promise, you pass a callback function to .then() which runs once each Promise resolves into a Message. That callback implicitly returns the result of .awaitMessages(), which is also a promise, and once that resolves, the next callback in the next .then() runs with the value of whatever the previous promise resolved to passed in as an argument, and so on.
Alright, so you want to the entire Promise chain to finish processing and resolve before proceeding to the next iteration, right? You can use the await keyword to suspend progress in the relevant anonymous function, until its associated promise-based operation either resolves or rejects. The catch is that that function has to be marked with the async keyword, and in your code, that is not actually the case, you are just making use of Promises and callback functions (regarding "but it is an async function I think"). So, let's add both the aforementioned keywords:
.then(async collected => { // Mark as async
question = `${collected.first()}?`;
message.channel.send('Question: ' + question);
for (var i = 0; i < args[1]; i++) {
await message.channel.send( // Wait for this entire Promise chain to resolve before proceeding
`What is option ${i + 1}?`
).then(() => {
message.channel.awaitMessages(filter, {
"max": 1,
"time": 15000,
});
}).then(collected => {
options[i] = collected.first;
message.channel.send(`Option ${i}: ${options[i]}`);
}).catch(error => {
message.channel.send("Poll has timed out.");
});
}
})
That should cause your desired behaviour, though my edits may have syntax errors as I have not ran it myself. If I got something wrong, please do comment.
You can read more here:
Using async-await
Using Promises
How can I set the duration of the message Example:
if (message.content === 'test') {
message.channel.send (`he say test in 22seconds`)
}
If you're looking for the time it took to the bot to receive the message, use:
if (message.content === 'test') {
const seconds = ((Date.now()-message.createdTimestamp)/1000).toFixed(2);
message.channel.send (`he say test in ${seconds} seconds`)
}
What you are looking for is setTimeout() function.
if (message.content === 'test') {
setTimeout(function(){
message.channel.send (`it took me 22seconds to send this message.`);
}, 22000);
}
Hmm.. the question is not too clear but I'm guessing you mean once the user types a command, the bot says something and then the user can reply with test and the bot tells you how long it took you to type test? (Give the code a try and if its not what you wanted you can take parts out. :) )
The code:
const prefix = ''; //Put whatever prefix you want in the `(prefix goes here)`
var intervals;
bot.on("message", msg => {
let args = msg.content.substring(prefix.length).split(" ");
switch (args[0]) {
case "test": // You can call the command whatever you want
let timer = 3;
msg.channel.send("Get ready").then(msg => {
intervals = setInterval(function() {
msg.edit(`Type test in the chat in **${timer--}**..`);
}, 1000);
});
setTimeout(() => {
clearInterval(intervals);
msg.channel
.send(`Type test in the chat`)
.then(() => {
const time = Date.now();
msg.channel
.awaitMessages(
function(userMsg) {
if (userMsg.content === "test") return true;
},
{
max: 1,
time: 10000,
errors: ["time"]
}
)
.then(function(collected) {
const endTime = Date.now();
let successMsg = "Congratulations!\n";
let collectedArr = Array.from(collected.values());
for (let msg of collectedArr) {
let timeDiff = (endTime - msg.createdTimestamp) / 100;
successMsg += `You took ${timeDiff} seconds to type test.\n`;
}
msg.channel.send(successMsg);
})
.catch(function(collected) {
msg.channel.send(`You did not answer in time!`);
});
})
.catch(function(err) {
console.log(err);
});
}, 5000);
break;
}
});
I'm not too sure what you're asking for but hope this is it! Again, give it a try and see if it works.
Im guessing you need the bot to send that message in 22 seconds. If thats the case then do this
if (message.content === 'test') {
setTimeout(() => { // setTimeout function dalays code inside of it for a set period of time
message.channel.send (`he say test in 22seconds`); // Your code
}, 22000); // The amount of time it should be delayed for. 22000 (milliseconds) = 22 seconds
}
hello I don't want the mods to do kick action in my server i see discord.js doesnt add guildKickAdd like guildMemberAdd
so how can i block kick or set limit kick ?
this is ban block when someone do ban action bot taking roles and gives him punished.
client.on("guildBanAdd", async function(guild, user) {
const entry = await guild
.fetchAuditLogs({ type: "MEMBER_BAN_ADD" })
.then(audit => audit.entries.first());
const yetkili = await guild.members.get(entry.executor.id);
setTimeout(async () => {
let logs = await guild.fetchAuditLogs({ type: "MEMBER_BAN_ADD" });
if (logs.entries.first().executor.bot) return;
guild.members
.get(logs.entries.first().executor.id)
.removeRoles(guild.members.get(logs.entries.first().executor.id).roles); ///TÜM ROLLERİNİ ALIR
setTimeout(() => {
guild.members
.get(logs.entries.first().executor.id)
.addRole("633026228537917460"); /// VERİLECEK CEZALI ROL İD
}, 3000);
const sChannel = guild.channels.find(c => c.id === "641032067840344064");
const cıks = new Discord.RichEmbed()
.setColor("RANDOM")
.setDescription(
`<#${yetkili.id}> ${user} adlı Kişiye Sağ tık ban Atıldığı için Banlayan Kişinin Yetkileri Alındı`
)
.setFooter("Created by Tokuchi");
sChannel.send(cıks);
guild.owner.send(
`Tokuchi Affetmez † Guard | ** <#${yetkili.id}> İsimili Yetkili <#${user.id}>** Adlı Kişiyi Banladı Ve Yetkilerini Aldım.`
);
}, 2000);
});```
You need to use guildMemberRemove event:
// When a member left. Maybe he left himself, but maybe he was kicked.
client.on("guildMemberRemove", (member) => {
// Get the last kick case of the server
const entry = await guild
.fetchAuditLogs({ type: "MEMBER_KICK" })
.then(audit => audit.entries.first());
// if there's not any kick case in this server
if(!entry) return;
// if the target was not the member who left
if(entry.target.id !== member.id) return;
// Else, you know the member was kicked, and you have the entry so you can do what you want
});
This is the best way to know if someone was kicked.
I'm new to the discordjs package and I've been digging around but for the last 2 days I'm stuck at this.
What I'm trying to achieve is "questionnaire" that will guide the user through some questions. An example would be:
User types: !askOrder
Q: Do you want red wine or white wine?
A: white wine
Q: You want white wine. Do you prefer a verdejo or a rueda?
A: rueda
Q: A rueda it's. Do you want it at room temperature or chill?
A: room temperature.
What I've is:
msg.author.send('Do you want red wine or white wine?');
msg.author.send(WineText)
.then((systemMsg) => {
systemMsg.channel.awaitMessages(response => response.content, {
max: 1,
time: 5000,
errors: ['time'],
}).then((collected) => {
systemMsg.channel.send(`You want ${collected.first().content}. Do you prefer a verdejo or a rueda?`);
collected.channel.awaitMessages(response => response.content, {
max: 1,
time: 10000
});
})then((collected2) => {
systemMsg.channel.send(`A ${collected2.first().content} it's. Do you want it at room temperature or chill? `);
}).catch((err) => {
return;
});
But it simply stops after it asks the second questions, not capturing/collecting the second answer. What is it that Im doing wrong?
Thanks a lot for your answers!
What I'd do is put all of the questions (and answers) in an array, wrap those statements in a function, and loop them over an iteration like this:
let i = 0; let questions = ['Q1', 'Q2'];
function askQuestion() {
const filter = m => m.author.id == message.author.id;
message.channel.send(questions[i]).then(() => {
message.channel.awaitMessages(filter, { max: 1, time: 120000, errors: ['time'] })
.then(async collected => {
//do stuff
message.channel.send(`answer was ${collected.first().content}`);
i++; //increase iteration
if (i === questions.length) return;
else askQuestion();
})
.catch(collected => {
//timed out
});
});
}
askQuestion();
It helps clean your code a little bit. You can change them as you see fit.
I made a bot that ask questions just like this, you can view the code here
You structured your awaitMessages events wrong:
msg.author.send('Do you want red wine or white wine?');
msg.author.send(WineText)
.then((systemMsg) => {
systemMsg.channel.awaitMessages(response => response.content, {
max: 1,
time: 5000,
errors: ['time']
}).then((collected) => {
systemMsg.channel.send(`You want ${collected.first().content}. Do you prefer a verdejo or a rueda?`);
collected.first().channel.awaitMessages(response => response.content, {
max: 1,
time: 10000
}).then((collected2) => {
systemMsg.channel.send(`A ${collected2.first().content} it's. Do you want it at room temperature or chill? `);
}).catch((err) => {
return;
});
});
});
There were 2 crucial errors you made:
(1) You sent a message to collected.channel. However, collected is a collection of messages, and doesn't have a channel property. To send it to the channel, just do collected.first().channel, since collected.first() is a message.
(2) You were missing two })s at the end of your code, because of the thens that you included and never closed.