Last active
June 16, 2024 22:37
-
-
Save jabedzaman/9df165ab6a2f22ff3bf1a1d6bc9f2d1b to your computer and use it in GitHub Desktop.
Fetch currently playing song on Spotify
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// pages/api/spotify. | |
import querystring from 'querystring'; | |
const { | |
NEXT_PUBLIC_SPOTIFY_CLIENT_ID: client_id, | |
NEXT_PUBLIC_SPOTIFY_CLIENT_SECRET: client_secret, | |
NEXT_PUBLIC_SPOTIFY_REFRESH_TOKEN: refresh_token, | |
} = process.env; | |
const basic = Buffer.from(`${client_id}:${client_secret}`).toString('base64'); | |
const NOW_PLAYING_ENDPOINT = `https://api.spotify.com/v1/me/player/currently-playing`; | |
const TOKEN_ENDPOINT = `https://accounts.spotify.com/api/token`; | |
const getAccessToken = async () => { | |
const response = await fetch(TOKEN_ENDPOINT, { | |
method: 'POST', | |
headers: { | |
Authorization: `Basic ${basic}`, | |
'Content-Type': 'application/x-www-form-urlencoded', | |
}, | |
body: querystring.stringify({ | |
grant_type: 'refresh_token', | |
refresh_token, | |
}), | |
}); | |
return response.json(); | |
}; | |
export const getNowPlaying = async () => { | |
const { access_token } = await getAccessToken(); | |
return fetch(NOW_PLAYING_ENDPOINT, { | |
headers: { | |
Authorization: `Bearer ${access_token}`, | |
}, | |
}); | |
}; | |
export default async (_, res) => { | |
const response = await getNowPlaying(); | |
if (response.status === 204 || response.status > 400) { | |
return res.status(200).json({ isPlaying: false }); | |
} | |
const song = await response.json(); | |
const isPlaying = song.is_playing; | |
const title = song.item.name; | |
const artist = song.item.artists.map((_artist) => _artist.name).join(', '); | |
const album = song.item.album.name; | |
const albumImageUrl = song.item.album.images[0].url; | |
const songUrl = song.item.external_urls.spotify; | |
return res.status(200).json({ | |
album, | |
albumImageUrl, | |
artist, | |
isPlaying, | |
songUrl, | |
title, | |
}); | |
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { useEffect } from "react"; | |
import { animate } from "motion"; | |
import useSWR from "swr"; | |
function AnimatedBars() { | |
useEffect(() => { | |
animate( | |
"#bar1", | |
{ | |
transform: [ | |
"scaleY(1.0) translateY(0rem)", | |
"scaleY(1.5) translateY(-0.082rem)", | |
"scaleY(1.0) translateY(0rem)", | |
], | |
}, | |
{ | |
duration: 1.0, | |
repeat: Infinity, | |
easing: ["ease-in-out"], | |
} | |
); | |
animate( | |
"#bar2", | |
{ | |
transform: [ | |
"scaleY(1.0) translateY(0rem)", | |
"scaleY(3) translateY(-0.083rem)", | |
"scaleY(1.0) translateY(0rem)", | |
], | |
}, | |
{ | |
delay: 0.2, | |
duration: 1.5, | |
repeat: Infinity, | |
easing: ["ease-in-out"], | |
} | |
); | |
animate( | |
"#bar3", | |
{ | |
transform: [ | |
"scaleY(1.0) translateY(0rem)", | |
"scaleY(0.5) translateY(0.37rem)", | |
"scaleY(1.0) translateY(0rem)", | |
], | |
}, | |
{ | |
delay: 0.3, | |
duration: 1.5, | |
repeat: Infinity, | |
easing: ["ease-in-out"], | |
} | |
); | |
}, []); | |
return ( | |
<div className="w-auto flex items-end overflow-hidden"> | |
<span | |
id="bar1" | |
className="w-1 mr-[3px] h-2 bg-gray-300 dark:bg-gray-500 opacity-75" | |
/> | |
<span | |
id="bar2" | |
className="w-1 mr-[3px] h-1 bg-gray-300 dark:bg-gray-500" | |
/> | |
<span | |
id="bar3" | |
className="w-1 h-3 bg-gray-300 dark:bg-gray-500 opacity-80" | |
/> | |
</div> | |
); | |
} | |
export default function Spotify() { | |
const fetcher = (url) => fetch(url).then((r) => r.json()); | |
const { data } = useSWR("../api/spotify", fetcher); | |
return ( | |
<section className="max-w-4xl mx-auto p-5"> | |
<div className="flex flex-row-reverse items-center sm:flex-row mb-8 space-x-0 sm:space-x-2 w-full"> | |
{data?.isPlaying ? ( | |
<AnimatedBars /> | |
) : ( | |
<svg className="h-4 w-4 ml-auto mt-[-2px]" viewBox="0 0 168 168"> | |
<path | |
fill="#1ED760" | |
d="M83.996.277C37.747.277.253 37.77.253 84.019c0 46.251 37.494 83.741 83.743 83.741 46.254 0 83.744-37.49 83.744-83.741 0-46.246-37.49-83.738-83.745-83.738l.001-.004zm38.404 120.78a5.217 5.217 0 01-7.18 1.73c-19.662-12.01-44.414-14.73-73.564-8.07a5.222 5.222 0 01-6.249-3.93 5.213 5.213 0 013.926-6.25c31.9-7.291 59.263-4.15 81.337 9.34 2.46 1.51 3.24 4.72 1.73 7.18zm10.25-22.805c-1.89 3.075-5.91 4.045-8.98 2.155-22.51-13.839-56.823-17.846-83.448-9.764-3.453 1.043-7.1-.903-8.148-4.35a6.538 6.538 0 014.354-8.143c30.413-9.228 68.222-4.758 94.072 11.127 3.07 1.89 4.04 5.91 2.15 8.976v-.001zm.88-23.744c-26.99-16.031-71.52-17.505-97.289-9.684-4.138 1.255-8.514-1.081-9.768-5.219a7.835 7.835 0 015.221-9.771c29.581-8.98 78.756-7.245 109.83 11.202a7.823 7.823 0 012.74 10.733c-2.2 3.722-7.02 4.949-10.73 2.739z" | |
/> | |
</svg> | |
)} | |
<div className="inline-flex flex-col sm:flex-row w-full max-w-full truncate"> | |
{data?.isPlaying ? ( | |
<a | |
className="capsize text-gray-800 dark:text-gray-200 font-medium max-w-max truncate" | |
href={data.songUrl} | |
target="_blank" | |
rel="noopener noreferrer" | |
> | |
{data.title} | |
</a> | |
) : ( | |
<p className="capsize text-gray-800 dark:text-gray-200 font-medium"> | |
Not Playing | |
</p> | |
)} | |
<span className="capsize mx-2 text-gray-500 dark:text-gray-300 hidden sm:block"> | |
{" – "} | |
</span> | |
{data?.isPlaying ? ( | |
<p className="capsize text-gray-500 dark:text-gray-300 max-w-max truncate"> | |
{data?.artist ?? "Spotify"} | |
</p> | |
) : ( | |
<p className="capsize text-gray-500 dark:text-gray-300 max-w-max truncate">Is sleeping 🛌</p> | |
)} | |
</div> | |
</div> | |
</section> | |
); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment