I'm running a dm prompt from my bot, where the player needs to reply before the bot continues asking. I set up a filter so that the bot doesn't detect and count its own message, but it doesn't seem to be triggering the ".then()" function.
My code:
let filter = m => m.author.id != client.user.id
channel.awaitMessages(filter, {max: 1, time: 1000*180, errors: ['time']})
.then(msg => {
console.log("got to the then")
let replymsgobject = msg.first()
let reply = replymsgobject.content
let checkstringarr = [
"payment",
"about",
"team",
"requirements"
]
if (contains("or", reply, checkstringarr)) {
channel.send(`Your post doesn't follow the format.`)
} else {
channel.send(`succesfully set your post message, would you like to add any extra comments?`)
let filter = m => m.author.id != client.user.id
channel.awaitMessages(filter, {max: 1, time: 1000*120, errors: ['time']})
.then(replymsg => {
if (contains("only", replymsg.content, "no")) {
//some stuff
} else {
//some stuff
}
})
.catch(collectedcatchmsg => {
channel.send(`timed out`)
})
}
})
.catch(collectedcatchmsg => {
channel.send(`timed out`)
})
#Toasty said (sorry Toasty), "it will wait until the timer is over". This is incorrect, it will give you the promise once for example the max messages have been reached.
why would it wait for 3 mins if it gets the required answer in 10secs??
Now I'm a little lost do you want the command executor to reply to that message collector or do you not? Because right now your filter is not accepting any messages sent by the command executor/message sender.
To fix this just edit your filter
const filter = m => m.author.id === message.author.id;
if you want someone else's message to be collected and not the message authors, then you would do
const filter = m => m.author.id !== message.author.id;
Turns out there were 2 errors! First off the filter dictionary was supposed to be inside the table with the requirements, etc., The second error was using != instead of !==, Thanks to #Patrik for helping out here!
Related
I am currently developing a Discord bot and I am trying to add a kind of menu as the bot is supposed to be a guide for a game.
To make that work I am trying to add bot messages after reacting to the prior message.
I am testing it on a test message and the bot is supposed to send Test1 if a user reacts with 👍
After reacting, the bot simply does nothing. It doesn't crash nor does it send the intended message.
My code:
case 'Testembed': //Testembed mit Reactions
message.channel.send({embeds: [Testembed.de.data]}).then((question) => {
question.react('🙃')
question.react('👍')
const filter = (reaction, user) => {
return ['👍','🙃'].includes(reaction.emoji.name) && !user.bot;
};
const collector = question.createReactionCollector(filter, { //<-- Here it stops working
max: 1,
time: 15000
});
collector.on('end', (collected, reason) => {
if (reason === 'time') {
message.channel.send('Ran out of time...');
} else {
let userReaction = collected.array()[0];
let emoji = userReaction._emoji.name;
if (emoji === '👍'){
message.channel.send('Test1');
} else if (emoji === '🙃') {
message.channel.send('Test2');
} else {
message.channel.send("I don't understand ${emoji}...");
}
}
});
});
break;
Edit: Bot now throws new error:
throw er; // Unhandled 'error' event
^
TypeError: collected.array is not a function
In discord.js#14.x.x, the method to create a reaction collector changed. Now, the collector would only take one argument and the filter variable would have to be passed in the object. An example would look like this:
const filter = (reaction, user) => {
return ['👍','🙃'].includes(reaction.emoji.name) && !user.bot;
};
const collector = question.createReactionCollector({
max: 1,
time: 15000,
filter
});
Im a bit new creating Discord bots, my plan with this is to have like a book with the help command that if you press the arrow it changes to the next page, and if you press another arrow it changes to the previus page, I'll simpifly my code to make it more easier to understand.
async execute(message, client){
var msg1 = await message.channel.send('how are')
msg1.react('▶') //send the message
client.on('messageReactionAdd', async (reaction, user) =>{ //wait for the reaction
if(user.bot) return
if (message.reaction.id === msg1.id){
message.channel.messages.fetch(msg1.id).then(msg => msg.delete())
var msg2 = await message.channel.send('you?')
msg2.react('◀') //delete the previus message, send the second and react to it
}
else if (message.reaction.id === msg2.id){
message.channel.messages.fetch(msg2.id).then(msg => msg.delete())
var msg1 = await message.channel.send('how are')
msg1.react('▶') //delete the second message, send the first and react
}
})
}
I know this isnt going to work but i hope you understand the major idea, how can i do this so it actually works?
If you want to listen for reactions to old messages you need to fetch the messageId, etc. This is simple to understand. Here is a Guide.
If you only want it to send a message, react to it, and listen to the next reaction it's easier. There is also a Guide for it.
In your case with the book, I would use the second method and then loop it.
So if someone presses the button it starts the function from the beginning.
This is only an example I never tested it and can't say if it works, It's only made to show you what I meant:
const reactionName1 = '▶';
const reactionName2 = '◀';
const text1= 'How are';
const text2 = 'you?';
module.exports = {
async execute(message, client) {
if(message.author.user.bot) return;
message.channel.send('Hello!').then(msg => {
nextMessage(msg, message.author, reactionName1, text1)
});
},
}
function nextMessage(message, author, reactionName, text) {
message.edit(text).then(() => {
message.react(reactionName);
const filter = (reaction, user) => {
return [reactionName].includes(reaction.emoji.name) && user.id === author.id;
};
message.awaitReactions({ filter, max: 1, time: 60000, errors: ['time'] })
.then(collected => {
const reaction = collected.first();
message.reactions.removeAll();
if(reaction.emoji.name === reactionName1) return nextMessage(message, author, reactionName2, text2);
if(reaction.emoji.name === reactionName2) return nextMessage(message, author, reactionName1, text1);
})
.catch(collected => {
message.reactions.removeAll();
return message.edit('You had to press the reaction').then(() => message.delete({ timeout: 4000 })).catch(o_O=>{});
});
});
};
I hope that it was a bit helpful.
I am trying to create a reaction message, but whenever I try to use a console.log in the .then it only executes it once the message is deleted.
async execute(message) {
const role = message.guild.roles.cache.find(r => r.name == 'Founder');
if (!role) return message.channel.send(`**${message.author.username}**, role not found`);
await message.delete();
const filter = (reaction) => reaction.emoji.name === '✅';
const ReactionMessage = await message.channel.send('React to this message to get the Founder role');
ReactionMessage.react('✅');
ReactionMessage.awaitReactions(filter, { max: 10, time: 15000 })
.then(collected => console.log(collected.size))
.catch(err => console.error(err));
}
My end game is to have it add a role to all of those users who react to it, but it won't even console.log the collected size until I delete the message. Anyone able to help me get this working?
The awaitMessages() will only resolve once either the message is deleted or the time has run out. What you can do instead is make a reactionCollector and wait for the collect event.
Here is some resources: https://discordjs.guide/popular-topics/collectors.html#reaction-collectors, https://discord.js.org/#/docs/main/stable/class/Message?scrollTo=createReactionCollector
Try replacing console.log(collected.size) with console.log(collected) and see how that works out.
I am trying to create a bot that a user can DM to start a "job" inquiry.
Example:
A user messages the bot with !inquiry, then the bot asks questions about the job such as if it's a personal project or for a company, then what is the company or personal projects twitter, it will then ask what type of service they are requesting by supplying options and based on that option the bot will respond with "Please explain what you have in mind for your new xxx job"
Then once the user answers all those questions the bot sends an embed with what they answered.
I was thinking of using MessageCollector but I got stuck with how to do the logic. I have the bot responding to the user so I understand how to send messages through DM to a user. just don't quite understand how to implement the rest. I need a little push.
client.on("message", async (msg) => {
if (!msg.content.startsWith(prefix) || msg.author.bot) return;
if (msg.channel.type === "dm") {
const args = msg.content.slice(prefix.length).split(/ +/);
const command = args.shift().toLowerCase();
const discordUser = msg.author.tag;
if (command !== "order") {
try {
sendFailMessage(msg, "wrongCommand");
} catch (e) {
console.warn("Failed sending Fail Message");
}
} else {
msg.channel.startTyping(1);
msg.author.send();
I've made something similar before so incase you want the full code and context: https://github.com/karizma/ravenxi/blob/master/commands/showcase/apply.js
But here's it rewritten for your context:
(note it's def not optimized since idk your context code, and you are passing variables for every call, but if you know js decently which you should if you are gonna use a libary, it shouldn't be too hard to better the code)
function sendNexQuestion(index, channel, questions, replys) {
return channel.send(questions[index])
.then(() => channel.awaitMessages(() => true, { max: 1, time: 30000, errors: ["time"] }))
.then(reply => {
const content = reply.first().content;
if (content === prefix + "cancel") throw "Self-Cancel";
if (content === prefix + "redo") {
replys.length = 0;
return sendNextQuestion(0, channel, questions, replys);
}
replys.push(content);
return index >= questions.length - 1 ? new Promise(res => res(replys)) : sendNextQuestion(index + 1, channel, questions, replys);
}).catch(err => {
if (err === "Self-Cancel") {
//user canceled
}
channel.send("Application Canceled");
});
}
client.on("message", async (msg) => {
if (!msg.content.startsWith(prefix) || msg.author.bot) return;
if (msg.channel.type === "dm") {
const args = msg.content.slice(prefix.length).split(/ +/);
const command = args.shift().toLowerCase();
const questions = ["Why do you want this?", "Question 2"];
if (command === "inquiry") {
sendNexQuestion(0, msg.channel, questions, []).then(replys => {
//array of replys
})
}
}
});
I'm trying to send a message to the first 5 people who react to the message, however it only sends a DM to the first person who reacted and does not allow anyone else to react or receive a DM.
How would I do this?
case 'await':
message.channel.sendMessage('React for dm').then(sentMessage => {
sentMessage.react('1️⃣').then(() => sentMessage.react('2️⃣'));
const filter = (reaction, user) => {
return ['1️⃣', '2️⃣'].includes(reaction.emoji.name);
};
sentMessage.awaitReactions(filter, {
max: 1,
time: 60000,
errors: ['time']
})
.then(collected => {
const reaction = collected.first();
if (reaction.emoji.name === '1️⃣') {
message.author.sendMessage('I told you I would!')
}
})
})
You have max: 1 That tells the collector to quit after it has successfully collected 1 reaction. You should set that to 5.
After that you need to loop through the collected to send a DM to all of them rather than using first().