export interface SlskdRawFile { filename: string size: number bitRate: number length: number } export interface SlskdRawResponse { username: string files: SlskdRawFile[] freeUploadSlots: number speed: number } export interface DedupedFile { displayName: string filename: string size: number bitRate: number length: number bestPeer: { username: string freeSlots: number speed: number } peerCount: number } function normalizeName(filename: string): string { // Strip path separators (Windows backslash or Unix forward slash) const basename = filename.replace(/^.*[\\\/]/, '') // Strip extension const noExt = basename.replace(/\.[^.]+$/, '') return noExt.toLowerCase().trim() } function prettyName(filename: string): string { return filename.replace(/^.*[\\\/]/, '').replace(/\.[^.]+$/, '') } export function extractBestFiles(responses: SlskdRawResponse[], limit = 30): DedupedFile[] { const groups = new Map() for (const peer of responses) { if (!peer.files?.length) continue for (const file of peer.files) { const key = normalizeName(file.filename) if (!key) continue const entry = { file, peer, displayName: prettyName(file.filename) } const existing = groups.get(key) if (existing) { existing.push(entry) } else { groups.set(key, [entry]) } } } const deduped: DedupedFile[] = [] for (const [, entries] of groups) { // Pick best peer: prefer freeUploadSlots > 0, then highest speed entries.sort((a, b) => { const aFree = a.peer.freeUploadSlots > 0 ? 1 : 0 const bFree = b.peer.freeUploadSlots > 0 ? 1 : 0 if (aFree !== bFree) return bFree - aFree return b.peer.speed - a.peer.speed }) const best = entries[0] deduped.push({ displayName: best.displayName, filename: best.file.filename, size: best.file.size, bitRate: best.file.bitRate, length: best.file.length, bestPeer: { username: best.peer.username, freeSlots: best.peer.freeUploadSlots, speed: best.peer.speed, }, peerCount: entries.length, }) } // Sort by highest bitRate first deduped.sort((a, b) => (b.bitRate || 0) - (a.bitRate || 0)) return deduped.slice(0, limit) }