Spotify: Implemented API request and tests for user tracks

This commit is contained in:
Philipp Wolfer 2023-11-22 10:24:33 +01:00
parent d0739aad0f
commit ed9debc127
No known key found for this signature in database
GPG key ID: 8FDF744D4919943B
4 changed files with 623 additions and 9 deletions

View file

@ -68,13 +68,27 @@ func (c Client) recentlyPlayed(after *time.Time, before *time.Time, limit int) (
request.SetQueryParam("after", strconv.FormatInt(after.Unix(), 10))
} else if before != nil {
request.SetQueryParam("before", strconv.FormatInt(before.Unix(), 10))
}
response, err := request.Get(path)
if response.StatusCode() != 200 {
err = errors.New(response.String())
return
}
return
}
func (c Client) UserTracks(offset int, limit int) (result TracksResult, err error) {
const path = "/me/tracks"
response, err := c.HttpClient.R().
SetQueryParams(map[string]string{
"offset": strconv.Itoa(offset),
"limit": strconv.Itoa(limit),
}).
SetResult(&result).
Get(path)
if response.StatusCode() != 200 {
err = errors.New(response.String())
}
return
}

View file

@ -22,9 +22,13 @@ THE SOFTWARE.
package spotify_test
import (
"net/http"
"testing"
"time"
"github.com/jarcoal/httpmock"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"go.uploadedlobster.com/scotty/backends/spotify"
"golang.org/x/oauth2"
)
@ -35,3 +39,53 @@ func TestNewClient(t *testing.T) {
client := spotify.NewClient(conf, token)
assert.IsType(t, spotify.Client{}, client)
}
func TestRecentlyPlayedAfter(t *testing.T) {
defer httpmock.DeactivateAndReset()
client := spotify.NewClient(oauth2.Config{}, nil)
setupHttpMock(t, client.HttpClient.GetClient(),
"https://api.spotify.com/v1/me/player/recently-played",
"testdata/recently-played.json")
result, err := client.RecentlyPlayedAfter(time.Now(), 3)
require.NoError(t, err)
assert := assert.New(t)
assert.Equal(3, result.Limit)
require.Len(t, result.Items, 3)
listen1 := result.Items[0]
assert.Equal("2023-11-21T15:00:07.229Z", listen1.PlayedAt)
assert.Equal("Evidence", listen1.Track.Name)
assert.Equal("Viva Emptiness", listen1.Track.Album.Name)
}
func TestGetUserTracks(t *testing.T) {
defer httpmock.DeactivateAndReset()
client := spotify.NewClient(oauth2.Config{}, nil)
setupHttpMock(t, client.HttpClient.GetClient(),
"https://api.spotify.com/v1/me/tracks",
"testdata/user-tracks.json")
result, err := client.UserTracks(0, 2)
require.NoError(t, err)
assert := assert.New(t)
assert.Equal(1243, result.Total)
require.Len(t, result.Items, 2)
track1 := result.Items[0]
assert.Equal("2022-02-13T21:46:08Z", track1.AddedAt)
assert.Equal("Death to the Holy", track1.Track.Name)
assert.Equal("Zeal & Ardor", track1.Track.Album.Name)
}
func setupHttpMock(t *testing.T, client *http.Client, url string, testDataPath string) {
httpmock.ActivateNonDefault(client)
responder, err := httpmock.NewJsonResponder(200, httpmock.File(testDataPath))
if err != nil {
t.Fatal(err)
}
httpmock.RegisterResponder("GET", url, responder)
}

View file

