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

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

Bearer BQADhOP1aWdC94cM313fwcDGVlhQ0UZbuJLc2VKcP3olGKxURvZx4p6bpHE28RDmECmqilv2T8_dQMJzm3ESVXxDf5jt-rDKHT9snPEuCppObY3GXu1jD8VtI8H-oHoVSzJmVUD4NrNdqLu8Ud4tBt-cPvNRh5I
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 🎧!