mirror of
https://github.com/th-ch/youtube-music.git
synced 2026-01-11 18:41:47 +00:00
fix(discord): improve activity management and state verification in Discord integration
This commit is contained in:
@ -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();
|
||||||
|
|||||||
Reference in New Issue
Block a user