@ -23,12 +23,18 @@ THE SOFTWARE.
package spotify
type TracksResult struct {
Href string `json:"href"`
Limit int `json:"limit"`
Next string `json:"next"`
Previous string `json:"previous"`
Offset int `json:"offset"`
Total int `json:"total"`
Href string `json:"href"`
Limit int `json:"limit"`
Next string `json:"next"`
Previous string `json:"previous"`
Offset int `json:"offset"`
Total int `json:"total"`
Items []SavedTrack `json:"items"`
}
type SavedTrack struct {
AddedAt string `json:"added_at"`
Track Track `json:"track"`
}
type RecentlyPlayedResult struct {
@ -45,8 +51,8 @@ type Cursors struct {
}
type Listen struct {
Track Track `json:"track"`
PlayedAt string `json:"played_at"`
Track Track `json:"track"`
}
type Track struct {

View file

@ -0,0 +1,540 @@
{
"href": "https://api.spotify.com/v1/me/tracks?offset=143&limit=2&locale=de,en-US;q=0.7,en;q=0.3",
"items": [
{
"added_at": "2022-02-13T21:46:08Z",
"track": {
"album": {
"album_type": "album",
"artists": [
{
"external_urls": {
"spotify": "https://open.spotify.com/artist/6yCjbLFZ9qAnWfsy9ujm5Y"
},
"href": "https://api.spotify.com/v1/artists/6yCjbLFZ9qAnWfsy9ujm5Y",
"id": "6yCjbLFZ9qAnWfsy9ujm5Y",
"name": "Zeal & Ardor",
"type": "artist",
"uri": "spotify:artist:6yCjbLFZ9qAnWfsy9ujm5Y"
}
],
"available_markets": [],
"external_urls": {
"spotify": "https://open.spotify.com/album/34u4cq27YP6837IcmzTTgX"
},
"href": "https://api.spotify.com/v1/albums/34u4cq27YP6837IcmzTTgX",
"id": "34u4cq27YP6837IcmzTTgX",
"images": [
{
"height": 640,
"url": "https://i.scdn.co/image/ab67616d0000b2731fedf861c139b6d8bebdc840",
"width": 640
},
{
"height": 300,
"url": "https://i.scdn.co/image/ab67616d00001e021fedf861c139b6d8bebdc840",
"width": 300
},
{
"height": 64,
"url": "https://i.scdn.co/image/ab67616d000048511fedf861c139b6d8bebdc840",
"width": 64
}
],
"name": "Zeal & Ardor",
"release_date": "2022-02-11",
"release_date_precision": "day",
"total_tracks": 14,
"type": "album",
"uri": "spotify:album:34u4cq27YP6837IcmzTTgX"
},
"artists": [
{
"external_urls": {
"spotify": "https://open.spotify.com/artist/6yCjbLFZ9qAnWfsy9ujm5Y"
},
"href": "https://api.spotify.com/v1/artists/6yCjbLFZ9qAnWfsy9ujm5Y",
"id": "6yCjbLFZ9qAnWfsy9ujm5Y",
"name": "Zeal & Ardor",
"type": "artist",
"uri": "spotify:artist:6yCjbLFZ9qAnWfsy9ujm5Y"
}
],
"available_markets": [],
"disc_number": 1,
"duration_ms": 187680,
"explicit": false,
"external_ids": {
"isrc": "CH8092101707"
},
"external_urls": {
"spotify": "https://open.spotify.com/track/07K2e1PXNra3Zd5SGCsLuZ"
},
"href": "https://api.spotify.com/v1/tracks/07K2e1PXNra3Zd5SGCsLuZ",
"id": "07K2e1PXNra3Zd5SGCsLuZ",
"is_local": false,
"name": "Death to the Holy",
"popularity": 0,
"preview_url": null,
"track_number": 3,
"type": "track",
"uri": "spotify:track:07K2e1PXNra3Zd5SGCsLuZ"
}
},
{
"added_at": "2022-02-13T21:34:31Z",
"track": {
"album": {
"album_type": "single",
"artists": [
{
"external_urls": {
"spotify": "https://open.spotify.com/artist/7FsZ5HKdtDFJ1xmK6NICBO"
},
"href": "https://api.spotify.com/v1/artists/7FsZ5HKdtDFJ1xmK6NICBO",
"id": "7FsZ5HKdtDFJ1xmK6NICBO",
"name": "Wucan",
"type": "artist",
"uri": "spotify:artist:7FsZ5HKdtDFJ1xmK6NICBO"
}
],
"available_markets": [
"AR",
"AU",
"AT",
"BE",
"BO",
"BR",
"BG",
"CA",
"CL",
"CO",
"CR",
"CY",
"CZ",
"DK",
"DO",
"DE",
"EC",
"EE",
"SV",
"FI",
"FR",
"GR",
"GT",
"HN",
"HK",
"HU",
"IS",
"IE",
"IT",
"LV",
"LT",
"LU",
"MY",
"MT",
"MX",
"NL",
"NZ",
"NI",
"NO",
"PA",
"PY",
"PE",
"PH",
"PL",
"PT",
"SG",
"SK",
"ES",
"SE",
"CH",
"TW",
"TR",
"UY",
"US",
"GB",
"AD",
"LI",
"MC",
"ID",
"JP",
"TH",
"VN",
"RO",
"IL",
"ZA",
"SA",
"AE",
"BH",
"QA",
"OM",
"KW",
"EG",
"MA",
"DZ",
"TN",
"LB",
"JO",
"PS",
"IN",
"BY",
"KZ",
"MD",
"UA",
"AL",
"BA",
"HR",
"ME",
"MK",
"RS",
"SI",
"KR",
"BD",
"PK",
"LK",
"GH",
"KE",
"NG",
"TZ",
"UG",
"AG",
"AM",
"BS",
"BB",
"BZ",
"BT",
"BW",
"BF",
"CV",
"CW",
"DM",
"FJ",
"GM",
"GE",
"GD",
"GW",
"GY",
"HT",
"JM",
"KI",
"LS",
"LR",
"MW",
"MV",
"ML",
"MH",
"FM",
"NA",
"NR",
"NE",
"PW",
"PG",
"WS",
"SM",
"ST",
"SN",
"SC",
"SL",
"SB",
"KN",
"LC",
"VC",
"SR",
"TL",
"TO",
"TT",
"TV",
"VU",
"AZ",
"BN",
"BI",
"KH",
"CM",
"TD",
"KM",
"GQ",
"SZ",
"GA",
"GN",
"KG",
"LA",
"MO",
"MR",
"MN",
"NP",
"RW",
"TG",
"UZ",
"ZW",
"BJ",
"MG",
"MU",
"MZ",
"AO",
"CI",
"DJ",
"ZM",
"CD",
"CG",
"IQ",
"LY",
"TJ",
"VE",
"ET",
"XK"
],
"external_urls": {
"spotify": "https://open.spotify.com/album/11XibdriTL2mncbfoWLwv7"
},
"href": "https://api.spotify.com/v1/albums/11XibdriTL2mncbfoWLwv7",
"id": "11XibdriTL2mncbfoWLwv7",
"images": [
{
"height": 640,
"url": "https://i.scdn.co/image/ab67616d0000b2734f84c9e19c3a309cd123c6e5",
"width": 640
},
{
"height": 300,
"url": "https://i.scdn.co/image/ab67616d00001e024f84c9e19c3a309cd123c6e5",
"width": 300
},
{
"height": 64,
"url": "https://i.scdn.co/image/ab67616d000048514f84c9e19c3a309cd123c6e5",
"width": 64
}
],
"name": "Night to Fall",
"release_date": "2018-10-22",
"release_date_precision": "day",
"total_tracks": 1,
"type": "album",
"uri": "spotify:album:11XibdriTL2mncbfoWLwv7"
},
"artists": [
{
"external_urls": {
"spotify": "https://open.spotify.com/artist/7FsZ5HKdtDFJ1xmK6NICBO"
},
"href": "https://api.spotify.com/v1/artists/7FsZ5HKdtDFJ1xmK6NICBO",
"id": "7FsZ5HKdtDFJ1xmK6NICBO",
"name": "Wucan",
"type": "artist",
"uri": "spotify:artist:7FsZ5HKdtDFJ1xmK6NICBO"
}
],
"available_markets": [
"AR",
"AU",
"AT",
"BE",
"BO",
"BR",
"BG",
"CA",
"CL",
"CO",
"CR",
"CY",
"CZ",
"DK",
"DO",
"DE",
"EC",
"EE",
"SV",
"FI",
"FR",
"GR",
"GT",
"HN",
"HK",
"HU",
"IS",
"IE",
"IT",
"LV",
"LT",
"LU",
"MY",
"MT",
"MX",
"NL",
"NZ",
"NI",
"NO",
"PA",
"PY",
"PE",
"PH",
"PL",
"PT",
"SG",
"SK",
"ES",
"SE",
"CH",
"TW",
"TR",
"UY",
"US",
"GB",
"AD",
"LI",
"MC",
"ID",
"JP",
"TH",
"VN",
"RO",
"IL",
"ZA",
"SA",
"AE",
"BH",
"QA",
"OM",
"KW",
"EG",
"MA",
"DZ",
"TN",
"LB",
"JO",
"PS",
"IN",
"BY",
"KZ",
"MD",
"UA",
"AL",
"BA",
"HR",
"ME",
"MK",
"RS",
"SI",
"KR",
"BD",
"PK",
"LK",
"GH",
"KE",
"NG",
"TZ",
"UG",
"AG",
"AM",
"BS",
"BB",
"BZ",
"BT",
"BW",
"BF",
"CV",
"CW",
"DM",
"FJ",
"GM",
"GE",
"GD",
"GW",
"GY",
"HT",
"JM",
"KI",
"LS",
"LR",
"MW",
"MV",
"ML",
"MH",
"FM",
"NA",
"NR",
"NE",
"PW",
"PG",
"WS",
"SM",
"ST",
"SN",
"SC",
"SL",
"SB",
"KN",
"LC",
"VC",
"SR",
"TL",
"TO",
"TT",
"TV",
"VU",
"AZ",
"BN",
"BI",
"KH",
"CM",
"TD",
"KM",
"GQ",
"SZ",
"GA",
"GN",
"KG",
"LA",
"MO",
"MR",
"MN",
"NP",
"RW",
"TG",
"UZ",
"ZW",
"BJ",
"MG",
"MU",
"MZ",
"AO",
"CI",
"DJ",
"ZM",
"CD",
"CG",
"IQ",
"LY",
"TJ",
"VE",
"ET",
"XK"
],
"disc_number": 1,
"duration_ms": 248372,
"explicit": false,
"external_ids": {
"isrc": "DEMV91805509"
},
"external_urls": {
"spotify": "https://open.spotify.com/track/30YxzMczS77DCXIWiXSzSK"
},
"href": "https://api.spotify.com/v1/tracks/30YxzMczS77DCXIWiXSzSK",
"id": "30YxzMczS77DCXIWiXSzSK",
"is_local": false,
"name": "Night to Fall",
"popularity": 29,
"preview_url": "https://p.scdn.co/mp3-preview/9d3edae25510e9f78194a04625a0773ee1f0db65?cid=5433a04d90a946f2a0e5175b1383604a",
"track_number": 1,
"type": "track",
"uri": "spotify:track:30YxzMczS77DCXIWiXSzSK"
}
}
],
"limit": 2,
"next": "https://api.spotify.com/v1/me/tracks?offset=145&limit=2&locale=de,en-US;q=0.7,en;q=0.3",
"offset": 143,
"previous": "https://api.spotify.com/v1/me/tracks?offset=141&limit=2&locale=de,en-US;q=0.7,en;q=0.3",
"total": 1243
}