Make deezify not pick up garbage albums

This commit is contained in:
Soph :3 2025-12-31 16:22:38 +02:00
parent a2cc4c7793
commit 6ca31b2916

View file

@ -1,14 +1,12 @@
import fs from "fs"; import fs from "fs";
import path from "path"; import path from "path";
import crypto from "crypto" import crypto from "crypto";
const CACHE_DIR = "./deezer_cache"; const CACHE_DIR = "./deezer_cache";
fs.mkdirSync(CACHE_DIR, { recursive: true }); fs.mkdirSync(CACHE_DIR, { recursive: true });
const artists = [ const artists = [];
]; const album_links = [];
const album_links = [
]
const BAD_KEYWORDS = [ const BAD_KEYWORDS = [
" remix", " remix",
"remix ", "remix ",
@ -22,7 +20,8 @@ const BAD_KEYWORDS = [
"anniversary", "anniversary",
"(remixes)", "(remixes)",
"(remix)", "(remix)",
"(acustic)" "(acustic)",
"mixes",
]; ];
function normalize(str) { function normalize(str) {
@ -31,8 +30,9 @@ function normalize(str) {
function hasBadKeyword(title) { function hasBadKeyword(title) {
const t = normalize(title); const t = normalize(title);
return BAD_KEYWORDS.some(k => t.includes(k)); return BAD_KEYWORDS.some((k) => t.includes(k));
} }
function cachePath(url) { function cachePath(url) {
const hash = crypto.createHash("sha1").update(url).digest("hex"); const hash = crypto.createHash("sha1").update(url).digest("hex");
return path.join(CACHE_DIR, `${hash}.json`); return path.join(CACHE_DIR, `${hash}.json`);
@ -53,13 +53,9 @@ async function cachedFetch(url) {
return json; return json;
} }
async function getArtistId(name) { async function getArtistId(name) {
const q = encodeURIComponent(name); const q = encodeURIComponent(name);
const data = await cachedFetch( const data = await cachedFetch(`https://api.deezer.com/search/artist?q=${q}`);
`https://api.deezer.com/search/artist?q=${q}`
);
return data?.data?.[0]?.id ?? null; return data?.data?.[0]?.id ?? null;
} }
@ -75,63 +71,84 @@ async function getAllAlbums(artistId) {
return out; return out;
} }
async function getAlbum(albumId) { async function getAlbum(albumId) {
const url = `https://api.deezer.com/album/${albumId}`; const url = `https://api.deezer.com/album/${albumId}`;
return await cachedFetch(url); return await cachedFetch(url);
} }
function selectBestAlbumVersions(albums) {
const byTitle = new Map();
for (const a of albums) { async function selectUniqueReleases(albums) {
if (hasBadKeyword(a.title)) continue; const seenTracks = new Set();
const finalReleases = [];
const key = normalize(a.title.replace(/\s*\(.*?\)\s*/g, "")); const albumsOnly = albums.filter(
(a) => a.record_type === "album" && !hasBadKeyword(a.title),
);
const singlesEPs = albums.filter(
(a) =>
(a.record_type === "single" || a.record_type === "ep") &&
!hasBadKeyword(a.title),
);
if (!byTitle.has(key)) { for (const a of albumsOnly) {
byTitle.set(key, a); const fullAlbum = await getAlbum(a.id);
continue; const tracks = (fullAlbum.tracks?.data ?? []).map((t) =>
normalize(t.title),
);
if (tracks.every((t) => seenTracks.has(t))) continue;
tracks.forEach((t) => seenTracks.add(t));
finalReleases.push(fullAlbum);
} }
const existing = byTitle.get(key); for (const s of singlesEPs) {
const fullSingle = await getAlbum(s.id);
const tracks = (fullSingle.tracks?.data ?? []).map((t) =>
normalize(t.title),
);
// Prefer explicit if (tracks.every((t) => seenTracks.has(t))) continue;
if (!existing.explicit_lyrics && a.explicit_lyrics) { tracks.forEach((t) => seenTracks.add(t));
byTitle.set(key, a); finalReleases.push(fullSingle);
}
} }
return [...byTitle.values()]; return finalReleases;
} }
(async () => { (async () => {
const links = []; const links = [];
const displays = [] const displays = [];
const album_links_raw = await Promise.all(album_links.map(async z => await getAlbum(z.replace(/[^\d]*(\d*)$/gm, "$1")))); const album_links_raw = await Promise.all(
album_links.map(
async (z) => await getAlbum(z.replace(/[^\d]*(\d*)$/gm, "$1")),
),
);
for (const artist of artists) { for (const artist of artists) {
console.log(`\n=== ${artist} ===`); console.log(`\n=== ${artist} ===`);
const artistId = typeof artist == "number" ? artist : await getArtistId(artist); const artistId =
typeof artist === "number" ? artist : await getArtistId(artist);
if (!artistId) { if (!artistId) {
console.log("Artist not found"); console.log("Artist not found");
continue; continue;
} }
const albums = (await getAllAlbums(artistId)); const albums = await getAllAlbums(artistId);
const cleanAlbums = await selectUniqueReleases(albums);
const cleanAlbums = selectBestAlbumVersions(albums);
let artistLines = []; let artistLines = [];
let extraCount = 0; let extraCount = 0;
for (const a of cleanAlbums) { for (const a of cleanAlbums) {
console.log( console.log(
`${a.title} | ${a.explicit_lyrics ? "EXPLICIT" : "CLEAN"} | https://www.deezer.com/en/album/${a.id}` `${a.title} | ${a.explicit_lyrics ? "EXPLICIT" : "CLEAN"} | https://www.deezer.com/en/album/${a.id}`,
); );
links.push(`https://www.deezer.com/en/album/${a.id}`); links.push(`https://www.deezer.com/en/album/${a.id}`);
if (artistLines.length < 100) { if (artistLines.length < 100) {
artistLines.push( artistLines.push(
`+ ${typeof artist == "number" ? `No name (${artist})` : artist} - ${a.title} ${a.explicit_lyrics ? "[E]" : ""}` `+ ${typeof artist === "number" ? `No name (${artist})` : artist} - ${a.title} ${a.explicit_lyrics ? "[E]" : ""}`,
); );
} else { } else {
extraCount++; extraCount++;
@ -144,16 +161,24 @@ function selectBestAlbumVersions(albums) {
displays.push(...artistLines); displays.push(...artistLines);
} }
album_links_raw.forEach(z => {
album_links_raw.forEach((z) => {
links.push(`https://www.deezer.com/en/album/${z.id}`); links.push(`https://www.deezer.com/en/album/${z.id}`);
displays.push( displays.push(
`+ ${z.artist.name} - ${z.title} ${z.explicit_lyrics ? "[E]" : ""}` `+ ${z.artist.name} - ${z.title} ${z.explicit_lyrics ? "[E]" : ""}`,
); );
}) });
fs.writeFileSync("orpheus_links.txt", links.join(" "))
fs.writeFileSync("discord_send.txt", displays.join(" \n").match(/.{1,2000}$/gms).map(z => z.trim()).join("\n\n"+'-'.repeat(15)+"\n\n"))
})().catch(err => { fs.writeFileSync("orpheus_links.txt", links.join(" "));
fs.writeFileSync(
"discord_send.txt",
displays
.join(" \n")
.match(/.{1,2000}$/gms)
.map((z) => z.trim())
.join("\n\n" + "-".repeat(15) + "\n\n"),
);
})().catch((err) => {
console.error(err); console.error(err);
process.exit(1); process.exit(1);
}); });