diff --git a/src/plugins/expressionCloner/index.tsx b/src/plugins/expressionCloner/index.tsx index 57bde0457..60f148651 100644 --- a/src/plugins/expressionCloner/index.tsx +++ b/src/plugins/expressionCloner/index.tsx @@ -26,7 +26,7 @@ import { Devs } from "@utils/constants"; import { getGuildAcronym, hasGuildFeature } from "@utils/discord"; import { Logger } from "@utils/Logger"; import definePlugin from "@utils/types"; -import { Guild, GuildSticker } from "@vencord/discord-types"; +import { Guild, GuildSticker, Message } from "@vencord/discord-types"; import { StickerFormatType } from "@vencord/discord-types/enums"; import { findByCodeLazy } from "@webpack"; import { Constants, EmojiStore, FluxDispatcher, Forms, GuildStore, IconUtils, Menu, Modal, openModalLazy, PermissionsBits, PermissionStore, React, RestAPI, StickersStore, Toasts, Tooltip, UserStore } from "@webpack/common"; @@ -366,18 +366,31 @@ function isGifUrl(url: string) { return u.pathname.endsWith(".gif") || u.searchParams.get("animated") === "true"; } -const messageContextMenuPatch: NavContextMenuPatchCallback = (children, props) => { - const { favoriteableId, itemHref, itemSrc, favoriteableType } = props ?? {}; +function resolveEmojiName(favoriteableId: string, message: Message) { + const emoji = EmojiStore.getCustomEmojiById(favoriteableId); + if (emoji) return emoji.name; + + const reaction = message.reactions.find(reaction => reaction.emoji.id === favoriteableId); + if (reaction) return reaction.emoji.name; + + const match = message.content.match(RegExp(`|https://cdn\\.discordapp\\.com/emojis/${favoriteableId}\\.[\\w?&=%]*`)); + if (!match) return null; + + return match[1] + ?? URL.parse(match[0])?.searchParams.get("name") + ?? "FakeNitroEmoji"; +} + +const messageContextMenuPatch: NavContextMenuPatchCallback = (children, props: Record<"favoriteableId" | "itemHref" | "itemSrc" | "favoriteableType", string> & { message: Message; }) => { + const { favoriteableId, itemHref, itemSrc, favoriteableType, message } = props ?? {}; if (!favoriteableId) return; const menuItem = (() => { switch (favoriteableType) { case "emoji": - const match = props.message.content.match(RegExp(`|https://cdn\\.discordapp\\.com/emojis/${favoriteableId}\\.`)); - const reaction = props.message.reactions.find(reaction => reaction.emoji.id === favoriteableId); - if (!match && !reaction) return; - const name = (match && match[1]) ?? reaction?.emoji.name ?? "FakeNitroEmoji"; + const name = resolveEmojiName(favoriteableId, message); + if (!name) return; return buildMenuItem("Emoji", () => ({ id: favoriteableId, @@ -385,7 +398,7 @@ const messageContextMenuPatch: NavContextMenuPatchCallback = (children, props) = isAnimated: isGifUrl(itemHref ?? itemSrc) })); case "sticker": - const sticker = props.message.stickerItems.find(s => s.id === favoriteableId); + const sticker = message.stickerItems.find(s => s.id === favoriteableId); if (sticker?.format_type === 3 /* LOTTIE */) return; return buildMenuItem("Sticker", () => fetchSticker(favoriteableId)); @@ -419,7 +432,7 @@ export default definePlugin({ description: "Allows you to clone Emotes & Stickers to your own server (right click them)", tags: ["Emotes", "Servers"], searchTerms: ["StickerCloner", "EmoteCloner", "EmojiCloner"], - authors: [Devs.Ven, Devs.Nuckyz], + authors: [Devs.Ven, Devs.Nuckyz, Devs.scattagain], contextMenus: { "message": messageContextMenuPatch, "expression-picker": expressionPickerPatch diff --git a/src/utils/constants.ts b/src/utils/constants.ts index 160408c53..28a0efd8b 100644 --- a/src/utils/constants.ts +++ b/src/utils/constants.ts @@ -666,6 +666,10 @@ export const Devs = /* #__PURE__*/ Object.freeze({ name: "yuna0x0", id: 213656926414831616n }, + scattagain: { + name: "Amelia", + id: 1098234477626544180n + }, Davri: { name: "Davri", id: 457579346282938368n