Skip to content

Commit

Permalink
Merge pull request #193 from zmb3/get-playlist-items-fix-local-tracks
Browse files Browse the repository at this point in the history
Fix local tracks in GetPlaylistItems
  • Loading branch information
strideynet authored Jun 26, 2022
2 parents c886435 + 13d000d commit 9a6dc27
Show file tree
Hide file tree
Showing 4 changed files with 49 additions and 17 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,4 @@
# vendor/

.idea/
.vscode/
11 changes: 11 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -90,3 +90,14 @@ Examples of the API can be found in the [examples](examples) directory.
You may find tools such as [Spotify's Web API Console](https://developer.spotify.com/web-api/console/)
or [Rapid API](https://rapidapi.com/package/SpotifyPublicAPI/functions?utm_source=SpotifyGitHub&utm_medium=button&utm_content=Vendor_GitHub)
valuable for experimenting with the API.

### Missing data in responses

It's extremely common that when there is no market information available in your
request, that the Spotify API will simply return null for details about a track
or episode.

This typically occurs when you are just using an application's auth token, and
aren't impersonating a user via oauth. As when you are using a token associated
with a user, the user's market seems to be extracted from their profile and
used when producing the response.
19 changes: 15 additions & 4 deletions examples/paging/page.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,12 @@ package main

import (
"context"
"log"
"os"

"github.com/zmb3/spotify/v2"
spotifyauth "github.com/zmb3/spotify/v2/auth"
"golang.org/x/oauth2/clientcredentials"
"log"
"os"
)

func main() {
Expand All @@ -24,14 +25,24 @@ func main() {
httpClient := spotifyauth.New().Client(ctx, token)
client := spotify.New(httpClient)

tracks, err := client.GetPlaylistTracks(ctx, "57qttz6pK881sjxj2TAEEo")
// Public playlist owned by noah.stride:
// "Long playlist for testing pagination"
playlistID := "1ckDytqUi4BUYzs6HIhcAN"
if id := os.Getenv("SPOTIFY_PLAYLIST"); id != "" {
playlistID = id
}

tracks, err := client.GetPlaylistItems(
ctx,
spotify.ID(playlistID),
)
if err != nil {
log.Fatal(err)
}

log.Printf("Playlist has %d total tracks", tracks.Total)
for page := 1; ; page++ {
log.Printf(" Page %d has %d tracks", page, len(tracks.Tracks))
log.Printf(" Page %d has %d tracks", page, len(tracks.Items))
err = client.NextPage(ctx, tracks)
if err == spotify.ErrNoMorePages {
break
Expand Down
35 changes: 22 additions & 13 deletions playlist.go
Original file line number Diff line number Diff line change
Expand Up @@ -209,36 +209,45 @@ type PlaylistItem struct {
Track PlaylistItemTrack `json:"track"`
}

// PlaylistItemTrack is a union type for both tracks and episodes.
// PlaylistItemTrack is a union type for both tracks and episodes. If both
// values are null, it's likely that the piece of content is not available in
// the configured market.
type PlaylistItemTrack struct {
Track *FullTrack
Episode *EpisodePage
}

// UnmarshalJSON customises the unmarshalling based on the type flags set.
func (t *PlaylistItemTrack) UnmarshalJSON(b []byte) error {
is := struct {
Episode bool `json:"episode"`
Track bool `json:"track"`
// Spotify API will return `track: null`` where the content is not available
// in the specified market. We should respect this and just pass the null
// up...
if bytes.Equal(b, []byte("null")) {
return nil
}

itemType := struct {
Type string `json:"type"`
}{}

err := json.Unmarshal(b, &is)
err := json.Unmarshal(b, &itemType)
if err != nil {
return err
}

if is.Episode {
switch itemType.Type {
case "episode":
err := json.Unmarshal(b, &t.Episode)
if err != nil {
return err
}
}

if is.Track {
case "track":
err := json.Unmarshal(b, &t.Track)
if err != nil {
return err
}
default:
return fmt.Errorf("unrecognized item type: %s", itemType.Type)
}

return nil
Expand Down Expand Up @@ -470,17 +479,17 @@ func (c *Client) RemoveTracksFromPlaylistOpt(
ctx context.Context,
playlistID ID,
tracks []TrackToRemove,
snapshotID string) (newSnapshotID string, err error) {

snapshotID string,
) (newSnapshotID string, err error) {
return c.removeTracksFromPlaylist(ctx, playlistID, tracks, snapshotID)
}

func (c *Client) removeTracksFromPlaylist(
ctx context.Context,
playlistID ID,
tracks interface{},
snapshotID string) (newSnapshotID string, err error) {

snapshotID string,
) (newSnapshotID string, err error) {
m := make(map[string]interface{})
m["tracks"] = tracks
if snapshotID != "" {
Expand Down

0 comments on commit 9a6dc27

Please sign in to comment.