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
This commit is contained in:
@@ -0,0 +1,41 @@
|
||||
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;
|
||||
}
|
||||
Reference in New Issue
Block a user