There is actually a much simpler way of checking if a message contains emoji(s), and separating them from message content. (This is posted more for future viewers of this question, as opposed to the OP who has already solved their problem).
Though the accepted answer works for detecting unicode emotes, it uses an external package, is based on an outdated way of doing this from pre-ES6, and overcomplicates things in some ways. You can check if a string contains an emoji, whether unicode or custom discord format (including animated emotes), with a very simple regex. All on a single, succinct line of code.
const emotes = (str) => str.match(/<a?:.+?:\d{18}>|\p{Extended_Pictographic}/gu);
// TESTS:
console.log(emotes("No emotes here"))
// -> null
console.log(emotes("None here 1234 either"))
// -> null
console.log(emotes("One over here "))
// -> [""]
console.log(emotes("One over here also <:yea:123456789012345678>"))
// -> ["<:yea:123456789012345678>"]
console.log(emotes("Two over <a:yea:123456789012345678> here "))
// -> ["<a:yea:123456789012345678>", ""]
console.log(emotes("Three emotes here "))
// -> ["", "", ""]
This is how this emotes()
method could be used in generic djs code:
if (emotes(message.content)) {
// Do what you want with the emotes
message.reply(`The emotes found were: ${emotes(message.content).join(", ")}`);
}
I will also explain what the regex is doing here so it is understandable. The regex looks for two different scenarios: discord's custom emote format and unicode emotes.
Custom emotes look something like this: <:emotename:123456789012345678>
. They have the emoji's name between two colons, and the ID of the emoji after the last colon. Animated emotes follow the same format, except for an 'a'
added before the first colon: <a:emotename:123456789012345678>
. The first part of the regex (<a?:.+?:\d{18}>
) checks for these two discord custom emote cases. a?
matches 0 or 1 of 'a'
, meaning it will find both animated and unanimated emotes. .+?
matches any combination of characters, in between the two specified colons (representing the emote's name). \d{18}
matches exactly 18 numerical digits (representing the emote's ID).
Unicode emotes represent text emojis and discord's built-in emojis, and they look something like this:
. This was what the OP found challenging to detect in message content. But thanks to ES6, it is possible to match specific categories of unicode characters using regex (assuming you have the u
unicode flag added to your regex, in our case we have that and the g
global flag added). The second part of the regex (\p{Extended_Pictographic}
) matches this case. This matches any unicode character belonging to the category Extended_Pictographic
, or in other words all of the emote characters.
(Note: there actually is a Emote
category that can be used with \p{Emote}
, but this unfortunately matches plaintext numbers and some punctuation on top of all emotes. Extended_Pictographic
matches just the emotes.)
These two parts of the regex are combined with a |
, meaning anything that matches the first OR second regex will be returned in the results. So emotes()
will return an array of any unicode or custom discord emotes found in the provided string, or null
if none are found.