I'm trying to write a discord bot, right now it's a command to get married.
Everything works as it should, except for one thing. In the awaitReactions function, I have a time of 10 seconds, and after this time I get this error:
node:internal/process/promises:246
triggerUncaughtException(err, true /* fromPromise */);
[UnhandledPromiseRejection: This error originated either by throwing inside of a
n async function without a catch block, or by rejecting a promise which was not
handled with .catch(). The promise rejected with the reason "#".] {
code: 'ERR_UNHANDLED_REJECTION'
}
I can't understand why this is happening, I have .catch() at the end of the function and in theory everything should work as it should.
Why doesn't .catch() work in my case? What could be the problem?
const { Command } = require('discord.js-commando');
const db = require("quick.db");
module.exports = class MarryCommand extends Command {
constructor(client) {
super(client, {
name: 'marry',
memberName: 'marry',
group: 'test',
description: 'Marry the mentioned user',
guildOnly: true,
args: [
{
key: 'userToMarry',
prompt: 'Please select the member you wish to marry.',
type: 'member'
}
]
});
}
run(message, { userToMarry }) {
const exists = db.get(`${message.author.id}.user`);
const married = db.get(`${userToMarry.id}.user`);
if (!userToMarry) {
return message.channel.send('Please try again with a valid user.')}
if (exists == message.author.id) {
return message.channel.send('You are already married!')}
if (married == userToMarry.id) {
return message.channel.send('This user is already married!')}
if (userToMarry.id == message.author.id) {
return message.channel.send('You cannot marry yourself!');
}
if (exists != message.author.id && married != userToMarry.id) {
message.channel.send(`**Important announcement!**
${message.author} makes a marriage proposal ${userToMarry}
Are you ready to get married?`).then(message => {
message.react('π').then(() => message.react('π'));
message.awaitReactions((reaction, user) => user.id == userToMarry.id && (reaction.emoji.name == 'π' || reaction.emoji.name == 'π'),
{ max: 1, time: 10000, errors: ['time'] })
.then(collected => {
const reaction = collected.first();
if (reaction.emoji.name === 'π') {
return message.channel.send('I think **no**...')}
if (reaction.emoji.name === 'π') {
db.set(message.author.id, { user: message.author.id, partner: userToMarry.id });
db.set(userToMarry.id, { user: userToMarry.id, partner: message.author.id });
message.channel.send(`${message.author} and ${userToMarry} now married!!`)
.catch(() => {
message.reply('No reaction after 10 seconds, operation canceled');
});
}
});
});
}}};
The mistake here is that every then chain should have a catch block. You have missed two catch blocks. The solution is to either add the catch blocks to all the then chains or you can connect all then chains into one big chain and finally use one catch block
Method 1
const { Command } = require("discord.js-commando");
const db = require("quick.db");
module.exports = class MarryCommand extends Command {
constructor(client) {
super(client, {
name: "marry",
memberName: "marry",
group: "test",
description: "Marry the mentioned user",
guildOnly: true,
args: [
{
key: "userToMarry",
prompt: "Please select the member you wish to marry.",
type: "member",
},
],
});
}
run(message, { userToMarry }) {
const exists = db.get(`${message.author.id}.user`);
const married = db.get(`${userToMarry.id}.user`);
if (!userToMarry) {
return message.channel.send("Please try again with a valid user.");
}
if (exists == message.author.id) {
return message.channel.send("You are already married!");
}
if (married == userToMarry.id) {
return message.channel.send("This user is already married!");
}
if (userToMarry.id == message.author.id) {
return message.channel.send("You cannot marry yourself!");
}
if (exists != message.author.id && married != userToMarry.id) {
message.channel
.send(
`**Important announcement!**
${message.author} makes a marriage proposal ${userToMarry}
Are you ready to get married?`
)
.then((message) => {
message.react("π")
.then(() => message.react("π"))
.catch(()=>{
//code
});
message.awaitReactions((reaction, user) =>
user.id == userToMarry.id && (reaction.emoji.name == "π" || reaction.emoji.name == "π"),
{ max: 1, time: 10000, errors: ["time"] }
).then((collected) => {
const reaction = collected.first();
if (reaction.emoji.name === "π") {
return message.channel.send("I think **no**...");
}
if (reaction.emoji.name === "π") {
db.set(message.author.id, {
user: message.author.id,
partner: userToMarry.id,
});
db.set(userToMarry.id, {
user: userToMarry.id,
partner: message.author.id,
});
message.channel
.send(`${message.author} and ${userToMarry} now married!!`)
.catch(() => {
message.reply(
"No reaction after 10 seconds, operation canceled"
);
});
}
}).catch(()=>{
//code
});
}).catch(()=>{
//code
});
}
}
};
Method 2
const { Command } = require("discord.js-commando");
const db = require("quick.db");
module.exports = class MarryCommand extends Command {
constructor(client) {
super(client, {
name: "marry",
memberName: "marry",
group: "test",
description: "Marry the mentioned user",
guildOnly: true,
args: [
{
key: "userToMarry",
prompt: "Please select the member you wish to marry.",
type: "member",
},
],
});
}
run(message, { userToMarry }) {
const exists = db.get(`${message.author.id}.user`);
const married = db.get(`${userToMarry.id}.user`);
if (!userToMarry) {
return message.channel.send("Please try again with a valid user.");
}
if (exists == message.author.id) {
return message.channel.send("You are already married!");
}
if (married == userToMarry.id) {
return message.channel.send("This user is already married!");
}
if (userToMarry.id == message.author.id) {
return message.channel.send("You cannot marry yourself!");
}
if (exists != message.author.id && married != userToMarry.id) {
message.channel
.send(
`**Important announcement!**
${message.author} makes a marriage proposal ${userToMarry}
Are you ready to get married?`
)
.then((message) => {
message.react("π")
.then(() => message.react("π"))
.catch(()=>{
//code
});
return message.awaitReactions((reaction, user) =>
user.id == userToMarry.id && (reaction.emoji.name == "π" || reaction.emoji.name == "π"),
{ max: 1, time: 10000, errors: ["time"] }
)
})
.then((collected) => {
const reaction = collected.first();
if (reaction.emoji.name === "π") {
return message.channel.send("I think **no**...");
}
if (reaction.emoji.name === "π") {
db.set(message.author.id, {
user: message.author.id,
partner: userToMarry.id,
});
db.set(userToMarry.id, {
user: userToMarry.id,
partner: message.author.id,
});
return message.channel
.send(`${message.author} and ${userToMarry} now married!!`)
}
})
.catch(()=>{
message.reply(
"No reaction after 10 seconds, operation canceled"
);
});
}
}
};
Related
Entire file below. I've been trying for an ungodly amount of time to get a reaction roles command working. Currently using MongoDB and everything is setup properly no errors my schema has worked properly as well there are no issues. Despite everything working I cannot get my event to fire at all with multiple revisions. Any help would be phenomenal on this one as I am too new to all of this to figure it out for myself...
const Schema = require('../reactions');
const Discord = require('discord.js');
const { client, intents } = require('..')
module.exports = {
name: 'messageReactionAdd',
run: async (reaction, message, user) => {
if (reaction.message.partial) await reaction.message.fetch();
if (reaction.partial) await reaction.fetch();
const { guild } = reaction.message;
if (!guild) return;
if (!guild.me.permissions.has("MANAGE_ROLES")) return;
isEmoji = function(emoji) {
const e = Discord.Util.parseEmoji(emoji);
if (e.id === null) {
return {
name: e.name,
id: e.id,
animated: e.animated,
response: false
}
} else {
return {
name: e.name,
id: e.id,
animated: e.animated,
response: true
}
}
}
const member = guild.members.cache.get(user.id);
await Schema.findOne({
guild_id: guild.id,
msg_id: reaction.message.id
}, async (err, db) => {
if (!db) return;
if (reaction.message.id != db.msg_id) return;
const data = db.rcs;
for (let i in data) {
if (reaction.emoji.id === null) {
if (reaction.emoji.name === data[i].emoji) {
member.roles.add(data[i].roleId, ['reaction role']).catch(err => console.log(err));
}
} else {
if (reaction.emoji.id === data[i].emoji) {
member.roles.add(data[i].roleId, ['reaction role']).catch(err => console.log(err));
}
}
}
});
},
};```
Intents
You need the GUILD_MESSAGE_REACTIONS in your client
I am coding a !ticket command and cannot handle allowing members without any permissions to react β.
Code
module.exports = {
name: "ticket",
slash: true,
aliases: [],
permissions: [],
description: "open a ticket!",
async execute(client, message, args) {
let chanel = message.guild.channels.cache.find(c => c.name === `ticket-${(message.author.username).toLowerCase()}`);
if (chanel) return message.channel.send('You already have a ticket open.');
const channel = await message.guild.channels.create(`ticket-${message.author.username}`)
channel.setParent("837065612546539531");
channel.updateOverwrite(message.guild.id, {
SEND_MESSAGE: false,
VIEW_CHANNEL: false,
});
channel.updateOverwrite(message.author, {
SEND_MESSAGE: true,
VIEW_CHANNEL: true,
});
const reactionMessage = await channel.send(`${message.author}, welcome to your ticket!\nHere you can:\n:one: Report an issue or bug of the server.\n:two: Suggest any idea for the server.\n:three: Report a staff member of the server.\n\nMake sure to be patient, support will be with you shortly.\n<#&837064899322052628>`)
try {
await reactionMessage.react("π");
await reactionMessage.react("β");
} catch (err) {
channel.send("Error sending emojis!");
throw err;
}
const collector = reactionMessage.createReactionCollector(
(reaction, user) => message.guild.members.cache.find((member) => member.id === user.id).hasPermission("ADMINISTRATOR"),
{ dispose: true }
);
collector.on("collect", (reaction, user) => {
switch (reaction.emoji.name) {
case "π":
channel.updateOverwrite(message.author, { SEND_MESSAGES: false });
break;
case "β":
channel.send("Deleting this ticket in 5 seconds...");
setTimeout(() => channel.delete(), 5000);
break;
}
});
message.channel
.send(`We will be right with you! ${channel}`)
.then((msg) => {
setTimeout(() => msg.delete(), 7000);
setTimeout(() => message.delete(), 3000);
})
.catch((err) => {
throw err;
});
},
};
It is related to the following part of the code.
const collector = reactionMessage.createReactionCollector(
(reaction, user) => message.guild.members.cache.find((member) => member.id === user.id).hasPermission("ADMINISTRATOR"),
{ dispose: true }
);
I want it to allow lock the ticket for administrators, and allow to close for everyone.
Not sure if I understand you correctly, but it seems you have two reactions and only want admins to use the π, and both admins and the original author to use the β.
Your current code only collects reactions from members who have ADMINISTRATOR permissions. You should change the filter to also collect reactions from the member who created the ticket.
The following filter does exactly that.
const filter = (reaction, user) => {
const isOriginalAuthor = message.author.id === user.id;
const isAdmin = message.guild.members.cache
.find((member) => member.id === user.id)
.hasPermission('ADMINISTRATOR');
return isOriginalAuthor || isAdmin;
}
There are other errors in your code, like there is no SEND_MESSAGE flag, only SEND_MESSAGES. You should also use more try-catch blocks to catch any errors.
It's also a good idea to explicitly allow the bot to send messages in the newly created channel. I use overwritePermissions instead of updateOverwrite. It allows you to use an array of overwrites, so you can update it with a single method.
To solve the issue with the lock emoji... I check the permissions of the member who reacted with a π, and if it has no ADMINISTRATOR, I simply delete their reaction using reaction.users.remove(user).
Check out the working code below:
module.exports = {
name: 'ticket',
slash: true,
aliases: [],
permissions: [],
description: 'open a ticket!',
async execute(client, message, args) {
const username = message.author.username.toLowerCase();
const parentChannel = '837065612546539531';
const ticketChannel = message.guild.channels.cache.find((ch) => ch.name === `ticket-${username}`);
if (ticketChannel)
return message.channel.send(`You already have a ticket open: ${ticketChannel}`);
let channel = null;
try {
channel = await message.guild.channels.create(`ticket-${username}`);
await channel.setParent(parentChannel);
await channel.overwritePermissions([
// disable access to everyone
{
id: message.guild.id,
deny: ['SEND_MESSAGES', 'VIEW_CHANNEL'],
},
// allow access for the one opening the ticket
{
id: message.author.id,
allow: ['SEND_MESSAGES', 'VIEW_CHANNEL'],
},
// make sure the bot can also send messages
{
id: client.user.id,
allow: ['SEND_MESSAGES', 'VIEW_CHANNEL'],
},
]);
} catch (error) {
console.log(error);
return message.channel.send('β οΈ Error creating ticket channel!');
}
let reactionMessage = null;
try {
reactionMessage = await channel.send(
`${message.author}, welcome to your ticket!\nHere you can:\n:one: Report an issue or bug of the server.\n:two: Suggest any idea for the server.\n:three: Report a staff member of the server.\n\nMake sure to be patient, support will be with you shortly.\n<#&837064899322052628>`,
);
} catch (error) {
console.log(error);
return message.channel.send(
'β οΈ Error sending message in ticket channel!',
);
}
try {
await reactionMessage.react('π');
await reactionMessage.react('β');
} catch (err) {
console.log(err);
return channel.send('β οΈ Error sending emojis!');
}
const collector = reactionMessage.createReactionCollector(
(reaction, user) => {
// collect only reactions from the original
// author and users w/ admin permissions
const isOriginalAuthor = message.author.id === user.id;
const isAdmin = message.guild.members.cache
.find((member) => member.id === user.id)
.hasPermission('ADMINISTRATOR');
return isOriginalAuthor || isAdmin;
},
{ dispose: true },
);
collector.on('collect', (reaction, user) => {
switch (reaction.emoji.name) {
// lock: admins only
case 'π':
const isAdmin = message.guild.members.cache
.find((member) => member.id === user.id)
.hasPermission('ADMINISTRATOR');
if (isAdmin) {
channel.updateOverwrite(message.author, {
SEND_MESSAGES: false,
});
} else {
// if not an admin, just remove the reaction
// like nothing's happened
reaction.users.remove(user);
}
break;
// close: anyone i.e. any admin and the member
// created the ticket
case 'β':
channel.send('Deleting this ticket in 5 seconds...');
setTimeout(() => channel.delete(), 5000);
break;
}
});
try {
const msg = await message.channel.send(`We will be right with you! ${channel}`);
setTimeout(() => msg.delete(), 7000);
setTimeout(() => message.delete(), 3000);
} catch (error) {
console.log(error);
}
},
};
I'm trying to have a bot react when users click the emojis on the bot's embeds.
I'm receiving in the console:
UnhandledPromiseRejectionWarning: TypeError: chestEmbed.awaitReactions
is not a function
The code:
module.exports = {
name: 'enterhouse',
aliases: 'eh',
permissions: ["ADMINISTRATOR", "MANAGE_MESSAGES", "CONNECT"],
description: "Pick a number",
async execute(client, message, args, Discord){
const chestEmbed = new MessageEmbed()
.setColor('#FFA500')
.setImage('https://imageURL.jpg');
message.channel.send(chestEmbed).then(chestEmbed => {chestEmbed.react('1οΈβ£').then(() => chestEmbed.react('2οΈβ£').then(() => chestEmbed.react('3οΈβ£')))}
)
.catch(() => console.error('One of the emojis failed to react.'));
const filter = (reaction, user) => {
return (['1οΈβ£', '2οΈβ£', '3οΈβ£'].includes(reaction.emoji.name) && user.id === message.author.id);
};
chestEmbed.awaitReactions(filter, { max: 1, time: 60000, errors: ['time'] })
.then(collected => {
const reaction = collected.first();
if (reaction.emoji.name === '1οΈβ£') {
chestEmbed.delete();
message.reply('you reacted with 1');
} else if (reaction.emoji.name === '2οΈβ£') {
message.reply('you reacted with 2');
} else {
message.reply('you reacted with 3');
}
})
.catch(collected => {
message.reply('Time is up, you did not react.');
});
}
}
It worked fine when it was message.awaitReactions instead.
Any help is really appreciated!
You are awaiting messages from the embed it's self not the message the embed is in.
Simple fix:
...
chestEmbed = await message.channel.send(chestEmbed)
...
Full Code:
module.exports = {
name: 'enterhouse',
aliases: 'eh',
permissions: ["ADMINISTRATOR", "MANAGE_MESSAGES", "CONNECT"],
description: "Pick a number",
async execute(client, message, args, Discord) {
const chestEmbed = new MessageEmbed()
.setColor('#FFA500')
.setImage('https://imageURL.jpg');
chestEmbed = await message.channel.send(chestEmbed)
chestEmbed.react('1οΈβ£').then(() => chestEmbed.react('2οΈβ£')).then(() => chestEmbed.react('3οΈβ£'))
const filter = (reaction, user) => {
return (['1οΈβ£', '2οΈβ£', '3οΈβ£'].includes(reaction.emoji.name) && user.id === message.author.id);
};
chestEmbed.awaitReactions(filter, { max: 1, time: 60000, errors: ['time'] })
.then(collected => {
const reaction = collected.first();
if (reaction.emoji.name === '1οΈβ£') {
chestEmbed.delete();
message.reply('you reacted with 1');
} else if (reaction.emoji.name === '2οΈβ£') {
message.reply('you reacted with 2');
} else {
message.reply('you reacted with 3');
}
})
.catch(collected => {
message.reply('Time is up, you did not react.');
});
}
}
my filter doesn't work. I want, filter OUT if the bot reacts and if the channel isn't same as bot's, but it filters out all other reactions. If other member (without bot) is in the channel and probably isn't bot, it will filter out the reaction.
I hope you find what you need in my code, and help me :)
pauseFalse(True)Reactions is array, serverQueue is JSON object, song is string
var filter = (reaction, user) => {
return pauseFalseReactions.includes(reaction.emoji.name) && message.guild.member(user.id).voice.channel == message.guild.member(botID).voice.channel && user.id != botID && user != bot.user;
};
awaitReact(message, filter, 1, Number(song.secs), pauseFalseReactions, serverQueue);
function awaitReact(message, filter, max, time, reactions, serverQueue) {
message.awaitReactions(filter, { max: max, time: time, errors: ['time'] })
.then(collected => {
const reaction = collected.first();
if (reaction.emoji.name == 'βΈ' && reactions.includes('βΈ')) {
Guild.findOneAndUpdate({
guildID: message.guild.id
}, {
musicBotPaused: true,
musicBotPlaying: false
}, function (err, result) {
if (err) {
return console.error(err);
}
});
serverQueue.connection.dispatcher.pause();
var newFilter = (reaction, user) => {
return pauseTrueReactions.includes(reaction.emoji.name) && message.guild.member(user.id).voice.channel == message.guild.member(botID).voice.channel && user.id != botID && user != bot.user;
};
message.reactions.removeAll().catch(error => console.error(error));
addReactions(message, pauseTrueReactions);
awaitReact(message, newFilter, max, (time + 250), pauseTrueReactions, serverQueue);
} else if (reaction.emoji.name == 'βΆοΈ' && reactions.includes('βΆοΈ')) {
Guild.findOneAndUpdate({
guildID: message.guild.id
}, {
musicBotPaused: false,
musicBotPlaying: true
}, function (err, result) {
if (err) {
return console.error(err);
}
});
serverQueue.connection.dispatcher.pause();
var newFilter = (reaction, user) => {
return pauseFalseReactions.includes(reaction.emoji.name) && message.guild.member(user.id).voice.channel == message.guild.member(botID).voice.channel && user.id != botID && user != bot.user;
};
message.reactions.removeAll().catch(error => console.error(error));
addReactions(message, pauseFalseReactions);
awaitReact(message, newFilter, max, (time + 250), pauseFalseReactions, serverQueue);
} else if (reaction.emoji.name == 'β') {
if (!serverQueue) {
const Embed = new Discord.MessageEmbed()
.setColor('#ff9745')
.setURL('https://discord.js.org/')
.setAuthor('Zigger', 'https://cdn.discordapp.com/app-icons/763859712340262972/010d590a764af0c59b999ad024cf89cb.png?size=128')
.setDescription('Ve frontΔ nic nenΓ.');
return message.channel.send(Embed);
}
message.channel.send(':fast_forward: **PΕeskoΔeno** :thumbsup:');
serverQueue.connection.dispatcher.end();
} else if (reaction.emoji.name == 'βΉ') {
if (serverQueue) {
serverQueue.connection.dispatcher.end();
queue.delete(message.guild.id);
}
message.channel.send(':stop_button: **Zastaveno!** :thumbsup:');
}
})
.catch(user => {
if (user.id != botID || user != bot.user) {
return;
} else {
message.reactions.removeAll().catch(error => console.error(error));
}
});
}
This will always be false:
message.guild.member(user.id).voice.channel == message.guild.member(botID).voice.channel
Use
message.guild.member(user.id).voice.channelID == message.guild.member(botID).voice.channelID
My problem is I want to delete d_msg after the reaction of the user. But it forgets what d_msg is and can't delete it. How can I fix it?
function English(thechannel, message) {
client.channels.cache.get(thechannel).send("Do u speak English?").then(d_msg => {
d_msg.react("β
");
d_msg.react("β");
client.on('messageReactionAdd', async (reaction, user) => {
if (user.tag === theuser) {
if (reaction.emoji.name === 'β
') {
var role = message.guild.roles.cache.find(role => role.name === "English");
message.member.roles.add(role);
}
}
d_msg.delete();
});
});
}
const Filter = (reaction, user) => {return (reaction.emoji.name == "β
" || reaction.emoji.name == "β") && user.id == message.author.id};
message.reply("Do you speak English? \n\n *This prompt will disappear in 30 seconds.*").then(async messageSent => {
await messageSent.react("β
");
await messageSent.react("β");
messageSent.awaitReactions(Filter, {max: 1, time: 30000, errors: ["time"]}).then(collected => {
messageSent.reactions.removeAll();
if (collected.first().emoji.name == "β
") {
messageSent.edit("You do speak English!");
} else if (collected.first().emoji.name == "β") {
messageSent.edit("You do not speak English!");
}
}).catch(e => {
messageSent.edit("This prompt expired.");
messageSent.reactions.removeAll();
});
});