[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
0

Configure Feed

Select the types of activity you want to include in your feed.

feat(database): Add query params for finding plays by queue

FoxxMD (May 6, 2026, 2:56 AM UTC) cbe996db 8fd870b9

+49 -4
+37 -3
src/backend/common/database/drizzle/repositories/PlayRepository.ts
··· 21 21 22 22 // https://github.com/drizzle-team/drizzle-orm/issues/695 may be useful for typing models with relations? 23 23 24 + export interface QueueCriteria { 25 + queueName: string 26 + queueStatus: QueueStateSelect['queueStatus'][] | QueueStateSelect['queueStatus'] 27 + } 28 + 24 29 export interface PlayWhereOpts { 25 30 state?: PlaySelect['state'][] 26 31 stateNot?: PlaySelect['state'][] ··· 28 33 platformId?: string 29 34 seenAt?: CompareDateOp 30 35 playedAt?: CompareDateOp 31 - queueCriteria?: {queueName: string, states?: QueueStateSelect['queueStatus'][]} 36 + queues?: QueueCriteria[] 32 37 uid?: string[] 33 38 } 34 39 ··· 179 184 180 185 findPlaysPaginated = async <T = PlaySelectRel>(args: QueryPlaysOpts, opts: HydrateOpts & ComponentConstrainedRepoOpts = {}): Promise<PaginatedResponse<T>> => { 181 186 const { 182 - limit, 187 + limit = 100, 183 188 offset = 0, 184 189 ...rest 185 190 } = args; ··· 709 714 in: args.uid 710 715 } 711 716 } 717 + const { 718 + queues = [] 719 + } = args; 720 + if(queues.length > 0) { 721 + // need to do this optimistically even if we overwrite with only 1 condition later 722 + where.queueStates = { 723 + OR: [] 724 + } 725 + // so that we can use this type 726 + // or else assigning an array to OR using only `typeof where.queueStates` causes a type error 727 + let queueWhere: typeof where.queueStates.OR[0][] = []; 728 + for(const q of queues) { 729 + queueWhere.push( 730 + { 731 + queueName: q.queueName, 732 + queueStatus: typeof q.queueStatus === 'string' ? q.queueStatus : { 733 + in: q.queueStatus 734 + } 735 + } 736 + ) 737 + } 738 + if(queueWhere.length === 1) { 739 + where.queueStates = queueWhere[0]; 740 + } else { 741 + where.queueStates = { 742 + OR: queueWhere 743 + } 744 + } 745 + } 712 746 return where; 713 747 } 714 748 ··· 764 798 order, 765 799 offset, 766 800 componentId, 767 - queueCriteria, 801 + queues, 768 802 ...rest 769 803 } = rec; 770 804
+12 -1
src/core/Atomic.ts
··· 600 600 export const REGEX_ISO8601_LOOSE = new RegExp(/\d{4}-[01]\d-[0-3]\dT/); 601 601 602 602 export const CLIENT_INGRESS_QUEUE = 'ingress'; 603 - export const CLIENT_DEAD_QUEUE = 'dead'; 603 + export const CLIENT_DEAD_QUEUE = 'dead'; 604 + 605 + /** 606 + * Useful TS type-only utility for testing type equality 607 + * 608 + * Usage: type EQ = IfEquals<any[], [number][], "same", "different">; // "different" 609 + * 610 + * @see https://stackoverflow.com/a/53808212/1469797 611 + */ 612 + export type IfEquals<T, U, Y=unknown, N=never> = 613 + (<G>() => G extends T ? 1 : 2) extends 614 + (<G>() => G extends U ? 1 : 2) ? Y : N;