diff --git a/index.html b/index.html index cde7020..3184ce7 100644 --- a/index.html +++ b/index.html @@ -5,7 +5,7 @@ Penelope Gwen - +

Penelope Gwen

@@ -24,7 +24,17 @@
-
+
@@ -73,7 +83,7 @@
@@ -116,5 +126,6 @@ + diff --git a/style/css/style.css b/style/css/style.css index 10b6ffc..b5ea616 100644 --- a/style/css/style.css +++ b/style/css/style.css @@ -98,12 +98,13 @@ p { .button { margin: 1vh 1vw; transition: 0.5s; + background-color: rgba(from var(--secondary-bg-color) r g b / 0.2); display:block; & > p { margin: 1vh 0vw; } &:hover{ - box-shadow: 0px 0px 30px rgba(from var(--main-fg-color) r g b / 0.8); + box-shadow: 0px 0px 30px rgba(from var(--secondary-bg-color) r g b / 0.6); transition: 0.25s; } } @@ -197,23 +198,21 @@ p { font-family: 'Overpass'; font-style: normal; font-weight: 400; - src: url(/style/fonts/overpass/latin-ext.woff2) format('woff2'); - unicode-range: U+0100-02AF, U+0304, U+0308, U+0329, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF; + src: url(/style/fonts/overpass/OverpassNerdFont-Regular.otf) format('opentype'); + /*unicode-range: U+0100-02AF, U+0304, U+0308, U+0329, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;*/ } -@font-face { +/*@font-face { font-family: 'Overpass'; font-style: normal; font-weight: 400; src: url(/style/fonts/overpass/latin.woff2) format('woff2'); unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; -} +}*/ -/*LASTFM NOWPLAYING*/ - +/*LISTENBRAINZ NOWPLAYING*/ a.now-playing { - opacity: 1; text-decoration: none; } .now-playing .np-metadata > span { @@ -224,18 +223,24 @@ a.now-playing { .now-playing .np-metadata { margin: auto 1vw auto; height: fit-content; - opacity: 0; transition: opacity 0.4s ease-out; transition-delay: 0.5s; } .now-playing.loaded .np-metadata,.now-playing.loaded img { opacity: 1; } +.np-title { + font-weight: bold; +} .now-playing img { border-radius: 8px; + color: transparent; + background-color: rgba(from var(--secondary-bg-color) r g b / 0.1); + font-size: 0px; + aspect-ratio: 1; width: 25%; } -.now-playing .np-metadata .np-heading { +#np-heading, #np-timestamp { font-size: 11px; font-weight: 900; opacity: 0.5; @@ -243,15 +248,16 @@ a.now-playing { letter-spacing: 0.11em; } .now-playing .np-metadata .breather { - margin-right: 8px; + margin-right: 4px; display: inline-block; animation: pulsate 5s linear 0s infinite; } @keyframes pulsate { - 0% { transform: scale(0.2, 0.2) rotate(0deg); opacity: 0.0; } - 50% { transform: scale(1, 1) rotate(50deg); opacity: 1; } - 80% { transform: scale(1.8, 1.8) rotate(80deg); opacity: 0.2; } - 100% { transform: scale(4, 4) rotate(100deg); opacity: 0; } + 0% { transform: scale(0.1, 0.1); opacity: 0.0; } + 50% { transform: scale(1, 1); opacity: 1; } + 80% { transform: scale(1.5, 1.5); opacity: 0.2; } + 90% { transform: scale(2, 2); opacity: 0; } + 100% { transform: scale(2, 2); opacity: 0; } } /*EMFED*/ diff --git a/style/fonts/overpass/OverpassNerdFont-Regular.otf b/style/fonts/overpass/OverpassNerdFont-Regular.otf new file mode 100644 index 0000000..4614dfd Binary files /dev/null and b/style/fonts/overpass/OverpassNerdFont-Regular.otf differ diff --git a/style/js/listenbrainz-nowplaying.js b/style/js/listenbrainz-nowplaying.js new file mode 100644 index 0000000..374cd8f --- /dev/null +++ b/style/js/listenbrainz-nowplaying.js @@ -0,0 +1,105 @@ +// Set the Listenbrainz username +const username = "pogmommy"; + +// Set displayElement to the now-playing widget text from the now_playing.html file +const displayTitle = document.getElementById("np-title"); +//displayTitle.href = "" +const displayArtist = document.getElementById("np-artist"); +const displayCover = document.getElementById("np-cover"); +const displayStatus = document.getElementById("np-heading"); +const displayTimestamp = document.getElementById("np-timestamp"); + +const widget = document.getElementById("now-playing"); + +// Update the widget attributes for the username set above +//displayTitle.href = `https://listenbrainz.org/user/${username}/`; +//displayElement.dataset.username = username; + +// Define endpoints from Listenbrainz API +const endpoints = { + nowPlaying: `https://api.listenbrainz.org/1/user/${username}/playing-now`, + recentTrack: `https://api.listenbrainz.org/1/user/${username}/listens?count=1`, +}; + +// Function to check the API response and fail gracefully if it doesn't work +async function fetchJson(url) { + const response = await fetch(url); + if (!response.ok) throw new Error(`HTTP error! status: ${response.status}`); + return response.json(); +} + +// Function to get the artwork via API response and fail gracefully if it doesn't work +async function fetchArtwork(url) { + const response = await fetch(url); + if (!response.ok) throw new Error(`HTTP error! status: ${response.status}`); + return response.json(); +} + +// Function to set the artist and track title returned from Listenbrainz (or set it to Unknown if nothing is found) +function renderTrack(nowPlaying, track, cover, timestamp) { + const artist = track?.artist_name || "Unknown Artist"; + const title = track?.track_name || "Unknown Track"; + displayTitle.textContent = `${title}`; + displayArtist.textContent = `${artist}`; + + if (nowPlaying) { + displayStatus.innerHTML = "Now Playing"; + displayTimestamp.hidden = true; + } else { + displayStatus.innerHTML = "Last Played" + displayTimestamp.textContent = `${timestamp}`; + displayTimestamp.hidden = false; + } + if (cover) { + const coverUrl = cover.images?.[0]?.thumbnails?.[500] || ""; + displayCover.setAttribute("alt", `Album artwork for ${title} by ${artist}`); + displayCover.setAttribute("src", coverUrl); + displayCover.hidden = false; + } else { + displayCover.hidden = true; + } + widget.hidden = false; +} + +// Function to update the widget +async function updateNowPlayingWidget() { + try { + // Fetch and parse data from the nowPlaying endpoint + const nowPlayingData = await fetchJson(endpoints.nowPlaying); + const playingNow = nowPlayingData?.payload?.playing_now; + const currentTrack = nowPlayingData?.payload?.listens?.[0]?.track_metadata; + + // If something is currently playing, update the widget with Now Playing: currentTrack + if (playingNow && currentTrack) { + const coverData = await fetchJson(`https://coverartarchive.org/release/${currentTrack?.additional_info.release_mbid}`); + renderTrack(true, currentTrack, coverData, ""); + return; + } + + // Fetch and parse data from the recentTrack endpoint + const recentData = await fetchJson(endpoints.recentTrack); + const recentTrack = recentData?.payload?.listens?.[0]?.track_metadata; + const listenTimestamp = new Date(recentData?.payload?.listens?.[0]?.listened_at * 1000); + const timestampFormatted = `(${listenTimestamp.getUTCFullYear()}-${listenTimestamp.getMonth() + 1}-${listenTimestamp.getUTCDate()})`; + + // If nothing is currently playing, update the widget with Last Played: recentTrack + if (recentTrack) { + const coverData = await fetchJson(`https://coverartarchive.org/release/${recentTrack?.additional_info.release_mbid}`); + renderTrack(false, recentTrack, coverData, timestampFormatted); + } + // If there is no recent track, update the widget to say This user has no listens yet + else { + displayStatus.textContent = "🎧 This user has no listens yet"; + } + } + // If the script can't fetch the data, update the widget to say Error loading track info. + // Also give more details in the console + catch (error) { + console.error("Failed to update Now Playing widget:", error); + displayStatus.textContent = "🎧 Error loading track info"; + } +} + +// Update the widget when the page loads, and then every minute after +updateNowPlayingWidget(); +setInterval(updateNowPlayingWidget, 60000); \ No newline at end of file diff --git a/style/js/views.js b/style/js/views.js deleted file mode 100644 index 8266641..0000000 --- a/style/js/views.js +++ /dev/null @@ -1,5 +0,0 @@ -fetch('/assets/views/footer.html') - .then(response => response.text()) - .then( resultText => document.getElementById('footer').innerHTML = resultText ); - -getNowPlaying();