HugoLAMOUREUX / Spotidata

Web application linked to Spotify that shows some statistics about your music tastes and miscellaneous informations
MIT License
4 stars 5 forks source link

New backend fix : Modify the getUserPlaylists method #47

Closed HugoLAMOUREUX closed 1 year ago

HugoLAMOUREUX commented 1 year ago

Description

Currently only 50 playlists are retrieved, but if the user has more than 50 playlists, we don't have them in the returned json. The goal of this issue is to make a loop or something until there are no more playlists available. In order to achieve this issue, we will need to call this method : spotifyApi.getUserPlaylists({ limit: 50, offset: 0 }) but change the offset for all the other calls (for example offset:50 means that you're retrieving not the first 50 playlists but the playlists 50-100). It is not possible to change the limit parameter because the API is capping the limit at 50.

Reproduction URL

https://github.com/HugoLAMOUREUX/Spotidata

Reproduction steps

1. Go to back/controllers/playListController.js
2. Modify the getUserPlaylists method

Screenshots

![DESCRIPTION](LINK.png)

Logs

No response

Browsers

No response

OS

No response

AlexLunaP commented 1 year ago

Hi, can I try to solve this?

HugoLAMOUREUX commented 1 year ago

Yes sure ! I assign you the issue

AlexLunaP commented 1 year ago

I tried to make a loop, so the method retrieves all the playlists from an user:

const getUserPlaylists = async (req, res) => {
  const spotifyApi = new SpotifyWebApi({
    accessToken: req.query.access_token,
  });

  let allPlaylists = [];
  let options = { limit: 50, offset: 0 };
  let data = await spotifyApi.getUserPlaylists(options);

  // Use a while loop to keep getting playlists until there are no more left
  while (data.body.items.length != 0) {
    allPlaylists = allPlaylists.concat(data.body.items);
    options.offset += 50;
    data = await spotifyApi.getUserPlaylists(options);
  }

  if (allPlaylists.body.href) {
    delete allPlaylists.body.href;
  }

  if (allPlaylists.body.items) {
    let count = 1;
    allPlaylists.forEach((item) => {
      item.rank = count;
      if (item.href) {
        delete item.href;
      }
      if (item.snapshot_id) {
        delete item.snapshot_id;
      }
      if (item.uri) {
        delete item.uri;
      }
      if (item.owner && item.owner.display_name) {
        item.owner_name = item.owner.display_name;
      }
      if (item.owner && item.owner.id) {
        item.owner_id = item.owner.id;
      }

      delete item.owner;

      count++;
    });
  }

  res.status(200).json(allPlaylists);
};

Nevertheless, when I test it on the web and click on the playlists section, after some seconds loading the page goes blank. I am not sure if this is related to how the playlists are being managed in the json file.

Screenshot from 2023-05-01 18-04-12

You can check my code here: https://github.com/AlexLunaP/Spotidata

HugoLAMOUREUX commented 1 year ago

I have tested your code and changed a few things. First of all, when you were checking :

if (allPlaylists.body.href) {
    delete allPlaylists.body.href;
  }

there is an error since you only concat the data.body.items and not the href, so you can simply remove this href test.

Secondly, you're adding data.body.items to allPlaylist. So, when you're doing if (allPlaylists.body.items) there is a problem because allPlaylist contains simply a list of items but no longer the .body.items structure.

Finally, The front-end expect a structure like this to display the playlists :

{items: [ //your playlists ] }

So I have added in the return an "items" key with allPlaylists as value so that it could be displayed withouth changes on the front end.

So here is my modified version that works well for me :

const getUserPlaylists = async (req, res) => {
  const spotifyApi = new SpotifyWebApi({
    accessToken: req.query.access_token,
  });

  let allPlaylists = [];
  let options = { limit: 50, offset: 0 };
  let data = await spotifyApi.getUserPlaylists(options);

  // Use a while loop to keep getting playlists until there are no more left
  while (data.body.items.length != 0) {
    allPlaylists = allPlaylists.concat(data.body.items);
    options.offset += 50;
    data = await spotifyApi.getUserPlaylists(options);
  }

  if (allPlaylists.length != 0) {
    let count = 1;
    allPlaylists.forEach((item) => {
      item.rank = count;
      if (item.href) {
        delete item.href;
      }
      if (item.snapshot_id) {
        delete item.snapshot_id;
      }
      if (item.uri) {
        delete item.uri;
      }
      if (item.owner && item.owner.display_name) {
        item.owner_name = item.owner.display_name;
      }
      if (item.owner && item.owner.id) {
        item.owner_id = item.owner.id;
      }

      delete item.owner;

      count++;
    });
  }

  res.status(200).json({ items: allPlaylists });
};

You can test again if all works well for you and if yes submit a pull request :)

AlexLunaP commented 1 year ago

Thanks Hugo! I made the changes and now it works perfectly :smile: