fix scrobble durations (#269)
* fix scrobble durations * Fix scrobble condition on last song in queue, normalize ms --------- Co-authored-by: jeffvli <jeffvictorli@gmail.com>
This commit is contained in:
parent
118a9f73d1
commit
6bac172bbe
1 changed files with 33 additions and 18 deletions
|
@ -36,17 +36,18 @@ Progress Events (Jellyfin only):
|
||||||
const checkScrobbleConditions = (args: {
|
const checkScrobbleConditions = (args: {
|
||||||
scrobbleAtDuration: number;
|
scrobbleAtDuration: number;
|
||||||
scrobbleAtPercentage: number;
|
scrobbleAtPercentage: number;
|
||||||
songCompletedDuration: number;
|
songCompletedDurationMs: number;
|
||||||
songDuration: number;
|
songDurationMs: number;
|
||||||
}) => {
|
}) => {
|
||||||
const { scrobbleAtDuration, scrobbleAtPercentage, songCompletedDuration, songDuration } = args;
|
const { scrobbleAtDuration, scrobbleAtPercentage, songCompletedDurationMs, songDurationMs } =
|
||||||
const percentageOfSongCompleted = songDuration
|
args;
|
||||||
? (songCompletedDuration / songDuration) * 100
|
const percentageOfSongCompleted = songDurationMs
|
||||||
|
? (songCompletedDurationMs / songDurationMs) * 100
|
||||||
: 0;
|
: 0;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
percentageOfSongCompleted >= scrobbleAtPercentage ||
|
percentageOfSongCompleted >= scrobbleAtPercentage ||
|
||||||
songCompletedDuration >= scrobbleAtDuration
|
songCompletedDurationMs >= scrobbleAtDuration
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -97,15 +98,15 @@ export const useScrobble = () => {
|
||||||
|
|
||||||
// const currentSong = current[0] as QueueSong | undefined;
|
// const currentSong = current[0] as QueueSong | undefined;
|
||||||
const previousSong = previous[0] as QueueSong;
|
const previousSong = previous[0] as QueueSong;
|
||||||
const previousSongTime = previous[1] as number;
|
const previousSongTimeSec = previous[1] as number;
|
||||||
|
|
||||||
// Send completion scrobble when song changes and a previous song exists
|
// Send completion scrobble when song changes and a previous song exists
|
||||||
if (previousSong?.id) {
|
if (previousSong?.id) {
|
||||||
const shouldSubmitScrobble = checkScrobbleConditions({
|
const shouldSubmitScrobble = checkScrobbleConditions({
|
||||||
scrobbleAtDuration: scrobbleSettings?.scrobbleAtDuration,
|
scrobbleAtDuration: scrobbleSettings?.scrobbleAtDuration,
|
||||||
scrobbleAtPercentage: scrobbleSettings?.scrobbleAtPercentage,
|
scrobbleAtPercentage: scrobbleSettings?.scrobbleAtPercentage,
|
||||||
songCompletedDuration: previousSongTime,
|
songCompletedDurationMs: previousSongTimeSec * 1000,
|
||||||
songDuration: previousSong.duration,
|
songDurationMs: previousSong.duration,
|
||||||
});
|
});
|
||||||
|
|
||||||
if (
|
if (
|
||||||
|
@ -114,7 +115,7 @@ export const useScrobble = () => {
|
||||||
) {
|
) {
|
||||||
const position =
|
const position =
|
||||||
previousSong?.serverType === ServerType.JELLYFIN
|
previousSong?.serverType === ServerType.JELLYFIN
|
||||||
? previousSongTime * 1e7
|
? previousSongTimeSec * 1e7
|
||||||
: undefined;
|
: undefined;
|
||||||
|
|
||||||
sendScrobble.mutate({
|
sendScrobble.mutate({
|
||||||
|
@ -168,7 +169,10 @@ export const useScrobble = () => {
|
||||||
);
|
);
|
||||||
|
|
||||||
const handleScrobbleFromStatusChange = useCallback(
|
const handleScrobbleFromStatusChange = useCallback(
|
||||||
(status: PlayerStatus | undefined) => {
|
(
|
||||||
|
current: (PlayerStatus | number | undefined)[],
|
||||||
|
previous: (PlayerStatus | number | undefined)[],
|
||||||
|
) => {
|
||||||
if (!isScrobbleEnabled) return;
|
if (!isScrobbleEnabled) return;
|
||||||
|
|
||||||
const currentSong = usePlayerStore.getState().current.song;
|
const currentSong = usePlayerStore.getState().current.song;
|
||||||
|
@ -180,8 +184,11 @@ export const useScrobble = () => {
|
||||||
? usePlayerStore.getState().current.time * 1e7
|
? usePlayerStore.getState().current.time * 1e7
|
||||||
: undefined;
|
: undefined;
|
||||||
|
|
||||||
|
const currentStatus = current[0] as PlayerStatus;
|
||||||
|
const currentTimeSec = current[1] as number;
|
||||||
|
|
||||||
// Whenever the player is restarted, send a 'start' scrobble
|
// Whenever the player is restarted, send a 'start' scrobble
|
||||||
if (status === PlayerStatus.PLAYING) {
|
if (currentStatus === PlayerStatus.PLAYING) {
|
||||||
sendScrobble.mutate({
|
sendScrobble.mutate({
|
||||||
query: {
|
query: {
|
||||||
event: 'unpause',
|
event: 'unpause',
|
||||||
|
@ -194,7 +201,7 @@ export const useScrobble = () => {
|
||||||
|
|
||||||
if (currentSong?.serverType === ServerType.JELLYFIN) {
|
if (currentSong?.serverType === ServerType.JELLYFIN) {
|
||||||
progressIntervalId.current = setInterval(() => {
|
progressIntervalId.current = setInterval(() => {
|
||||||
const currentTime = usePlayerStore.getState().current.time;
|
const currentTime = currentTimeSec;
|
||||||
handleScrobbleFromSeek(currentTime);
|
handleScrobbleFromSeek(currentTime);
|
||||||
}, 10000);
|
}, 10000);
|
||||||
}
|
}
|
||||||
|
@ -215,12 +222,17 @@ export const useScrobble = () => {
|
||||||
clearInterval(progressIntervalId.current as ReturnType<typeof setInterval>);
|
clearInterval(progressIntervalId.current as ReturnType<typeof setInterval>);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
const isLastTrackInQueue = usePlayerStore.getState().actions.checkIsLastTrack();
|
||||||
|
const previousTimeSec = previous[1] as number;
|
||||||
|
|
||||||
// If not already scrobbled, send a 'submission' scrobble if conditions are met
|
// If not already scrobbled, send a 'submission' scrobble if conditions are met
|
||||||
const shouldSubmitScrobble = checkScrobbleConditions({
|
const shouldSubmitScrobble = checkScrobbleConditions({
|
||||||
scrobbleAtDuration: scrobbleSettings?.scrobbleAtDuration,
|
scrobbleAtDuration: scrobbleSettings?.scrobbleAtDuration,
|
||||||
scrobbleAtPercentage: scrobbleSettings?.scrobbleAtPercentage,
|
scrobbleAtPercentage: scrobbleSettings?.scrobbleAtPercentage,
|
||||||
songCompletedDuration: usePlayerStore.getState().current.time,
|
// If scrobbling the last song in the queue, use the previous time instead of the current time since otherwise time value will be 0
|
||||||
songDuration: currentSong.duration,
|
songCompletedDurationMs:
|
||||||
|
(isLastTrackInQueue ? previousTimeSec : currentTimeSec) * 1000,
|
||||||
|
songDurationMs: currentSong.duration,
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!isCurrentSongScrobbled && shouldSubmitScrobble) {
|
if (!isCurrentSongScrobbled && shouldSubmitScrobble) {
|
||||||
|
@ -263,8 +275,8 @@ export const useScrobble = () => {
|
||||||
const shouldSubmitScrobble = checkScrobbleConditions({
|
const shouldSubmitScrobble = checkScrobbleConditions({
|
||||||
scrobbleAtDuration: scrobbleSettings?.scrobbleAtDuration,
|
scrobbleAtDuration: scrobbleSettings?.scrobbleAtDuration,
|
||||||
scrobbleAtPercentage: scrobbleSettings?.scrobbleAtPercentage,
|
scrobbleAtPercentage: scrobbleSettings?.scrobbleAtPercentage,
|
||||||
songCompletedDuration: currentTime,
|
songCompletedDurationMs: currentTime,
|
||||||
songDuration: currentSong.duration,
|
songDurationMs: currentSong.duration,
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!isCurrentSongScrobbled && shouldSubmitScrobble) {
|
if (!isCurrentSongScrobbled && shouldSubmitScrobble) {
|
||||||
|
@ -313,8 +325,11 @@ export const useScrobble = () => {
|
||||||
);
|
);
|
||||||
|
|
||||||
const unsubStatusChange = usePlayerStore.subscribe(
|
const unsubStatusChange = usePlayerStore.subscribe(
|
||||||
(state) => state.current.status,
|
(state) => [state.current.status, state.current.time],
|
||||||
handleScrobbleFromStatusChange,
|
handleScrobbleFromStatusChange,
|
||||||
|
{
|
||||||
|
equalityFn: (a, b) => (a[0] as PlayerStatus) === (b[0] as PlayerStatus),
|
||||||
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
return () => {
|
return () => {
|
||||||
|
|
Reference in a new issue