A Guide to Discord Bots
Awaiting Messages & Reactions
I want the user to confirm that he wants to execute a part of code.
Thankfully, we have channel.awaitMessages() and message.awaitReactions().
This is just an example but can be used in many other ways!
Be creative ^.^
Awaiting Messages
client.on('message', message => {
// Command handler, seen previously
switch (command) {
case 'shutdown': {
message.reply('The bot will now shut down.\n'
+ 'Confirm with `yes` or deny with `no`.');
// First argument is a filter function - which is made of conditions
// m is a 'Message' object
message.channel.awaitMessages(m => m.author.id == message.author.id,
{max: 1, time: 30000}).then(collected => {
// only accept messages by the user who sent the command
// accept only 1 message, and return the promise after 30000ms = 30s
// first (and, in this case, only) message of the collection
if (collected.first().content.toLowerCase() == 'yes') {
message.reply('Shutting down...');
client.destroy();
}
else
message.reply('Operation canceled.');
}).catch(() => {
message.reply('No answer after 30 seconds, operation canceled.');
});
break;
}
}
});
Awaiting Reactions
client.on('message', message => {
// Command handler, seen previously
switch (command) {
case 'shutdown': {
message.reply('The bot will now shut down.\n'
+ 'Confirm with a thumb up or deny with a thumb down.');
// Reacts so the user only have to click the emojis
message.react('👍').then(r => {
message.react('👎');
});
// First argument is a filter function
message.awaitReactions((reaction, user) => user.id == message.author.id && (reaction.emoji.name == '👍' || reaction.emoji.name == '👎'),
{ max: 1, time: 30000 }).then(collected => {
if (collected.first().emoji.name == '👍') {
message.reply('Shutting down...');
client.destroy();
}
else
message.reply('Operation canceled.');
}).catch(() => {
message.reply('No reaction after 30 seconds, operation canceled');
});
break;
}
}
});
The Reaction object.
To get emoji's name, you can use the emoji with \
before it, on any Discord text channel.\:thumbsup: \:thumbsdown:
will output 👍 👎
.
Note: this doesn't always work, so you could use console.log(collected.first().emoji.name)
to get the name instead.
Why not use events instead?
For this example, it could be harder to use client.on('message')
, and you should know how to use it by now.
BUT we could use client.on('messageReactionAdd')
for other cases.
Let's take another example: we have a unique message that users can react to, to get (or remove) a role.
// We'll call it 'reaction' for short, but it is actually a 'MessageReaction' object
client.on('messageReactionAdd', (reaction, user) => {
let message = reaction.message, emoji = reaction.emoji;
if (emoji.name == '✅') {
// We don't have the member, but only the user...
// Thanks to the previous part, we know how to fetch it
message.guild.fetchMember(user.id).then(member => {
member.addRole('role_id');
});
}
else if (emoji.name == '❎') {
message.guild.fetchMember(user.id).then(member => {
member.removeRole('role_id');
});
}
// Remove the user's reaction
reaction.remove(user);
});
The messageReactionAdd event, the MessageReaction object.
Done!... Restart the bot, and you can now cl- oh. It stopped working.
Discord.js caches messages when they are created only.
If it already exists, and it's not in cache, we have to fetch it using channel.fetchMessage() (or fetchMessages() if we're working with multiple messages).
client.on('ready', () => {
client.guilds.get('guild_id').channels.get('channel_id').fetchMessage('message_id');
/* We could use .then() here but we don't need the returning promise in this case
This will just cache the specified message, to make sure
that 'messageReactionAdd' will always get called */
});
// Same code as above
client.on('messageReactionAdd', (reaction, user) => {
let message = reaction.message, emoji = reaction.emoji;
if (emoji.name == '✅') {
// We don't have the member, but only the user...
// Thanks to the previous part, we know how to fetch it
message.guild.fetchMember(user.id).then(member => {
member.addRole('role_id');
});
}
else if (emoji.name == '❎') {
message.guild.fetchMember(user.id).then(member => {
member.removeRole('role_id');
});
}
// Remove the user's reaction
reaction.remove(user);
});