Fixes & Chrome

This commit is contained in:
thororen1234 2025-08-07 18:32:14 -04:00
parent 06645f3bfd
commit 81f4ec3d07
No known key found for this signature in database
7 changed files with 81 additions and 172 deletions

44
.github/workflows/publish.yml vendored Normal file
View file

@ -0,0 +1,44 @@
name: Release Browser Extension
on:
push:
tags:
- v*
jobs:
Publish:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: check that tag matches package.json version
run: |
pkg_version="v$(jq -r .version < package.json)"
if [[ "${{ github.ref_name }}" != "$pkg_version" ]]; then
echo "Tag ${{ github.ref_name }} does not match package.json version $pkg_version" >&2
exit 1
fi
- uses: pnpm/action-setup@v3
- name: Use Node.js 19
uses: actions/setup-node@v4
with:
node-version: 20
cache: "pnpm"
- name: Install dependencies
run: pnpm install --frozen-lockfile
- name: Build web
run: pnpm buildWebStandalone
- name: Publish extension
run: |
cd dist/chromium-unpacked
pnpx chrome-webstore-upload-cli@2.1.0 upload --auto-publish
env:
EXTENSION_ID: ${{ secrets.CHROME_EXTENSION_ID }}
CLIENT_ID: ${{ secrets.CHROME_CLIENT_ID }}
CLIENT_SECRET: ${{ secrets.CHROME_CLIENT_SECRET }}
REFRESH_TOKEN: ${{ secrets.CHROME_REFRESH_TOKEN }}

View file

@ -1,60 +0,0 @@
import { FluxStore } from "..";
export interface Sticker {
available: boolean;
description: string;
id: string;
name: string;
tags: string;
type: number;
t: "Sticker";
format_type: number;
image: string;
title: string;
stickerPackId: StickerPackMeta["id"];
guild_id: string;
filename?: string;
isAnimated?: boolean;
}
export interface StickerPackMeta {
id: string;
title: string;
author?: {
name: string;
url?: string;
};
logo: Sticker;
dynamic?: DynamicStickerPackMeta["dynamic"];
}
export interface DynamicStickerPackMeta extends StickerPackMeta {
dynamic: {
version?: string;
refreshUrl: string;
authHeaders?: Record<string, string>;
};
}
export interface StickerPack extends StickerPackMeta {
stickers: Sticker[];
}
export interface StickerCategoryType {
id: string;
name: string;
iconUrl?: string;
}
export class StickerStore 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;
}

View file

