-
Notifications
You must be signed in to change notification settings - Fork 295
/
page.go
162 lines (134 loc) · 4.58 KB
/
page.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
package spotify
import (
"context"
"errors"
"fmt"
"reflect"
)
// ErrNoMorePages is the error returned when you attempt to get the next
// (or previous) set of data but you've reached the end of the data set.
var ErrNoMorePages = errors.New("spotify: no more pages")
// This file contains the types that implement Spotify's paging object.
// See: https://developer.spotify.com/web-api/object-model/#paging-object
// basePage contains all of the fields in a Spotify paging object, except
// for the actual items. This type is meant to be embedded in other types
// that add the Items field.
type basePage struct {
// A link to the Web API Endpoint returning the full
// result of this request.
Endpoint string `json:"href"`
// The maximum number of items in the response, as set
// in the query (or default value if unset).
Limit Numeric `json:"limit"`
// The offset of the items returned, as set in the query
// (or default value if unset).
Offset Numeric `json:"offset"`
// The total number of items available to return.
Total Numeric `json:"total"`
// The URL to the next page of items (if available).
Next string `json:"next"`
// The URL to the previous page of items (if available).
Previous string `json:"previous"`
}
// FullArtistPage contains [FullArtists] returned by the Web API.
type FullArtistPage struct {
basePage
Artists []FullArtist `json:"items"`
}
// SimpleAlbumPage contains [SimpleAlbums] returned by the Web API.
type SimpleAlbumPage struct {
basePage
Albums []SimpleAlbum `json:"items"`
}
// SavedAlbumPage contains [SavedAlbums] returned by the Web API.
type SavedAlbumPage struct {
basePage
Albums []SavedAlbum `json:"items"`
}
// SavedShowPage contains [SavedShows] returned by the Web API
type SavedShowPage struct {
basePage
Shows []SavedShow `json:"items"`
}
// SimplePlaylistPage contains [SimplePlaylists] returned by the Web API.
type SimplePlaylistPage struct {
basePage
Playlists []SimplePlaylist `json:"items"`
}
// SimpleTrackPage contains [SimpleTracks] returned by the Web API.
type SimpleTrackPage struct {
basePage
Tracks []SimpleTrack `json:"items"`
}
// FullTrackPage contains [FullTracks] returned by the Web API.
type FullTrackPage struct {
basePage
Tracks []FullTrack `json:"items"`
}
// SavedTrackPage contains [SavedTracks] return by the Web API.
type SavedTrackPage struct {
basePage
Tracks []SavedTrack `json:"items"`
}
// PlaylistTrackPage contains information about tracks in a playlist.
type PlaylistTrackPage struct {
basePage
Tracks []PlaylistTrack `json:"items"`
}
// CategoryPage contains [Category] objects returned by the Web API.
type CategoryPage struct {
basePage
Categories []Category `json:"items"`
}
// SimpleEpisodePage contains [EpisodePage] returned by the Web API.
type SimpleEpisodePage struct {
basePage
Episodes []EpisodePage `json:"items"`
}
// SimpleShowPage contains [ShowPage] returned by the Web API.
type SimpleShowPage struct {
basePage
Shows []FullShow `json:"items"`
}
// pageable is an internal interface for types that support paging
// by embedding basePage.
type pageable interface{ canPage() }
func (b *basePage) canPage() {}
// NextPage fetches the next page of items and writes them into p.
// It returns [ErrNoMorePages] if p already contains the last page.
func (c *Client) NextPage(ctx context.Context, p pageable) error {
if p == nil || reflect.ValueOf(p).IsNil() {
return fmt.Errorf("spotify: p must be a non-nil pointer to a page")
}
val := reflect.ValueOf(p).Elem()
field := val.FieldByName("Next")
nextURL := field.Interface().(string)
if len(nextURL) == 0 {
return ErrNoMorePages
}
// Zero out the page so that we can overwrite it in the next
// call to get. This is necessary because encoding/json does
// not clear out existing values when unmarshaling JSON null.
zero := reflect.Zero(val.Type())
val.Set(zero)
return c.get(ctx, nextURL, p)
}
// PreviousPage fetches the previous page of items and writes them into p.
// It returns [ErrNoMorePages] if p already contains the last page.
func (c *Client) PreviousPage(ctx context.Context, p pageable) error {
if p == nil || reflect.ValueOf(p).IsNil() {
return fmt.Errorf("spotify: p must be a non-nil pointer to a page")
}
val := reflect.ValueOf(p).Elem()
field := val.FieldByName("Previous")
prevURL := field.Interface().(string)
if len(prevURL) == 0 {
return ErrNoMorePages
}
// Zero out the page so that we can overwrite it in the next
// call to get. This is necessary because encoding/json does
// not clear out existing values when unmarshaling JSON null.
zero := reflect.Zero(val.Type())
val.Set(zero)
return c.get(ctx, prevURL, p)
}