made changes

This commit is contained in:
KoenDR06 2025-12-27 13:48:06 +01:00
parent 7813a44af0
commit f7cc4c9a5c
4 changed files with 798 additions and 59 deletions

View file

@ -2,7 +2,7 @@
body {
background-color: #262626;
margin: 20px;
margin: 1vw;
color: #ffffff;
overflow: clip;
font-family:Work Sans,sans-serif;
@ -14,29 +14,24 @@ body {
justify-content: space-between;
}
#title {
max-width: 500px;
}
/* --- Left column --- */
.song {
position: relative;
}
#song-image {
width: 500px;
height: 500px;
border-radius: 20px;
width: 25vw;
height: 25vw;
border-radius: 1vw;
}
#song-diff {
font-size: 2rem;
padding: 16px;
min-width: 80px;
height: 40px;
border-radius: 20px;
border: 1px solid black;
font-size: 3vh;
padding: 0.8vw;
min-width: 5vw;
height: 2vw;
border-radius: 1vw;
border: 0.02vw solid black;
position: absolute;
top: 0;
@ -46,7 +41,7 @@ body {
text-align: center;
}
#song-diff.stale {
#song-diff.stale, #song-diff.new {
background-color: gray;
}
@ -58,6 +53,16 @@ body {
background-color: red;
}
.current-column {
font-size: 2.25vh;
}
.current-column h1 {
margin-bottom: 0;
}
.current-column h2 {
margin: 0;
}
/* --- Middle column --- */
.left-divide {
@ -66,18 +71,17 @@ body {
}
.song-stats {
margin-left: 100px;
margin-left: 2vw;
}
.artist-info p {
margin: 0;
padding: 0;
.artist-info {
font-size: 2.25vh;
}
/* --- Right column --- */
#queue {
width: 700px;
width: 35vw;
}
.queue-item {
@ -86,18 +90,21 @@ body {
}
.queue-item .song-title {
font-size: 2rem;
margin-left: 20px;
font-size: 3vh;
margin-left: 1vw;
}
.queue-item .song-artist {
font-size: 1.5rem;
margin-left: 20px;
font-size: 2.25vh;
margin-left: 1vw;
color: #ccc;
}
.queue-item .song-time {
text-align: right;
margin-right: 10px;
font-size: 1.5rem;
margin-right: 0.5vw;
font-size: 2.25vh;
justify-content: right;
display: flex;
gap: 1.5vw;
}
.queue-right-wrapper {
width: 100%;
@ -109,10 +116,17 @@ body {
}
.queue-image {
height: 100px;
width: 100px;
height: 5vw;
width: 5vw;
}
.queue-item.playing {
background-color: #1a1a1a;
}
.song-diff.queue-risen {
color: green;
}
.song-diff.queue-fallen {
color: red;
}

View file

@ -15,16 +15,15 @@
<img id="song-image">
<div id="song-diff"></div>
</div>
<h1 id="title"></h1>
<h2 id="artist"></h2>
<h3 id="position"></h3>
</div>
<div class="song-stats">
<canvas id="graph" width=500 height=500></canvas>
<canvas id="graph"></canvas>
</div>
</div>
<div class="artist-info">
<h1 id="title"></h1>
<h2 id="artist"></h2>
<h2>Trivia</h2>
<ul>
<li id="trivia-songcount"></li>

View file

@ -1,10 +1,14 @@
window.onload = async (e) => {
const res = await (await fetch("https://www.nporadio2.nl/api/charts/npo-radio-2-top-2000-van-2025-12-25", {})).json();
const res = await (await fetch("/ranking", {})).json();
window.ranking = res.positions;
const offset = +window.location.search.slice(1);
window.offset = offset;
const canvas = document.querySelector('#graph');
canvas.width = 0.35 * window.innerWidth;
canvas.height = 0.50 * window.innerHeight;
const now = Date.now() - offset * 1000;
const curr = window.ranking.find(it => it.broadcastUnixTime < now);
var current = curr.position.current;
@ -30,8 +34,7 @@ function update(curr) {
diff.classList = curr.position.type;
document.querySelector("#title").innerText = curr.track.title;
document.querySelector("#artist").innerText = curr.track.artist;
document.querySelector("#position").innerText = `Nummer ${curr.position.current}`;
document.querySelector("#artist").innerText = `${curr.track.artist} (#${curr.position.current})`;
getGraph(curr.track.artist, curr.track.title);
queue(curr.position.current);
@ -41,19 +44,68 @@ function update(curr) {
async function getGraph(artist, title) {
const res = await (await fetch(`/graph/${artist.replace("?", "")}/${title}`, {})).json();
const width = 500;
const labelSpace = 50;
const barWidth = (width - labelSpace) / res.length;
const height = 500;
const cv = document.querySelector("#graph");
const ctx = cv.getContext('2d');
const width = cv.width;
const labelSpace = 100;
const barWidth = (width - labelSpace) / res.length;
const height = cv.height;
const graphHeight = height - 60;
ctx.clearRect(0, 0, width, height);
for (let i = 0; i <= 2000; i += 200) {
const fraction = (i / 2000) * height;
// Dots
let minPos = 2001;
let maxPos = -1;
let minYear = undefined;
let maxYear = undefined;
for (let i = 0; i < res.length; i++) {
const position = res[i].position;
if (position != undefined) {
if (position < minPos) {
minPos = position;
minYear = i;
}
if (position > maxPos) {
maxPos = position;
maxYear = i;
}
}
const fraction = (position / 2000) * graphHeight;
ctx.beginPath();
ctx.fillStyle = "white";
ctx.arc(labelSpace + barWidth * i + 10, fraction, 2.5, 0, 2*Math.PI);
ctx.fill();
}
// Min and Max lines
for (let p of [minPos, maxPos]) {
const fraction = (p / 2000) * graphHeight;
ctx.beginPath();
ctx.strokeStyle = "#808080";
ctx.lineWidth = 1;
ctx.moveTo(labelSpace, fraction);
ctx.lineTo(width, fraction);
ctx.stroke();
ctx.font = "40px sans-serif";
ctx.fillStyle = "#808080";
ctx.fillText(p.toString(), 0, fraction);
}
// Y axis
for (let i = 200; i <= 2000; i += 200) {
const fraction = (i / 2000) * graphHeight;
const lineDist = 70;
if (Math.abs(i-minPos) <= lineDist || Math.abs(i-maxPos) <= lineDist) {
continue;
}
ctx.beginPath();
ctx.strokeStyle = "#808080";
@ -62,27 +114,39 @@ async function getGraph(artist, title) {
ctx.lineTo(width, fraction);
ctx.stroke();
ctx.font = "20px sans-serif";
ctx.font = "40px sans-serif";
ctx.fillStyle = "#808080";
ctx.fillText(i.toString(), 0, fraction);
}
for (let i = 0; i < res.length; i++) {
const position = res[i].position;
const fraction = (position / 2000) * height;
// X axis
const startYear = 1999;
const endYear = 2025;
const years = endYear-startYear+1;
for (let i of [...new Set([res.findIndex(it => it.position != undefined), minYear, maxYear])]) {
const fraction = 10 + labelSpace + (i * (width - labelSpace)) / (years);
console.log(fraction)
let year = (100 + i - 1) % 100;
// ctx.fillRect(barWidth * i, 0, barWidth, position / 10)
ctx.beginPath();
ctx.fillStyle = "white";
ctx.arc(labelSpace + barWidth * i + 10, fraction, 2.5, 0, 2*Math.PI);
ctx.fill();
ctx.strokeStyle = "#808080";
ctx.lineWidth = 1;
ctx.moveTo(fraction, 0);
ctx.lineTo(fraction, graphHeight);
ctx.stroke();
ctx.font = "40px sans-serif";
ctx.fillStyle = "#808080";
ctx.fillText(year.toString(), fraction-3, height-10);
}
// Line plot
for (let i = 0; i < res.length-1; i++) {
const curr = res[i].position;
const next = res[i+1].position;
const currFraction = (curr / 2000) * height;
const nextFraction = (next / 2000) * height;
const currFraction = (curr / 2000) * graphHeight;
const nextFraction = (next / 2000) * graphHeight;
// ctx.fillRect(barWidth * i, 0, barWidth, position / 10)
ctx.beginPath();
@ -102,14 +166,17 @@ function queue(currPos) {
queueEl.innerHTML = "";
for (const song of upcoming.reverse()) {
const broadcastDT = new Date(song.broadcastUnixTime - offset * 1000);
const broadcastDT = new Date(song.broadcastUnixTime + offset * 1000);
queueEl.innerHTML += `
<div class="queue-item${song.position.current == currPos ? " playing" : ""}">
<img class="queue-image" src="${song.track.coverUrl}">
<div class="queue-right-wrapper">
<p class="song-title">${song.track.title}</p>
<p class="song-artist">${song.track.artist}</p>
<p class="song-time">${broadcastDT.getHours().toString().padStart(2, "0")}:${broadcastDT.getMinutes().toString().padStart(2, "0")}</p>
<span class="song-time">
<span class="song-diff queue-${song.position.type}">${song.position.label}</span>
<span class="song-time">${broadcastDT.getHours().toString().padStart(2, "0")}:${broadcastDT.getMinutes().toString().padStart(2, "0")}</span>
</span>
</div>
</div>
`
@ -132,12 +199,12 @@ async function getTrivia(curr) {
if (artistsSongs[0].position == curr.position.current) {
document.querySelector("#trivia-first").innerText = `Dit is het hoogste nummer van ${curr.track.artist} in de lijst.`;
} else {
document.querySelector("#trivia-first").innerText = `Het hoogste nummer van ${curr.track.artist} is ${artistsSongs[0].title}.`;
document.querySelector("#trivia-first").innerText = `Het hoogste nummer van ${curr.track.artist} is ${artistsSongs[0].title} (#${artistsSongs[0].position}).`;
}
if (artistsSongs.at(-1).position == curr.position.current) {
document.querySelector("#trivia-last").innerText = `Dit is het laagste nummer van ${curr.track.artist} in de lijst.`;
} else {
document.querySelector("#trivia-last").innerText = `Het laagste nummer van ${curr.track.artist} is ${artistsSongs.at(-1).title}.`;
document.querySelector("#trivia-last").innerText = `Het laagste nummer van ${curr.track.artist} is ${artistsSongs.at(-1).title} (#${artistsSongs.at(-1).position}).`;
}
}

663
server.js
View file

@ -10,6 +10,665 @@ app.get("/", (req, res) => {
res.sendFile(path.resolve('./index.html'))
})
app.get('/ranking', async (req, res) => {
// const ranking = await (await fetch("https://www.nporadio2.nl/api/charts/npo-radio-2-top-2000-van-2025-12-25", {})).json();
res.send({
"chartDate": "2025-12-25 00:00:00",
"editionIsActive": true,
"downloadUrls": {
"excelUrl": "https://cms-assets.nporadio.nl/npoRadio2/TOP2000-2025.xls?v=1765830938",
"pdfUrl": "https://cms-assets.nporadio.nl/npoRadio2/NPO-Radio-2-Top-2000-2025.pdf?v=1765831780"
},
"positions": [
{
"broadcastTime": "2025-12-27T15:08:15+01:00",
"broadcastTimeFormatted": "zaterdag 27 dec 2025 15:00 - 16:00 uur",
"broadcastUnixTime": 1766844495000,
"id": "6f4ca036-438f-4932-b048-04cf12995060",
"position": {
"current": 1201,
"label": "-68",
"previous": 1133,
"type": "fallen"
},
"totalPositions": 1,
"track": {
"artist": "Snowy White",
"coverUrl": "https://npo-artistdb.b-cdn.net/images/e8b0c345-b123-4a84-a472-29298d4dc7ed__Bird-Of-Paradise.jpg?aspect_ratio=501%3A500&width=500&height=500",
"detailUrl": "/muziek/nummers/6f4ca036-438f-4932-b048-04cf12995060/bird-of-paradise",
"historyUrl": "/top2000/statistieken/door-de-jaren-heen/snowy-white/bird-of-paradise",
"id": "6f4ca036-438f-4932-b048-04cf12995060",
"isAvailable": true,
"previewUrl": "https://p.scdn.co/mp3-preview/4bedf26f99d7c5d2072f301ca852a9375398d867?cid=e10971e8edab41f8b0986464de19b8f3",
"title": "Bird Of Paradise"
}
},
{
"broadcastTime": "2025-12-27T15:05:00+01:00",
"broadcastTimeFormatted": "zaterdag 27 dec 2025 15:00 - 16:00 uur",
"broadcastUnixTime": 1766844300000,
"id": "a7ef1907-c656-4bd2-8fbd-248add9c1222",
"position": {
"current": 1202,
"label": "-79",
"previous": 1123,
"type": "fallen"
},
"totalPositions": 1,
"track": {
"artist": "Crosby, Stills, Nash & Young",
"coverUrl": "https://npo-artistdb.b-cdn.net/images/db03712e-7235-45ef-8371-f1ed5afc4e71__Teach-Your-Children.jpg?aspect_ratio=501%3A500&width=500&height=500",
"detailUrl": "/muziek/nummers/a7ef1907-c656-4bd2-8fbd-248add9c1222/teach-your-children",
"historyUrl": "/top2000/statistieken/door-de-jaren-heen/crosby-stills-nash-young/teach-your-children",
"id": "a7ef1907-c656-4bd2-8fbd-248add9c1222",
"isAvailable": true,
"previewUrl": "https://p.scdn.co/mp3-preview/a4b0d977cac5cf760933592681cb865231133142?cid=e10971e8edab41f8b0986464de19b8f3",
"title": "Teach Your Children"
}
},
{
"broadcastTime": "2025-12-27T14:51:52+01:00",
"broadcastTimeFormatted": "zaterdag 27 dec 2025 14:00 - 15:00 uur",
"broadcastUnixTime": 1766843512000,
"id": "4db20c37-c402-45c2-b90d-8cab3a8fd593",
"position": {
"current": 1203,
"label": "-137",
"previous": 1066,
"type": "fallen"
},
"totalPositions": 1,
"track": {
"artist": "Beth Hart & Joe Bonamassa",
"coverUrl": "https://npo-artistdb.b-cdn.net/images/18f83c48-a15f-440c-b85f-5b8bcf051d48__I-ll-Take-Care-Of-You.jpg?aspect_ratio=501%3A500&width=500&height=500",
"detailUrl": "/muziek/nummers/4db20c37-c402-45c2-b90d-8cab3a8fd593/ill-take-care-of-you",
"historyUrl": "/top2000/statistieken/door-de-jaren-heen/beth-hart-joe-bonamassa/ill-take-care-of-you-albumversie",
"id": "4db20c37-c402-45c2-b90d-8cab3a8fd593",
"isAvailable": true,
"previewUrl": null,
"title": "I'll Take Care Of You (Albumversie)"
}
},
{
"broadcastTime": "2025-12-27T14:47:50+01:00",
"broadcastTimeFormatted": "zaterdag 27 dec 2025 14:00 - 15:00 uur",
"broadcastUnixTime": 1766843270000,
"id": "e88bbf6c-a39a-4334-9575-039077721319",
"position": {
"current": 1204,
"label": "-55",
"previous": 1149,
"type": "fallen"
},
"totalPositions": 1,
"track": {
"artist": "Kaleo",
"coverUrl": "https://npo-artistdb.b-cdn.net/images/be57f7e6-f541-471d-88e1-cda0cfd54550__Kaleo-0.jpg?aspect_ratio=501%3A500&width=500&height=500",
"detailUrl": "/muziek/nummers/e88bbf6c-a39a-4334-9575-039077721319/way-down-we-go",
"historyUrl": "/top2000/statistieken/door-de-jaren-heen/kaleo/way-down-we-go",
"id": "e88bbf6c-a39a-4334-9575-039077721319",
"isAvailable": true,
"previewUrl": "https://p.scdn.co/mp3-preview/d98c7057adac754607c1a2ab8c72113c3e7a2338?cid=e10971e8edab41f8b0986464de19b8f3",
"title": "Way Down We Go"
}
},
{
"broadcastTime": "2025-12-27T14:41:31+01:00",
"broadcastTimeFormatted": "zaterdag 27 dec 2025 14:00 - 15:00 uur",
"broadcastUnixTime": 1766842891000,
"id": "184d9d04-27e2-46e0-b42f-8db9599dc4e9",
"position": {
"current": 1205,
"label": "+483",
"previous": 1688,
"type": "risen"
},
"totalPositions": 1,
"track": {
"artist": "Michael Jackson",
"coverUrl": "https://npo-artistdb.b-cdn.net/images/47fd63a8-800b-45f8-afa6-1b00a330c535__Don-t-Stop-til-You-Get-Enough.jpg?aspect_ratio=501%3A500&width=500&height=500",
"detailUrl": "/muziek/nummers/184d9d04-27e2-46e0-b42f-8db9599dc4e9/dont-stop-til-you-get-enough",
"historyUrl": "/top2000/statistieken/door-de-jaren-heen/michael-jackson/dont-stop-til-you-get-enough-albumversie",
"id": "184d9d04-27e2-46e0-b42f-8db9599dc4e9",
"isAvailable": true,
"previewUrl": null,
"title": "Don't Stop 'Til You Get Enough (Albumversie)"
}
},
{
"broadcastTime": "2025-12-27T14:37:20+01:00",
"broadcastTimeFormatted": "zaterdag 27 dec 2025 14:00 - 15:00 uur",
"broadcastUnixTime": 1766842640000,
"id": "01978d13-e960-73d9-ac0f-10889762874d",
"position": {
"current": 1206,
"label": "-10",
"previous": 1196,
"type": "fallen"
},
"totalPositions": 1,
"track": {
"artist": "Rammstein",
"coverUrl": "https://npo-artistdb.b-cdn.net/images/a6bf6875-56bb-448b-b4e4-b7ec4cfa1749__AMERIKA.jpg?aspect_ratio=501%3A500&width=500&height=500",
"detailUrl": "/muziek/nummers/01978d13-e960-73d9-ac0f-10889762874d/amerika",
"historyUrl": "/top2000/statistieken/door-de-jaren-heen/rammstein/amerika",
"id": "01978d13-e960-73d9-ac0f-10889762874d",
"isAvailable": true,
"previewUrl": null,
"title": "Amerika"
}
},
{
"broadcastTime": "2025-12-27T14:31:49+01:00",
"broadcastTimeFormatted": "zaterdag 27 dec 2025 14:00 - 15:00 uur",
"broadcastUnixTime": 1766842309000,
"id": "6677b744-b8c5-4095-870f-732488e9d7f6",
"position": {
"current": 1207,
"label": "-92",
"previous": 1115,
"type": "fallen"
},
"totalPositions": 1,
"track": {
"artist": "Carole King",
"coverUrl": "https://npo-artistdb.b-cdn.net/images/48a6fc6c-406f-4ecb-903a-664816c8332a__You-ve-Got-A-Friend.jpg?aspect_ratio=501%3A500&width=500&height=500",
"detailUrl": "/muziek/nummers/6677b744-b8c5-4095-870f-732488e9d7f6/youve-got-a-friend",
"historyUrl": "/top2000/statistieken/door-de-jaren-heen/carole-king/youve-got-a-friend",
"id": "6677b744-b8c5-4095-870f-732488e9d7f6",
"isAvailable": true,
"previewUrl": "https://assets.stemtool.npox.nl/audio/382/c-624e2d14d6f182bc79083a372e277ded-6.mp3?v=1725881570",
"title": "You've Got A Friend"
}
},
{
"broadcastTime": "2025-12-27T14:27:45+01:00",
"broadcastTimeFormatted": "zaterdag 27 dec 2025 14:00 - 15:00 uur",
"broadcastUnixTime": 1766842065000,
"id": "2be29add-afef-447c-af86-41bc90b47f3c",
"position": {
"current": 1208,
"label": "+321",
"previous": 1529,
"type": "risen"
},
"totalPositions": 1,
"track": {
"artist": "Normaal",
"coverUrl": "https://npo-artistdb.b-cdn.net/images/8dc9855f-f807-4731-9f01-49fa5b19186a__ikbun.jpg?aspect_ratio=501%3A500&width=500&height=500",
"detailUrl": "/muziek/nummers/2be29add-afef-447c-af86-41bc90b47f3c/ik-bun-moar-een-eenvoudige-boerenlul",
"historyUrl": "/top2000/statistieken/door-de-jaren-heen/normaal/ik-bun-moar-een-eenvoudige-boerenlul",
"id": "2be29add-afef-447c-af86-41bc90b47f3c",
"isAvailable": true,
"previewUrl": "https://p.scdn.co/mp3-preview/3b532e7f39c38b02ce0804d177173c94a9c16458?cid=19f7f13455664bcab5373cb63d176694",
"title": "Ik Bun Moar Een Eenvoudige Boerenlul"
}
},
{
"broadcastTime": "2025-12-27T14:23:19+01:00",
"broadcastTimeFormatted": "zaterdag 27 dec 2025 14:00 - 15:00 uur",
"broadcastUnixTime": 1766841799000,
"id": "ed0818ac-2c6d-4cf6-983a-9125d18c871b",
"position": {
"current": 1209,
"label": "-132",
"previous": 1077,
"type": "fallen"
},
"totalPositions": 1,
"track": {
"artist": "Temple Of The Dog",
"coverUrl": "https://npo-artistdb.b-cdn.net/images/8785ddb5-fde6-4382-877d-61192b18ea53__Hunger-Strike.jpg?aspect_ratio=501%3A500&width=500&height=500",
"detailUrl": "/muziek/nummers/ed0818ac-2c6d-4cf6-983a-9125d18c871b/hunger-strike",
"historyUrl": "/top2000/statistieken/door-de-jaren-heen/temple-of-the-dog/hunger-strike",
"id": "ed0818ac-2c6d-4cf6-983a-9125d18c871b",
"isAvailable": true,
"previewUrl": "https://assets.stemtool.npox.nl/audio/7420/c-d2f6dbf57ba43a2ce6a880d01e0924cb-4.mp3?v=1726670780",
"title": "Hunger Strike"
}
},
{
"broadcastTime": "2025-12-27T14:19:31+01:00",
"broadcastTimeFormatted": "zaterdag 27 dec 2025 14:00 - 15:00 uur",
"broadcastUnixTime": 1766841571000,
"id": "0197396d-e247-702b-9e36-76524e91b54f",
"position": {
"current": 1210,
"label": "-314",
"previous": 896,
"type": "fallen"
},
"totalPositions": 1,
"track": {
"artist": "Red Hot Chili Peppers",
"coverUrl": "https://npo-artistdb.b-cdn.net/images/7a409ed7-4ab2-4ea1-a307-7e7081f2a012__Road-Trippin.jpg?aspect_ratio=501%3A500&width=500&height=500",
"detailUrl": "/muziek/nummers/0197396d-e247-702b-9e36-76524e91b54f/road-trippin",
"historyUrl": "/top2000/statistieken/door-de-jaren-heen/red-hot-chili-peppers/road-trippin",
"id": "0197396d-e247-702b-9e36-76524e91b54f",
"isAvailable": true,
"previewUrl": null,
"title": "Road Trippin'"
}
},
{
"broadcastTime": "2025-12-27T14:15:17+01:00",
"broadcastTimeFormatted": "zaterdag 27 dec 2025 14:00 - 15:00 uur",
"broadcastUnixTime": 1766841317000,
"id": "085923f8-8e0b-4764-8077-49efde92b2c8",
"position": {
"current": 1211,
"label": "-186",
"previous": 1025,
"type": "fallen"
},
"totalPositions": 1,
"track": {
"artist": "Depeche Mode",
"coverUrl": "https://npo-artistdb.b-cdn.net/images/03c66f3f-4cea-4921-8cc8-0bae5493bb55__Just-Can-t-Get-Enough.jpg?aspect_ratio=501%3A500&width=500&height=500",
"detailUrl": "/muziek/nummers/085923f8-8e0b-4764-8077-49efde92b2c8/just-cant-get-enough",
"historyUrl": "/top2000/statistieken/door-de-jaren-heen/depeche-mode/just-cant-get-enough-live",
"id": "085923f8-8e0b-4764-8077-49efde92b2c8",
"isAvailable": true,
"previewUrl": null,
"title": "Just Can't Get Enough (Live)"
}
},
{
"broadcastTime": "2025-12-27T14:09:41+01:00",
"broadcastTimeFormatted": "zaterdag 27 dec 2025 14:00 - 15:00 uur",
"broadcastUnixTime": 1766840981000,
"id": "703dd67b-c81b-48cd-9faf-cfcfece72f43",
"position": {
"current": 1212,
"label": "-84",
"previous": 1128,
"type": "fallen"
},
"totalPositions": 1,
"track": {
"artist": "Paul McCartney & Wings",
"coverUrl": "https://npo-artistdb.b-cdn.net/images/eca307ce-aa89-4252-a586-9b5a0b6cba6a__Band-On-The-Run.jpg?aspect_ratio=501%3A500&width=500&height=500",
"detailUrl": "/muziek/nummers/703dd67b-c81b-48cd-9faf-cfcfece72f43/band-on-the-run",
"historyUrl": "/top2000/statistieken/door-de-jaren-heen/paul-mccartney-wings/band-on-the-run",
"id": "703dd67b-c81b-48cd-9faf-cfcfece72f43",
"isAvailable": true,
"previewUrl": "https://assets.stemtool.npox.nl/audio/3223/c-673f51dffb08f804ba20f033a68a36cc-6.mp3?v=1725882494",
"title": "Band On The Run"
}
},
{
"broadcastTime": "2025-12-27T14:05:00+01:00",
"broadcastTimeFormatted": "zaterdag 27 dec 2025 14:00 - 15:00 uur",
"broadcastUnixTime": 1766840700000,
"id": "744695e9-65c3-4952-ad4e-aa1303194809",
"position": {
"current": 1213,
"label": "+206",
"previous": 1419,
"type": "risen"
},
"totalPositions": 1,
"track": {
"artist": "Live",
"coverUrl": "https://npo-artistdb.b-cdn.net/images/069b9569-749b-4d1d-842f-b7ffa830e890__The-Dolphin-s-Cry.jpg?aspect_ratio=501%3A500&width=500&height=500",
"detailUrl": "/muziek/nummers/744695e9-65c3-4952-ad4e-aa1303194809/the-dolphins-cry",
"historyUrl": "/top2000/statistieken/door-de-jaren-heen/live/the-dolphins-cry",
"id": "744695e9-65c3-4952-ad4e-aa1303194809",
"isAvailable": true,
"previewUrl": "https://assets.stemtool.npox.nl/audio/6069/c-e5613c8e9fc457ba934245a41c17b13c-10.mp3?v=1726670475",
"title": "The Dolphin's Cry"
}
},
{
"broadcastTime": "2025-12-27T13:53:52+01:00",
"broadcastTimeFormatted": "zaterdag 27 dec 2025 13:00 - 14:00 uur",
"broadcastUnixTime": 1766840032000,
"id": "effa8e82-a30f-44ec-9a8e-e39f26d673ba",
"position": {
"current": 1214,
"label": "+112",
"previous": 1326,
"type": "risen"
},
"totalPositions": 1,
"track": {
"artist": "Lee Towers",
"coverUrl": "https://npo-artistdb.b-cdn.net/images/999335b3-104f-4fd6-9ef5-89995013dff9__Lee-Towers.jpg?aspect_ratio=501%3A500&width=500&height=500",
"historyUrl": "/top2000/statistieken/door-de-jaren-heen/lee-towers/youll-never-walk-alone",
"id": "effa8e82-a30f-44ec-9a8e-e39f26d673ba",
"isAvailable": false,
"previewUrl": "https://assets.stemtool.npox.nl/audio/3503/c-21a78d481b33c0835916b64c97da9e55-5.mp3?v=1725882662",
"title": "You'll Never Walk Alone"
}
},
{
"broadcastTime": "2025-12-27T13:49:55+01:00",
"broadcastTimeFormatted": "zaterdag 27 dec 2025 13:00 - 14:00 uur",
"broadcastUnixTime": 1766839795000,
"id": "33529033-d41a-4989-9f7b-8a3cde2c7713",
"position": {
"current": 1215,
"label": "-23",
"previous": 1192,
"type": "fallen"
},
"totalPositions": 1,
"track": {
"artist": "Madness",
"coverUrl": "https://npo-artistdb.b-cdn.net/images/df9b191a-8bc0-4b49-be74-bca0267a4597__Our-House.jpg?aspect_ratio=501%3A500&width=500&height=500",
"detailUrl": "/muziek/nummers/33529033-d41a-4989-9f7b-8a3cde2c7713/our-house",
"historyUrl": "/top2000/statistieken/door-de-jaren-heen/madness/our-house",
"id": "33529033-d41a-4989-9f7b-8a3cde2c7713",
"isAvailable": true,
"previewUrl": null,
"title": "Our House"
}
},
{
"broadcastTime": "2025-12-27T13:45:05+01:00",
"broadcastTimeFormatted": "zaterdag 27 dec 2025 13:00 - 14:00 uur",
"broadcastUnixTime": 1766839505000,
"id": "2aef0127-2a14-4acf-bd03-fd47307be9bb",
"position": {
"current": 1216,
"label": "+671",
"previous": 1887,
"type": "risen"
},
"totalPositions": 1,
"track": {
"artist": "Golden Earring",
"coverUrl": "https://npo-artistdb.b-cdn.net/images/50ae3f52-5f44-427c-a941-2781e36f7208__Weekend-Love.jpg?aspect_ratio=501%3A500&width=500&height=500",
"detailUrl": "/muziek/nummers/2aef0127-2a14-4acf-bd03-fd47307be9bb/weekend-love",
"historyUrl": "/top2000/statistieken/door-de-jaren-heen/golden-earring/weekend-love",
"id": "2aef0127-2a14-4acf-bd03-fd47307be9bb",
"isAvailable": true,
"previewUrl": "https://p.scdn.co/mp3-preview/c496cd2634741a1f07297d825beedf6ceaf2690e?cid=e10971e8edab41f8b0986464de19b8f3",
"title": "Weekend Love"
}
},
{
"broadcastTime": "2025-12-27T13:40:14+01:00",
"broadcastTimeFormatted": "zaterdag 27 dec 2025 13:00 - 14:00 uur",
"broadcastUnixTime": 1766839214000,
"id": "15984792-6bce-4ceb-9d33-dccecdf6fd60",
"position": {
"current": 1217,
"label": "-80",
"previous": 1137,
"type": "fallen"
},
"totalPositions": 1,
"track": {
"artist": "Heart",
"coverUrl": "https://npo-artistdb.b-cdn.net/images/5ffe2ce6-d704-4d5a-acb6-bb18ff2f13e0__Crazy-On-You.jpg?aspect_ratio=501%3A500&width=500&height=500",
"detailUrl": "/muziek/nummers/15984792-6bce-4ceb-9d33-dccecdf6fd60/crazy-on-you",
"historyUrl": "/top2000/statistieken/door-de-jaren-heen/heart/crazy-on-you",
"id": "15984792-6bce-4ceb-9d33-dccecdf6fd60",
"isAvailable": true,
"previewUrl": "https://assets.stemtool.npox.nl/audio/2326/c-e635161f60fc50d78cf48c004273a98b-5.mp3?v=1725882298",
"title": "Crazy On You"
}
},
{
"broadcastTime": "2025-12-27T13:37:36+01:00",
"broadcastTimeFormatted": "zaterdag 27 dec 2025 13:00 - 14:00 uur",
"broadcastUnixTime": 1766839056000,
"id": null,
"position": {
"current": 1218,
"label": "+654",
"previous": 1872,
"type": "risen"
},
"totalPositions": 1,
"track": {
"artist": "The Beatles",
"coverUrl": null,
"historyUrl": "/top2000/statistieken/door-de-jaren-heen/the-beatles/sgt-peppers-lonely-hearts-club-band",
"id": null,
"isAvailable": false,
"previewUrl": null,
"title": "Sgt. Pepper's Lonely Hearts Club Band"
}
},
{
"broadcastTime": "2025-12-27T13:33:26+01:00",
"broadcastTimeFormatted": "zaterdag 27 dec 2025 13:00 - 14:00 uur",
"broadcastUnixTime": 1766838806000,
"id": "0196fa5d-96e3-73ac-ac1c-7196f2c7d7f1",
"position": {
"current": 1219,
"label": "-126",
"previous": 1093,
"type": "fallen"
},
"totalPositions": 1,
"track": {
"artist": "Keane",
"coverUrl": "https://npo-artistdb.b-cdn.net/images/44586fa9-a0b5-438d-b0df-01a2a5c516a3__Everybody-s-Changing.jpg?aspect_ratio=501%3A500&width=500&height=500",
"detailUrl": "/muziek/nummers/0196fa5d-96e3-73ac-ac1c-7196f2c7d7f1/everybodys-changing",
"historyUrl": "/top2000/statistieken/door-de-jaren-heen/keane/everybodys-changing",
"id": "0196fa5d-96e3-73ac-ac1c-7196f2c7d7f1",
"isAvailable": true,
"previewUrl": null,
"title": "Everybody's Changing"
}
},
{
"broadcastTime": "2025-12-27T13:28:55+01:00",
"broadcastTimeFormatted": "zaterdag 27 dec 2025 13:00 - 14:00 uur",
"broadcastUnixTime": 1766838535000,
"id": "f08f3125-bcd7-441b-890b-43000b508e84",
"position": {
"current": 1220,
"label": "+55",
"previous": 1275,
"type": "risen"
},
"totalPositions": 1,
"track": {
"artist": "Kim Wilde",
"coverUrl": "https://npo-artistdb.b-cdn.net/images/5e4eaca7-af95-48f8-a39d-b1469f75291b__Cambodia.jpg?aspect_ratio=501%3A500&width=500&height=500",
"detailUrl": "/muziek/nummers/f08f3125-bcd7-441b-890b-43000b508e84/cambodia",
"historyUrl": "/top2000/statistieken/door-de-jaren-heen/kim-wilde/cambodia",
"id": "f08f3125-bcd7-441b-890b-43000b508e84",
"isAvailable": true,
"previewUrl": "https://p.scdn.co/mp3-preview/a7e79e67acda3f841498e2de39524a3ebfaec71f?cid=e10971e8edab41f8b0986464de19b8f3",
"title": "Cambodia"
}
},
{
"broadcastTime": "2025-12-27T13:23:57+01:00",
"broadcastTimeFormatted": "zaterdag 27 dec 2025 13:00 - 14:00 uur",
"broadcastUnixTime": 1766838237000,
"id": "731979b1-8161-450c-8b33-407abd1c3260",
"position": {
"current": 1221,
"label": "-189",
"previous": 1032,
"type": "fallen"
},
"totalPositions": 1,
"track": {
"artist": "Eminem & Rihanna",
"coverUrl": "https://npo-artistdb.b-cdn.net/images/69d0ef3c-ce86-4977-89d6-a94ca95b21ca__ab67616d0000b273900afe4507ebed53340370e9.jpg?aspect_ratio=501%3A500&width=500&height=500",
"detailUrl": "/muziek/nummers/731979b1-8161-450c-8b33-407abd1c3260/love-the-way-you-lie",
"historyUrl": "/top2000/statistieken/door-de-jaren-heen/eminem-rihanna/love-the-way-you-lie",
"id": "731979b1-8161-450c-8b33-407abd1c3260",
"isAvailable": true,
"previewUrl": "https://p.scdn.co/mp3-preview/7a10fb23288965b683412c1fad19a9d6705b1702?cid=19f7f13455664bcab5373cb63d176694",
"title": "Love The Way You Lie"
}
},
{
"broadcastTime": "2025-12-27T13:18:39+01:00",
"broadcastTimeFormatted": "zaterdag 27 dec 2025 13:00 - 14:00 uur",
"broadcastUnixTime": 1766837919000,
"id": "5a960895-87ec-4beb-86c2-0c3d70d8ce62",
"position": {
"current": 1222,
"label": "+223",
"previous": 1445,
"type": "risen"
},
"totalPositions": 1,
"track": {
"artist": "Whitney Houston",
"coverUrl": "https://npo-artistdb.b-cdn.net/images/47c92d62-d525-479a-850b-164b42f8282f__I-Have-Nothing.jpg?aspect_ratio=501%3A500&width=500&height=500",
"detailUrl": "/muziek/nummers/5a960895-87ec-4beb-86c2-0c3d70d8ce62/i-have-nothing",
"historyUrl": "/top2000/statistieken/door-de-jaren-heen/whitney-houston/i-have-nothing",
"id": "5a960895-87ec-4beb-86c2-0c3d70d8ce62",
"isAvailable": true,
"previewUrl": "https://p.scdn.co/mp3-preview/c0f4dcce1ca7f6142d709185db1ffa44ff2d4d4a?cid=e10971e8edab41f8b0986464de19b8f3",
"title": "I Have Nothing"
}
},
{
"broadcastTime": "2025-12-27T13:13:29+01:00",
"broadcastTimeFormatted": "zaterdag 27 dec 2025 13:00 - 14:00 uur",
"broadcastUnixTime": 1766837609000,
"id": "9cc4ea52-267e-41e7-803f-e6c073563c36",
"position": {
"current": 1223,
"label": "Nieuw",
"previous": 0,
"type": "new"
},
"totalPositions": 1,
"track": {
"artist": "Chris Stapleton & Dua Lipa",
"coverUrl": null,
"historyUrl": "/top2000/statistieken/door-de-jaren-heen/chris-stapleton-dua-lipa/think-im-in-love-with-you-live-from-the-59th-acm-awards",
"id": "9cc4ea52-267e-41e7-803f-e6c073563c36",
"isAvailable": false,
"previewUrl": null,
"title": "Think I'm In Love with You (Live from the 59th ACM Awards)"
}
},
{
"broadcastTime": "2025-12-27T13:08:47+01:00",
"broadcastTimeFormatted": "zaterdag 27 dec 2025 13:00 - 14:00 uur",
"broadcastUnixTime": 1766837327000,
"id": "149294b8-ffd7-4ac1-9544-3d6191359d3c",
"position": {
"current": 1224,
"label": "+541",
"previous": 1765,
"type": "risen"
},
"totalPositions": 1,
"track": {
"artist": "Hozier",
"coverUrl": "https://npo-artistdb.b-cdn.net/images/edc2d36d-6beb-49a3-9a8e-d65d61e38954__Scherm-afbeelding-2024-03-28-om-15-06-37.png?aspect_ratio=501%3A500&width=500&height=500",
"detailUrl": "/muziek/nummers/149294b8-ffd7-4ac1-9544-3d6191359d3c/too-sweet",
"historyUrl": "/top2000/statistieken/door-de-jaren-heen/hozier/too-sweet",
"id": "149294b8-ffd7-4ac1-9544-3d6191359d3c",
"isAvailable": true,
"previewUrl": "https://assets.stemtool.npox.nl/audio/123686/da77b34adced724758a0a5b8ea3269e4.mp3?v=1733413983",
"title": "Too Sweet"
}
},
{
"broadcastTime": "2025-12-27T13:05:00+01:00",
"broadcastTimeFormatted": "zaterdag 27 dec 2025 13:00 - 14:00 uur",
"broadcastUnixTime": 1766837100000,
"id": "3e03854f-4b35-442f-94c7-53a3f8c08159",
"position": {
"current": 1225,
"label": "-144",
"previous": 1081,
"type": "fallen"
},
"totalPositions": 1,
"track": {
"artist": "The Black Keys",
"coverUrl": "https://npo-artistdb.b-cdn.net/images/fef71b31-5d67-4381-a26c-c98f9c40373f__Lonely-Boy.jpg?aspect_ratio=501%3A500&width=500&height=500",
"detailUrl": "/muziek/nummers/3e03854f-4b35-442f-94c7-53a3f8c08159/lonely-boy",
"historyUrl": "/top2000/statistieken/door-de-jaren-heen/the-black-keys/lonely-boy",
"id": "3e03854f-4b35-442f-94c7-53a3f8c08159",
"isAvailable": true,
"previewUrl": "https://p.scdn.co/mp3-preview/6b462b2d89ed30b669470c39c65b0f04d6ac740b?cid=e10971e8edab41f8b0986464de19b8f3",
"title": "Lonely Boy"
}
},
{
"broadcastTime": "2025-12-27T12:53:13+01:00",
"broadcastTimeFormatted": "zaterdag 27 dec 2025 12:00 - 13:00 uur",
"broadcastUnixTime": 1766836393000,
"id": "0197448b-9c29-7212-abdc-3d37c5176273",
"position": {
"current": 1226,
"label": "+397",
"previous": 1623,
"type": "risen"
},
"totalPositions": 1,
"track": {
"artist": "S10",
"coverUrl": "https://npo-artistdb.b-cdn.net/images/9b53b46b-2773-45be-9665-b8acdaa90cfe__29c3780d2a4112eec70cccdf4d556c86-300x300x1.jpg?aspect_ratio=501%3A500&width=500&height=500",
"detailUrl": "/muziek/nummers/0197448b-9c29-7212-abdc-3d37c5176273/adem-je-in",
"historyUrl": "/top2000/statistieken/door-de-jaren-heen/s10/adem-je-in",
"id": "0197448b-9c29-7212-abdc-3d37c5176273",
"isAvailable": true,
"previewUrl": "https://assets.stemtool.npox.nl/audio/96294/8ff0a2caca813e5be52e0e61e9fdf7e1.mp3?v=1730473658",
"title": "Adem Je In"
}
},
{
"broadcastTime": "2025-12-27T12:48:42+01:00",
"broadcastTimeFormatted": "zaterdag 27 dec 2025 12:00 - 13:00 uur",
"broadcastUnixTime": 1766836122000,
"id": "e99d8695-b52e-456c-b89e-e45c2e8e1aaa",
"position": {
"current": 1227,
"label": "+584",
"previous": 1811,
"type": "risen"
},
"totalPositions": 1,
"track": {
"artist": "David Bowie",
"coverUrl": "https://npo-artistdb.b-cdn.net/images/c8da04c4-0d09-4404-946e-a9d0927006cc__The-Man-Who-Sold-The-World.jpg?aspect_ratio=501%3A500&width=500&height=500",
"detailUrl": "/muziek/nummers/e99d8695-b52e-456c-b89e-e45c2e8e1aaa/the-man-who-sold-the-world",
"historyUrl": "/top2000/statistieken/door-de-jaren-heen/david-bowie/the-man-who-sold-the-world",
"id": "e99d8695-b52e-456c-b89e-e45c2e8e1aaa",
"isAvailable": true,
"previewUrl": "https://p.scdn.co/mp3-preview/a5087777859441e02ee48409082f9f9713183ca7?cid=e10971e8edab41f8b0986464de19b8f3",
"title": "The Man Who Sold The World"
}
},
{
"broadcastTime": "2025-12-27T12:45:13+01:00",
"broadcastTimeFormatted": "zaterdag 27 dec 2025 12:00 - 13:00 uur",
"broadcastUnixTime": 1766835913000,
"id": "65b4d1e1-4652-4b98-8792-62caa514ab68",
"position": {
"current": 1228,
"label": "+83",
"previous": 1311,
"type": "risen"
},
"totalPositions": 1,
"track": {
"artist": "Boudewijn De Groot",
"coverUrl": "https://npo-artistdb.b-cdn.net/images/2c890071-c9e6-408c-961f-fdce42fc9716__Het-Land-Van-Maas-En-Waal.jpg?aspect_ratio=501%3A500&width=500&height=500",
"detailUrl": "/muziek/nummers/65b4d1e1-4652-4b98-8792-62caa514ab68/het-land-van-maas-en-waal",
"historyUrl": "/top2000/statistieken/door-de-jaren-heen/boudewijn-de-groot/het-land-van-maas-en-waal",
"id": "65b4d1e1-4652-4b98-8792-62caa514ab68",
"isAvailable": true,
"previewUrl": "https://assets.stemtool.npox.nl/audio/38252/c-7a00422cbb7b85b5074199cae8de73b3-3.mp3?v=1729610149",
"title": "Het Land Van Maas En Waal"
}
}
],
"slug": "npo-radio-2-top-2000-van-2025-12-25"
})
// res.send(ranking);
})
app.get('/graph/:artist/:title', async (req, res) => {
const artist = req.params.artist;
const title = req.params.title;
@ -33,6 +692,6 @@ app.get('/trivia/:artist', async (req, res) => {
})
app.listen(3000, () => {
console.log("Listening on port 3000")
app.listen(5438, () => {
console.log("Listening on port 5438")
})