@ -2,10 +2,42 @@ import { FluxStore, GuildSticker, PremiumStickerPack, Sticker } from "..";
export type StickerGuildMap = Map<string, GuildSticker[]>;
export interface StickerPackMeta {
id: string;
title: string;
author?: {
name: string;
url?: string;
};
logo: Sticker;
dynamic?: DynamicStickerPackMeta["dynamic"];
}
export interface DynamicStickerPackMeta extends StickerPackMeta {
dynamic: {
version?: string;
refreshUrl: string;
authHeaders?: Record<string, string>;
};
}
export interface StickerPack extends StickerPackMeta {
stickers: Sticker[];
}
export interface StickerCategoryType {
id: string;
name: string;
iconUrl?: string;
}
export class StickersStore extends FluxStore {
getAllGuildStickers(): StickerGuildMap;
getRawStickersByGuild(): StickerGuildMap;
getPremiumPacks(): PremiumStickerPack[];
getAllStickersIterator(): IterableIterator<Sticker>;
getStickerById(id: string): Sticker | undefined;
getStickerPack(id: string): PremiumStickerPack | undefined;

View file

@ -17,7 +17,6 @@ export * from "./TypingStore";
export * from "./UserProfileStore";
export * from "./UserStore";
export * from "./WindowStore";
export * from "./StickerStore";
/**
* React hook that returns stateful data for one or more stores

View file

@ -1,106 +0,0 @@
/*
* Vencord, a Discord client mod
* Copyright (c) 2025 Vendicated and contributors
* SPDX-License-Identifier: GPL-3.0-or-later
*/
import { findGroupChildrenByChildId, NavContextMenuPatchCallback } from "@api/ContextMenu";
import { Devs } from "@utils/constants";
import { copyWithToast } from "@utils/misc";
import definePlugin from "@utils/types";
import { Menu, React, StickerStore } from "@webpack/common";
import { Promisable } from "type-fest";
interface Sticker {
t: "Sticker";
format_type: number;
id: string;
type: number;
}
const StickerExt = [, "png", "png", "json", "gif"] as const;
function getUrl(data: Sticker) {
if (data.format_type === 4)
return `https:${window.GLOBAL_ENV.MEDIA_PROXY_ENDPOINT}/stickers/${data.id}.gif?size=4096&lossless=true`;
return `https://${window.GLOBAL_ENV.CDN_HOST}/stickers/${data.id}.${StickerExt[data.format_type]}?size=4096&lossless=true`;
}
function buildMenuItem(Sticker, fetchData: () => Promisable<Omit<Sticker, "t">>) {
return (
<>
<Menu.MenuSeparator></Menu.MenuSeparator>
<Menu.MenuItem
id="copystickerurl"
key="copystickerurl"
label={"Copy URL"}
action={async () => {
const res = await fetchData();
const data = { t: Sticker, ...res } as Sticker;
const url = getUrl(data);
copyWithToast(url, "Link copied!");
}
}
/>
<Menu.MenuItem
id="openstickerlink"
key="openstickerlink"
label={"Open URL"}
action={async () => {
const res = await fetchData();
const data = { t: Sticker, ...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) return;
return buildMenuItem("Sticker", () => props.message.stickerItems[0]);
}
})();
if (menuItem)
findGroupChildrenByChildId("devmode-copy-id", children, true)?.push(menuItem);
};
const expressionPickerPatch: NavContextMenuPatchCallback = (children, props: { target: HTMLElement; }) => {
const { id } = props?.target?.dataset ?? {};
if (!id) return;
if (!props.target.className?.includes("lottieCanvas")) {
const stickerCache = StickerStore.getStickerById(id);
if (stickerCache) {
const stickerInfo = {
format_type: stickerCache.format_type,
id: stickerCache.id,
type: stickerCache.type
};
children.push(buildMenuItem("Sticker", () => stickerInfo));
}
}
};
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
}
});

View file

@ -9,7 +9,7 @@ import { migratePluginSettings } from "@api/Settings";
import { Devs, EquicordDevs } from "@utils/constants";
import definePlugin from "@utils/types";
import type { Guild } from "@vencord/discord-types";
import { EmojiStore, Menu, StickerStore } from "@webpack/common";
import { EmojiStore, Menu, StickersStore } from "@webpack/common";
import { zipSync } from "fflate";
const Patch: NavContextMenuPatchCallback = (children, { guild }: { guild: Guild; }) => {
@ -30,7 +30,7 @@ async function zipGuildAssets(guild: Guild, type: "emojis" | "stickers") {
const isEmojis = type === "emojis";
const items = isEmojis
? EmojiStore.getGuilds()[guild.id]?.emojis
: StickerStore.getStickersByGuildId(guild.id);
: StickersStore.getStickersByGuildId(guild.id);
if (!items) {
return console.log("Server not found!");

View file

@ -9,7 +9,7 @@ import "./styles.css";
import { EquicordDevs } from "@utils/constants";
import { Logger } from "@utils/Logger";
import definePlugin from "@utils/types";
import { StickerStore } from "@webpack/common";
import { StickersStore } from "@webpack/common";
import { getMimeType, isLinkAnImage, settings, stripDiscordParams } from "./settings";
@ -121,10 +121,10 @@ 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) {
switch (stickerData.format_type) {
case 1:
stickerType = "png";
break;