Skip to content

Commit 13e0528

Browse files
committed
Rewrite player api methods and add docs
1 parent b9794d8 commit 13e0528

File tree

3 files changed

+133
-44
lines changed

3 files changed

+133
-44
lines changed

CHANGELOG.md

+4-1
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,12 @@
22

33
#### 5.0.0 (27 Sep 2020)
44

5+
* **BREAKING CHANGE**. Some methods controlling the player has changed. If a change has been made, a new primary argument has been added. This is because it's required by Spotify's API and should therefore not be placed in `options`.
56
* Bumped dependencies to resolve critical security issues.
6-
* Added support for [Implicit Grant flow](https://developer.spotify.com/documentation/general/guides/authorization-guide/#implicit-grant-flow) - Thanks [@gaganza](https://github.com/gaganza) and [@noahp78](https://github.com/noahp78)!
7+
* Added support for [Implicit Grant flow](https://developer.spotify.com/documentation/general/guides/authorization-guide/#implicit-grant-flow) - Thanks [@gaganza](https://github.com/gaganza), [@reblws](https://github.com/reblws) and [@noahp78](https://github.com/noahp78)!
78
* `position_ms` added to `play` method. Thanks [@alqubo](https://github.com/alqubo), [@koflin](https://github.com/koflin), [@DoctorFishy](https://github.com/DoctorFishy).
9+
* Documentation updates to keep up to date with ES6, thanks [@dandv](https://github.com/dandv)!
10+
* `reason` added to error object, which is returned by the [Player API](https://developer.spotify.com/documentation/web-api/reference/player/). Much appreciated [@konstantinjdobler](https://github.com/konstantinjdobler)!
811

912
More coming before NPM release.
1013

README.md

+70-6
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ The library includes helper functions to do the following:
4848
#### Your Music library
4949

5050
* Add, remove, and get tracks and albums that are in the signed in user's Your Music library
51-
* Check if a track or album is in the signed in user's Your Music library
51+
* Check if a track or album is in the signed in user's Your Music library
5252

5353
#### Personalization
5454

@@ -64,6 +64,22 @@ The library includes helper functions to do the following:
6464
* Get recommendations based on seeds
6565
* Get available genre seeds
6666

67+
#### Player
68+
69+
* Get a User's Available Devices
70+
* Get Information About The User's Current Playback State
71+
* Get Current User's Recently Played Tracks
72+
* Get the User's Currently Playing Track
73+
* Pause a User's Playback
74+
* Seek To Position In Currently Playing Track
75+
* Set Repeat Mode On User’s Playback
76+
* Set Volume For User's Playback
77+
* Skip User’s Playback To Next Track
78+
* Skip User’s Playback To Previous Track
79+
* Start/Resume a User's Playback
80+
* Toggle Shuffle For User’s Playback
81+
* Transfer a User's Playback
82+
6783
#### Follow
6884

6985
* Follow and unfollow users
@@ -693,21 +709,69 @@ spotifyApi.getPlaylistsForCategory('party', {
693709
console.log("Something went wrong!", err);
694710
});
695711

712+
// Get Recommendations Based on Seeds
713+
// TBD
696714

715+
// Get available genre seeds
716+
// TBD
697717

698718
/* Player */
699719

700-
// Get information about current playing song for signed in user
701-
spotifyApi.getMyCurrentPlaybackState({
702-
})
720+
// Get a User's Available Devices
721+
// TBD
722+
723+
// Get Information About The User's Current Playback State
724+
spotifyApi.getMyCurrentPlaybackState()
703725
.then(function(data) {
704726
// Output items
705-
console.log("Now Playing: ",data.body);
727+
if (data.body && data.body.is_playing) {
728+
console.log("User is currently playing something!");
729+
} else {
730+
console.log("User is not playing anything, or doing so in private.");
731+
}
732+
}, function(err) {
733+
console.log('Something went wrong!', err);
734+
});
735+
736+
// Get Current User's Recently Played Tracks
737+
spotifyApi.getMyRecentlyPlayedTracks({
738+
limit : 20
739+
}).then(function(data) {
740+
// Output items
741+
console.log("Your 20 most recently played tracks are:");
742+
data.body.items.forEach(item => console.log(item.track));
706743
}, function(err) {
707744
console.log('Something went wrong!', err);
708745
});
709746

710-
/* Get Recommendations Based on Seeds */
747+
// Get the User's Currently Playing Track
748+
// TBD
749+
750+
// Pause a User's Playback
751+
// TBD
752+
753+
// Seek To Position In Currently Playing Track
754+
// TBD
755+
756+
// Set Repeat Mode On User’s Playback
757+
// TBD
758+
759+
// Set Volume For User's Playback
760+
// TBD
761+
762+
// Skip User’s Playback To Next Track
763+
// TBD
764+
765+
// Skip User’s Playback To Previous Track
766+
// TBD
767+
768+
// Start/Resume a User's Playback
769+
// TBD
770+
771+
// Toggle Shuffle For User’s Playback
772+
// TBD
773+
774+
// Transfer a User's Playback
711775
// TBD
712776

713777

src/spotify-web-api.js

+59-37
Original file line numberDiff line numberDiff line change
@@ -1016,8 +1016,9 @@ SpotifyWebApi.prototype = {
10161016
* Get the Current User's Recently Played Tracks
10171017
* @param {Object} [options] Options, being type, after, limit, before.
10181018
* @param {requestCallback} [callback] Optional callback method to be called instead of the promise.
1019-
* @returns {Promise|undefined} A promise that if successful, resolves into a paging object of tracks,
1020-
* otherwise an error. Not returned if a callback is given.
1019+
* @returns {Promise|undefined} A promise that if successful, resolves into a paging object of play history objects,
1020+
* otherwise an error. Not returned if a callback is given. Note that the response will be empty
1021+
* in case the user has enabled private session.
10211022
*/
10221023
getMyRecentlyPlayedTracks: function(options, callback) {
10231024
return WebApiRequest.builder(this.getAccessToken())
@@ -1028,9 +1029,9 @@ SpotifyWebApi.prototype = {
10281029
},
10291030

10301031
/**
1031-
* Get the Current User's Connect Devices
1032+
* Get the Current User's Available Devices
10321033
* @param {requestCallback} [callback] Optional callback method to be called instead of the promise.
1033-
* @returns {Promise|undefined} A promise that if successful, resolves into a paging object of tracks,
1034+
* @returns {Promise|undefined} A promise that if successful, resolves into an array of device objects,
10341035
* otherwise an error. Not returned if a callback is given.
10351036
*/
10361037
getMyDevices: function(callback) {
@@ -1056,8 +1057,8 @@ SpotifyWebApi.prototype = {
10561057
},
10571058

10581059
/**
1059-
* Get the Current User's Current Playback State
1060-
* @param {Object} [options] Options, being market.
1060+
* Get Information About The User's Current Playback State
1061+
* @param {Object} [options] Options, being market and additional_types.
10611062
* @param {requestCallback} [callback] Optional callback method to be called instead of the promise.
10621063
* @returns {Promise|undefined} A promise that if successful, resolves into a paging object of tracks,
10631064
* otherwise an error. Not returned if a callback is given.
@@ -1072,17 +1073,19 @@ SpotifyWebApi.prototype = {
10721073

10731074
/**
10741075
* Transfer a User's Playback
1075-
* @param {Object} [options] Options, being market.
1076+
* @param {string[]} [deviceIds] An _array_ containing a device ID on which playback should be started/transferred.
1077+
* (NOTE: The API is currently only supporting a single device ID.)
1078+
* @param {Object} [options] Options, the only one being 'play'.
10761079
* @param {requestCallback} [callback] Optional callback method to be called instead of the promise.
1077-
* @returns {Promise|undefined} A promise that if successful, resolves into a paging object of tracks,
1080+
* @returns {Promise|undefined} A promise that if successful, resolves into an empty response,
10781081
* otherwise an error. Not returned if a callback is given.
10791082
*/
1080-
transferMyPlayback: function(options, callback) {
1083+
transferMyPlayback: function(deviceIds, options, callback) {
10811084
return WebApiRequest.builder(this.getAccessToken())
10821085
.withPath('/v1/me/player')
10831086
.withHeaders({ 'Content-Type': 'application/json' })
10841087
.withBodyParameters({
1085-
device_ids: options.deviceIds,
1088+
device_ids: deviceIds,
10861089
play: !!options.play
10871090
})
10881091
.build()
@@ -1093,8 +1096,8 @@ SpotifyWebApi.prototype = {
10931096
* Starts o Resumes the Current User's Playback
10941097
* @param {Object} [options] Options, being device_id, context_uri, offset, uris, position_ms.
10951098
* @param {requestCallback} [callback] Optional callback method to be called instead of the promise.
1096-
* @example playbackResume({context_uri: 'spotify:album:5ht7ItJgpBH7W6vJ5BqpPr'}).then(...)
1097-
* @returns {Promise|undefined} A promise that if successful, resolves into a paging object of tracks,
1099+
* @example play({context_uri: 'spotify:album:5ht7ItJgpBH7W6vJ5BqpPr'}).then(...)
1100+
* @returns {Promise|undefined} A promise that if successful, resolves into an empty response,
10981101
* otherwise an error. Not returned if a callback is given.
10991102
*/
11001103
play: function(options, callback) {
@@ -1120,10 +1123,10 @@ SpotifyWebApi.prototype = {
11201123

11211124
/**
11221125
* Pauses the Current User's Playback
1123-
* @param {Object} [options] Options, for now device_id,
1126+
* @param {Object} [options] Options, being device_id. If left empty will target the user's currently active device.
11241127
* @param {requestCallback} [callback] Optional callback method to be called instead of the promise.
1125-
* @example playbackPause().then(...)
1126-
* @returns {Promise|undefined} A promise that if successful, resolves into a paging object of tracks,
1128+
* @example pause().then(...)
1129+
* @returns {Promise|undefined} A promise that if successful, resolves into an empty response,
11271130
* otherwise an error. Not returned if a callback is given.
11281131
*/
11291132
pause: function(options, callback) {
@@ -1142,29 +1145,37 @@ SpotifyWebApi.prototype = {
11421145

11431146
/**
11441147
* Skip the Current User's Playback To Previous Track
1148+
* @param {Object} [options] Options, being device_id. If left empty will target the user's currently active device.
11451149
* @param {requestCallback} [callback] Optional callback method to be called instead of the promise.
1146-
* @example playbackPrevious().then(...)
1147-
* @returns {Promise|undefined} A promise that if successful, resolves into a paging object of tracks,
1150+
* @example skipToPrevious().then(...)
1151+
* @returns {Promise|undefined} A promise that if successful, resolves into an empty response,
11481152
* otherwise an error. Not returned if a callback is given.
11491153
*/
11501154
skipToPrevious: function(callback) {
11511155
return WebApiRequest.builder(this.getAccessToken())
11521156
.withPath('/v1/me/player/previous')
1157+
.withQueryParameters(
1158+
options && options.device_id ? { device_id: options.device_id } : null
1159+
)
11531160
.withHeaders({ 'Content-Type': 'application/json' })
11541161
.build()
11551162
.execute(HttpManager.post, callback);
11561163
},
11571164

11581165
/**
11591166
* Skip the Current User's Playback To Next Track
1167+
* @param {Object} [options] Options, being device_id. If left empty will target the user's currently active device.
11601168
* @param {requestCallback} [callback] Optional callback method to be called instead of the promise.
1161-
* @example playbackNext().then(...)
1162-
* @returns {Promise|undefined} A promise that if successful, resolves into a paging object of tracks,
1169+
* @example skipToNext().then(...)
1170+
* @returns {Promise|undefined} A promise that if successful, resolves into an empty response,
11631171
* otherwise an error. Not returned if a callback is given.
11641172
*/
11651173
skipToNext: function(callback) {
11661174
return WebApiRequest.builder(this.getAccessToken())
11671175
.withPath('/v1/me/player/next')
1176+
.withQueryParameters(
1177+
options && options.device_id ? { device_id: options.device_id } : null
1178+
)
11681179
.withHeaders({ 'Content-Type': 'application/json' })
11691180
.build()
11701181
.execute(HttpManager.post, callback);
@@ -1174,7 +1185,7 @@ SpotifyWebApi.prototype = {
11741185
* Seeks to the given position in the user’s currently playing track.
11751186
*
11761187
* @param {number} positionMs The position in milliseconds to seek to. Must be a positive number.
1177-
* @param {Object} options A JSON object with options that can be passed.
1188+
* @param {Object} options Options, being device_id. If left empty will target the user's currently active device.
11781189
* @param {function(Object,Object)} callback An optional callback that receives 2 parameters. The first
11791190
* one is the error object (null if no error), and the second is the value if the request succeeded.
11801191
* @return {Object} Null if a callback is provided, a `Promise` object otherwise
@@ -1197,45 +1208,56 @@ SpotifyWebApi.prototype = {
11971208

11981209
/**
11991210
* Set Repeat Mode On The Current User's Playback
1200-
* @param {Object} [options] Options, being state (track, context, off).
1211+
* @param {string} [state] State (track, context, or off)
1212+
* @param {Object} [options] Options, being device_id. If left empty will target the user's currently active device.
12011213
* @param {requestCallback} [callback] Optional callback method to be called instead of the promise.
1202-
* @example playbackRepeat({state: 'context'}).then(...)
1203-
* @returns {Promise|undefined} A promise that if successful, resolves into a paging object of tracks,
1214+
* @example setRepeat({state: 'context'}).then(...)
1215+
* @returns {Promise|undefined} A promise that if successful, resolves into an empty response,
12041216
* otherwise an error. Not returned if a callback is given.
12051217
*/
1206-
setRepeat: function(options, callback) {
1218+
setRepeat: function(state, options, callback) {
1219+
var params = {
1220+
state: state
1221+
};
1222+
if (options && 'device_id' in options) {
1223+
/* jshint camelcase: false */
1224+
params.device_id = options.device_id;
1225+
}
12071226
return WebApiRequest.builder(this.getAccessToken())
12081227
.withPath('/v1/me/player/repeat')
1209-
.withQueryParameters({
1210-
state: options.state || 'off'
1211-
})
1228+
.withQueryParameters(params)
12121229
.build()
12131230
.execute(HttpManager.put, callback);
12141231
},
12151232

12161233
/**
12171234
* Set Shuffle Mode On The Current User's Playback
1218-
* @param {Object} [options] Options, being state (true, false).
1235+
* @param {string} [state] State (true, false)
1236+
* @param {Object} [options] Options, being device_id. If left empty will target the user's currently active device.
12191237
* @param {requestCallback} [callback] Optional callback method to be called instead of the promise.
1220-
* @example playbackShuffle({state: 'false'}).then(...)
1221-
* @returns {Promise|undefined} A promise that if successful, resolves into a paging object of tracks,
1238+
* @example setShuffle({state: 'false'}).then(...)
1239+
* @returns {Promise|undefined} A promise that if successful, resolves into an empty response,
12221240
* otherwise an error. Not returned if a callback is given.
12231241
*/
1224-
setShuffle: function(options, callback) {
1242+
setShuffle: function(state, options, callback) {
1243+
var params = {
1244+
state: state
1245+
};
1246+
if (options && 'device_id' in options) {
1247+
/* jshint camelcase: false */
1248+
params.device_id = options.device_id;
1249+
}
12251250
return WebApiRequest.builder(this.getAccessToken())
12261251
.withPath('/v1/me/player/shuffle')
1227-
.withQueryParameters({
1228-
state: options.state || 'false'
1229-
})
1252+
.withQueryParameters(params)
12301253
.build()
12311254
.execute(HttpManager.put, callback);
12321255
},
12331256

12341257
/**
12351258
* Set the volume for the user’s current playback device.
1236-
*
1237-
* @param {number} volumePercent The volume to set. Must be a value from 0 to 100 inclusive.
1238-
* @param {Object} options A JSON object with options that can be passed.
1259+
* @param {number} volumePercent The volume to set. Must be a value from 0 to 100.
1260+
* @param {Object} options Options, being device_id. If left empty will target the user's currently active device.
12391261
* @param {function(Object,Object)} callback An optional callback that receives 2 parameters. The first
12401262
* one is the error object (null if no error), and the second is the value if the request succeeded.
12411263
* @return {Object} Null if a callback is provided, a `Promise` object otherwise

0 commit comments

Comments
 (0)