From f6b007356b962f57b0abbffda357d4067b54807e Mon Sep 17 00:00:00 2001
From: Cory Dransfeldt <cory.dransfeldt@gmail.com>
Date: Thu, 24 Aug 2023 17:20:30 -0700
Subject: [PATCH] feat: now playing display

---
 .gitignore                               |  3 ++
 netlify/edge-functions/now-playing.js    | 40 ++++++++++++++++++++++++
 src/_includes/base.liquid                |  6 ++++
 src/_includes/partials/now-topper.liquid |  7 +++++
 src/assets/scripts/script.js             | 40 ++++++++++++++++++++++++
 tailwind.css                             |  9 ++++++
 6 files changed, 105 insertions(+)
 create mode 100644 netlify/edge-functions/now-playing.js
 create mode 100644 src/assets/scripts/script.js

diff --git a/.gitignore b/.gitignore
index 1bd0165b..398406c6 100644
--- a/.gitignore
+++ b/.gitignore
@@ -9,3 +9,6 @@ node_modules
 
 # system files
 .DS_Store
+
+# netlify
+.netlify
diff --git a/netlify/edge-functions/now-playing.js b/netlify/edge-functions/now-playing.js
new file mode 100644
index 00000000..297ab4d1
--- /dev/null
+++ b/netlify/edge-functions/now-playing.js
@@ -0,0 +1,40 @@
+const emojiMap = (genre, artist) => {
+  if (artist === 'David Bowie') return '👨‍🎤'
+  if (genre.includes('metal')) return '🤘'
+  if (genre.includes('emo')) return '😢'
+  if (genre.includes('alternative')) return '🎸'
+  if (genre.includes('grind') || genre.includes('powerviolence')) return '🫨'
+  if (genre.includes('country') || genre.includes('americana') || genre.includes('bluegrass'))
+    return '🪕'
+  if (genre.includes('post-punk')) return '😔'
+  if (genre.includes('punk') || genre.includes('hardcore')) return '✊'
+  if (genre.includes('hip hop')) return '🎤'
+  if (genre.includes('dance') || genre.includes('electronic')) return '💻'
+  return '🎧'
+}
+
+export default async () => {
+  // eslint-disable-next-line no-undef
+  const MUSIC_KEY = Netlify.env.get('API_KEY_LASTFM')
+  const trackUrl = `https://ws.audioscrobbler.com/2.0/?method=user.getrecenttracks&user=cdrn_&api_key=${MUSIC_KEY}&limit=1&format=json`
+  const trackRes = await fetch(trackUrl, {
+    type: 'json',
+  }).catch()
+  const trackData = await trackRes.json()
+  const track = trackData['recenttracks']['track'][0]
+  const genreUrl = `https://musicbrainz.org/ws/2/artist/${track['artist']['mbid']}?inc=aliases+genres&fmt=json`
+  const genreRes = await fetch(genreUrl, {
+    type: 'json',
+  }).catch()
+  const genreData = await genreRes.json()
+  const genre = genreData.genres.sort((a, b) => b.count - a.count)[0]['name']
+
+  return Response.json({
+    artist: track['artist']['#text'],
+    title: track['name'],
+    genre,
+    emoji: emojiMap(genre, track['artist']['#text']),
+  })
+}
+
+export const config = { path: '/api/now-playing' }
diff --git a/src/_includes/base.liquid b/src/_includes/base.liquid
index c6d1f057..e204436c 100644
--- a/src/_includes/base.liquid
+++ b/src/_includes/base.liquid
@@ -69,5 +69,11 @@
   </head>
   <body class="dark:text-white bg-white dark:bg-gray-900 font-sans text-gray-800 scrollbar-thin scrollbar-thumb-purple-500 scrollbar-track-purple-100">
     {{ content }}
+    {% capture js %}
+      {% render "../assets/scripts/script.js" %}
+    {% endcapture %}
+    <script>
+      {{ js }}
+    </script>
   </body>
 </html>
\ No newline at end of file
diff --git a/src/_includes/partials/now-topper.liquid b/src/_includes/partials/now-topper.liquid
index d1f2da6e..376f97af 100644
--- a/src/_includes/partials/now-topper.liquid
+++ b/src/_includes/partials/now-topper.liquid
@@ -15,5 +15,12 @@
       <span class="pt-1 md:pt-0 mr-1">{{ status.emoji }}</span>
       <span>{{ status.content }}</span>
     </p>
+    <p id="now-playing" class="mb-0 flex flex-row items-start md:items-center">
+      <span id="now-playing-loading" class="text--blur">Loading...</span>
+      <span id="now-playing-display">
+        <span id="now-playing-emoji" class="pt-1 md:pt-0 mr-1"></span>
+        <span id="now-playing-content"></span>
+      </span>
+    </p>
   </div>
 </div>
\ No newline at end of file
diff --git a/src/assets/scripts/script.js b/src/assets/scripts/script.js
new file mode 100644
index 00000000..f059231f
--- /dev/null
+++ b/src/assets/scripts/script.js
@@ -0,0 +1,40 @@
+;(async function () {
+  const nowPlaying = document.getElementById('now-playing')
+  if (nowPlaying) {
+    const emoji = document.getElementById('now-playing-emoji')
+    const content = document.getElementById('now-playing-content')
+    const loading = document.getElementById('now-playing-loading')
+
+    try {
+      const cache = JSON.parse(localStorage.getItem('now-playing'))
+      if (cache) {
+        loading.style.display = 'none'
+        emoji.innerText = cache.emoji
+        content.innerText = `${cache.title} by ${cache.artist}`
+        emoji.classList.remove('hidden')
+        content.classList.remove('hidden')
+      }
+    } catch (e) {
+      /* quiet catch */
+    }
+
+    const res = await fetch('/api/now-playing', {
+      type: 'json',
+    }).catch()
+    const data = await res.json()
+
+    try {
+      localStorage.setItem('now-playing', JSON.stringify(data))
+    } catch (e) {
+      /* quiet catch */
+    }
+
+    if (!JSON.parse(localStorage.getItem('now-playing')) && !data) nowPlaying.remove()
+
+    loading.style.display = 'none'
+    emoji.innerText = data.emoji
+    content.innerText = `${data.title} by ${data.artist}`
+    emoji.classList.remove('hidden')
+    content.classList.remove('hidden')
+  }
+})()
diff --git a/tailwind.css b/tailwind.css
index 34844030..8a558aab 100644
--- a/tailwind.css
+++ b/tailwind.css
@@ -174,6 +174,11 @@ code[class*=language-], pre[class*=language-] {
   color: theme(colors.pink.500)
 }
 
+.text--blur {
+  color: transparent;
+  text-shadow: 0 0 5px rgba(0,0,0,0.5);
+}
+
 @media (prefers-color-scheme: dark) {
   body {
     --pagefind-ui-primary: theme(colors.purple.400);
@@ -209,4 +214,8 @@ code[class*=language-], pre[class*=language-] {
     color: theme(colors.gray.900);
     background: theme(colors.purple.400);
   }
+  
+  .text--blur {
+    text-shadow: 0 0 5px rgba(255,255,255,0.5);
+  }
 }
\ No newline at end of file