// Last.fm Stats Interactive Module (function () { "use strict"; const LASTFM_API_URL = "https://ws.audioscrobbler.com/2.0/"; const LASTFM_API_KEY = "3a4fef48fecc593d25e0f9a40df1fefe"; // Store current stats for export let currentStats = { artists: [], totalTracks: 0, period: "", username: "", }; // Calculate timestamps based on period function getTimestamps(period) { const now = Math.floor(Date.now() / 1000); let from; if (period === "7day") { from = now - 7 * 24 * 60 * 60; // 7 days } else if (period === "1month") { from = now - 30 * 24 * 60 * 60; // 30 days } return { from, to: now }; } // Fetch top artists for the specified period async function fetchTopArtists(username, period) { const url = `${LASTFM_API_URL}?method=user.gettopartists&user=${username}&api_key=${LASTFM_API_KEY}&format=json&period=${period}&limit=5`; const response = await fetch(url); if (!response.ok) { throw new Error(`Failed to fetch top artists: ${response.statusText}`); } const data = await response.json(); // Check for Last.fm API errors if (data.error) { throw new Error(data.message || "Last.fm API error"); } return data.topartists?.artist || []; } // Fetch recent tracks to count total scrobbles in period async function fetchTrackCount(username, period) { const { from, to } = getTimestamps(period); const url = `${LASTFM_API_URL}?method=user.getrecenttracks&user=${username}&api_key=${LASTFM_API_KEY}&format=json&from=${from}&to=${to}&limit=1`; const response = await fetch(url); if (!response.ok) { throw new Error(`Failed to fetch track count: ${response.statusText}`); } const data = await response.json(); // Check for Last.fm API errors if (data.error) { throw new Error(data.message || "Last.fm API error"); } return data.recenttracks?.["@attr"]?.total || 0; } // Generate markdown format function generateMarkdown() { const periodText = currentStats.period === "7day" ? "Past Week" : "Past Month"; let markdown = `## Last.fm Stats - ${periodText}\n\n`; markdown += `**Total Tracks:** ${currentStats.totalTracks}\n\n`; markdown += `**Top 5 Artists:**\n\n`; currentStats.artists.forEach((artist) => { markdown += `- [${artist.name}](${artist.url}) - ${artist.playcount} plays\n`; }); return markdown; } // Generate plain text format function generatePlainText() { const periodText = currentStats.period === "7day" ? "Past Week" : "Past Month"; let text = `Last.fm Stats - ${periodText}\n\n`; text += `Total Tracks: ${currentStats.totalTracks}\n\n`; text += `Top 5 Artists:\n\n`; currentStats.artists.forEach((artist) => { text += `- ${artist.name} - ${artist.playcount} plays\n`; }); return text; } // Copy to clipboard async function copyToClipboard(text, button) { try { await navigator.clipboard.writeText(text); const originalText = button.textContent; button.textContent = "Copied!"; button.classList.add("copied"); setTimeout(() => { button.textContent = originalText; button.classList.remove("copied"); }, 2000); } catch (err) { console.error("Failed to copy:", err); alert("Failed to copy to clipboard"); } } // Display the stats function displayStats(artists, totalTracks, period, username) { const artistsList = document.getElementById("top-artists"); const totalTracksEl = document.getElementById("total-tracks"); // Store current stats for export currentStats = { artists, totalTracks, period, username }; // Update total tracks totalTracksEl.textContent = totalTracks; // Clear and populate artists list artistsList.innerHTML = ""; if (artists.length === 0) { artistsList.innerHTML = "