mirror of
https://github.com/Equicord/Equicord.git
synced 2025-06-07 13:43:03 -04:00
EmojiDumper -> GuildPickerDumper + StickersStore
Some checks failed
Test / Test (push) Has been cancelled
Some checks failed
Test / Test (push) Has been cancelled
This commit is contained in:
parent
df6b6a0766
commit
a884f24e31
7 changed files with 102 additions and 85 deletions
|
@ -52,7 +52,6 @@ You can join our [discord server](https://discord.gg/5Xh2W87egW) for commits, ch
|
|||
- DisableAnimations by S€th
|
||||
- DisableCameras by Joona
|
||||
- DontFilterMe by Samwich
|
||||
- EmojiDumper by Cortex, Samwich, Woosh
|
||||
- Encryptcord by Inbestigator
|
||||
- EquicordHelper by thororen & nyx
|
||||
- Equissant by SomeAspy & thororen
|
||||
|
@ -77,6 +76,7 @@ You can join our [discord server](https://discord.gg/5Xh2W87egW) for commits, ch
|
|||
- Glide by Samwich
|
||||
- GlobalBadges by HypedDomi & Hosted by Wolfie
|
||||
- GoogleThat by Samwich
|
||||
- GuildPickerDumper by Cortex, Samwich, Woosh, thororen
|
||||
- HideChatButtons by iamme
|
||||
- HideServers by bepvte
|
||||
- HolyNotes by Wolfie
|
||||
|
|
|
@ -1,62 +0,0 @@
|
|||
/*
|
||||
* Vencord, a Discord client mod
|
||||
* Copyright (c) 2024 Vendicated and contributors
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*/
|
||||
|
||||
import { findGroupChildrenByChildId, NavContextMenuPatchCallback } from "@api/ContextMenu";
|
||||
import { Devs, EquicordDevs } from "@utils/constants";
|
||||
import definePlugin from "@utils/types";
|
||||
import { Menu } from "@webpack/common";
|
||||
import type { Guild } from "discord-types/general";
|
||||
import { zipSync } from "fflate";
|
||||
|
||||
const Patch: NavContextMenuPatchCallback = (children, { guild }: { guild: Guild; }) => {
|
||||
// Assuming "privacy" is the correct ID for the group you want to modify.
|
||||
const group = findGroupChildrenByChildId("privacy", children);
|
||||
|
||||
if (group) {
|
||||
group.push(
|
||||
<Menu.MenuItem id="emoji.download" label="Download Emojis" action={() => zipServerEmojis(guild)}></Menu.MenuItem>
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
export default definePlugin({
|
||||
name: "EmojiDumper",
|
||||
description: "Context menu to dump and download a server's emojis.",
|
||||
authors: [EquicordDevs.Cortex, Devs.Samwich, EquicordDevs.Woosh],
|
||||
contextMenus: {
|
||||
"guild-context": Patch,
|
||||
"guild-header-popout": Patch
|
||||
}
|
||||
});
|
||||
|
||||
async function zipServerEmojis(guild: Guild) {
|
||||
|
||||
const emojis = Vencord.Webpack.Common.EmojiStore.getGuilds()[guild.id]?.emojis;
|
||||
if (!emojis) {
|
||||
return console.log("Server not found!");
|
||||
}
|
||||
|
||||
const fetchEmojis = async e => {
|
||||
const filename = e.id + (e.animated ? ".gif" : ".png");
|
||||
const emoji = await fetch("https://cdn.discordapp.com/emojis/" + filename + "?size=512&quality=lossless").then(res => res.blob());
|
||||
return { file: new Uint8Array(await emoji.arrayBuffer()), filename };
|
||||
};
|
||||
const emojiPromises = emojis.map(e => fetchEmojis(e));
|
||||
|
||||
Promise.all(emojiPromises)
|
||||
.then(results => {
|
||||
const emojis = zipSync(Object.fromEntries(results.map(({ file, filename }) => [filename, file])));
|
||||
const blob = new Blob([emojis], { type: "application/zip" });
|
||||
const link = document.createElement("a");
|
||||
link.href = URL.createObjectURL(blob);
|
||||
link.download = `${guild.name}-emojis.zip`;
|
||||
link.click();
|
||||
link.remove();
|
||||
})
|
||||
.catch(error => {
|
||||
console.error(error);
|
||||
});
|
||||
}
|
75
src/equicordplugins/guildPickerDumper/index.tsx
Normal file
75
src/equicordplugins/guildPickerDumper/index.tsx
Normal file
|
@ -0,0 +1,75 @@
|
|||
/*
|
||||
* Vencord, a Discord client mod
|
||||
* Copyright (c) 2024 Vendicated and contributors
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*/
|
||||
|
||||
import { findGroupChildrenByChildId, NavContextMenuPatchCallback } from "@api/ContextMenu";
|
||||
import { migratePluginSettings } from "@api/Settings";
|
||||
import { Devs, EquicordDevs } from "@utils/constants";
|
||||
import definePlugin from "@utils/types";
|
||||
import { EmojiStore, Menu, StickersStore } from "@webpack/common";
|
||||
import type { Guild } from "discord-types/general";
|
||||
import { zipSync } from "fflate";
|
||||
|
||||
const Patch: NavContextMenuPatchCallback = (children, { guild }: { guild: Guild; }) => {
|
||||
// Assuming "privacy" is the correct ID for the group you want to modify.
|
||||
const group = findGroupChildrenByChildId("privacy", children);
|
||||
|
||||
if (group) {
|
||||
group.push(
|
||||
<>
|
||||
<Menu.MenuItem id="emoji.download" label="Download Emojis" action={() => zipGuildAssets(guild, "emojis")}></Menu.MenuItem>
|
||||
<Menu.MenuItem id="sticker.download" label="Download Stickers" action={() => zipGuildAssets(guild, "stickers")}></Menu.MenuItem>
|
||||
</>
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
async function zipGuildAssets(guild: Guild, type: "emojis" | "stickers") {
|
||||
const isEmojis = type === "emojis";
|
||||
const items = isEmojis
|
||||
? EmojiStore.getGuilds()[guild.id]?.emojis
|
||||
: StickersStore.getStickersByGuildId(guild.id);
|
||||
|
||||
if (!items) {
|
||||
return console.log("Server not found!");
|
||||
}
|
||||
|
||||
const fetchAsset = async e => {
|
||||
const ext = e.animated ? ".gif" : ".png";
|
||||
const filename = e.id + ext;
|
||||
const url = isEmojis
|
||||
? `https://${window.GLOBAL_ENV.MEDIA_PROXY_ENDPOINT}/emojis/${filename}?size=512&quality=lossless`
|
||||
: `https://${window.GLOBAL_ENV.MEDIA_PROXY_ENDPOINT}/stickers/${filename}?size=4096&lossless=true`;
|
||||
|
||||
const response = await fetch(url);
|
||||
const blob = await response.blob();
|
||||
return { file: new Uint8Array(await blob.arrayBuffer()), filename };
|
||||
};
|
||||
|
||||
const assetPromises = items.map(e => fetchAsset(e));
|
||||
|
||||
Promise.all(assetPromises)
|
||||
.then(results => {
|
||||
const zipped = zipSync(Object.fromEntries(results.map(({ file, filename }) => [filename, file])));
|
||||
const blob = new Blob([zipped], { type: "application/zip" });
|
||||
const link = document.createElement("a");
|
||||
link.href = URL.createObjectURL(blob);
|
||||
link.download = `${guild.name}-${type}.zip`;
|
||||
link.click();
|
||||
link.remove();
|
||||
})
|
||||
.catch(console.error);
|
||||
}
|
||||
|
||||
migratePluginSettings("GuildPickerDumper", "EmojiDumper");
|
||||
export default definePlugin({
|
||||
name: "GuildPickerDumper",
|
||||
description: "Context menu to dump and download a server's emojis and stickers.",
|
||||
authors: [EquicordDevs.Cortex, Devs.Samwich, EquicordDevs.Woosh, EquicordDevs.thororen],
|
||||
contextMenus: {
|
||||
"guild-context": Patch,
|
||||
"guild-header-popout": Patch
|
||||
}
|
||||
});
|
|
@ -9,14 +9,11 @@ import "./styles.css";
|
|||
import { EquicordDevs } from "@utils/constants";
|
||||
import { Logger } from "@utils/Logger";
|
||||
import definePlugin from "@utils/types";
|
||||
import { findStoreLazy } from "@webpack";
|
||||
import { StickersStore } from "@webpack/common";
|
||||
|
||||
import { getMimeType, isLinkAnImage, settings, stripDiscordParams } from "./settings";
|
||||
|
||||
const logger = new Logger("ImagePreview", "#FFFFFF");
|
||||
const StickerStore = findStoreLazy("StickersStore") as {
|
||||
getStickerById(id: string): any;
|
||||
};
|
||||
|
||||
let currentPreview: HTMLDivElement | null = null;
|
||||
let currentPreviewFile: HTMLImageElement | HTMLVideoElement | null = null;
|
||||
|
@ -124,7 +121,7 @@ function loadImagePreview(url: string, sticker: boolean) {
|
|||
|
||||
if (sticker) {
|
||||
const stickerId = url.split("/").pop()?.split(".")[0] ?? null;
|
||||
const stickerData = stickerId ? StickerStore.getStickerById(stickerId) : null;
|
||||
const stickerData = stickerId ? StickersStore.getStickerById(stickerId) : null;
|
||||
|
||||
if (stickerData) {
|
||||
switch (stickerData.type) {
|
||||
|
|
|
@ -24,7 +24,7 @@ import { getCurrentGuild, getEmojiURL } from "@utils/discord";
|
|||
import { Logger } from "@utils/Logger";
|
||||
import definePlugin, { OptionType, Patch } from "@utils/types";
|
||||
import { findByCodeLazy, findByPropsLazy, findStoreLazy, proxyLazyWebpack } from "@webpack";
|
||||
import { Alerts, ChannelStore, DraftType, EmojiStore, FluxDispatcher, Forms, GuildMemberStore, lodash, Parser, PermissionsBits, PermissionStore, UploadHandler, UserSettingsActionCreators, UserStore } from "@webpack/common";
|
||||
import { Alerts, ChannelStore, DraftType, EmojiStore, FluxDispatcher, Forms, GuildMemberStore, lodash, Parser, PermissionsBits, PermissionStore, StickersStore, UploadHandler, UserSettingsActionCreators, UserStore } from "@webpack/common";
|
||||
import type { Emoji } from "@webpack/types";
|
||||
import type { Message } from "discord-types/general";
|
||||
import { applyPalette, GIFEncoder, quantize } from "gifenc";
|
||||
|
@ -33,12 +33,6 @@ import type { ReactElement, ReactNode } from "react";
|
|||
// @ts-ignore
|
||||
const premiumType = UserStore?.getCurrentUser()?._realPremiumType ?? UserStore?.getCurrentUser()?.premiumType ?? 0;
|
||||
|
||||
const StickerStore = findStoreLazy("StickersStore") as {
|
||||
getPremiumPacks(): StickerPack[];
|
||||
getAllGuildStickers(): Map<string, Sticker[]>;
|
||||
getStickerById(id: string): Sticker | undefined;
|
||||
};
|
||||
|
||||
const UserSettingsProtoStore = findStoreLazy("UserSettingsProtoStore");
|
||||
|
||||
const BINARY_READ_OPTIONS = findByPropsLazy("readerFactory");
|
||||
|
@ -558,8 +552,8 @@ export default definePlugin({
|
|||
|
||||
const gifMatch = child.props.href.match(fakeNitroGifStickerRegex);
|
||||
if (gifMatch) {
|
||||
// There is no way to differentiate a regular gif attachment from a fake nitro animated sticker, so we check if the StickerStore contains the id of the fake sticker
|
||||
if (StickerStore.getStickerById(gifMatch[1])) return null;
|
||||
// There is no way to differentiate a regular gif attachment from a fake nitro animated sticker, so we check if the StickersStore contains the id of the fake sticker
|
||||
if (StickersStore.getStickerById(gifMatch[1])) return null;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -647,7 +641,7 @@ export default definePlugin({
|
|||
url = new URL(item);
|
||||
} catch { }
|
||||
|
||||
const stickerName = StickerStore.getStickerById(imgMatch[1])?.name ?? url?.searchParams.get("name") ?? "FakeNitroSticker";
|
||||
const stickerName = StickersStore.getStickerById(imgMatch[1])?.name ?? url?.searchParams.get("name") ?? "FakeNitroSticker";
|
||||
stickers.push({
|
||||
format_type: 1,
|
||||
id: imgMatch[1],
|
||||
|
@ -660,9 +654,9 @@ export default definePlugin({
|
|||
|
||||
const gifMatch = item.match(fakeNitroGifStickerRegex);
|
||||
if (gifMatch) {
|
||||
if (!StickerStore.getStickerById(gifMatch[1])) continue;
|
||||
if (!StickersStore.getStickerById(gifMatch[1])) continue;
|
||||
|
||||
const stickerName = StickerStore.getStickerById(gifMatch[1])?.name ?? "FakeNitroSticker";
|
||||
const stickerName = StickersStore.getStickerById(gifMatch[1])?.name ?? "FakeNitroSticker";
|
||||
stickers.push({
|
||||
format_type: 2,
|
||||
id: gifMatch[1],
|
||||
|
@ -695,8 +689,8 @@ export default definePlugin({
|
|||
|
||||
const gifMatch = embed.url!.match(fakeNitroGifStickerRegex);
|
||||
if (gifMatch) {
|
||||
// There is no way to differentiate a regular gif attachment from a fake nitro animated sticker, so we check if the StickerStore contains the id of the fake sticker
|
||||
if (StickerStore.getStickerById(gifMatch[1])) return true;
|
||||
// There is no way to differentiate a regular gif attachment from a fake nitro animated sticker, so we check if the StickersStore contains the id of the fake sticker
|
||||
if (StickersStore.getStickerById(gifMatch[1])) return true;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -713,8 +707,8 @@ export default definePlugin({
|
|||
|
||||
const match = attachment.url.match(fakeNitroGifStickerRegex);
|
||||
if (match) {
|
||||
// There is no way to differentiate a regular gif attachment from a fake nitro animated sticker, so we check if the StickerStore contains the id of the fake sticker
|
||||
if (StickerStore.getStickerById(match[1])) return false;
|
||||
// There is no way to differentiate a regular gif attachment from a fake nitro animated sticker, so we check if the StickersStore contains the id of the fake sticker
|
||||
if (StickersStore.getStickerById(match[1])) return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
|
@ -870,7 +864,7 @@ export default definePlugin({
|
|||
if (!s.enableStickerBypass)
|
||||
break stickerBypass;
|
||||
|
||||
const sticker = StickerStore.getStickerById(extra.stickers?.[0]!);
|
||||
const sticker = StickersStore.getStickerById(extra.stickers?.[0]!);
|
||||
if (!sticker)
|
||||
break stickerBypass;
|
||||
|
||||
|
|
|
@ -54,6 +54,7 @@ export let RelationshipStore: Stores.RelationshipStore & t.FluxStore & {
|
|||
};
|
||||
|
||||
export let EmojiStore: t.EmojiStore;
|
||||
export let StickersStore: t.StickersStore;
|
||||
export let ThemeStore: t.ThemeStore;
|
||||
export let WindowStore: t.WindowStore;
|
||||
export let DraftStore: t.DraftStore;
|
||||
|
@ -86,5 +87,6 @@ waitForStore("GuildChannelStore", m => GuildChannelStore = m);
|
|||
waitForStore("MessageStore", m => MessageStore = m);
|
||||
waitForStore("WindowStore", m => WindowStore = m);
|
||||
waitForStore("EmojiStore", m => EmojiStore = m);
|
||||
waitForStore("StickersStore", m => StickersStore = m);
|
||||
waitForStore("TypingStore", m => TypingStore = m);
|
||||
waitForStore("ThemeStore", m => ThemeStore = m);
|
||||
|
|
11
src/webpack/common/types/stores.d.ts
vendored
11
src/webpack/common/types/stores.d.ts
vendored
|
@ -177,6 +177,17 @@ export class EmojiStore extends FluxStore {
|
|||
};
|
||||
}
|
||||
|
||||
export class StickersStore extends FluxStore {
|
||||
getStickerById(id: string): Sticker | undefined;
|
||||
getStickerPack(id: string): StickerPack | undefined;
|
||||
getPremiumPacks(): StickerPack[];
|
||||
isPremiumPack(id: string): boolean;
|
||||
getRawStickersByGuild(): Map<string, Sticker[]>;
|
||||
getAllStickersIterator(): IterableIterator<Sticker>;
|
||||
getAllGuildStickers(): Map<string, Sticker[]>;
|
||||
getStickersByGuildId(id: string): Sticker[] | undefined;
|
||||
}
|
||||
|
||||
export interface DraftObject {
|
||||
channelId: string;
|
||||
timestamp: number;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue