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:
Kendall Garner 2023-10-06 04:45:47 +00:00 committed by GitHub
parent 118a9f73d1
commit 6bac172bbe
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23

View file

@ -36,17 +36,18 @@ Progress Events (Jellyfin only):
const checkScrobbleConditions = (args: {
scrobbleAtDuration: number;
scrobbleAtPercentage: number;
songCompletedDuration: number;
songDuration: number;
songCompletedDurationMs: number;
songDurationMs: number;
}) => {
const { scrobbleAtDuration, scrobbleAtPercentage, songCompletedDuration, songDuration } = args;
const percentageOfSongCompleted = songDuration
? (songCompletedDuration / songDuration) * 100
const { scrobbleAtDuration, scrobbleAtPercentage, songCompletedDurationMs, songDurationMs } =
args;
const percentageOfSongCompleted = songDurationMs
? (songCompletedDurationMs / songDurationMs) * 100
: 0;
return (
percentageOfSongCompleted >= scrobbleAtPercentage ||
songCompletedDuration >= scrobbleAtDuration
songCompletedDurationMs >= scrobbleAtDuration
);
};
@ -97,15 +98,15 @@ export const useScrobble = () => {
// const currentSong = current[0] as QueueSong | undefined;
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
if (previousSong?.id) {
const shouldSubmitScrobble = checkScrobbleConditions({
scrobbleAtDuration: scrobbleSettings?.scrobbleAtDuration,
scrobbleAtPercentage: scrobbleSettings?.scrobbleAtPercentage,
songCompletedDuration: previousSongTime,
songDuration: previousSong.duration,
songCompletedDurationMs: previousSongTimeSec * 1000,
songDurationMs: previousSong.duration,
});
if (
@ -114,7 +115,7 @@ export const useScrobble = () => {
) {
const position =
previousSong?.serverType === ServerType.JELLYFIN
? previousSongTime * 1e7
? previousSongTimeSec * 1e7
: undefined;
sendScrobble.mutate({
@ -168,7 +169,10 @@ export const useScrobble = () => {
);
const handleScrobbleFromStatusChange = useCallback(
(status: PlayerStatus | undefined) => {
(
current: (PlayerStatus | number | undefined)[],
previous: (PlayerStatus | number | undefined)[],
) => {
if (!isScrobbleEnabled) return;
const currentSong = usePlayerStore.getState().current.song;
@ -180,8 +184,11 @@ export const useScrobble = () => {
? usePlayerStore.getState().current.time * 1e7
: undefined;
const currentStatus = current[0] as PlayerStatus;
const currentTimeSec = current[1] as number;
// Whenever the player is restarted, send a 'start' scrobble
if (status === PlayerStatus.PLAYING) {
if (currentStatus === PlayerStatus.PLAYING) {
sendScrobble.mutate({
query: {
event: 'unpause',
@ -194,7 +201,7 @@ export const useScrobble = () => {
if (currentSong?.serverType === ServerType.JELLYFIN) {
progressIntervalId.current = setInterval(() => {
const currentTime = usePlayerStore.getState().current.time;
const currentTime = currentTimeSec;
handleScrobbleFromSeek(currentTime);
}, 10000);
}
@ -215,12 +222,17 @@ export const useScrobble = () => {
clearInterval(progressIntervalId.current as ReturnType<typeof setInterval>);
}
} 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
const shouldSubmitScrobble = checkScrobbleConditions({
scrobbleAtDuration: scrobbleSettings?.scrobbleAtDuration,
scrobbleAtPercentage: scrobbleSettings?.scrobbleAtPercentage,
songCompletedDuration: usePlayerStore.getState().current.time,
songDuration: currentSong.duration,
// If scrobbling the last song in the queue, use the previous time instead of the current time since otherwise time value will be 0
songCompletedDurationMs:
(isLastTrackInQueue ? previousTimeSec : currentTimeSec) * 1000,
songDurationMs: currentSong.duration,
});
if (!isCurrentSongScrobbled && shouldSubmitScrobble) {
@ -263,8 +275,8 @@ export const useScrobble = () => {
const shouldSubmitScrobble = checkScrobbleConditions({
scrobbleAtDuration: scrobbleSettings?.scrobbleAtDuration,
scrobbleAtPercentage: scrobbleSettings?.scrobbleAtPercentage,
songCompletedDuration: currentTime,
songDuration: currentSong.duration,
songCompletedDurationMs: currentTime,
songDurationMs: currentSong.duration,
});
if (!isCurrentSongScrobbled && shouldSubmitScrobble) {
@ -313,8 +325,11 @@ export const useScrobble = () => {
);
const unsubStatusChange = usePlayerStore.subscribe(
(state) => state.current.status,
(state) => [state.current.status, state.current.time],
handleScrobbleFromStatusChange,
{
equalityFn: (a, b) => (a[0] as PlayerStatus) === (b[0] as PlayerStatus),
},
);
return () => {