fix(discord): improve activity management and state verification in Discord integration

This commit is contained in:
MindLated
2025-05-10 22:47:28 +02:00
parent 0c1d300103
commit d88406447e

View File

@ -39,10 +39,9 @@ const info: Info = {
const refreshCallbacks: (() => void)[] = []; const refreshCallbacks: (() => void)[] = [];
const truncateString = (str: string, length: number): string => { const truncateString = (str: string, length: number): string => {
if (str.length > length) if (str.length > length) return `${str.substring(0, length - 3)}...`;
return `${str.substring(0, length - 3)}...`;
return str; return str;
} };
const resetInfo = () => { const resetInfo = () => {
info.ready = false; info.ready = false;
@ -119,7 +118,7 @@ export const registerRefresh = (cb: () => void) => refreshCallbacks.push(cb);
export const isConnected = () => info.rpc?.isConnected; export const isConnected = () => info.rpc?.isConnected;
let lastActivitySongId: string | null = null; let lastActivitySongId: string | null = null;
let lastPausedState: boolean | null = null; let lastPausedState: boolean = false; // Initialize with a default boolean
let lastElapsedSeconds: number = 0; let lastElapsedSeconds: number = 0;
let updateTimeout: NodeJS.Timeout | null = null; let updateTimeout: NodeJS.Timeout | null = null;
let lastProgressUpdate: number = 0; // timestamp of the last throttled update let lastProgressUpdate: number = 0; // timestamp of the last throttled update
@ -130,7 +129,24 @@ function isSeek(oldSec: number, newSec: number) {
return Math.abs((newSec ?? 0) - (oldSec ?? 0)) > 2; return Math.abs((newSec ?? 0) - (oldSec ?? 0)) > 2;
} }
function sendActivityToDiscord(songInfo: SongInfo, config: DiscordPluginConfig) { function manageActivityClearTimer(
isPaused: boolean | undefined,
config: DiscordPluginConfig,
) {
clearTimeout(clearActivity); // Clear any existing timer
// Set a new timer only if the song is paused and the feature is enabled
if (isPaused === true && config.activityTimeoutEnabled) {
clearActivity = setTimeout(
() => info.rpc.user?.clearActivity().catch(console.error),
config.activityTimeoutTime ?? 10_000,
);
}
}
function sendActivityToDiscord(
songInfo: SongInfo,
config: DiscordPluginConfig,
) {
if (songInfo.title.length === 0 && songInfo.artist.length === 0) { if (songInfo.title.length === 0 && songInfo.artist.length === 0) {
return; return;
} }
@ -219,7 +235,10 @@ export const backend = createBackend<
updateTimeout = null; updateTimeout = null;
sendActivityToDiscord(songInfo, config); sendActivityToDiscord(songInfo, config);
lastActivitySongId = songInfo.videoId; lastActivitySongId = songInfo.videoId;
lastPausedState = songInfo.isPaused ?? null; // Update lastPausedState only if songInfo.isPaused is a boolean
if (typeof songInfo.isPaused === 'boolean') {
lastPausedState = songInfo.isPaused;
}
lastElapsedSeconds = songInfo.elapsedSeconds ?? 0; lastElapsedSeconds = songInfo.elapsedSeconds ?? 0;
lastProgressUpdate = now; lastProgressUpdate = now;
return; return;
@ -231,30 +250,26 @@ export const backend = createBackend<
lastElapsedSeconds = songInfo.elapsedSeconds ?? 0; lastElapsedSeconds = songInfo.elapsedSeconds ?? 0;
} else { } else {
if (updateTimeout) clearTimeout(updateTimeout); if (updateTimeout) clearTimeout(updateTimeout);
// Capture current state for verification before sending // Capture a snapshot of songInfo for the timeout callback
const expectedVideoId = songInfo.videoId; const songInfoSnapshot = { ...songInfo };
const expectedPaused = songInfo.isPaused; updateTimeout = setTimeout(
updateTimeout = setTimeout(() => { () => {
// Only send if state hasn't changed // Only send if the current global song state still matches what was expected
// at the time the timeout was set (i.e., the snapshot's state)
if ( if (
info.lastSongInfo?.videoId === expectedVideoId && info.lastSongInfo?.videoId === songInfoSnapshot.videoId &&
info.lastSongInfo?.isPaused === expectedPaused info.lastSongInfo?.isPaused === songInfoSnapshot.isPaused
) { ) {
sendActivityToDiscord(info.lastSongInfo, config); // Use the snapshot for sending activity and updating last elapsed time
sendActivityToDiscord(songInfoSnapshot, config);
lastProgressUpdate = Date.now(); lastProgressUpdate = Date.now();
lastElapsedSeconds = info.lastSongInfo.elapsedSeconds ?? 0; lastElapsedSeconds = songInfoSnapshot.elapsedSeconds ?? 0;
} }
}, PROGRESS_THROTTLE_MS - (now - lastProgressUpdate)); },
} PROGRESS_THROTTLE_MS - (now - lastProgressUpdate),
if (songInfo.isPaused && config.activityTimeoutEnabled) {
clearTimeout(clearActivity);
clearActivity = setTimeout(
() => info.rpc.user?.clearActivity().catch(console.error),
config.activityTimeoutTime ?? 10_000,
); );
} else {
clearTimeout(clearActivity);
} }
manageActivityClearTimer(songInfo.isPaused, config);
}, },
async start(ctx) { async start(ctx) {
this.config = await ctx.getConfig(); this.config = await ctx.getConfig();