ExpressionCloner: improve FakeNitro emoji handling (#4526)

Co-authored-by: Vendicated <vendicated@riseup.net>
This commit is contained in:
Scatt 2026-09-28 03:43:59 +04:00 • committed by GitHub
parent a581197a27
commit 4e4cdedae4
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 26 additions and 9 deletions

View file

@ -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(`<a?:(\\w+)(?:~\\d+)?:${favoriteableId}>|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(`<a?:(\\w+)(?:~\\d+)?:${favoriteableId}>|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

View file

@ -666,6 +666,10 @@ export const Devs = /* #__PURE__*/ Object.freeze({
name: "yuna0x0",
id: 213656926414831616n
},
scattagain: {
name: "Amelia",
id: 1098234477626544180n
},
Davri: {
name: "Davri",
id: 457579346282938368n