mirror of
https://github.com/jeffvli/feishin.git
synced 2026-05-10 04:30:25 +02:00
add logs to scrobble events
This commit is contained in:
@@ -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,41 +92,29 @@ 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 || '' },
|
{
|
||||||
query: {
|
apiClientProps: { serverId: currentSong._serverId || '' },
|
||||||
event: 'start',
|
query: {
|
||||||
id: currentSong.id,
|
event: 'start',
|
||||||
position: 0,
|
id: currentSong.id,
|
||||||
submission: false,
|
position: 0,
|
||||||
|
submission: false,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
});
|
{
|
||||||
|
onSuccess: () => {
|
||||||
|
logFn.debug(logMsg[LogCategory.SCROBBLE].scrobbledStart, {
|
||||||
|
category: LogCategory.SCROBBLE,
|
||||||
|
meta: {
|
||||||
|
id: currentSong.id,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
},
|
||||||
|
},
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
setIsCurrentSongScrobbled(false);
|
setIsCurrentSongScrobbled(false);
|
||||||
@@ -138,15 +128,27 @@ 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 || '' },
|
{
|
||||||
query: {
|
apiClientProps: { serverId: currentSong._serverId || '' },
|
||||||
event: 'timeupdate',
|
query: {
|
||||||
id: currentSong.id,
|
event: 'timeupdate',
|
||||||
position,
|
id: currentSong.id,
|
||||||
submission: false,
|
position,
|
||||||
|
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 || '' },
|
{
|
||||||
query: {
|
apiClientProps: { serverId: currentSong._serverId || '' },
|
||||||
id: currentSong.id,
|
query: {
|
||||||
position,
|
id: currentSong.id,
|
||||||
submission: true,
|
position,
|
||||||
|
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 || '' },
|
{
|
||||||
query: {
|
apiClientProps: { serverId: previousSong._serverId || '' },
|
||||||
id: previousSong.id,
|
query: {
|
||||||
position,
|
id: previousSong.id,
|
||||||
submission: true,
|
position,
|
||||||
|
submission: true,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
});
|
{
|
||||||
|
onSuccess: () => {
|
||||||
|
logFn.debug(logMsg[LogCategory.SCROBBLE].scrobbledStart, {
|
||||||
|
category: LogCategory.SCROBBLE,
|
||||||
|
meta: {
|
||||||
|
id: previousSong.id,
|
||||||
|
reason: 'from song change',
|
||||||
|
},
|
||||||
|
});
|
||||||
|
},
|
||||||
|
},
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -265,15 +293,27 @@ 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 || '' },
|
{
|
||||||
query: {
|
apiClientProps: { serverId: currentSong._serverId || '' },
|
||||||
event: 'start',
|
query: {
|
||||||
id: currentSong.id,
|
event: 'start',
|
||||||
position: 0,
|
id: currentSong.id,
|
||||||
submission: false,
|
position: 0,
|
||||||
|
submission: false,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
});
|
{
|
||||||
|
onSuccess: () => {
|
||||||
|
logFn.debug(logMsg[LogCategory.SCROBBLE].scrobbledStart, {
|
||||||
|
category: LogCategory.SCROBBLE,
|
||||||
|
meta: {
|
||||||
|
id: currentSong.id,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
},
|
||||||
|
},
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}, 2000);
|
}, 2000);
|
||||||
|
|
||||||
@@ -311,26 +351,50 @@ 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 || '' },
|
{
|
||||||
query: {
|
apiClientProps: { serverId: currentSong._serverId || '' },
|
||||||
event: 'unpause',
|
query: {
|
||||||
id: currentSong.id,
|
event: 'unpause',
|
||||||
position,
|
id: currentSong.id,
|
||||||
submission: false,
|
position,
|
||||||
|
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 || '' },
|
{
|
||||||
query: {
|
apiClientProps: { serverId: currentSong._serverId || '' },
|
||||||
event: 'pause',
|
query: {
|
||||||
id: currentSong.id,
|
event: 'pause',
|
||||||
position,
|
id: currentSong.id,
|
||||||
submission: false,
|
position,
|
||||||
|
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 || '' },
|
{
|
||||||
query: {
|
apiClientProps: { serverId: currentSong._serverId || '' },
|
||||||
id: currentSong.id,
|
query: {
|
||||||
submission: true,
|
id: currentSong.id,
|
||||||
|
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,15 +460,27 @@ export const useScrobble = () => {
|
|||||||
|
|
||||||
const position = properties.timestamp * 1e7;
|
const position = properties.timestamp * 1e7;
|
||||||
|
|
||||||
sendScrobble.mutate({
|
sendScrobble.mutate(
|
||||||
apiClientProps: { serverId: currentSong._serverId || '' },
|
{
|
||||||
query: {
|
apiClientProps: { serverId: currentSong._serverId || '' },
|
||||||
event: 'timeupdate',
|
query: {
|
||||||
id: currentSong.id,
|
event: 'timeupdate',
|
||||||
position,
|
id: currentSong.id,
|
||||||
submission: false,
|
position,
|
||||||
|
submission: false,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
});
|
{
|
||||||
|
onSuccess: () => {
|
||||||
|
logFn.debug(logMsg[LogCategory.SCROBBLE].scrobbledTimeupdate, {
|
||||||
|
category: LogCategory.SCROBBLE,
|
||||||
|
meta: {
|
||||||
|
id: currentSong.id,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
},
|
||||||
|
},
|
||||||
|
);
|
||||||
},
|
},
|
||||||
[isScrobbleEnabled, isPrivateModeEnabled, sendScrobble],
|
[isScrobbleEnabled, isPrivateModeEnabled, sendScrobble],
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -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]: {},
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -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',
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user