mirror of
https://github.com/jeffvli/feishin.git
synced 2026-06-16 16:34:24 +02:00
adjust jellyfin scrobble conditions, remove status change event (#1274)
This commit is contained in:
@@ -69,6 +69,7 @@ export const useScrobble = () => {
|
|||||||
const previousSongRef = useRef<QueueSong | undefined>(undefined);
|
const previousSongRef = useRef<QueueSong | undefined>(undefined);
|
||||||
const previousTimestampRef = useRef<number>(0);
|
const previousTimestampRef = useRef<number>(0);
|
||||||
const lastProgressEventRef = useRef<number>(0);
|
const lastProgressEventRef = useRef<number>(0);
|
||||||
|
const lastSeekEventRef = useRef<number>(0);
|
||||||
const songChangeTimeoutRef = useRef<ReturnType<typeof setTimeout> | undefined>(undefined);
|
const songChangeTimeoutRef = useRef<ReturnType<typeof setTimeout> | undefined>(undefined);
|
||||||
const notifyTimeoutRef = useRef<ReturnType<typeof setTimeout> | undefined>(undefined);
|
const notifyTimeoutRef = useRef<ReturnType<typeof setTimeout> | undefined>(undefined);
|
||||||
|
|
||||||
@@ -153,8 +154,10 @@ export const useScrobble = () => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const preventScrobbleFromProgress = currentSong._serverType === ServerType.JELLYFIN;
|
||||||
|
|
||||||
// Check if we should submit scrobble based on conditions
|
// Check if we should submit scrobble based on conditions
|
||||||
if (!isCurrentSongScrobbled) {
|
if (!isCurrentSongScrobbled && !preventScrobbleFromProgress) {
|
||||||
const shouldSubmitScrobble = checkScrobbleConditions({
|
const shouldSubmitScrobble = checkScrobbleConditions({
|
||||||
scrobbleAtDurationMs: (scrobbleSettings?.scrobbleAtDuration ?? 0) * 1000,
|
scrobbleAtDurationMs: (scrobbleSettings?.scrobbleAtDuration ?? 0) * 1000,
|
||||||
scrobbleAtPercentage: scrobbleSettings?.scrobbleAtPercentage,
|
scrobbleAtPercentage: scrobbleSettings?.scrobbleAtPercentage,
|
||||||
@@ -331,123 +334,123 @@ export const useScrobble = () => {
|
|||||||
],
|
],
|
||||||
);
|
);
|
||||||
|
|
||||||
const handleScrobbleFromStatusChange = useCallback(
|
// const handleScrobbleFromStatusChange = useCallback(
|
||||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
// // eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||||
(properties: { status: PlayerStatus }, _prev: { status: PlayerStatus }) => {
|
// (properties: { status: PlayerStatus }, _prev: { status: PlayerStatus }) => {
|
||||||
if (!isScrobbleEnabled || isPrivateModeEnabled) return;
|
// if (!isScrobbleEnabled || isPrivateModeEnabled) return;
|
||||||
|
|
||||||
const currentSong = usePlayerStore.getState().getCurrentSong();
|
// const currentSong = usePlayerStore.getState().getCurrentSong();
|
||||||
const currentTimestamp =
|
// const currentTimestamp =
|
||||||
usePlayerStore.getState().player.index >= 0 ? previousTimestampRef.current : 0;
|
// usePlayerStore.getState().player.index >= 0 ? previousTimestampRef.current : 0;
|
||||||
|
|
||||||
if (!currentSong?.id) return;
|
// if (!currentSong?.id) return;
|
||||||
|
|
||||||
const position =
|
// const position =
|
||||||
currentSong._serverType === ServerType.JELLYFIN
|
// currentSong._serverType === ServerType.JELLYFIN
|
||||||
? currentTimestamp * 1e7
|
// ? currentTimestamp * 1e7
|
||||||
: undefined;
|
// : undefined;
|
||||||
|
|
||||||
const currentStatus = properties.status;
|
// const currentStatus = properties.status;
|
||||||
|
|
||||||
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',
|
||||||
id: currentSong.id,
|
// id: currentSong.id,
|
||||||
position,
|
// position,
|
||||||
submission: false,
|
// submission: false,
|
||||||
},
|
// },
|
||||||
},
|
// },
|
||||||
{
|
// {
|
||||||
onSuccess: () => {
|
// onSuccess: () => {
|
||||||
logFn.debug(logMsg[LogCategory.SCROBBLE].scrobbledUnpause, {
|
// logFn.debug(logMsg[LogCategory.SCROBBLE].scrobbledUnpause, {
|
||||||
category: LogCategory.SCROBBLE,
|
// category: LogCategory.SCROBBLE,
|
||||||
meta: {
|
// meta: {
|
||||||
id: currentSong.id,
|
// 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',
|
||||||
id: currentSong.id,
|
// id: currentSong.id,
|
||||||
position,
|
// position,
|
||||||
submission: false,
|
// submission: false,
|
||||||
},
|
// },
|
||||||
},
|
// },
|
||||||
{
|
// {
|
||||||
onSuccess: () => {
|
// onSuccess: () => {
|
||||||
logFn.debug(logMsg[LogCategory.SCROBBLE].scrobbledPause, {
|
// logFn.debug(logMsg[LogCategory.SCROBBLE].scrobbledPause, {
|
||||||
category: LogCategory.SCROBBLE,
|
// category: LogCategory.SCROBBLE,
|
||||||
meta: {
|
// meta: {
|
||||||
id: currentSong.id,
|
// 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();
|
||||||
const isFirstTrackInQueue = usePlayerStore.getState().isFirstTrackInQueue();
|
// const isFirstTrackInQueue = usePlayerStore.getState().isFirstTrackInQueue();
|
||||||
const previousTimestamp = previousTimestampRef.current;
|
// const previousTimestamp = previousTimestampRef.current;
|
||||||
|
|
||||||
const shouldSubmitScrobble = checkScrobbleConditions({
|
// const shouldSubmitScrobble = checkScrobbleConditions({
|
||||||
scrobbleAtDurationMs: (scrobbleSettings?.scrobbleAtDuration ?? 0) * 1000,
|
// scrobbleAtDurationMs: (scrobbleSettings?.scrobbleAtDuration ?? 0) * 1000,
|
||||||
scrobbleAtPercentage: scrobbleSettings?.scrobbleAtPercentage,
|
// scrobbleAtPercentage: scrobbleSettings?.scrobbleAtPercentage,
|
||||||
// If scrobbling the last song in the queue, use the previous time
|
// // If scrobbling the last song in the queue, use the previous time
|
||||||
// Note: if queue has one item (both first and last), use current time
|
// // Note: if queue has one item (both first and last), use current time
|
||||||
songCompletedDurationMs:
|
// songCompletedDurationMs:
|
||||||
(isLastTrackInQueue && !isFirstTrackInQueue
|
// (isLastTrackInQueue && !isFirstTrackInQueue
|
||||||
? previousTimestamp
|
// ? previousTimestamp
|
||||||
: currentTimestamp) * 1000,
|
// : currentTimestamp) * 1000,
|
||||||
songDurationMs: currentSong.duration,
|
// songDurationMs: currentSong.duration,
|
||||||
});
|
// });
|
||||||
|
|
||||||
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: () => {
|
// onSuccess: () => {
|
||||||
logFn.debug(logMsg[LogCategory.SCROBBLE].scrobbledSubmission, {
|
// logFn.debug(logMsg[LogCategory.SCROBBLE].scrobbledSubmission, {
|
||||||
category: LogCategory.SCROBBLE,
|
// category: LogCategory.SCROBBLE,
|
||||||
meta: {
|
// meta: {
|
||||||
id: currentSong.id,
|
// id: currentSong.id,
|
||||||
reason: 'from status change',
|
// reason: 'from status change',
|
||||||
},
|
// },
|
||||||
});
|
// });
|
||||||
},
|
// },
|
||||||
},
|
// },
|
||||||
);
|
// );
|
||||||
|
|
||||||
setIsCurrentSongScrobbled(true);
|
// setIsCurrentSongScrobbled(true);
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
},
|
// },
|
||||||
[
|
// [
|
||||||
isScrobbleEnabled,
|
// isScrobbleEnabled,
|
||||||
isPrivateModeEnabled,
|
// isPrivateModeEnabled,
|
||||||
scrobbleSettings?.scrobbleAtDuration,
|
// scrobbleSettings?.scrobbleAtDuration,
|
||||||
scrobbleSettings?.scrobbleAtPercentage,
|
// scrobbleSettings?.scrobbleAtPercentage,
|
||||||
isCurrentSongScrobbled,
|
// isCurrentSongScrobbled,
|
||||||
sendScrobble,
|
// sendScrobble,
|
||||||
],
|
// ],
|
||||||
);
|
// );
|
||||||
|
|
||||||
const handleScrobbleFromSeek = useCallback(
|
const handleScrobbleFromSeek = useCallback(
|
||||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||||
@@ -458,8 +461,19 @@ export const useScrobble = () => {
|
|||||||
|
|
||||||
if (!currentSong?.id || currentSong._serverType !== ServerType.JELLYFIN) return;
|
if (!currentSong?.id || currentSong._serverType !== ServerType.JELLYFIN) return;
|
||||||
|
|
||||||
|
const now = Date.now();
|
||||||
|
const timeSinceLastSeek = now - lastSeekEventRef.current;
|
||||||
|
|
||||||
|
// Only allow seek scrobble once per second
|
||||||
|
if (timeSinceLastSeek < 1000) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
const position = properties.timestamp * 1e7;
|
const position = properties.timestamp * 1e7;
|
||||||
|
|
||||||
|
lastProgressEventRef.current = properties.timestamp;
|
||||||
|
lastSeekEventRef.current = now;
|
||||||
|
|
||||||
sendScrobble.mutate(
|
sendScrobble.mutate(
|
||||||
{
|
{
|
||||||
apiClientProps: { serverId: currentSong._serverId || '' },
|
apiClientProps: { serverId: currentSong._serverId || '' },
|
||||||
@@ -499,13 +513,7 @@ export const useScrobble = () => {
|
|||||||
onCurrentSongChange: handleScrobbleFromSongChange,
|
onCurrentSongChange: handleScrobbleFromSongChange,
|
||||||
onPlayerProgress: handleProgressUpdate,
|
onPlayerProgress: handleProgressUpdate,
|
||||||
onPlayerSeekToTimestamp: handleScrobbleFromSeek,
|
onPlayerSeekToTimestamp: handleScrobbleFromSeek,
|
||||||
onPlayerStatus: handleScrobbleFromStatusChange,
|
|
||||||
},
|
},
|
||||||
[
|
[handleScrobbleFromSongChange, handleProgressUpdate, handleScrobbleFromSeek],
|
||||||
handleScrobbleFromSongChange,
|
|
||||||
handleProgressUpdate,
|
|
||||||
handleScrobbleFromSeek,
|
|
||||||
handleScrobbleFromStatusChange,
|
|
||||||
],
|
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user