Files
R3ap3r 3178b8f4f7 Aurora SpotiRip desktop and web app
- Spotify playlist, library, album and artist browsing with in-app playback
- Song, playlist and album downloads via spotdl with YouTube and Bandcamp fallbacks
- Electron desktop app (castLabs Widevine) with a permanent sidebar layout
- Linux and Windows packaging scripts
2026-09-25 23:20:57 -05:00

42 lines
1022 B
TypeScript

export type LibraryIdentityInput = {
isrc?: string;
title?: string;
artist?: string;
album?: string;
};
function normalize(value?: string) {
return (value || "")
.toLowerCase()
.normalize("NFKD")
.replace(/[\u0300-\u036f]/g, "")
.replace(/[^a-z0-9]+/g, " ")
.trim();
}
export function makeLibraryIdentity(input: LibraryIdentityInput) {
if (input.isrc?.trim()) return `isrc:${input.isrc.trim().toUpperCase()}`;
return [
"meta",
normalize(input.artist),
normalize(input.title),
normalize(input.album),
].join(":");
}
export function findDuplicateIdentities(items: LibraryIdentityInput[]) {
const seen = new Map<string, number>();
const duplicates = new Set<number>();
items.forEach((item, index) => {
const identity = makeLibraryIdentity(item);
const first = seen.get(identity);
if (typeof first === "number") {
duplicates.add(first);
duplicates.add(index);
} else {
seen.set(identity, index);
}
});
return duplicates;
}