Something went wrong. Try again.
[READ-ONLY] Mirror of https://github.com/FoxxMD/multi-scrobbler. Scrobble plays from multiple sources to multiple clients docs.multi-scrobbler.app
deezer docker jellyfin koito lastfm listenbrainz maloja mopidy mpris music music-assistant plex scrobble self-hosted spotify subsonic tautulli youtube-music
Something went wrong. Try again.
3.8 kB · 124 lines
TSX
at strict
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124import type { Card, IconProps, HTMLChakraProps} from '@chakra-ui/react';import { Span } from '@chakra-ui/react';import type {PlayApiCommonDetailed} from '../../core/Api';import { type LifecycleStep, QUEUE_STATUS_COMPLETED, QUEUE_STATUS_FAILED } from '../../core/Atomic';import { isErrorIsh, type ErrorIsh } from '../../core/ErrorUtils';
export const cardHeaderSeparator: Card.HeaderProps = { borderBottomWidth: "1px", paddingBottom: "2"};
export const timelineTextFormatting: HTMLChakraProps<"span"> = { textAlign: "left", textWrap: "balance" }
export const timelineIconProps: IconProps = { fontSize: 'md'}
export const TimelineItemSummaryText = (props: HTMLChakraProps<"span"> & {children: React.ReactNode}) => <Span {...timelineTextFormatting}>{props.children}</Span>
export const activityTransformHasIssue = (steps: LifecycleStep[]): 'warn' | 'error' | undefined => { for(const step of steps) { if(step.flowKnownState === 'prereq') { return 'warn'; } if(step.flowKnownState === 'skip') { continue; } if(step.error !== undefined && step.error !== null && Object.keys(step.error).length > 0) { return 'error'; } } return undefined;}
export const activityTimelineHasIssue = (activity: PlayApiCommonDetailed): 'warn' | 'error' | undefined => { const { queueStates = [], play: { lifecycle = [], scrobble: { error: scrobbleError, warnings: scrobbleWarnings = [] } = {}, } = {}, } = activity; const transformIssue = activityTransformHasIssue(lifecycle); if(transformIssue !== undefined) { return transformIssue; } if (scrobbleError !== undefined) { return 'error'; } if(scrobbleWarnings.length > 0) { return 'warn'; } if (queueStates.some(x => x.queueStatus === QUEUE_STATUS_FAILED) && !queueStates.some(x => x.queueStatus === QUEUE_STATUS_COMPLETED)) { return 'error'; }
return undefined;}
export interface ErrorData { name?: string code?: string message?: string stack?: string}
export const walkError = (err: ErrorIsh, errors: ErrorData[] = []): ErrorData[] => { const thisErr: ErrorData = { name: err.name, code: 'code' in err ? err.code : undefined, message: err.message, stack: err.stack }; errors.push(thisErr); if(isErrorIsh(err.cause)) { return walkError(err.cause, errors); } return errors;}
export const findAuthCheckError = (err: ErrorIsh): ErrorIsh | undefined => { if(err.name === 'Authentication Check') { return err; } if(err.cause === undefined || !isErrorIsh(err.cause)) { return undefined; } return findAuthCheckError(err.cause);}
export const findAuthError = (err: ErrorIsh): ErrorIsh | undefined => { if(err.name === 'Authentication Error') { return err; } if(err.cause === undefined || !isErrorIsh(err.cause)) { return undefined; } return findAuthError(err.cause);}
export const findAnyAuthError = (e: ErrorIsh): [ErrorIsh, boolean] => { const aError = findAuthError(e); const aCheckError = findAuthCheckError(e); if(aError) if(aError !== undefined && 'unrecoverable' in aError && aError.unrecoverable === true) { return [aError, true]; } if(aCheckError !== undefined && 'unrecoverable' in aCheckError && aCheckError.unrecoverable === true) { return [aCheckError, true]; } if(aError !== undefined) { return [aError, false]; } if(aCheckError !== undefined) { return [aCheckError, false]; } return [undefined, false];}