add logs to scrobble events

This commit is contained in:
jeffvli
2025-11-28 13:25:55 -08:00
parent 7016446be7
commit 2f32534cf9
3 changed files with 189 additions and 92 deletions
@@ -3,6 +3,8 @@ import { useCallback, useRef, useState } from 'react';
import { usePlayerEvents } from '/@/renderer/features/player/audio-player/hooks/use-player-events'; import { usePlayerEvents } from '/@/renderer/features/player/audio-player/hooks/use-player-events';
import { useSendScrobble } from '/@/renderer/features/player/mutations/scrobble-mutation'; import { useSendScrobble } from '/@/renderer/features/player/mutations/scrobble-mutation';
import { useAppStore, usePlaybackSettings, usePlayerStore } from '/@/renderer/store'; import { useAppStore, usePlaybackSettings, usePlayerStore } from '/@/renderer/store';
import { LogCategory, logFn } from '/@/renderer/utils/logger';
import { logMsg } from '/@/renderer/utils/logger-message';
import { QueueSong, ServerType } from '/@/shared/types/domain-types'; import { QueueSong, ServerType } from '/@/shared/types/domain-types';
import { PlayerStatus } from '/@/shared/types/types'; import { PlayerStatus } from '/@/shared/types/types';
@@ -90,33 +92,10 @@ export const useScrobble = () => {
previousTime >= 10 && // Was playing for at least 10 seconds previousTime >= 10 && // Was playing for at least 10 seconds
currentSong._uniqueId === previousSongRef.current?._uniqueId currentSong._uniqueId === previousSongRef.current?._uniqueId
) { ) {
// Handle song restart scrobble
const shouldSubmitScrobble = checkScrobbleConditions({
scrobbleAtDurationMs: (scrobbleSettings?.scrobbleAtDuration ?? 0) * 1000,
scrobbleAtPercentage: scrobbleSettings?.scrobbleAtPercentage,
songCompletedDurationMs: previousTime * 1000,
songDurationMs: currentSong.duration,
});
if (!isCurrentSongScrobbled && shouldSubmitScrobble) {
const position =
currentSong._serverType === ServerType.JELLYFIN
? previousTime * 1e7
: undefined;
sendScrobble.mutate({
apiClientProps: { serverId: currentSong._serverId || '' },
query: {
id: currentSong.id,
position,
submission: true,
},
});
}
// Send start event for Jellyfin on restart // Send start event for Jellyfin on restart
if (currentSong._serverType === ServerType.JELLYFIN) { if (currentSong._serverType === ServerType.JELLYFIN) {
sendScrobble.mutate({ sendScrobble.mutate(
{
apiClientProps: { serverId: currentSong._serverId || '' }, apiClientProps: { serverId: currentSong._serverId || '' },
query: { query: {
event: 'start', event: 'start',
@@ -124,7 +103,18 @@ export const useScrobble = () => {
position: 0, position: 0,
submission: false, submission: false,
}, },
},
{
onSuccess: () => {
logFn.debug(logMsg[LogCategory.SCROBBLE].scrobbledStart, {
category: LogCategory.SCROBBLE,
meta: {
id: currentSong.id,
},
}); });
},
},
);
} }
setIsCurrentSongScrobbled(false); setIsCurrentSongScrobbled(false);
@@ -138,7 +128,8 @@ export const useScrobble = () => {
const timeSinceLastProgress = currentTime - lastProgressEventRef.current; const timeSinceLastProgress = currentTime - lastProgressEventRef.current;
if (timeSinceLastProgress >= 10) { if (timeSinceLastProgress >= 10) {
const position = currentTime * 1e7; const position = currentTime * 1e7;
sendScrobble.mutate({ sendScrobble.mutate(
{
apiClientProps: { serverId: currentSong._serverId || '' }, apiClientProps: { serverId: currentSong._serverId || '' },
query: { query: {
event: 'timeupdate', event: 'timeupdate',
@@ -146,7 +137,18 @@ export const useScrobble = () => {
position, position,
submission: false, submission: false,
}, },
},
{
onSuccess: () => {
logFn.debug(logMsg[LogCategory.SCROBBLE].scrobbledTimeupdate, {
category: LogCategory.SCROBBLE,
meta: {
id: currentSong.id,
},
}); });
},
},
);
lastProgressEventRef.current = currentTime; lastProgressEventRef.current = currentTime;
} }
} }
@@ -166,14 +168,27 @@ export const useScrobble = () => {
? currentTime * 1e7 ? currentTime * 1e7
: undefined; : undefined;
sendScrobble.mutate({ sendScrobble.mutate(
{
apiClientProps: { serverId: currentSong._serverId || '' }, apiClientProps: { serverId: currentSong._serverId || '' },
query: { query: {
id: currentSong.id, id: currentSong.id,
position, position,
submission: true, submission: true,
}, },
},
{
onSuccess: () => {
logFn.debug(logMsg[LogCategory.SCROBBLE].scrobbledSubmission, {
category: LogCategory.SCROBBLE,
meta: {
id: currentSong.id,
reason: 'from song progress',
},
}); });
},
},
);
setIsCurrentSongScrobbled(true); setIsCurrentSongScrobbled(true);
} }
@@ -244,14 +259,27 @@ export const useScrobble = () => {
? previousTimestamp * 1e7 ? previousTimestamp * 1e7
: undefined; : undefined;
sendScrobble.mutate({ sendScrobble.mutate(
{
apiClientProps: { serverId: previousSong._serverId || '' }, apiClientProps: { serverId: previousSong._serverId || '' },
query: { query: {
id: previousSong.id, id: previousSong.id,
position, position,
submission: true, submission: true,
}, },
},
{
onSuccess: () => {
logFn.debug(logMsg[LogCategory.SCROBBLE].scrobbledStart, {
category: LogCategory.SCROBBLE,
meta: {
id: previousSong.id,
reason: 'from song change',
},
}); });
},
},
);
} }
} }
@@ -265,7 +293,8 @@ export const useScrobble = () => {
// Send start scrobble when song changes and the new song is playing // Send start scrobble when song changes and the new song is playing
if (currentStatus === PlayerStatus.PLAYING && currentSong?.id) { if (currentStatus === PlayerStatus.PLAYING && currentSong?.id) {
sendScrobble.mutate({ sendScrobble.mutate(
{
apiClientProps: { serverId: currentSong._serverId || '' }, apiClientProps: { serverId: currentSong._serverId || '' },
query: { query: {
event: 'start', event: 'start',
@@ -273,7 +302,18 @@ export const useScrobble = () => {
position: 0, position: 0,
submission: false, submission: false,
}, },
},
{
onSuccess: () => {
logFn.debug(logMsg[LogCategory.SCROBBLE].scrobbledStart, {
category: LogCategory.SCROBBLE,
meta: {
id: currentSong.id,
},
}); });
},
},
);
} }
}, 2000); }, 2000);
@@ -311,7 +351,8 @@ export const useScrobble = () => {
if (currentStatus === PlayerStatus.PLAYING) { if (currentStatus === PlayerStatus.PLAYING) {
// Send unpause event // Send unpause event
sendScrobble.mutate({ sendScrobble.mutate(
{
apiClientProps: { serverId: currentSong._serverId || '' }, apiClientProps: { serverId: currentSong._serverId || '' },
query: { query: {
event: 'unpause', event: 'unpause',
@@ -319,10 +360,22 @@ export const useScrobble = () => {
position, position,
submission: false, submission: false,
}, },
},
{
onSuccess: () => {
logFn.debug(logMsg[LogCategory.SCROBBLE].scrobbledUnpause, {
category: LogCategory.SCROBBLE,
meta: {
id: currentSong.id,
},
}); });
},
},
);
} else if (currentSong._serverType === ServerType.JELLYFIN) { } else if (currentSong._serverType === ServerType.JELLYFIN) {
// Send pause event for Jellyfin // Send pause event for Jellyfin
sendScrobble.mutate({ sendScrobble.mutate(
{
apiClientProps: { serverId: currentSong._serverId || '' }, apiClientProps: { serverId: currentSong._serverId || '' },
query: { query: {
event: 'pause', event: 'pause',
@@ -330,7 +383,18 @@ export const useScrobble = () => {
position, position,
submission: false, submission: false,
}, },
},
{
onSuccess: () => {
logFn.debug(logMsg[LogCategory.SCROBBLE].scrobbledPause, {
category: LogCategory.SCROBBLE,
meta: {
id: currentSong.id,
},
}); });
},
},
);
} else { } else {
// For non-Jellyfin servers, check scrobble conditions on pause // For non-Jellyfin servers, check scrobble conditions on pause
const isLastTrackInQueue = usePlayerStore.getState().isLastTrackInQueue(); const isLastTrackInQueue = usePlayerStore.getState().isLastTrackInQueue();
@@ -350,13 +414,26 @@ export const useScrobble = () => {
}); });
if (!isCurrentSongScrobbled && shouldSubmitScrobble) { if (!isCurrentSongScrobbled && shouldSubmitScrobble) {
sendScrobble.mutate({ sendScrobble.mutate(
{
apiClientProps: { serverId: currentSong._serverId || '' }, apiClientProps: { serverId: currentSong._serverId || '' },
query: { query: {
id: currentSong.id, id: currentSong.id,
submission: true, submission: true,
}, },
},
{
onSuccess: () => {
logFn.debug(logMsg[LogCategory.SCROBBLE].scrobbledSubmission, {
category: LogCategory.SCROBBLE,
meta: {
id: currentSong.id,
reason: 'from status change',
},
}); });
},
},
);
setIsCurrentSongScrobbled(true); setIsCurrentSongScrobbled(true);
} }
@@ -383,7 +460,8 @@ export const useScrobble = () => {
const position = properties.timestamp * 1e7; const position = properties.timestamp * 1e7;
sendScrobble.mutate({ sendScrobble.mutate(
{
apiClientProps: { serverId: currentSong._serverId || '' }, apiClientProps: { serverId: currentSong._serverId || '' },
query: { query: {
event: 'timeupdate', event: 'timeupdate',
@@ -391,8 +469,19 @@ export const useScrobble = () => {
position, position,
submission: false, submission: false,
}, },
},
{
onSuccess: () => {
logFn.debug(logMsg[LogCategory.SCROBBLE].scrobbledTimeupdate, {
category: LogCategory.SCROBBLE,
meta: {
id: currentSong.id,
},
}); });
}, },
},
);
},
[isScrobbleEnabled, isPrivateModeEnabled, sendScrobble], [isScrobbleEnabled, isPrivateModeEnabled, sendScrobble],
); );
+7
View File
@@ -45,5 +45,12 @@ export const logMsg = {
toggleRepeat: 'Toggle repeat', toggleRepeat: 'Toggle repeat',
toggleShuffle: 'Toggle shuffle', toggleShuffle: 'Toggle shuffle',
}, },
[LogCategory.SCROBBLE]: {
scrobbledPause: 'Scrobbled a pause event',
scrobbledStart: 'Scrobbled a start event',
scrobbledSubmission: 'Scrobbled a submission event',
scrobbledTimeupdate: 'Scrobbled a timeupdate event',
scrobbledUnpause: 'Scrobbled an unpause event',
},
[LogCategory.SYSTEM]: {}, [LogCategory.SYSTEM]: {},
}; };
+1
View File
@@ -5,6 +5,7 @@ export enum LogCategory {
API = 'api', API = 'api',
OTHER = 'other', OTHER = 'other',
PLAYER = 'player', PLAYER = 'player',
SCROBBLE = 'scrobble',
SYSTEM = 'system', SYSTEM = 'system',
} }