add new-releases (cursed ass script)

This commit is contained in:
Soph :3 2026-02-01 16:46:18 +02:00
parent bf09f00d45
commit 823af0c65f
3 changed files with 153 additions and 1 deletions

3
.gitignore vendored
View file

@ -2,5 +2,8 @@
deezer_cache
orpheus_links.txt
discord_send.txt
new_releases.json
state.json
node_modules
fixcache.js
new-releases-reparser.js

View file

@ -10,7 +10,8 @@
"request-bot": "bun run src/request-bot.js",
"pillow": "bun run src/pillow.js",
"sendgb": "bun run src/sendgb.js",
"uamal": "bun run src/unambigious-artist-lookup.js"
"uamal": "bun run src/unambigious-artist-lookup.js",
"new-releases": "bun run src/new-releases"
},
"engineStrict": true,
"engines": {

148
src/new-releases.js Normal file
View file

@ -0,0 +1,148 @@
#!/usr/bin/env bun
import { writeFileSync, mkdirSync, readFileSync, existsSync } from "fs";
import crypto from "crypto";
import path from "path";
const MIN_DATE = new Date("2026-01-01");
const CONCURRENT_LIMIT = 2;
const CACHE_DIR = "./deezer_cache";
mkdirSync(CACHE_DIR, { recursive: true });
function cachePath(url) {
const hash = crypto.createHash("sha1").update(url).digest("hex");
return path.join(CACHE_DIR, `${hash}.json`);
}
async function cachedFetch(url) {
const file = cachePath(url);
if (existsSync(file)) {
return JSON.parse(readFileSync(file, "utf8"));
}
const res = await fetch(url);
if (!res.ok) throw new Error(`${res.status} ${res.statusText}`);
const json = await res.json();
writeFileSync(file, JSON.stringify(json, null, 2));
return json;
}
async function subsonicRequest(endpoint, params = {}) {
params.u = process.env.NAVIDROME_USER;
params.p = process.env.NAVIDROME_PASS;
params.v = "1.16.1";
params.c = "NewAlbumChecker";
params.f = "json";
const urlParams = new URLSearchParams(params);
const url = `${process.env.NAVIDROME_URL}/rest/${endpoint}.view?${urlParams}`;
const res = await fetch(url);
if (!res.ok) throw new Error(`Subsonic request failed: ${res.status}`);
const data = await res.json();
return data["subsonic-response"];
}
async function getAllArtists() {
const data = await subsonicRequest("getArtists");
return data.artists.index.flatMap((z) => z.artist).map((a) => a.name);
}
async function searchDeezerArtist(artistName) {
try {
const data = await cachedFetch(
`https://api.deezer.com/search/artist?q=${encodeURIComponent(artistName)}`,
);
if (!data.data || !data.data.length) return null;
return data.data[0].id;
} catch (err) {
return null;
}
}
async function getDeezerAlbums(artistId) {
try {
const data = await cachedFetch(
`https://api.deezer.com/artist/${artistId}/albums`,
);
return data.data
.filter((album) => {
if (!album.release_date) return false;
const date = new Date(album.release_date);
return date >= MIN_DATE;
})
.map((album) => ({
title: album.title,
explicit: album.explicit_lyrics,
release_date: album.release_date,
url: album.link,
}));
} catch (err) {
return [];
}
}
async function runWithConcurrency(items, worker, limit = CONCURRENT_LIMIT) {
const results = [];
let i = 0;
async function next() {
if (i >= items.length) return;
const index = i++;
try {
const res = await worker(items[index]);
results.push(...res);
} catch (e) {
console.error("Error processing", items[index], e);
}
return next();
}
const runners = Array.from({ length: Math.min(limit, items.length) }, next);
await Promise.all(runners);
return results;
}
async function checkNewReleases() {
const artists = await getAllArtists();
console.log(`Found ${artists.length} artists, checking Deezer...`);
const releases = await runWithConcurrency(
artists,
async (artist) => {
console.log("checking " + artist);
const deezerId = await searchDeezerArtist(artist);
if (!deezerId) return [];
const albums = await getDeezerAlbums(deezerId);
const formatted = albums.map((a) => ({
artist,
album: a.title,
release_date: a.release_date,
url: a.url,
explicit: a.explicit,
}));
console.log("checked " + artist);
return formatted;
},
CONCURRENT_LIMIT,
);
return releases;
}
(async () => {
const releases = await checkNewReleases();
if (releases.length) {
console.log("New albums/tracks since 2026-01-01 on Deezer:");
releases.forEach((r) => {
console.log(`${r.release_date} - ${r.artist} - ${r.album}`);
});
writeFileSync("new_releases.json", JSON.stringify(releases, null, 2));
} else {
console.log("No new releases found since 2026-01-01.");
}
})();