diff --git a/src/equicordplugins/gensokyoRadioRPC/index.tsx b/src/equicordplugins/gensokyoRadioRPC/index.tsx new file mode 100644 index 000000000..b1bc2d7f0 --- /dev/null +++ b/src/equicordplugins/gensokyoRadioRPC/index.tsx @@ -0,0 +1,104 @@ +/* + * Vencord, a Discord client mod + * Copyright (c) 2024 Vendicated and contributors + * SPDX-License-Identifier: GPL-3.0-or-later + */ + +import { definePluginSettings } from "@api/Settings"; +import { Paragraph } from "@components/Paragraph"; +import { Devs, EquicordDevs } from "@utils/constants"; +import definePlugin, { OptionType, PluginNative, ReporterTestable } from "@utils/types"; +import { Activity } from "@vencord/discord-types"; +import { ActivityFlags, ActivityType } from "@vencord/discord-types/enums"; +import { ApplicationAssetUtils, FluxDispatcher } from "@webpack/common"; + + +const Native = VencordNative.pluginHelpers.GensokyoRadioRPC as PluginNative; + +const applicationId = "1253772057926303804"; + +function setActivity(activity: Activity | null) { + FluxDispatcher.dispatch({ + type: "LOCAL_ACTIVITY_UPDATE", + activity, + socketId: "GensokyoRadio", + }); +} + +function getImageAsset(data: string) { + return ApplicationAssetUtils.fetchAssetIds(applicationId, [data]).then(ids => ids[0]); +} + +const settings = definePluginSettings({ + refreshInterval: { + type: OptionType.SLIDER, + description: "The interval between activity refreshes (seconds)", + markers: [1, 2, 2.5, 3, 5, 10, 15], + default: 15, + restartNeeded: true, + } +}); + +export default definePlugin({ + name: "GensokyoRadioRPC", + description: "Discord rich presence for Gensokyo Radio!", + authors: [Devs.RyanCaoDev, EquicordDevs.Prince527], + reporterTestable: ReporterTestable.None, + + settingsAboutComponent() { + return <> + + Discord rich presence for Gensokyo Radio! + + ; + }, + + settings, + + start() { + this.updatePresence(); + this.updateInterval = setInterval(() => { this.updatePresence(); }, settings.store.refreshInterval * 1000); + }, + + stop() { + clearInterval(this.updateInterval); + FluxDispatcher.dispatch({ type: "LOCAL_ACTIVITY_UPDATE", activity: null }); + }, + + updatePresence() { + this.getActivity().then(activity => { setActivity(activity); }); + }, + + async getActivity(): Promise { + const trackData = await Native.fetchTrackData(); + if (!trackData) return null; + + return { + application_id: applicationId, + + name: "Gensokyo Radio", + details: trackData.title, + state: trackData.artist, + + timestamps: { + // start: Date.now() - (trackData.position * 1000), + start: trackData.position * 1000, + // end: Date.now() - (trackData.position * 1000) + (trackData.duration * 1000), + end: trackData.duration * 1000, + }, + + assets: { + large_image: await getImageAsset(trackData.artwork), + large_text: trackData.album, + small_image: await getImageAsset("logo"), + small_text: "Gensokyo Radio" + }, + + buttons: undefined, + metadata: { button_urls: undefined }, + + type: ActivityType.LISTENING, + flags: ActivityFlags.INSTANCE, + }; + } +}); diff --git a/src/equicordplugins/gensokyoRadioRPC/native.ts b/src/equicordplugins/gensokyoRadioRPC/native.ts new file mode 100644 index 000000000..69dbe37a0 --- /dev/null +++ b/src/equicordplugins/gensokyoRadioRPC/native.ts @@ -0,0 +1,20 @@ +/* + * Vencord, a Discord client mod + * Copyright (c) 2024 Vendicated and contributors + * SPDX-License-Identifier: GPL-3.0-or-later + */ + +import type { TrackData } from "./types"; + +export async function fetchTrackData(): Promise { + const song = await (await fetch("https://gensokyoradio.net/api/station/playing/")).json(); + + return { + title: song.SONGINFO.TITLE, + album: song.SONGINFO.ALBUM, + artist: song.SONGINFO.ARTIST, + position: song.SONGTIMES.SONGSTART, + duration: song.SONGTIMES.SONGEND, + artwork: song.MISC.ALBUMART ? `https://gensokyoradio.net/images/albums/500/${song.MISC.ALBUMART}` : "undefined", + }; +} diff --git a/src/equicordplugins/gensokyoRadioRPC/types.ts b/src/equicordplugins/gensokyoRadioRPC/types.ts new file mode 100644 index 000000000..21b44194e --- /dev/null +++ b/src/equicordplugins/gensokyoRadioRPC/types.ts @@ -0,0 +1,48 @@ +/* + * Vencord, a Discord client mod + * Copyright (c) 2024 Vendicated and contributors + * SPDX-License-Identifier: GPL-3.0-or-later + */ + +export interface ActivityAssets { + large_image?: string; + large_text?: string; + small_image?: string; + small_text?: string; +} + +export interface Activity { + state: string; + details?: string; + timestamps?: { + start?: number; + end?: number; + }; + assets?: ActivityAssets; + buttons?: Array; + name: string; + application_id: string; + metadata?: { + button_urls?: Array; + }; + type: number; + flags: number; +} + +export interface ActivityAssets { + large_image?: string; + large_text?: string; + small_image?: string; + small_text?: string; +} + +export interface TrackData { + title: string; + album: string; + artist: string; + + artwork: string; + + position: number; + duration: number; +} diff --git a/src/plugins/imageZoom/index.tsx b/src/plugins/imageZoom/index.tsx index 3d25eda96..0f10db3e9 100644 --- a/src/plugins/imageZoom/index.tsx +++ b/src/plugins/imageZoom/index.tsx @@ -234,11 +234,12 @@ export default definePlugin({ renderMagnifier(instance) { try { if (instance.props.id === ELEMENT_ID) { - if (!this.currentMagnifierElement) { - this.currentMagnifierElement = ; + if (!this.root) { this.root = createRoot(this.element!); - this.root.render(this.currentMagnifierElement); } + + this.currentMagnifierElement = ; + this.root.render(this.currentMagnifierElement); } } catch (error) { new Logger("ImageZoom").error("Failed to render magnifier:", error); @@ -246,7 +247,6 @@ export default definePlugin({ }, updateMagnifier(instance) { - this.unMountMagnifier(); this.renderMagnifier(instance); },