jefflix-website/lib/slskd-dedup.ts

91 lines
2.3 KiB
TypeScript

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<string, { file: SlskdRawFile; peer: SlskdRawResponse; displayName: string }[]>()
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)
}