update now-playing widget to use listenbrainz
This commit is contained in:
parent
8eee6a1529
commit
6460a513d7
5 changed files with 140 additions and 23 deletions
17
index.html
17
index.html
|
|
@ -5,7 +5,7 @@
|
|||
<title>Penelope Gwen</title>
|
||||
<meta name="viewport" content="width=device-width,initial-scale=1">
|
||||
<link rel="stylesheet" href="/style/css/style.css">
|
||||
<script src="/style/js/lastfm-nowplaying.js"></script>
|
||||
<!-- <script src="/style/js/lastfm-nowplaying.js"></script>-->
|
||||
</head>
|
||||
<body>
|
||||
<h1>Penelope Gwen</h1>
|
||||
|
|
@ -24,7 +24,17 @@
|
|||
<div id='random-buttons'>
|
||||
</div>
|
||||
</div>
|
||||
<div id="nowplaying-placeholder"></div>
|
||||
<div id="now-playing" hidden="true">
|
||||
<a class="flexrow now-playing" href="https://listenbrainz.org/user/pogmommy/">
|
||||
<img id="np-cover" src="" hidden="true">
|
||||
<div class="np-metadata sidebar-caption">
|
||||
<span id="np-heading">Now Playing</span>
|
||||
<span id="np-timestamp" hidden="true"></span>
|
||||
<span id="np-title" class="np-title">Title</span>
|
||||
<span id="np-artist">Artist</span>
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
<div>
|
||||
<h3 class="sidebar-caption">Check out my friends!</h3>
|
||||
<a href="https://cassiecandles.net/">
|
||||
|
|
@ -73,7 +83,7 @@
|
|||
<script type="module" src="https://esm.sh/emfed@1"></script>
|
||||
<script>
|
||||
document.getElementById("emfed-placeholder").innerHTML = "";
|
||||
getNowPlaying();
|
||||
// getNowPlaying();
|
||||
</script>
|
||||
<div class="pagecontent">
|
||||
<div class="bubble">
|
||||
|
|
@ -116,5 +126,6 @@
|
|||
<!-- <div id="footer"><p>Click <a href="https://pogmom.me/links.html">here</a> or enable javascript to view my social links</p></div>
|
||||
<script src="/style/js/views.js"></script>-->
|
||||
<script src="/style/js/buttons.js"></script>
|
||||
<script src="/style/js/listenbrainz-nowplaying.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
|||
|
|
@ -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*/
|
||||
|
|
|
|||
BIN
style/fonts/overpass/OverpassNerdFont-Regular.otf
Normal file
BIN
style/fonts/overpass/OverpassNerdFont-Regular.otf
Normal file
Binary file not shown.
105
style/js/listenbrainz-nowplaying.js
Normal file
105
style/js/listenbrainz-nowplaying.js
Normal file
|
|
@ -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 = "<span class=\"breather\"></span>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);
|
||||
|
|
@ -1,5 +0,0 @@
|
|||
fetch('/assets/views/footer.html')
|
||||
.then(response => response.text())
|
||||
.then( resultText => document.getElementById('footer').innerHTML = resultText );
|
||||
|
||||
getNowPlaying();
|
||||
Loading…
Add table
Reference in a new issue