/* * sophies.rocks * * Copyright (C) 2026 Zofia Szweda * * This file is part of sophies.rocks. * * sophies.rocks is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation, either version 3 of * the License, or (at your option) any later version. * * sophies.rocks is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with sophies.rocks. If not, see . */ const LIBREFM_USER = 'sophii.xyz'; const LIBREFM_API_KEY = '00000000000000000000000000000000'; const LIBREFM_CACHE_KEY = 'scrobbles-cache'; const LIBREFM_CACHE_TTL_MS = 60_000; async function loadScrobbles(limit = 7) { const cached = localStorage.getItem(LIBREFM_CACHE_KEY); if (cached) { const { data, ts } = JSON.parse(cached); if (Date.now() - ts < LIBREFM_CACHE_TTL_MS) return data; } const url = `https://libre.fm/2.0/?method=user.getrecenttracks&user=${LIBREFM_USER}&api_key=${LIBREFM_API_KEY}&format=json&limit=${limit}`; const res = await fetch(url); if (!res.ok) throw new Error('Could not fetch scrobbles'); const data = await res.json(); const tracks = data.recenttracks?.track ?? []; localStorage.setItem(LIBREFM_CACHE_KEY, JSON.stringify({ data: tracks, ts: Date.now() })); return tracks; } async function renderScrobbles() { const list = document.querySelector('#recent-scrobbles ul'); try { const tracks = await loadScrobbles(); if (tracks.length === 0) { list.innerHTML = '
  • No scrobbles yet.
  • '; return; } list.innerHTML = ''; tracks.forEach(track => { const li = document.createElement('li'); const artist = track.artist?.['#text'] ?? ''; const nowPlaying = track['@attr']?.nowplaying === 'true'; li.innerHTML = ` ${track.name}
    ${artist}${nowPlaying ? ' - listening now' : ''}
    `; list.appendChild(li); }); } catch (err) { console.error('Failed to load libre.fm scrobbles:', err); list.innerHTML = "
  • Couldn't load scrobbles right now.
  • "; } } renderScrobbles();