Published
Spotify Playlist folder
I feel proud of my musical taste, I invest my self some hours to look for music that I like, I must say that with Spotify I enjoy discovering music even more. Every Discovery Week matches the mood of my previous week, not always what I wish for but most of the time I'm very satisfied.
My girlfriend is often suggesting friends subscribe to my discovery weekly because she found it nice. So I thought why not just share with the rest of the worlds that ends here?
Every now and then, mainly when I remember, I backup my Discovery Weekly in a SongDiary. So I thought, every time I have a new playlist I will like to add it here in my blog.
But with as the excitement grows while studying the Spotify API, I unfortunately end my search at this issue, which means that Spotify would not make available a way to fetch folders.
Well, that was bad luck, but hey it's not my problem only, and seems someone has already built a solution. Although this practice delivers the same value, the script has to run where there is an Authenticate Spotify installed.
And since I was planning to run this in a cron, I might rethink how I want this to work in the first place.
So I decided to give a try this script let's see how it goes.
The idea
I want to extrapolate the playlist id and I want to create a simple org file with just the URL of the playlist and maybe also the image. I'm already thinking I can apply a nice effect to it.
Ahh.. this is getting juicy. When I create a new playlist maybe I should also publish it to my Social channels. But that is for later.
The plan
Let's start by downloading the script as recommended by the project.
curl -L https://git.io/folders > /usr/local/bin/spotifyfolders
chmod +x /usr/local/bin/spotifyfolders
Then let's try to use this thing
spotifyfolders https://open.spotify.com/user/1134797920/folder/bdb20f3c4fb707ff
{"uri": "spotify:user:1134797920:folder:bdb20f3c4fb707ff", "type": "folder", "children": [{"type": "playlist", "uri": "spotify:playlist:6fKJji10mSRO1hg4wLEOMN"}, {"type": "playlist", "uri": "spotify:playlist:2UUX93YEn6rE2ZrkzrsGVF"}, {"type": "playlist", "uri": "spotify:playlist:5AreCygyGXhMO1M6BkQeyE"}, {"type": "playlist", "uri": "spotify:playlist:3pRRYgIBprnqbxE4xT9ggE"}, {"type": "playlist", "uri": "spotify:playlist:0r7eWDbGdYX31aJSw4lga9"}, {"type": "playlist", "uri": "spotify:playlist:30tmtDDsivDY18ofv5a6PI"}, {"type": "playlist", "uri": "spotify:playlist:6QS8AuFX9F4MlLIN9A4ZWL"}, {"type": "playlist", "uri": "spotify:playlist:2WrKjL3wHHVNyxlw3tURXu"}, {"type": "playlist", "uri": "spotify:playlist:1ME16lmOpbPFOw5yCxR1es"}, {"type": "playlist", "uri": "spotify:playlist:7vTInzvufSRmtcynzC94Lj"}, {"type": "playlist", "uri": "spotify:playlist:3JjTlH6BuqGERXSPJ1J1fM"}, {"type": "playlist", "uri": "spotify:playlist:36XRObcnOGzL0kC9fNf795"}, {"type": "playlist", "uri": "spotify:playlist:6JQRzApaNHYTRpPwwiUPSW"}, {"type": "playlist", "uri": "spotify:playlist:12x4f5SQ5NWycFZ6q5jfKl"}, {"type": "playlist", "uri": "spotify:playlist:0IyEuRHMDfIOyksJ9vzdZA"}, {"type": "playlist", "uri": "spotify:playlist:4595BMbHRnNyoumoyKLmn4"}, {"type": "playlist", "uri": "spotify:playlist:3fT23BOUb9TjQam1aMdjO4"}, {"type": "playlist", "uri": "spotify:playlist:6lGHEwpyB7tvkBtoD74CgU"}, {"type": "playlist", "uri": "spotify:playlist:4r6kTdE9Eq1UtITi3etD0g"}, {"type": "playlist", "uri": "spotify:playlist:3zOlIHtrkLroSUxCDwsasb"}, {"type": "playlist", "uri": "spotify:playlist:1PqTvVYQR9l44Z9rq0fZaa"}, {"type": "playlist", "uri": "spotify:playlist:2nL0vbniGbDEoOmUSAikAU"}, {"type": "playlist", "uri": "spotify:playlist:1Tjw9O8wVn0g1iVe1hvlhx"}, {"type": "playlist", "uri": "spotify:playlist:3CQkOVxZQvhBf08r5ppity"}, {"type": "playlist", "uri": "spotify:playlist:4AS72fR60eMtYybedC51oo"}, {"type": "playlist", "uri": "spotify:playlist:0Tt7x6dbGZtxVzrhTM1eUK"}, {"type": "playlist", "uri": "spotify:playlist:4oYG8MitLWLkbc7fmScvtC"}, {"type": "playlist", "uri": "spotify:playlist:3qehgg4yTj5I8gZ4GBYrbV"}, {"type": "playlist", "uri": "spotify:playlist:3kymwfqpIkfc4C7jskjsNy"}, {"type": "playlist", "uri": "spotify:playlist:2KlIIVJF2vq2FPyaAPhzsK"}, {"type": "playlist", "uri": "spotify:playlist:0cQmRrb34C1Xf11u59kDVC"}, {"type": "playlist", "uri": "spotify:playlist:50WNdOrhIHKwwuENXNarN3"}, {"type": "playlist", "uri": "spotify:playlist:6vSRItZPm2cytWJESVedOt"}], "name": "SongDiary"}
Well seems that we got already far enough. I'm pleasedly surprised. Ok now let's grab each playlist and create a document for each of them.
So let's loop through those elements and fetch the list of each detail
const http = require("https");
const fetch = (options) =>
new Promise((resolve) => {
const req = http.request(options, (response) => {
const res = [];
response.on("data", (chunck) => res.push(chunck));
response.on("end", () => resolve(res.join("")));
});
req.end();
});
const list_playlist = list != "" ? JSON.parse(list) : [];
Promise.all(
list_playlist.children
.filter((i) => !!i.uri)
.map((i) =>
fetch({
host: "api.spotify.com",
path: `/v1/playlists/${i.uri.replace("spotify:playlist:", "")}`,
headers: {
Accept: "application/json",
"Content-Type": "application/json",
Authorization: token.trim(),
},
})
)
)
.then((res) => {
return res
.map((playlist) => JSON.parse(playlist))
.filter((playlist) => !!playlist.tracks.items.length)
.map(({ images, name, description, id, tracks }) => ({
images,
name,
description,
id,
tracks: tracks.items.map(({ track: { name, album, artists } }) => ({
name,
album: album.name,
images: album.images,
artists: artists.map(({ name }) => name).join(", "),
})),
}));
})
.catch(console.log)
.then((res) => console.log(JSON.stringify(res, null, 4)));
So now that we have extracted all the information that we need let's template this in a convinient way:
const fs = require("fs");
data = JSON.parse(data);
data.forEach(({ name, id, tracks, images }) => {
const getPlayer = () => `
<div class="playlist-player">
<img src="${!!images.length ? images[0].url : ""}" />
<iframe src="https://open.spotify.com/embed/playlist/${id}" frameBorder="0" allowtransparency="true" allow="encrypted-media"></iframe>
</div>`;
const itemList = ({ name, album, artists, images }) => `
<li>
<img class="album-preview" src="${
images.filter(({ height }) => height < 100)[0].url
}" />
<div>
<span class="track">${name}</span>
<span class="artist">${artists}</span>
<span class="album">${album}</span>
</div>
</li>`;
const getList = () => `
<ul>
${tracks.map(itemList).join("")}
</ul>`;
fs.writeFileSync(
`../playlist/${name.replace(/\s/g, "").toLowerCase()}-${id}.org`,
`
#+TITLE: ${name}
* ${name}
#+begin_export html
<div class="playlist">
${getPlayer()}
${getList()}
</div>
#+end_export
`
);
});
🎉 After the execution of the above script, I basically have my folder with a post for each playlist!
So it's time to enjoy the result 🎧!