From adc3e8ce85248bd17550c4a04ab31ea4727c5980 Mon Sep 17 00:00:00 2001 From: thororen1234 <78185467+thororen1234@users.noreply.github.com> Date: Mon, 15 Sep 2025 16:51:20 -0400 Subject: [PATCH 1/6] Properly Ignore zips and such when building --- scripts/build/common.mjs | 1 + 1 file changed, 1 insertion(+) diff --git a/scripts/build/common.mjs b/scripts/build/common.mjs index b9b603396..240409673 100644 --- a/scripts/build/common.mjs +++ b/scripts/build/common.mjs @@ -162,6 +162,7 @@ export const globPlugins = kind => ({ const fileName = file.name; if (fileName.startsWith("_") || fileName.startsWith(".")) continue; if (fileName === "index.ts") continue; + if (/\.(zip|rar|7z|tar|gz|bz2)/.test(fileName)) continue; const target = getPluginTarget(fileName); From dbc3bf8f84622ffc0d81332baa0c94cec471abfe Mon Sep 17 00:00:00 2001 From: thororen1234 <78185467+thororen1234@users.noreply.github.com> Date: Mon, 15 Sep 2025 17:37:49 -0400 Subject: [PATCH 2/6] Update Cloud cap --- src/components/settings/tabs/sync/CloudTab.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/settings/tabs/sync/CloudTab.tsx b/src/components/settings/tabs/sync/CloudTab.tsx index 7f8295ff8..a77c7bd38 100644 --- a/src/components/settings/tabs/sync/CloudTab.tsx +++ b/src/components/settings/tabs/sync/CloudTab.tsx @@ -135,7 +135,7 @@ function CloudTab() { Equicord comes with a cloud integration allowing settings to be synced across apps and devices.
- We use Vencord's cloud source code to provide our cloud instance which has a 32MB backup cap. + We use Vencord's cloud source code to provide our cloud instance which has a 60MB backup cap.
Our privacy policy allows you to see what information we store, how we use it, and data retention.
From 3b6d8696f7cbb5b4bc44cacff59bedaf6134308f Mon Sep 17 00:00:00 2001 From: SerStars <90714930+SerStars@users.noreply.github.com> Date: Mon, 15 Sep 2025 23:57:00 +0200 Subject: [PATCH 3/6] Format (#394) --- src/equicordplugins/jellyfinRichPresence/index.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/equicordplugins/jellyfinRichPresence/index.tsx b/src/equicordplugins/jellyfinRichPresence/index.tsx index 91ae774bf..8a6c301a4 100644 --- a/src/equicordplugins/jellyfinRichPresence/index.tsx +++ b/src/equicordplugins/jellyfinRichPresence/index.tsx @@ -282,7 +282,7 @@ export default definePlugin({ const getDetails = () => { if (mediaData.type === "Episode" && mediaData.seriesName) { - return mediaData.name; + return mediaData.seriesName; } return mediaData.name; }; @@ -291,7 +291,7 @@ export default definePlugin({ if (mediaData.type === "Episode" && mediaData.seriesName) { const season = mediaData.seasonNumber ? `S${mediaData.seasonNumber}` : ""; const episode = mediaData.episodeNumber ? `E${mediaData.episodeNumber}` : ""; - return `${mediaData.seriesName} ${season}${episode}`.trim(); + return `${mediaData.name} ${season} - ${episode}`.trim(); } return mediaData.artist || (mediaData.year ? `(${mediaData.year})` : undefined); }; From 9c47e13a15b55229af85eaacb9ef659c7b797a20 Mon Sep 17 00:00:00 2001 From: SerStars <90714930+SerStars@users.noreply.github.com> Date: Tue, 16 Sep 2025 00:44:13 +0200 Subject: [PATCH 4/6] Add TheMovieDB Button & Large Image (#395) * Add TheMovieDB Button & Large Image * A lil formatting --- .../jellyfinRichPresence/index.tsx | 62 ++++++++++++++++--- 1 file changed, 55 insertions(+), 7 deletions(-) diff --git a/src/equicordplugins/jellyfinRichPresence/index.tsx b/src/equicordplugins/jellyfinRichPresence/index.tsx index 8a6c301a4..4de24d4f5 100644 --- a/src/equicordplugins/jellyfinRichPresence/index.tsx +++ b/src/equicordplugins/jellyfinRichPresence/index.tsx @@ -19,6 +19,11 @@ interface ActivityAssets { small_text?: string; } +interface ActivityButton { + label: string; + url: string; +} + interface Activity { state: string; details?: string; @@ -26,6 +31,7 @@ interface Activity { start?: number; }; assets?: ActivityAssets; + buttons?: Array; name: string; application_id: string; metadata?: { @@ -50,8 +56,6 @@ interface MediaData { position?: number; } - - const settings = definePluginSettings({ serverUrl: { description: "Jellyfin server URL (e.g., https://jellyfin.example.com)", @@ -78,6 +82,11 @@ const settings = definePluginSettings({ description: "Custom Rich Presence name (only used if 'Custom' is selected).\nOptions: {name}, {series}, {season}, {episode}, {artist}, {album}, {year}", type: OptionType.STRING, }, + showTMDBButton: { + description: "Show TheMovieDB button in Rich Presence", + type: OptionType.BOOLEAN, + default: true, + }, overrideRichPresenceType: { description: "Override the rich presence type", type: OptionType.SELECT, @@ -123,6 +132,27 @@ function setActivity(activity: Activity | null) { }); } +async function fetchTmdbData(query: string) { + try { + const res = await fetch(`https://api.vmohammad.dev/tmdb/search/multi?q=${encodeURIComponent(query)}`); + if (!res.ok) throw `${res.status} ${res.statusText}`; + const data = await res.json(); + if (data.results && data.results.length > 0) { + const topResult = data.results[0]; + return { + url: `https://www.themoviedb.org/${topResult.media_type}/${topResult.id}`, + posterPath: topResult.poster_path + ? `https://image.tmdb.org/t/p/original${topResult.poster_path}` + : null + }; + } + return null; + } catch (e) { + console.error("Failed to fetch TMDb data:", e); + return null; + } +} + export default definePlugin({ name: "JellyfinRichPresence", description: "Rich presence for Jellyfin media server", @@ -274,12 +304,26 @@ export default definePlugin({ break; } - const largeImage = mediaData.imageUrl; + let tmdbData: { url: string; posterPath?: string | null } | null = null; + if (settings.store.showTMDBButton) { + tmdbData = await fetchTmdbData(mediaData.seriesName || mediaData.name); + } + const assets: ActivityAssets = { - large_image: largeImage ? await getApplicationAsset(largeImage) : await getApplicationAsset("jellyfin"), - large_text: mediaData.album || mediaData.seriesName || undefined, + large_image: tmdbData?.posterPath ? await getApplicationAsset(tmdbData.posterPath) : mediaData.imageUrl ? await getApplicationAsset(mediaData.imageUrl) : undefined, + large_text: mediaData.seriesName || mediaData.album || undefined, }; + const buttons: ActivityButton[] = []; + if (settings.store.showTMDBButton) { + const result = await fetchTmdbData(mediaData.seriesName || mediaData.name); + if (result?.url) tmdbData = { url: result.url }; + buttons.push({ + label: "View on TheMovieDB", + url: `${tmdbData?.url}` + }); + } + const getDetails = () => { if (mediaData.type === "Episode" && mediaData.seriesName) { return mediaData.seriesName; @@ -291,7 +335,7 @@ export default definePlugin({ if (mediaData.type === "Episode" && mediaData.seriesName) { const season = mediaData.seasonNumber ? `S${mediaData.seasonNumber}` : ""; const episode = mediaData.episodeNumber ? `E${mediaData.episodeNumber}` : ""; - return `${mediaData.name} ${season} - ${episode}`.trim(); + return `${mediaData.name} (${season} - ${episode})`.trim(); } return mediaData.artist || (mediaData.year ? `(${mediaData.year})` : undefined); }; @@ -309,8 +353,12 @@ export default definePlugin({ assets, timestamps, + buttons: buttons.length ? buttons.map(v => v.label) : undefined, + metadata: { + button_urls: buttons.map(v => v.url), + }, type: richPresenceType, - flags: 1, + flags: 1 }; } }); From f51f53fcc55225a12a8b720fbfdb1a2b2ed021e1 Mon Sep 17 00:00:00 2001 From: thororen1234 <78185467+thororen1234@users.noreply.github.com> Date: Tue, 16 Sep 2025 11:49:06 -0400 Subject: [PATCH 5/6] Dev: Use Different Settings File --- src/main/utils/constants.ts | 40 ++++++++++++++++++++++++++++++------- 1 file changed, 33 insertions(+), 7 deletions(-) diff --git a/src/main/utils/constants.ts b/src/main/utils/constants.ts index 00f1eb47a..e9fa39ab4 100644 --- a/src/main/utils/constants.ts +++ b/src/main/utils/constants.ts @@ -17,16 +17,15 @@ */ import { app } from "electron"; +import { copyFileSync, existsSync, readFileSync, writeFileSync } from "fs"; import { join } from "path"; -export const DATA_DIR = process.env.EQUICORD_USER_DATA_DIR ?? process.env.VENCORD_USER_DATA_DIR ?? ( +const suffix = IS_DEV ? "dev" : ""; + +export const DATA_DIR = process.env.EQUICORD_USER_DATA_DIR ?? ( process.env.DISCORD_USER_DATA_DIR - ? IS_VESKTOP - ? join(process.env.DISCORD_USER_DATA_DIR, "..", "VencordData") - : join(process.env.DISCORD_USER_DATA_DIR, "..", "EquicordData") - : IS_VESKTOP - ? join(app.getPath("userData"), "..", "Vencord") - : join(app.getPath("userData"), "..", "Equicord") + ? join(process.env.DISCORD_USER_DATA_DIR, "..", "EquicordData", suffix) + : join(app.getPath("userData"), "..", "Equicord", suffix) ); export const SETTINGS_DIR = join(DATA_DIR, "settings"); @@ -34,6 +33,7 @@ export const THEMES_DIR = join(DATA_DIR, "themes"); export const QUICKCSS_PATH = join(SETTINGS_DIR, "quickCss.css"); export const SETTINGS_FILE = join(SETTINGS_DIR, "settings.json"); export const NATIVE_SETTINGS_FILE = join(SETTINGS_DIR, "native-settings.json"); +export const DEV_MIGRATED = join(SETTINGS_DIR, "migration"); export const ALLOWED_PROTOCOLS = [ "https:", "http:", @@ -45,3 +45,29 @@ export const ALLOWED_PROTOCOLS = [ ]; export const IS_VANILLA = /* @__PURE__ */ process.argv.includes("--vanilla"); + +if (IS_DEV) { + const prodDir = join(DATA_DIR, ".."); + const settings = join(prodDir, "settings", "settings.json"); + const quickCss = join(prodDir, "settings", "quickCss.css"); + + let migrated = false; + if (existsSync(DEV_MIGRATED)) { + const content = readFileSync(DEV_MIGRATED, "utf-8"); + migrated = content.includes("migrated"); + } + + if (!migrated) { + setTimeout(() => { + try { + if (existsSync(settings)) copyFileSync(settings, SETTINGS_FILE); + if (existsSync(quickCss)) copyFileSync(quickCss, QUICKCSS_PATH); + writeFileSync(DEV_MIGRATED, "migrated"); + app.relaunch(); + app.exit(0); + } catch (err) { + console.error("[Equicord] Failed to copy prod data:", err); + } + }, 5000); + } +} From ba52251611e5e08c5143b8b33b6cb2c9d4fbdd12 Mon Sep 17 00:00:00 2001 From: Jake <134332787+justjxke@users.noreply.github.com> Date: Tue, 16 Sep 2025 16:49:35 +0100 Subject: [PATCH 6/6] fix/tone indicators (#396) * add tone indicators plugin * im tired of this man * oh my fucking god its EquicordDevs not Devs * dont use json * Update index.tsx * fix regex for custom indicators and http:// * add support for hyphens, +, underscores, numbers, unicode. * Update index.tsx * bruh --------- Co-authored-by: thororen1234 <78185467+thororen1234@users.noreply.github.com> Co-authored-by: justjxke --- src/equicordplugins/toneIndicators/index.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/equicordplugins/toneIndicators/index.tsx b/src/equicordplugins/toneIndicators/index.tsx index b70bc0d4a..9965fac3e 100644 --- a/src/equicordplugins/toneIndicators/index.tsx +++ b/src/equicordplugins/toneIndicators/index.tsx @@ -57,7 +57,7 @@ function splitTextWithIndicators(text: string): ReactNode[] { const nodes: ReactNode[] = []; let lastIndex = 0; let count = 0; - const regex = /\/([a-z]{1,20})(?=\s|$|[^\w])/gi; + const regex = /(?:^|\s)\/([^/\s]+)(?:$|\s|\p{P})/giu; let match: RegExpExecArray | null; while ((match = regex.exec(text)) && count < settings.store.maxIndicators) {