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