diff --git a/README.md b/README.md index 1e7a9cd6..faf3868d 100644 --- a/README.md +++ b/README.md @@ -499,6 +499,14 @@ spotifyApi.uploadCustomPlaylistCoverImage('5ieJqeLJjjI8iJWaxeBLuK','longbase64ur console.log('Something went wrong!', err); }); +// Retrieve a playlist cover image +spotifyApi.getPlaylistCoverImage("3cEYpjA9oz9GiPac4AsH4n") + .then(function(data) { + console.log("Retrieved playlist cover of URL: ", data.body[0].url); + }, function(err) { + console.log("Error in retrieving playlist cover image", err); + }); + // Follow a playlist (privately) spotifyApi.followPlaylist('5ieJqeLJjjI8iJWaxeBLuK', { @@ -782,10 +790,25 @@ spotifyApi.getAvailableGenreSeeds() console.log('Something went wrong!', err); }); + +/* Markets */ + +//Get the available markets +spotifyApi.getAvailableMarkets().then((function(data)) { + console.log("Got markets of size ", data.body.markets.length) +}, function(err) { + console.log("Erorr when fetching available markets", err) +}) + /* Player */ // Add an Item to the User's Playback Queue -// TBD +spotfiyApi.addToPlaybackQueue(uri) + .then(function(data) { + console.log("Added ", data.body, " to playback queue.") + }, function(err) { + console.log("Error adding to playback queue", err); + }) // Get a User's Available Devices spotifyApi.getMyDevices() @@ -969,6 +992,7 @@ spotifyApi .then(function(data) { console.log(data.body); }); + ``` ### Authorization diff --git a/__tests__/spotify-web-api.js b/__tests__/spotify-web-api.js index 8222a0d4..27334e82 100644 --- a/__tests__/spotify-web-api.js +++ b/__tests__/spotify-web-api.js @@ -4690,4 +4690,90 @@ describe('Spotify Web API', () => { done(); }); + test("testing adding to a user's playback queue", done => { + sinon.stub(HttpManager, '_makeRequest').callsFake(function( + method, + options, + uri, + callback + ) { + expect(method).toBe(superagent.post); + expect(uri).toBe("https://api.spotify.com/v1/me/player/queue"); + expect(options.query).toEqual({ + uri: "spotify:track:2ouFrmMwYik8nQX2n9SeZu" + }); + expect(options.headers).toEqual({ + Authorization: 'Bearer someAccessToken' + }); + callback(null, null); + }); + + var api = new SpotifyWebApi({ + accessToken: 'someAccessToken' + }); + + api.addToPlaybackQueue("spotify:track:2ouFrmMwYik8nQX2n9SeZu").then(done); + }); + + + test("testing getting available markets", done => { + sinon.stub(HttpManager, '_makeRequest').callsFake(function( + method, + options, + uri, + callback + ) { + expect(method).toBe(superagent.post); + expect(uri).toBe("https://api.spotify.com/v1/markets"); + expect(options.query).toBeFalsy(); + expect(options.data).toBeFalsy(); + callback(null, null); + }); + + var api = new SpotifyWebApi(); + + api.getAvailableMarkets().then( + function(data) { + expect(data.body).toBeTruthy() + done() + }, + function(err) { + done(err); + } + ); + }); + + test("testing getting a playlist cover image", done => { + sinon.stub(HttpManager, '_makeRequest').callsFake(function( + method, + options, + uri, + callback + ) { + expect(method).toBe(superagent.get); + expect(uri).toBe( + 'https://api.spotify.com/v1/playlists/3cEYpjA9oz9GiPac4AsH4n/images' + ); + expect(options.query).toBeFalsy(); + callback(null, { + body: { + uri: 'spotify:playlist:3cEYpjA9oz9GiPac4AsH4n' + }, + statusCode: 200 + }); + }); + + var api = new SpotifyWebApi(); + api.setAccessToken('myVeryVeryLongAccessToken'); + + api.getPlaylistCoverImage("3cEYpjA9oz9GiPac4AsH4n", {}, function(err, data) { + expect(data.body.uri).toBe('spotify:playlist:3cEYpjA9oz9GiPac4AsH4n'); + expect(data.statusCode).toBe(200); + expect(data.body).toBe(!null); + expect(data.body[0].url).toBe("https://i.scdn.co/image/ab67616d00001e02ff9ca10b55ce82ae553c8228") + done(); + }); + }); + + }); diff --git a/src/spotify-web-api.js b/src/spotify-web-api.js index 2a756da8..9b75a58e 100644 --- a/src/spotify-web-api.js +++ b/src/spotify-web-api.js @@ -106,6 +106,54 @@ SpotifyWebApi.prototype = { } }, + /** + * Returns an object containing the playlist cover image. + * @param {string} playlistId The ID of the associated playlist. + * @param {requestCallback} callback Optional callback method to be called instead of the promise. + * @returns {Promise|undefined} A promise that, if successful, returns an object containing the + * Playlist Cover image alongside its dimensions + */ + getPlaylistCoverImage: function(playlistId, callback) { + return WebApiRequest.builder(this.getAccessToken()) + .withPath("/v1/playlists/" + playlistId + "/images") + .withHeaders({"Content-Type": 'application/json'}) + .build() + .execute(HttpManager.get, callback); + }, + + + /** + * Adds an item to the users playback queue. + * @param {string} uri The URI of the song you wish to add. + * @param {requestCallback} callback Optional callback method to be called instead of the promise. + * @returns {Promise|undefined} A promise that, if successful, returns a 204 response and adds + * the associated song to the user's playback queue + */ + addToPlaybackQueue: function(uri, callback) { + var baseUrl = "/v1/me" + var path = "/player/queue" + return WebApiRequest.builder(this.getAccessToken()) + .withPath(baseUrl + path) + .withQueryParameters({ uri: JSON.stringify(uri) }) + .build() + .execute(HttpManager.post, callback); + }, + + /** + * Gets the available markets + * @param {requestCallback} callback Optional callback method to be called instead of the promise. + * @returns {Promise|undefined} A promise that, if successful, returns an array of objects containing + * Country abbreviations + */ + getAvailableMarkets: function(callback) { + var path = "/v1/markets" + return WebApiRequest.builder(this.getAccessToken()) + .withPath(path) + .withHeaders({ 'Content-Type': 'application/json' }) + .build() + .execute(HttpManager.get, callback); + }, + /** * Look up a track. * @param {string} trackId The track's ID. @@ -971,6 +1019,8 @@ SpotifyWebApi.prototype = { }, + + /** * Get the Current User's Available Devices * @param {requestCallback} [callback] Optional callback method to be called instead of the promise. @@ -984,6 +1034,7 @@ SpotifyWebApi.prototype = { .execute(HttpManager.get, callback); }, + /** * Get the Current User's Currently Playing Track. * @param {Object} [options] Options, being market.