// HTML Elements const e_songDetails = { title: document.getElementById("current-title"), playlist: document.getElementById("current-playlist"), artist: document.getElementById("current-artist"), }; const e_playlist = document.getElementById("current-playlist"); const e_songListSection = document.getElementById("song-list"); const e_songList = { next: document.getElementById("list-next"), current: document.getElementById("list-current"), previous: document.getElementById("list-previous"), }; const e_listeners = { current: document.querySelector(".listeners.current"), total: document.querySelector(".listeners.total"), unique: document.querySelector(".listeners.unique"), }; const e_audio = document.getElementById("audio"); e_audio.volume = 0.2; const e_warningMessage = document.getElementById("warning-message"); const e_player = document.getElementById("player"); const e_progressBar = document.getElementById("progress-bar"); const e_volumeBar = document.getElementById("volume-bar"); const e_channels = document.querySelectorAll(".channel"); /** * Return a random integer between 0 and a given limit. * @param {int} limit - The maximum returnable integer */ const rRng = (limit) => Math.floor(Math.random() * limit); /** * Return a random item from a given array. * @param {Array} array - The maximum returnable integer */ const rArr = (array) => array[rRng(array.length)]; // :^) const lainon = { life: "https://radio.scuf.ru/", }; // Set a random background image const backgrounds = ["bg205.gif", "bg_307.gif", "bg_315.gif", "patternTV2.gif"]; document.body.style.setProperty( "background-image", `url("./public/asset/${rArr(backgrounds)}")` ); // Default settings let isPlaying = false; let currentChannel = "cafe"; let progressStep = 0; /** * Send a GET request to lainon.life, then do stuff with the reponse. * @returns {Object} data - Information about the present radio state */ async function fetchData() { // Since lainon.life doesn't allow CORS, the request must be // made through a proxy. This "crosscloak" is my fork of // cors-anywhere, and just in case you're thinking about it, // no, it's not public and your domain is not on the whitelist. const data = await fetch(`https://radio.scuf.ru/api/nowplaying/scuf_fm`) .then((response) => response.json()) .catch((ERROR) => { console.error(ERROR); e_warningMessage.classList.remove("hidden"); }); parseData(data); return data; } /** * Parse the reponse data from lainon.life and display it on the page. * @param {Object} radioData - Present state of the lainon.life radio. */ function parseData(radioData) { // Update listeners for (const listenerType in radioData.listeners) { e_listeners[listenerType].innerText = radioData.listeners[listenerType]; } // Go over the radioData object. // If the object exists, set the corresponding element's // innerText to its value, or otherwise to say that it // wasn't found. for (const itemType in e_songDetails) { e_songDetails[itemType].innerText = radioData.now_playing.song[itemType] ? radioData.now_playing.song[itemType] : `${itemType.toUpperCase()} NOT FOUND`; } e_playlist.innerText = radioData.now_playing.playlist; // Current song's length in seconds const songLength = radioData.now_playing.duration; // Increment for the progress bar as a percentage of 100 progressStep = (1 / songLength) * 100; // Set the progress bar to display the current song's elapsed time e_progressBar.style.setProperty( "width", progressStep * Math.floor(radioData.now_playing.elapsed) + "%" ); e_songListSection.style = `background-image: url(${radioData.now_playing.song.art})`; // Clear the entire song list for (const element in e_songList) e_songList[element].innerHTML = ""; // Fill in the upcoming songs const { song, duration } = radioData.playing_next; const e_songEntry = document.createElement("div"); e_songEntry.className = "song-entry"; e_songEntry.innerHTML = `