From 7951d0083ab2432c31d6d23637e76be56ff5b618 Mon Sep 17 00:00:00 2001 From: kmmiio99o Date: Sun, 26 Jul 2026 16:01:01 +0200 Subject: [PATCH] fix: showing album images in Rich Presence atleast try, lol. --- plugins/multi-scrobbler/src/constants.ts | 2 +- plugins/multi-scrobbler/src/manager.ts | 5 --- plugins/multi-scrobbler/src/modules.ts | 8 ++++ plugins/multi-scrobbler/src/utils/activity.ts | 45 +++++++++++++++++-- 4 files changed, 51 insertions(+), 9 deletions(-) diff --git a/plugins/multi-scrobbler/src/constants.ts b/plugins/multi-scrobbler/src/constants.ts index 3173733..17a73bc 100644 --- a/plugins/multi-scrobbler/src/constants.ts +++ b/plugins/multi-scrobbler/src/constants.ts @@ -4,7 +4,7 @@ const Constants = { DEFAULT_APP_NAME: "Music", DEFAULT_TIME_INTERVAL: 5, // Discord application ID - APPLICATION_ID: "1368513179272871956", + APPLICATION_ID: "1054951789318909972", // Don't check more than once every 3 seconds to avoid getting rate limited MIN_UPDATE_INTERVAL: 3, // Libre.fm specifically requested a 1-minute minimum to reduce load diff --git a/plugins/multi-scrobbler/src/manager.ts b/plugins/multi-scrobbler/src/manager.ts index 2cd0a98..94947f2 100644 --- a/plugins/multi-scrobbler/src/manager.ts +++ b/plugins/multi-scrobbler/src/manager.ts @@ -66,9 +66,6 @@ class PluginManager { const serviceName = serviceFactory.getCurrentService().getServiceName(); logVerbose(`Fetching latest track from ${serviceName}...`); - // keep track of whether we actually need to update Discord - let willUpdateRPC = false; - try { // Check if any ignored app is active if (currentSettings.ignoreList && currentSettings.ignoreList.length > 0) { @@ -122,8 +119,6 @@ class PluginManager { return; } - willUpdateRPC = true; - log(`🎵 Track changed: ${lastTrack.artist} - ${lastTrack.name}`); // set up timestamps for the track diff --git a/plugins/multi-scrobbler/src/modules.ts b/plugins/multi-scrobbler/src/modules.ts index 9cb29da..8b1ea8f 100644 --- a/plugins/multi-scrobbler/src/modules.ts +++ b/plugins/multi-scrobbler/src/modules.ts @@ -10,6 +10,14 @@ export const AssetManager = findByProps("getAssetIds") as { [key: PropertyKey]: any; }; +// Discord's internal HTTP client — automatically includes auth token +export const HTTPUtils = findByProps("getAPIBaseURL", "get") as { + get: (opts: { url: string; query?: string; rejectWithError?: boolean; oldFormErrors?: boolean }) => Promise; + post: (opts: { url: string; body?: any; rejectWithError?: boolean; oldFormErrors?: boolean }) => Promise; + getAPIBaseURL: () => string; + [key: PropertyKey]: any; +}; + export const SelfPresenceStore = findByStoreName("SelfPresenceStore") as { getActivities: () => any[]; findActivity: (filter: (activity) => boolean) => any; diff --git a/plugins/multi-scrobbler/src/utils/activity.ts b/plugins/multi-scrobbler/src/utils/activity.ts index d153278..ce64b31 100644 --- a/plugins/multi-scrobbler/src/utils/activity.ts +++ b/plugins/multi-scrobbler/src/utils/activity.ts @@ -4,7 +4,7 @@ import { pluginState } from ".."; import { Activity } from "../../../defs"; import Constants from "../constants"; import { stop } from "../manager"; -import { AssetManager } from "../modules"; +import { AssetManager, HTTPUtils } from "../modules"; /** Clears the user's activity */ export function clearActivity() { @@ -28,7 +28,33 @@ export function sendRequest(activity: Activity | null) { }); } -/** Fetches Discord application assets */ +async function resolveExternalAssets( + urls: string[], + appId: string, +): Promise { + const baseUrl = HTTPUtils.getAPIBaseURL(); + const endpoint = `${baseUrl}/applications/${appId}/external-assets`; + + const resp = await HTTPUtils.post({ + url: endpoint, + body: { urls }, + oldFormErrors: true, + rejectWithError: false, + }); + + console.log("[Multi-Scrobbler] External assets response:", JSON.stringify(resp)); + const body = resp?.body; + console.log("[Multi-Scrobbler] Response body:", JSON.stringify(body)); + + if (!Array.isArray(body)) return []; + + return body.map( + (item: { url: string; external_asset_path: string }) => + `mp:${item.external_asset_path}`, + ); +} + +/** Resolves external image URLs to Discord asset paths */ export async function fetchAsset( asset: string[], appId: string = Constants.APPLICATION_ID, @@ -36,7 +62,20 @@ export async function fetchAsset( if (!asset?.length) return []; try { - return await AssetManager.fetchAssetIds(appId, asset); + const result = await AssetManager.fetchAssetIds(appId, asset); + + // If it returned an actual array with results, use it + if (Array.isArray(result) && result.length > 0 && result[0]) { + return result; + } + + // fetchAssetIds returned empty/broken — try external-assets API + const externalUrls = asset.filter( + (url) => url && (url.startsWith("http:") || url.startsWith("https:")), + ); + if (externalUrls.length === 0) return []; + + return await resolveExternalAssets(externalUrls, appId); } catch (error) { console.error("[Multi-Scrobbler] Failed to fetch assets:", error); return [];