feat: release payload disk cache, batched rip status for list, artwork 404, stricter input handling
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
import type { DB } from './db.js'
|
||||
import { isConfidentMatch } from './matcher.js'
|
||||
import { isConfidentMatch, normalize } from './matcher.js'
|
||||
|
||||
export type RipStatus = 'ripped' | 'not_ripped'
|
||||
|
||||
@@ -29,3 +29,36 @@ export function resolveRipStatus(db: DB, userId: number, itemId: number): RipSta
|
||||
.all(userId) as { title: string; artist: string }[]
|
||||
return albums.some((a) => isConfidentMatch(item, a)) ? 'ripped' : 'not_ripped'
|
||||
}
|
||||
|
||||
/**
|
||||
* Batch resolution for list views: loads albums and match links once per
|
||||
* user instead of per item (GET /api/collection is otherwise O(items x albums)).
|
||||
* Resolution order matches resolveRipStatus.
|
||||
*/
|
||||
export function resolveRipStatusBatch(
|
||||
db: DB,
|
||||
userId: number,
|
||||
items: { id: number; title: string; artist: string; rip_override: number | null }[]
|
||||
): RipStatus[] {
|
||||
const albums = db
|
||||
.prepare('SELECT title, artist FROM digital_albums WHERE user_id = ?')
|
||||
.all(userId) as { title: string; artist: string }[]
|
||||
const albumKeys = new Set(
|
||||
albums.map((a) => `${normalize(a.title)}|${normalize(a.artist)}`)
|
||||
)
|
||||
const linked = new Set(
|
||||
(
|
||||
db.prepare('SELECT item_id FROM match_links WHERE user_id = ?').all(userId) as {
|
||||
item_id: number
|
||||
}[]
|
||||
).map((r) => r.item_id)
|
||||
)
|
||||
return items.map((item) => {
|
||||
if (item.rip_override !== null && item.rip_override !== undefined) {
|
||||
return item.rip_override === 1 ? 'ripped' : 'not_ripped'
|
||||
}
|
||||
if (linked.has(item.id)) return 'ripped'
|
||||
const key = `${normalize(item.title)}|${normalize(item.artist)}`
|
||||
return albumKeys.has(key) ? 'ripped' : 'not_ripped'
|
||||
})
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user