diff --git a/packages/discord-types/src/common/Guild.d.ts b/packages/discord-types/src/common/Guild.d.ts index 5b5c3c745..65e973ffe 100644 --- a/packages/discord-types/src/common/Guild.d.ts +++ b/packages/discord-types/src/common/Guild.d.ts @@ -47,7 +47,7 @@ export class Guild extends DiscordRecord { }; premiumProgressBarEnabled: boolean; premiumSubscriberCount: number; - premiumTier: number; + premiumTier: 0 | 1 | 2 | 3; profile: { badge: string | undefined; tag: string | undefined; diff --git a/src/plugins/expressionCloner/index.tsx b/src/plugins/expressionCloner/index.tsx index 45022e604..11a596bb8 100644 --- a/src/plugins/expressionCloner/index.tsx +++ b/src/plugins/expressionCloner/index.tsx @@ -26,6 +26,7 @@ import { Margins } from "@utils/margins"; import { ModalContent, ModalHeader, ModalRoot, openModalLazy } from "@utils/modal"; import definePlugin from "@utils/types"; import { Guild, GuildSticker } from "@vencord/discord-types"; +import { StickerFormatType } from "@vencord/discord-types/enums"; import { findByCodeLazy } from "@webpack"; import { Constants, EmojiStore, FluxDispatcher, Forms, GuildStore, IconUtils, Menu, PermissionsBits, PermissionStore, React, RestAPI, StickersStore, Toasts, Tooltip, UserStore } from "@webpack/common"; import { Promisable } from "type-fest"; @@ -47,13 +48,32 @@ interface Emoji { type Data = Emoji | Sticker; -const StickerExt = [, "png", "png", "json", "gif"] as const; +const StickerExtMap = { + [StickerFormatType.PNG]: "png", + [StickerFormatType.APNG]: "png", + [StickerFormatType.LOTTIE]: "json", + [StickerFormatType.GIF]: "gif" +} as const; + +const PremiumTierStickerLimitMap = { + 0: 5, + 1: 15, + 2: 30, + 3: 60 +} as const; + +function getGuildMaxStickerSlots(guild: Guild) { + if (guild.features.has("MORE_STICKERS") && guild.premiumTier === 3) + return 120; + + return PremiumTierStickerLimitMap[guild.premiumTier] ?? PremiumTierStickerLimitMap[0]; +} function getUrl(data: Data) { if (data.t === "Emoji") return `${location.protocol}//${window.GLOBAL_ENV.CDN_HOST}/emojis/${data.id}.${data.isAnimated ? "gif" : "png"}?size=4096&lossless=true`; - return `${window.GLOBAL_ENV.MEDIA_PROXY_ENDPOINT}/stickers/${data.id}.${StickerExt[data.format_type]}?size=4096&lossless=true`; + return `${window.GLOBAL_ENV.MEDIA_PROXY_ENDPOINT}/stickers/${data.id}.${StickerExtMap[data.format_type]}?size=4096&lossless=true`; } async function fetchSticker(id: string) { @@ -118,17 +138,25 @@ function getGuildCandidates(data: Data) { (PermissionStore.getGuildPermissions({ id: g.id }) & PermissionsBits.CREATE_GUILD_EXPRESSIONS) === PermissionsBits.CREATE_GUILD_EXPRESSIONS; if (!canCreate) return false; - if (data.t === "Sticker") return true; + if (data.t === "Sticker") { + const stickerSlots = getGuildMaxStickerSlots(g); + const stickers = StickersStore.getStickersByGuildId(g.id); + + return !stickers || stickers.length < stickerSlots; + } const { isAnimated } = data as Emoji; const emojiSlots = getGuildMaxEmojiSlots(g); - const { emojis } = EmojiStore.getGuilds()[g.id]; + const emojis = EmojiStore.getGuildEmoji(g.id); let count = 0; - for (const emoji of emojis) - if (emoji.animated === isAnimated && !emoji.managed) + for (const emoji of emojis) { + if (emoji.animated === isAnimated && !emoji.managed) { count++; + } + } + return count < emojiSlots; }).sort((a, b) => a.name.localeCompare(b.name)); }