From 98d251b994a7d458553ab562ce8df933e627505b Mon Sep 17 00:00:00 2001 From: derpystuff <3515180-derpystuff@users.noreply.gitlab.com> Date: Mon, 25 Mar 2024 22:47:18 +0100 Subject: [PATCH] detailed emoji info --- commands/interaction/slash/utils/emoji.js | 11 +- commands/interaction/slash/utils/emojiinfo.js | 147 +++++++++++++++++ commands/message/utils/emoji.js | 9 - commands/message/utils/emojiinfo.js | 154 ++++++++++++++++++ labscore/api/index.js | 3 +- 5 files changed, 304 insertions(+), 20 deletions(-) create mode 100644 commands/interaction/slash/utils/emojiinfo.js create mode 100644 commands/message/utils/emojiinfo.js diff --git a/commands/interaction/slash/utils/emoji.js b/commands/interaction/slash/utils/emoji.js index 0d1cca6..03cbafd 100644 --- a/commands/interaction/slash/utils/emoji.js +++ b/commands/interaction/slash/utils/emoji.js @@ -31,7 +31,6 @@ function toCodePoint(unicodeSurrogates, sep) { return r.join(sep || '-'); } - module.exports = { name: 'emoji', description: 'Turn emoji into images. Supports both built-in and custom emoji.', @@ -150,9 +149,7 @@ module.exports = { if (ctx.userId !== context.userId) return await ctx.respond(InteractionCallbackTypes.DEFERRED_UPDATE_MESSAGE); // this sucks but works, ensures the newly selected option stays selected - // update 25/03/24 - it sucks even more now - console.log(ctx.data) - + // update 25/03/24 - it sucks even more now if(ctx.data.customId == "emoji-type"){ currentPlatform = ctx.data.values[0]; @@ -172,21 +169,17 @@ module.exports = { components.components[1].components[0].options = newVersionOptions - console.log("new type is " + currentPlatform + " with version " + currentRevision) } else if(ctx.data.customId == "emoji-version"){ for (let i = 0; i < components.components[1].components[0].options.length; i++) { components.components[1].components[0].options[i].default = (components.components[1].components[0].options[i].value == ctx.data.values[0]) } currentRevision = ctx.data.values[0]; - console.log("new version is " + currentRevision); } - console.log("getting asset for " + currentPlatform + " ver " + currentRevision); const emojiAsset = res.data.platforms[currentPlatform].images.filter((p)=>{ return p.id == currentRevision }) - console.log("got asset: " + emojiAsset) currentView = createEmbed("default", context, { author: { @@ -204,9 +197,7 @@ module.exports = { } }) - console.log("acknowledging for plat " + currentPlatform + " and ver " + currentRevision) await ctx.editOrRespond({embeds: [currentView], components}) - console.log("acknowledged") }, }); diff --git a/commands/interaction/slash/utils/emojiinfo.js b/commands/interaction/slash/utils/emojiinfo.js new file mode 100644 index 0000000..2e78eac --- /dev/null +++ b/commands/interaction/slash/utils/emojiinfo.js @@ -0,0 +1,147 @@ +const { InteractionCallbackTypes, MessageComponentButtonStyles, ApplicationCommandOptionTypes } = require("detritus-client/lib/constants"); +const { emojipedia } = require("../../../../labscore/api"); + +const { createEmbed } = require("../../../../labscore/utils/embed"); +const { pill } = require("../../../../labscore/utils/markdown"); +const { editOrReply } = require("../../../../labscore/utils/message"); +const { STATICS } = require("../../../../labscore/utils/statics"); +const { Components } = require("detritus-client/lib/utils"); + +const onlyEmoji = require('emoji-aware').onlyEmoji; + +function toCodePoint(unicodeSurrogates, sep) { + var + r = [], + c = 0, + p = 0, + i = 0; + while (i < unicodeSurrogates.length) { + c = unicodeSurrogates.charCodeAt(i++); + if (p) { + r.push((0x10000 + ((p - 0xD800) << 10) + (c - 0xDC00)).toString(16)); + p = 0; + } else if (0xD800 <= c && c <= 0xDBFF) { + p = c; + } else { + r.push(c.toString(16)); + } + } + return r.join(sep || '-'); +} + + +module.exports = { + name: 'emoji-info', + description: 'Shows detailed information about an emoji.', + contexts: [ + 0, + 1, + 2 + ], + integrationTypes: [ + 1 + ], + options: [ + { + name: 'emoji', + description: 'Emoji to enlarge. Use two built-in emoji to mix them.', + type: ApplicationCommandOptionTypes.TEXT, + required: true + } + ], + run: async (context, args) => { + await context.respond({data: {}, type: InteractionCallbackTypes.DEFERRED_CHANNEL_MESSAGE_WITH_SOURCE}) + + const emoji = onlyEmoji(args.emoji) + if(!emoji){ + return editOrReply(context, + createEmbed("warning", context, "No emoji found.") + ) + } + + // Regular Emoji Handling + if(emoji.length == 0) return await editOrReply(context, createEmbed("warning", context, "You need to specify an emoji to enlarge.")) + + let res; + try{ + res = await emojipedia(context, emoji[0]) + res = res.response.body + }catch(e){ + return await editOrReply(context, createEmbed("error", context, `No emoji data available for ${emoji[0]}.`)) + } + + + const components = new Components({ + timeout: 100000, + run: async (ctx) => { + if (ctx.userId !== context.userId) return await ctx.respond(InteractionCallbackTypes.DEFERRED_UPDATE_MESSAGE); + + let newView = await emojipedia(context, ctx.data.customId) + newView = newView.response.body + + ico = newView.data.platforms["twitter"].images[0].src + if(!newView.data.platforms["twitter"]) ico = Object.values(newView.data.platforms)[0].images[0].src + + currentView = createEmbed("default", context, { + author: { + iconUrl: ico, + name: `${newView.data.name} • Unicode ${newView.data.metadata.version.unicode}`, + url: newView.data.link + }, + description: newView.data.codes.map((c)=>pill(c)).join(' ') + "\n\n" + newView.data.metadata.description, + image: { + url: newView.data.platforms["twitter"].images[0].src + }, + footer: { + iconUrl: STATICS.emojipedia, + text: `Emojipedia • ${context.application.name}` + } + }) + + components.clear(); + for(const e of newView.data.metadata.similar.splice(0, 5)){ + components.addButton({ + customId: e, + emoji: e, + style: MessageComponentButtonStyles.SECONDARY + }) + } + + await ctx.editOrRespond({embeds: [currentView], components}) + } + }) + + for(const e of res.data.metadata.similar.splice(0, 5)){ + components.addButton({ + customId: e, + emoji: e, + style: MessageComponentButtonStyles.SECONDARY + }) + } + + // Use the high-res emojipedia icon, if available + let ico = `https://abs.twimg.com/emoji/v2/72x72/${toCodePoint(emoji[0])}.png` + if(!res.data.platforms["twitter"]) ico = Object.values(res.data.platforms)[0].images[0].src + + currentView = createEmbed("default", context, { + author: { + iconUrl: ico, + name: `${res.data.name} • Unicode ${res.data.metadata.version.unicode}`, + url: res.data.link + }, + description: res.data.codes.map((c)=>pill(c)).join(' ') + "\n\n" + res.data.metadata.description, + image: { + url: res.data.platforms["twitter"].images[0].src + }, + footer: { + iconUrl: STATICS.emojipedia, + text: `Emojipedia • ${context.application.name}` + } + }) + + return editOrReply(context, { + embeds: [currentView], + components + }) + } +}; \ No newline at end of file diff --git a/commands/message/utils/emoji.js b/commands/message/utils/emoji.js index cf99d9e..4fa7339 100644 --- a/commands/message/utils/emoji.js +++ b/commands/message/utils/emoji.js @@ -178,8 +178,6 @@ module.exports = { // this sucks but works, ensures the newly selected option stays selected // update 25/03/24 - it sucks even more now - console.log(ctx.data) - if(ctx.data.customId == "emoji-type"){ currentPlatform = ctx.data.values[0]; @@ -199,21 +197,16 @@ module.exports = { components.components[1].components[0].options = newVersionOptions - console.log("new type is " + currentPlatform + " with version " + currentRevision) } else if(ctx.data.customId == "emoji-version"){ - for (let i = 0; i < components.components[1].components[0].options.length; i++) { components.components[1].components[0].options[i].default = (components.components[1].components[0].options[i].value == ctx.data.values[0]) } currentRevision = ctx.data.values[0]; - console.log("new version is " + currentRevision); } - console.log("getting asset for " + currentPlatform + " ver " + currentRevision); const emojiAsset = res.data.platforms[currentPlatform].images.filter((p)=>{ return p.id == currentRevision }) - console.log("got asset: " + emojiAsset) currentView = createEmbed("default", context, { author: { @@ -231,9 +224,7 @@ module.exports = { } }) - console.log("acknowledging for plat " + currentPlatform + " and ver " + currentRevision) await ctx.editOrRespond({embeds: [currentView], components}) - console.log("acknowledged") }, }); diff --git a/commands/message/utils/emojiinfo.js b/commands/message/utils/emojiinfo.js new file mode 100644 index 0000000..55b1f2a --- /dev/null +++ b/commands/message/utils/emojiinfo.js @@ -0,0 +1,154 @@ +const { Constants, Utils } = require("detritus-client"); +const { Permissions, InteractionCallbackTypes, MessageComponentButtonStyles } = require("detritus-client/lib/constants"); +const { emojipedia, emojiKitchen } = require("../../../labscore/api"); + +const { EMOJIPEDIA_PLATFORM_TYPES, EMOJIPEDIA_PLATFORM_TYPE_ALIASES } = require("../../../labscore/constants"); +const { createEmbed } = require("../../../labscore/utils/embed"); +const { icon, pill, iconPill, highlight, timestamp, smallIconPill } = require("../../../labscore/utils/markdown"); +const { editOrReply } = require("../../../labscore/utils/message"); +const { STATICS } = require("../../../labscore/utils/statics"); +const { Components, Snowflake } = require("detritus-client/lib/utils"); +const { bold } = require("detritus-client/lib/utils/markup"); + +const onlyEmoji = require('emoji-aware').onlyEmoji; + +function toCodePoint(unicodeSurrogates, sep) { + var + r = [], + c = 0, + p = 0, + i = 0; + while (i < unicodeSurrogates.length) { + c = unicodeSurrogates.charCodeAt(i++); + if (p) { + r.push((0x10000 + ((p - 0xD800) << 10) + (c - 0xDC00)).toString(16)); + p = 0; + } else if (0xD800 <= c && c <= 0xDBFF) { + p = c; + } else { + r.push(c.toString(16)); + } + } + return r.join(sep || '-'); +} + +module.exports = { + label: "emoji", + name: "emojiinfo", + aliases: ['ei'], + metadata: { + description: `${smallIconPill("reply", "Supports Replies")}\n\nDisplays more detailed information about emoji. Only supports unicode emoji.`, + description_short: 'Detailed information about an emoji.', + examples: ['ei 😀'], + category: 'utils', + usage: 'emojiinfo ' + }, + permissionsClient: [Permissions.EMBED_LINKS, Permissions.SEND_MESSAGES, Permissions.READ_MESSAGE_HISTORY, Permissions.USE_EXTERNAL_EMOJIS], + run: async (context, args) => { + await context.triggerTyping() + let msg = context.message; + if (context.message.messageReference) { + msg = await context.message.channel.fetchMessage(context.message.messageReference.messageId) + args.emoji = msg.content + } + + const emoji = onlyEmoji(args.emoji) + if(!emoji){ + return editOrReply(context, + createEmbed("warning", context, "No emoji found.") + ) + } + + // Regular Emoji Handling + if(emoji.length == 0) return await editOrReply(context, createEmbed("warning", context, "You need to specify an emoji to enlarge.")) + + let res; + try{ + res = await emojipedia(context, emoji[0]) + res = res.response.body + }catch(e){ + return await editOrReply(context, createEmbed("error", context, `No emoji data available for ${emoji[0]}.`)) + } + + + const components = new Components({ + timeout: 100000, + run: async (ctx) => { + if (ctx.userId !== context.userId) return await ctx.respond(InteractionCallbackTypes.DEFERRED_UPDATE_MESSAGE); + + let newView = await emojipedia(context, ctx.data.customId) + newView = newView.response.body + + ico = newView.data.platforms["twitter"].images[0].src + if(!newView.data.platforms["twitter"]) ico = Object.values(newView.data.platforms)[0].images[0].src + + currentView = createEmbed("default", context, { + author: { + iconUrl: ico, + name: `${newView.data.name} • Unicode ${newView.data.metadata.version.unicode}`, + url: newView.data.link + }, + description: newView.data.codes.map((c)=>pill(c)).join(' ') + "\n\n" + newView.data.metadata.description, + image: { + url: newView.data.platforms["twitter"].images[0].src + }, + footer: { + iconUrl: STATICS.emojipedia, + text: `Emojipedia • ${context.application.name}` + } + }) + + components.clear(); + for(const e of newView.data.metadata.similar.splice(0, 5)){ + components.addButton({ + customId: e, + emoji: e, + style: MessageComponentButtonStyles.SECONDARY + }) + } + + await ctx.editOrRespond({embeds: [currentView], components}) + } + }) + + for(const e of res.data.metadata.similar.splice(0, 5)){ + components.addButton({ + customId: e, + emoji: e, + style: MessageComponentButtonStyles.SECONDARY + }) + } + + setTimeout(()=>{ + editOrReply(context, { + embeds:[currentView], + components:[] + }) + }, 100000) + + // Use the high-res emojipedia icon, if available + let ico = `https://abs.twimg.com/emoji/v2/72x72/${toCodePoint(emoji[0])}.png` + if(!res.data.platforms["twitter"]) ico = Object.values(res.data.platforms)[0].images[0].src + + currentView = createEmbed("default", context, { + author: { + iconUrl: ico, + name: `${res.data.name} • Unicode ${res.data.metadata.version.unicode}`, + url: res.data.link + }, + description: res.data.codes.map((c)=>pill(c)).join(' ') + "\n\n" + res.data.metadata.description, + image: { + url: res.data.platforms["twitter"].images[0].src + }, + footer: { + iconUrl: STATICS.emojipedia, + text: `Emojipedia • ${context.application.name}` + } + }) + + return editOrReply(context, { + embeds: [currentView], + components + }) + } +}; \ No newline at end of file diff --git a/labscore/api/index.js b/labscore/api/index.js index 8b7fdc7..1f58f00 100644 --- a/labscore/api/index.js +++ b/labscore/api/index.js @@ -306,7 +306,8 @@ module.exports.dictionary = async function(context, query, language){ module.exports.emojipedia = async function(context, emoji){ return await request(Api.UTILS_EMOJIPEDIA, "GET", {}, { - emoji: emoji + emoji: emoji, + with_metadata: "" }) }