const discordEmoji = require('discord-emoji'); const emoji = {}; Object.values(discordEmoji).forEach(value => { Object.keys(value).forEach(key => { emoji[key] = value[key]; }); }); const mappings = { 'a': [':regional_indicator_a:', ':a:'], 'b': [':regional_indicator_b:', ':b:'], 'c': [':regional_indicator_c:'], 'd': [':regional_indicator_d:'], 'e': [':regional_indicator_e:'], 'f': [':regional_indicator_f:'], 'g': [':regional_indicator_g:', ':compression:'], 'h': [':regional_indicator_h:'], 'i': [':regional_indicator_i:', ':information_source:'], 'j': [':regional_indicator_j:'], 'k': [':regional_indicator_k:'], 'l': [':regional_indicator_l:'], 'm': [':regional_indicator_m:', ':m:'], 'n': [':regional_indicator_n:'], 'o': [':regional_indicator_o:', ':o2:', ':o:'], 'p': [':regional_indicator_p:', ':parking:'], 'q': [':regional_indicator_q:'], 'r': [':regional_indicator_r:'], 's': [':regional_indicator_s:'], 't': [':regional_indicator_t:', ':cross:'], 'u': [':regional_indicator_u:'], 'v': [':regional_indicator_v:'], 'w': [':regional_indicator_w:'], 'x': [':regional_indicator_x:', ':heavy_multiplication_x:', ':x:', ':negative_squared_cross_mark:'], 'y': [':regional_indicator_y:'], 'z': [':regional_indicator_z:'], '0': [':zero:'], '1': [':one:'], '2': [':two:'], '3': [':three:'], '4': [':four:'], '5': [':five:'], '6': [':six:'], '7': [':seven:'], '8': [':eight:'], '9': [':nine:'], '!': [':exclamation:', ':grey_exclamation:'], '?': [':question:', ':grey_question:'], '*': [':asterisk:', ':eight_spoked_asterisk:'], '#': [':hash:'], '$': [':heavy_dollar_sign:'] }; function clone(object) { const newObject = {}; Object.keys(object).forEach(key => { if (object[key] instanceof Array) { newObject[key] = new Array(...object[key]); } else { newObject[key] = object[key]; } }); return newObject; } function emojiToUnicode(input) { if (/^:regional_indicator_[a-z]:$/.test(input)) { return String.fromCharCode(55356) + String.fromCharCode(56806 + input.substr(20, 1).charCodeAt(0) - 97); } return emoji[input.slice(1, -1)]; } function react(message, remaining, allowedMappings) { if (remaining.length < 1) { // We're out of stuff return; } const char = remaining.shift().toLowerCase(); if (!char) { return; } if (!allowedMappings[char]) { // Not a usable char return; } const next = allowedMappings[char].shift(); if (!next) { // We have no more mappings available return; } message.react(emojiToUnicode(next)).then(() => { react(message, remaining, allowedMappings); }); } exports.run = async (client, message, args, level) => { if (args.length < 1) { await message.reply("you should actually try to tell me what I should react with...") message.delete(); client.user.lastMessage.delete(5000); } const fetchOptions = { limit: 1 }; if (args[1]) { if (!/\d{18}/.test(args[1])) { await message.reply(`${args[1]} isn't a valid message ID!`); message.delete(); client.user.lastMessage.delete(5000); } fetchOptions.around = args[1]; } else { fetchOptions.before = message.id; } message.channel.fetchMessages(fetchOptions).then(messages => { if (messages.length < 1) { return message.reply("I couldn't find the specified message."); } const target = messages.first(); const allowedMappings = clone(mappings); // Remove current reactions from allowed emojis target.reactions.forEach(reaction => { const emoji = reaction.toString(); for (const key in allowedMappings) { const index = allowedMappings[key].indexOf(emoji); if (index > -1) { allowedMappings[key].splice(index, 1); } } }); message.delete(); react(target, args[0].split(''), allowedMappings); }).catch(message.error); }; exports.conf = { enabled: true, guildOnly: false, aliases: [], permLevel: "User" }; exports.help = { name: "react", category: "Fun", description: "Reacts to the last sent message (or another message) with a given text; your response cannot contain spaces.", usage: "react [message ID]" };