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.
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
});
I have a suggest command and I'm trying to make it so that when i react with emoji "x" message get's deleted. Can someone help me?
owner.send(embed).then(m => {
m.react("✅")
m.react('❌')
})
To listen react change on message is sent you need to using createReactionCollector() guide here
This code is what you are looking for
Note: Your exec or run function must be async function
const newMsg = await owner.send(embed);
await newMsg.react('❌');
const filter = (reaction, user) => {
return user.id === msg.author.id; // Note msg is start commands message
};
let collector = await newMsg.createReactionCollector(filter, {
time: 30000,
});
collector.on('collect', async (r) => {
if (r.emoji.name ==='❌') {
collector.stop('delete');
await newMsg.delete();
}
});
How do I edit an embed field with discord.js?
execute(client, connection, message, args) {
message.channel.send(client.helpers.get('CreateEmptyEmbed').execute("Poll", client, false)
.setTitle('test')
.addField(`0`)
).then(embedMessage => {
embedMessage.react(`✅`)
embedMessage.react(`❎`)
})
client.on('messageReactionAdd', (reaction, user) => {
if (user.id === client.user.id) return // if reaction is == bot return
if (reaction.emoji.name == '✅') message.channel.send(reaction.count)
embed.editfield("hi")
})
Any help would be greatly appriciated.
First of all, client.on('messageReactionAdd') fires for all reactions, and doesn't stop, it keeps firing until you stop the bot, so you need to use a Reaction Collector and to edit embed, you need to change the embeds field and edit the message itself.
execute(client, connection, message, args) {
message.channel.send(client.helpers.get('CreateEmptyEmbed').execute("Poll", client, false)
.setTitle('test')
.addField(`0`)
).then(embedMessage => {
embedMessage.react(`✅`)
embedMessage.react(`❎`)
const filter = (reaction, user) => user.bot!; //Ignores bot reactions
collector = embedMessage.createReactionCollector(filter,{time:15000)) //The time parameter (in milliseconds) specified for how much time the reactionCollector collects reactions
collector.on('collect',(reaction,user)=>{ //When a reaction is collected
const embed = embedMessage.embeds[0] // Get the embed that you want to edit.
embed.fields[0] = {name : 'The name of the new field' , value : 'Value of new field'}
await embedMessage.edit(embed)
})
collector.on('end',()=>{ //When the time we specified earlier is over
//Do stuff
})
})
let filter = m => m.author.id === message.author.id // to ensure same author is responding
message.channel.send(embedMessage).then(() =>{
message.channel.awaitMessages(filter, { // after he sends a message to the same channel
// You can also use ".awaitReactions" if you want to wait for reactions on the message sent
max: 1,// maximum responses
time: 30000,// timeout for waiting
errors: ['time']// type of error
})
.then(message =>{
// do what everyou like with the response
})
.catch(error => console.log)
});
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
})
}
}
});