Skip to content

Load all tracks #1

@Mees-Molenaar

Description

@Mees-Molenaar

Hi,

First off, thanks for creating this!
Unfortunately, the current implementation doesn't work for playlists with more than 100 tracks, because the endpoint that is currently used, has a limit of responding with 100 tracks.
I have adjusted the implementation, but was not able to push my branch to this repository.
So if you want to take over the implementation, here is the code:

import { SPOTIFY_API_BASE, SPOTIFY_TOKEN_SOURCE } from "../data/config.ts" ;

export async function getSpotifyToken(): Promise<string> {
  const response = await fetch(`${SPOTIFY_TOKEN_SOURCE}`, {
    mode: 'cors',
    headers: {
      'Accept': 'application/json'
    }
  });
  const data = await response.json();
  console.log(data)
  return data['token'];
}

export function extractPlaylistId(url: string): string {
  const patterns = [
    /spotify:playlist:([a-zA-Z0-9]+)/, // Spotify URI
    /playlist\/([a-zA-Z0-9]+)/, // Web URL
    /^([a-zA-Z0-9]+)$/, // Direct ID
  ];

  for (const pattern of patterns) {
    const match = url.match(pattern);
    if (match) {
      return match[1];
    }
  }

  throw new Error('Invalid Spotify playlist URL or ID');
}

export async function getTotalTrackNumber(playlistId: string, token: string): promise<number> {
  const response = await fetch(
    `${SPOTIFY_API_BASE}/playlists/${playlistId}`,
    {
      headers: {
        Authorization: `Bearer ${token}`,
      },
    }
  );

  if (!response.ok) {
    throw new Error('Failed to fetch playlist data');
  }

  const data = await response.json();

  const total_songs = data.tracks.total;

  return total_songs;
}

export async function fetchPlaylistTracks(playlistId: string): Promise<Song[]> {
  const token = await getSpotifyToken();

  const total_songs = await getTotalTrackNumber(playlistId, token);
  const step = 100; // NOTE: You can fetch 100 tracks in one request

  var all_tracks = [];

  for (let i = 0; i <= total_songs; i += step) {
    const tracks_response = await fetch(
      `${SPOTIFY_API_BASE}/playlists/${playlistId}/tracks?fields=items(track(uri,name,artists(name),album(release_date)))&offset=${i}`,
      {
        headers: {
          Authorization: `Bearer ${token}`,
        },
      }
    );

    if (!tracks_response.ok) {
      throw new Error('Failed to fetch playlist data');
    }

    const track_data = await tracks_response.json();

    const tracks = track_data.items
    .filter((item: { track: SpotifyTrack | null }) => item.track)
    .map((item: { track: SpotifyTrack }) => ({
      title: item.track.name,
      artist: item.track.artists[0].name,
      year: parseInt(item.track.album.release_date.substring(0, 4), 10),
      spotifyUri: item.track.uri,
    }));

    all_tracks = [...all_tracks, ...tracks];

  }

  return all_tracks;
}

Basically, in the above code, first you fetch the total of numbers of tracks and then you request the tracks (100 at a time) until you got everything.

Kind regards,
Mees

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions