I have been following the Worn Off Keys Discord.JS guide to get to know discord.js better, even though I understand JS fairly well. I got to a problem though when coding the reaction roles. I cloned the code for a special file from the WOK Discord JS repository. I usually clone the files and then adapt them to my liking, adding and removing some parts. But this time when I ran the code to test the basic clone out, I got an error saying TypeError [EMOJI_TYPE]: Emoji must be a string or GuildEmoji/ReactionEmoji
I couldn't find any place where I could fix this, as it worked in the tutorial video with the exact same code.
Here is my code for the special reaction roles file:
const firstMessage = require('./first-message')
module.exports = (client) => {
const channelId = '870818745109585920'
const getEmoji = (emojiName) => client.emojis.cache.find((emoji) => emoji.name === emojiName)
const emojis = {
red_circle: 'CrackShot / Sniper',
orange_circle: 'Scrambler / Shotgun',
yellow_circle: 'Whipper / P90',
green_circle: 'RPEGG / RPG',
blue_circle: 'Free Ranger / Semi-Auto',
purple_circle: 'EGG-K / AK-47',
white_circle: 'TriHard / AUG',
black_circle: 'Cluck-9mm / Pistol'
}
const reactions = []
let emojiText = '**GUN ROLES**\n\n'
for (const key in emojis) {
const emoji = getEmoji(key)
reactions.push(emoji)
const role = emojis[key]
emojiText += `${emoji} = ${role}\n`
}
firstMessage(client, channelId, emojiText, reactions)
const handleReaction = (reaction, user, add) => {
if (user.id === '869698265698947102') {
return
}
const emoji = reaction._emoji.name
const { guild } = reaction.message
const roleName = emojis[emoji]
if(!roleName) {
return
}
const role = guild.roles.cache.find((role) => role.name === roleName)
const member = guild.members.cache.find((member) => member.id === user.id)
if (add) {
member.roles.add(role)
} else {
member.roles.remove(role)
}
}
client.on('messageReactionAdd', (reaction, user) => {
if (reaction.message.channel.id === channelId) {
handleReaction(reaction, user, true)
}
})
client.on('messageReactionRemove', (reaction, user) => {
if (reaction.message.channel.id === channelId) {
handleReaction(reaction, user, false)
}
})
}
The first-message
file that you see there is:
const addReactions = (message, reactions) => {
message.react(reactions[0])
reactions.shift()
if (reactions.length > 0) {
setTimeout(() => addReactions(message, reactions), 750)
}
}
module.exports = async (client, id, text, reactions = []) => {
const channel = await client.channels.fetch(id)
channel.messages.fetch().then((messages) => {
if (messages.size === 0) {
channel.send(text).then((message) => {
addReactions(message, reactions)
})
} else {
for (const message of messages) {
message[1].edit(text)
addReactions(message[1], reactions)
}
}
})
}
And all I added from those files to the main index.js
file is const roleClaim = require('./role-claim')
and later inside the client.on(ready)
etc. part I added roleClaim(client)
to run the bot code. Any suggestions? Sorry for the giant amounts of text. Please help.
The problem is that you don't have emojis with names like red_circle
, orange_circle
, etc. client.emojis.cache
only contains custom emojis the bot has access to.
So, when you use getEmoji()
to get the emoji you'll receive undefined. You don't check the emoji
value inside that function and just add it to an array (reactions.push(emoji)
). Later, when you try to add the reaction (addReactions()
), you try to react with undefined
. As it's not an emoji, you receive the error.
A solution would be to use emojis available, and you could also simplify the for loop
let emojis = {
'🔴': 'CrackShot / Sniper',
'🟠': 'Scrambler / Shotgun',
'🟡': 'Whipper / P90',
'🟢': 'RPEGG / RPG',
'🔵': 'Free Ranger / Semi-Auto',
'🟣': 'EGG-K / AK-47',
};
let emojiText = '**GUN ROLES**\n\n';
let reactions = [];
Object.entries(emojis).forEach(([emoji, role]) => {
reactions.push(emoji);
emojiText += `${emoji} = ${role}\n`;
});
console.log(emojiText)
console.log(reactions)
module.exports = (client) => {
let channelId = '870818745109585920';
let emojis = {
'🔴': 'CrackShot / Sniper',
'🟠': 'Scrambler / Shotgun',
'🟡': 'Whipper / P90',
'🟢': 'RPEGG / RPG',
'🔵': 'Free Ranger / Semi-Auto',
'🟣': 'EGG-K / AK-47',
};
let reactions = [];
let emojiText = '**GUN ROLES**\n\n';
Object.entries(emojis).forEach(([emoji, role]) => {
reactions.push(emoji);
emojiText += `${emoji} = ${role}\n`;
});
firstMessage(client, channelId, emojiText, reactions);
function handleReaction(reaction, user, add) {
if (user.id === '869698265698947102') return;
let emoji = reaction._emoji.name;
let { guild } = reaction.message;
let roleName = emojis[emoji];
if (!roleName) return;
let role = guild.roles.cache.find((role) => role.name === roleName);
let member = guild.members.cache.find((member) => member.id === user.id);
// TODO: check if role and member exist
if (add) {
member.roles.add(role);
} else {
member.roles.remove(role);
}
}
client.on('messageReactionAdd', (reaction, user) => {
if (reaction.message.channel.id === channelId) {
handleReaction(reaction, user, true);
}
});
client.on('messageReactionRemove', (reaction, user) => {
if (reaction.message.channel.id === channelId) {
handleReaction(reaction, user, false);
}
});
};