Skip to content

Commit

Permalink
fix scrobble durations (#269)
Browse files Browse the repository at this point in the history
* fix scrobble durations

* Fix scrobble condition on last song in queue, normalize ms

---------

Co-authored-by: jeffvli <[email protected]>
  • Loading branch information
kgarner7 and jeffvli authored Oct 6, 2023
1 parent 118a9f7 commit 6bac172
Showing 1 changed file with 33 additions and 18 deletions.
51 changes: 33 additions & 18 deletions src/renderer/features/player/hooks/use-scrobble.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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
);
};

Expand Down Expand Up @@ -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 (
Expand All @@ -114,7 +115,7 @@ export const useScrobble = () => {
) {
const position =
previousSong?.serverType === ServerType.JELLYFIN
? previousSongTime * 1e7
? previousSongTimeSec * 1e7
: undefined;

sendScrobble.mutate({
Expand Down Expand Up @@ -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;
Expand All @@ -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',
Expand All @@ -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);
}
Expand All @@ -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) {
Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -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 () => {
Expand Down

1 comment on commit 6bac172

@vercel
Copy link

@vercel vercel bot commented on 6bac172 Oct 6, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Successfully deployed to the following URLs:

feishin – ./

feishin-jeffvli.vercel.app
feishin-git-development-jeffvli.vercel.app
feishin.vercel.app

Please sign in to comment.