Skip to content

Commit

Permalink
DiscordRPC - Native Working
Browse files Browse the repository at this point in the history
  • Loading branch information
Inrixia committed Jun 25, 2024
1 parent 3fbe29f commit 5de20ab
Show file tree
Hide file tree
Showing 3 changed files with 60 additions and 62 deletions.
File renamed without changes.
71 changes: 9 additions & 62 deletions plugins/DiscordRPC/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,25 +1,13 @@
import { store, intercept } from "@neptune";
import { getMediaURLFromID } from "@neptune/utils";
import { Presence } from "discord-rpc";
import { intercept } from "@neptune";
import { html } from "@neptune/voby";

import { DiscordRPC } from "./DiscordRPC";

// @ts-expect-error Types dont include @plugin
import { storage } from "@plugin";

import { MediaItem } from "neptune-types/tidal";
import { SwitchSetting } from "@inrixia/lib/components/SwitchSetting";
import getPlaybackControl from "@inrixia/lib/getPlaybackControl";
import { TrackItemCache } from "@inrixia/lib/Caches/TrackItemCache";

const rpcClient = new DiscordRPC("1130698654987067493");

const STR_MAX_LEN = 127;
const formatLongString = (s?: string) => {
if (s === undefined) return "";
return s.length >= STR_MAX_LEN ? s.slice(0, STR_MAX_LEN - 3) + "..." : s;
};
import { updateRPC } from "./updateRPC.native";

enum AudioQuality {
HiRes = "HI_RES_LOSSLESS",
Expand All @@ -42,63 +30,22 @@ interface PlaybackContext {
playbackSessionId: string;
sampleRate: number | null;
}
const unloadTimeUpdate = intercept("playbackControls/TIME_UPDATE", ([current]) => {
updateRPC(current);
export const onUnload = intercept("playbackControls/TIME_UPDATE", ([current]) => {
onTimeUpdate();
});

const updateRPC = async (currentTime?: number) => {
const onTimeUpdate = async () => {
const { playbackContext, playbackState, latestCurrentTime } = getPlaybackControl();
currentTime ??= latestCurrentTime;
if (playbackState === undefined || latestCurrentTime === undefined || playbackContext === undefined) return;

const mediaItemId = (<PlaybackContext | null | undefined>playbackContext)?.actualProductId;
const mediaItemId = playbackContext.actualProductId;
if (mediaItemId === undefined) return;

const currentlyPlaying = await TrackItemCache.ensure(mediaItemId);
if (currentlyPlaying === undefined) return;

const _rpcClient = await rpcClient.ensureRPC().catch((err) => console.error("Failed to connect to DiscordRPC", err));
if (_rpcClient === undefined) return;

const activityState: Presence = {
buttons: [],
};
if (currentlyPlaying.url) activityState.buttons?.push({ url: currentlyPlaying.url, label: "Play on Tidal" });

// Pause indicator
if (playbackState === "NOT_PLAYING") {
if (storage.keepRpcOnPause === false) return _rpcClient.clearActivity();
activityState.smallImageKey = "paused-icon";
activityState.smallImageText = "Paused";
} else if (currentlyPlaying.duration !== undefined && currentTime !== undefined) {
// Playback/Time
activityState.startTimestamp = Math.floor(Date.now() / 1000);
activityState.endTimestamp = Math.floor((Date.now() + (currentlyPlaying.duration - currentTime) * 1000) / 1000);
}

// Album
if (currentlyPlaying.album !== undefined) {
activityState.largeImageKey = getMediaURLFromID(currentlyPlaying.album.cover);
activityState.largeImageText = formatLongString(currentlyPlaying.album.title);
}

// Title/Artist
const artist = `by ${currentlyPlaying?.artist?.name ?? currentlyPlaying.artists?.[0]?.name ?? "Unknown Artist"}`;
const desc = `${currentlyPlaying.title} ${artist}`;
if (desc.length >= 32) {
activityState.details = formatLongString(currentlyPlaying.title);
activityState.state = formatLongString(artist);
} else {
activityState.details = formatLongString(desc);
}

return _rpcClient.setActivity(activityState);
updateRPC(currentlyPlaying, playbackState, latestCurrentTime, storage.keepRpcOnPause);
};

export async function onUnload() {
unloadTimeUpdate();
await rpcClient.cleanp();
}
updateRPC();
onTimeUpdate();

storage.keepRpcOnPause ??= false;
export function Settings() {
Expand Down
51 changes: 51 additions & 0 deletions plugins/DiscordRPC/src/updateRPC.native.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import { Presence } from "discord-rpc";
import { DiscordRPC } from "./DiscordRPC.native";
import { PlaybackState, TrackItem } from "neptune-types/tidal";

const rpcClient = new DiscordRPC("1130698654987067493");

const STR_MAX_LEN = 127;
const formatLongString = (s?: string) => {
if (s === undefined) return "";
return s.length >= STR_MAX_LEN ? s.slice(0, STR_MAX_LEN - 3) + "..." : s;
};
const getMediaURLFromID = (id?: string, path = "/1280x1280.jpg") => (id ? "https://resources.tidal.com/images/" + id.split("-").join("/") + path : undefined);

export const updateRPC = async (currentlyPlaying: TrackItem, playbackState: PlaybackState, currentTime: number, keepRpcOnPause: boolean) => {
const _rpcClient = await rpcClient.ensureRPC().catch((err) => console.error("Failed to connect to DiscordRPC", err));
if (_rpcClient === undefined) return;

const activityState: Presence = {
buttons: [],
};
if (currentlyPlaying.url) activityState.buttons?.push({ url: currentlyPlaying.url, label: "Play on Tidal" });

// Pause indicator
if (playbackState === "NOT_PLAYING") {
if (keepRpcOnPause === false) return _rpcClient.clearActivity();
activityState.smallImageKey = "paused-icon";
activityState.smallImageText = "Paused";
} else if (currentlyPlaying.duration !== undefined && currentTime !== undefined) {
// Playback/Time
activityState.startTimestamp = Math.floor(Date.now() / 1000);
activityState.endTimestamp = Math.floor((Date.now() + (currentlyPlaying.duration - currentTime) * 1000) / 1000);
}

// Album
if (currentlyPlaying.album !== undefined) {
activityState.largeImageKey = getMediaURLFromID(currentlyPlaying.album.cover);
activityState.largeImageText = formatLongString(currentlyPlaying.album.title);
}

// Title/Artist
const artist = `by ${currentlyPlaying?.artist?.name ?? currentlyPlaying.artists?.[0]?.name ?? "Unknown Artist"}`;
const desc = `${currentlyPlaying.title} ${artist}`;
if (desc.length >= 32) {
activityState.details = formatLongString(currentlyPlaying.title);
activityState.state = formatLongString(artist);
} else {
activityState.details = formatLongString(desc);
}

return _rpcClient.setActivity(activityState);
};

0 comments on commit 5de20ab

Please sign in to comment.