Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(plugin): CopyStickerLinks #3191

Open
wants to merge 14 commits into
base: dev
Choose a base branch
from
150 changes: 150 additions & 0 deletions src/plugins/copyStickerLinks/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,150 @@
/*
* Vencord, a modification for Discord's desktop app
* Copyright (c) 2024 Vendicated and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/

import { findGroupChildrenByChildId, NavContextMenuPatchCallback } from "@api/ContextMenu";

Check failure on line 19 in src/plugins/copyStickerLinks/index.tsx

View workflow job for this annotation

GitHub Actions / test

Run autofix to sort these imports!
import { Devs } from "@utils/constants";
import definePlugin from "@utils/types";
import { findStoreLazy } from "@webpack";
import { Constants, Clipboard, FluxDispatcher, Menu, React, RestAPI, Toasts } from "@webpack/common";
import { Promisable } from "type-fest";

const StickersStore = findStoreLazy("StickersStore");

interface Sticker {
t: "Sticker";
description: string;
format_type: number;
guild_id: string;
id: string;
name: string;
tags: string;
type: number;
}

interface Emoji {
byeoon marked this conversation as resolved.
Show resolved Hide resolved
t: "Emoji";
id: string;
name: string;
isAnimated: boolean;
}

type Data = Emoji | Sticker;

const StickerExt = [, "png", "png", "json", "gif"] as const;

function getUrl(data: Data) {
if (data.t === "Sticker")
return `https:${window.GLOBAL_ENV.MEDIA_PROXY_ENDPOINT}/stickers/${data.id}.${StickerExt[data.format_type]}?size=2048&lossless=true`;

return "oops Couldnt get it sorry boss";
byeoon marked this conversation as resolved.
Show resolved Hide resolved
}

async function fetchSticker(id: string) {
const cached = StickersStore.getStickerById(id);
if (cached) return cached;

const { body } = await RestAPI.get({
url: Constants.Endpoints.STICKER(id)
});

FluxDispatcher.dispatch({
type: "STICKER_FETCH_SUCCESS",
sticker: body
});

return body as Sticker;
}

function buildMenuItem(type: "Sticker", fetchData: () => Promisable<Omit<Sticker, "t">>) {
return (
<>
<Menu.MenuSeparator></Menu.MenuSeparator>

<Menu.MenuItem
id="copystickerurl"
key="copystickerurl"
label={"Copy Sticker Link"}
action={async () => {
const res = await fetchData();
const data = { t: type, ...res } as Sticker;
const url = getUrl(data);
console.log("URL: " + url + "\n" + "Data: " + data);
byeoon marked this conversation as resolved.
Show resolved Hide resolved
Toasts.show({
message: "Link to sticker copied!",
type: Toasts.Type.SUCCESS,
id: Toasts.genId()
});
Clipboard.copy(url);
}
}
/>

<Menu.MenuItem
id="openstickerlink"
key="openstickerlink"
label={"Open Sticker Link"}
byeoon marked this conversation as resolved.
Show resolved Hide resolved
action={async () => {
const res = await fetchData();
const data = { t: type, ...res } as Sticker;
const url = getUrl(data);
VencordNative.native.openExternal(url);
}
}
/>
</>
);
}

const messageContextMenuPatch: NavContextMenuPatchCallback = (children, props) => {
const { favoriteableId, favoriteableType } = props ?? {};
if (!favoriteableId) return;
const menuItem = (() => {
switch (favoriteableType) {
case "sticker":
const sticker = props.message.stickerItems.find(s => s.id === favoriteableId);
if (sticker?.format_type === 3) return;

return buildMenuItem("Sticker", () => fetchSticker(favoriteableId));
}
})();

if (menuItem)
findGroupChildrenByChildId(`devmode-copy-id`, children, true)?.push(menuItem);

Check failure on line 127 in src/plugins/copyStickerLinks/index.tsx

View workflow job for this annotation

GitHub Actions / test

Strings must use doublequote
};

const expressionPickerPatch: NavContextMenuPatchCallback = (children, props: { target: HTMLElement; }) => {
const { id, type } = props?.target?.dataset ?? {};
if (!id) return;

if (type === "sticker" && !props.target.className?.includes("lottieCanvas")) {
children.push(buildMenuItem("Sticker", () => fetchSticker(id)));
}
};

export default definePlugin({
name: "CopyStickerLinks",
description: "Adds the ability to copy and open sticker links to your browser.",
authors: [Devs.Byeoon],
contextMenus: {
"message": messageContextMenuPatch,
"expression-picker": expressionPickerPatch
}
});



2 changes: 1 addition & 1 deletion src/utils/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -471,7 +471,7 @@ export const Devs = /* #__PURE__*/ Object.freeze({
name: "Sqaaakoi",
id: 259558259491340288n
},
Byron: {
Byeoon: {
name: "byeoon",
id: 1167275288036655133n
},
Expand Down
Loading