Skip to content

Commit d9ef8cf

Browse files
committed
Add Get Show endpoint
1 parent 185aeff commit d9ef8cf

File tree

3 files changed

+274
-2
lines changed

3 files changed

+274
-2
lines changed

README.md

+7-1
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,12 @@ The library includes helper functions to do the following:
105105
* Set volume
106106
* Seek playback to a given position
107107

108+
#### Shows
109+
110+
* [Get a Show](https://developer.spotify.com/documentation/web-api/reference/shows/get-a-show/)
111+
112+
### Authentication
113+
108114
All methods require authentication, which can be done using these flows:
109115

110116
* [Client credentials flow](http://tools.ietf.org/html/rfc6749#section-4.4) (Application-only authentication)
@@ -828,7 +834,7 @@ spotifyApi
828834
```
829835

830836
### Authorization
831-
Supplying an access token is required for all requests to the Spotify API. This wrapper supports all three authorization flows - The Authorization Code flow (signed by a user), the Client Credentials flow (application authentication - the user isn't involved), and the Implicit Grant Flow (For completely clientside applications). See Spotify's [Authorization guide](https://developer.spotify.com/spotify-web-api/authorization-guide/) for detailed information on these flows.
837+
Supplying an access token is required for all requests to the Spotify API. This wrapper supports three authorization flows - The Authorization Code flow (signed by a user), the Client Credentials flow (application authentication - the user isn't involved), and the Implicit Grant Flow (For completely clientside applications). See Spotify's [Authorization guide](https://developer.spotify.com/spotify-web-api/authorization-guide/) for detailed information on these flows.
832838

833839
**Important: If you are writing a universal/isomorphic web app using this library, you will not be able to use those methods that send a client secret to the Spotify authorization service. Client secrets should be kept server-side and not exposed. Never include your client secret in the public JS served to the browser.**
834840

__tests__/spotify-web-api.js

+50
Original file line numberDiff line numberDiff line change
@@ -4184,4 +4184,54 @@ describe('Spotify Web API', () => {
41844184
}
41854185
);
41864186
});
4187+
4188+
/**
4189+
* Shows
4190+
*/
4191+
4192+
/* Get a Show */
4193+
test('should get a show', done => {
4194+
sinon.stub(HttpManager, '_makeRequest').callsFake(function(
4195+
method,
4196+
options,
4197+
uri,
4198+
callback
4199+
) {
4200+
expect(method).toBe(superagent.get);
4201+
expect(uri).toBe(
4202+
'https://api.spotify.com/v1/shows/123'
4203+
);
4204+
expect(options.query.market).toBe('SE');
4205+
4206+
callback(null, {
4207+
body: {
4208+
total_episodes : 3,
4209+
type : "show",
4210+
name : "The API show",
4211+
episodes : [{
4212+
items : [
4213+
{
4214+
"audio_preview_url" : "https://p.scdn.co/mp3-preview/7a785904a33e34b0b2bd382c82fca16be7060c36",
4215+
"duration_ms" : 2677448
4216+
}
4217+
]
4218+
}]
4219+
},
4220+
statusCode: 200
4221+
})
4222+
});
4223+
4224+
var api = new SpotifyWebApi();
4225+
4226+
api.getShow('123', { market: 'SE' }).then(
4227+
function(data) {
4228+
expect(data.body.total_episodes).toBe(3);
4229+
expect(data.body.episodes[0].items[0].duration_ms).toBe(2677448);
4230+
done();
4231+
},
4232+
function(err) {
4233+
done(err);
4234+
}
4235+
);
4236+
});
41874237
});

src/spotify-web-api.js

+217-1
Original file line numberDiff line numberDiff line change
@@ -1538,9 +1538,225 @@ SpotifyWebApi.prototype = {
15381538
.withQueryParameters(options)
15391539
.build()
15401540
.execute(HttpManager.get, callback);
1541-
}
1541+
},
1542+
1543+
/**
1544+
* Get a show.
1545+
* @param {string} showId The show's ID.
1546+
* @param {Object} [options] The possible options, currently only market.
1547+
* @param {requestCallback} [callback] Optional callback method to be called instead of the promise.
1548+
* @example getShow('3Qm86XLflmIXVm1wcwkgDK').then(...)
1549+
* @returns {Promise|undefined} A promise that if successful, returns an object containing information
1550+
* about the show. Not returned if a callback is given.
1551+
*/
1552+
getShow: function(showId, options, callback) {
1553+
return WebApiRequest.builder(this.getAccessToken())
1554+
.withPath('/v1/shows/' + showId)
1555+
.withQueryParameters(options)
1556+
.build()
1557+
.execute(HttpManager.get, callback);
1558+
},
1559+
1560+
/**
1561+
* Look up several shows.
1562+
* @param {string[]} showIds The IDs of the shows.
1563+
* @param {Object} [options] The possible options, currently only market.
1564+
* @param {requestCallback} [callback] Optional callback method to be called instead of the promise.
1565+
* @example getShows(['0oSGxfWSnnOXhD2fKuz2Gy', '3dBVyJ7JuOMt4GE9607Qin']).then(...)
1566+
* @returns {Promise|undefined} A promise that if successful, returns an object containing information
1567+
* about the shows. Not returned if a callback is given.
1568+
*/
1569+
getShows: function(showIds, options, callback) {
1570+
// In case someone is using a version where options parameter did not exist.
1571+
var actualCallback, actualOptions;
1572+
if (typeof options === 'function' && !callback) {
1573+
actualCallback = options;
1574+
actualOptions = {};
1575+
} else {
1576+
actualCallback = callback;
1577+
actualOptions = options;
1578+
}
1579+
return WebApiRequest.builder(this.getAccessToken())
1580+
.withPath('/v1/shows')
1581+
.withQueryParameters(
1582+
{
1583+
ids: showIds.join(',')
1584+
},
1585+
actualOptions
1586+
)
1587+
.build()
1588+
.execute(HttpManager.get, actualCallback);
1589+
},
1590+
1591+
/**
1592+
* Check if one or more shows is already saved in the current Spotify user’s “Your Music” library.
1593+
* @param {string[]} showIds The show IDs
1594+
* @param {requestCallback} [callback] Optional callback method to be called instead of the promise.
1595+
* @returns {Promise|undefined} A promise that if successful, resolves into an array of booleans. The order
1596+
* of the returned array's elements correspond to the show ID in the request.
1597+
* The boolean value of true indicates that the show is part of the user's library, otherwise false.
1598+
* Not returned if a callback is given.
1599+
*/
1600+
containsMySavedShows: function(showIds, callback) {
1601+
return WebApiRequest.builder(this.getAccessToken())
1602+
.withPath('/v1/me/shows/contains')
1603+
.withQueryParameters({
1604+
ids: showIds.join(',')
1605+
})
1606+
.build()
1607+
.execute(HttpManager.get, callback);
1608+
},
1609+
1610+
/**
1611+
* Remove an show from the authenticated user's Your Music library.
1612+
* @param {string[]} showIds The show IDs
1613+
* @param {requestCallback} [callback] Optional callback method to be called instead of the promise.
1614+
* @returns {Promise|undefined} A promise that if successful returns null, otherwise an error.
1615+
* Not returned if a callback is given.
1616+
*/
1617+
removeFromMySavedShows: function(showIds, callback) {
1618+
return WebApiRequest.builder(this.getAccessToken())
1619+
.withPath('/v1/me/shows')
1620+
.withHeaders({ 'Content-Type': 'application/json' })
1621+
.withBodyParameters(showIds)
1622+
.build()
1623+
.execute(HttpManager.del, callback);
1624+
},
1625+
1626+
/**
1627+
* Add a show from the authenticated user's Your Music library.
1628+
* @param {string[]} showIds The show IDs
1629+
* @param {requestCallback} [callback] Optional callback method to be called instead of the promise.
1630+
* @returns {Promise|undefined} A promise that if successful returns null, otherwise an error. Not returned if a callback is given.
1631+
*/
1632+
addToMySavedShows: function(showIds, callback) {
1633+
return WebApiRequest.builder(this.getAccessToken())
1634+
.withPath('/v1/me/shows')
1635+
.withHeaders({ 'Content-Type': 'application/json' })
1636+
.withBodyParameters(showIds)
1637+
.build()
1638+
.execute(HttpManager.put, callback);
1639+
},
1640+
1641+
/**
1642+
* Retrieve the shows that are saved to the authenticated users Your Music library.
1643+
* @param {Object} [options] Options, being market, limit, and/or offset.
1644+
* @param {requestCallback} [callback] Optional callback method to be called instead of the promise.
1645+
* @returns {Promise|undefined} A promise that if successful, resolves to an object containing a paging object which in turn contains
1646+
* playlist show objects. Not returned if a callback is given.
1647+
*/
1648+
getMySavedShows: function(options, callback) {
1649+
return WebApiRequest.builder(this.getAccessToken())
1650+
.withPath('/v1/me/shows')
1651+
.withQueryParameters(options)
1652+
.build()
1653+
.execute(HttpManager.get, callback);
1654+
},
1655+
1656+
/**
1657+
* Get the episodes of an show.
1658+
* @param showId the show's ID.
1659+
* @options {Object} [options] The possible options, e.g. limit.
1660+
* @param {requestCallback} [callback] Optional callback method to be called instead of the promise.
1661+
* @example getShowEpisodes('41MnTivkwTO3UUJ8DrqEJJ', { limit : 5, offset : 1 }).then(...)
1662+
* @returns {Promise|undefined} A promise that if successful, returns an object containing the
1663+
* episodes in the album. The result is paginated. If the promise is rejected.
1664+
* it contains an error object. Not returned if a callback is given.
1665+
*/
1666+
getShowEpisodes: function(showId, options, callback) {
1667+
return WebApiRequest.builder(this.getAccessToken())
1668+
.withPath('/v1/shows/' + showId + '/episodes')
1669+
.withQueryParameters(options)
1670+
.build()
1671+
.execute(HttpManager.get, callback);
1672+
},
1673+
1674+
/**
1675+
* Search for a show.
1676+
* @param {string} query The search query.
1677+
* @param {Object} [options] The possible options, e.g. limit, offset.
1678+
* @param {requestCallback} [callback] Optional callback method to be called instead of the promise.
1679+
* @example searchShows('Space Oddity', { limit : 5, offset : 1 }).then(...)
1680+
* @returns {Promise|undefined} A promise that if successful, returns an object containing the
1681+
* search results. The result is paginated. If the promise is rejected,
1682+
* it contains an error object. Not returned if a callback is given.
1683+
*/
1684+
searchShows: function(query, options, callback) {
1685+
return this.search(query, ['show'], options, callback);
1686+
},
1687+
1688+
/**
1689+
* Search for an episode.
1690+
* @param {string} query The search query.
1691+
* @param {Object} [options] The possible options, e.g. limit, offset.
1692+
* @param {requestCallback} [callback] Optional callback method to be called instead of the promise.
1693+
* @example searchEpisodes('Space Oddity', { limit : 5, offset : 1 }).then(...)
1694+
* @returns {Promise|undefined} A promise that if successful, returns an object containing the
1695+
* search results. The result is paginated. If the promise is rejected,
1696+
* it contains an error object. Not returned if a callback is given.
1697+
*/
1698+
searchEpisodes: function(query, options, callback) {
1699+
return this.search(query, ['episode'], options, callback);
1700+
},
1701+
1702+
/**
1703+
* Look up an episode.
1704+
* @param {string} episodeId The episode's ID.
1705+
* @param {Object} [options] The possible options, currently only market.
1706+
* @param {requestCallback} [callback] Optional callback method to be called instead of the promise.
1707+
* @example getEpisode('3Qm86XLflmIXVm1wcwkgDK').then(...)
1708+
* @returns {Promise|undefined} A promise that if successful, returns an object containing information
1709+
* about the episode. Not returned if a callback is given.
1710+
*/
1711+
getEpisode: function(episodeId, options, callback) {
1712+
var actualCallback, actualOptions;
1713+
if (typeof options === 'function' && !callback) {
1714+
actualCallback = options;
1715+
actualOptions = {};
1716+
} else {
1717+
actualCallback = callback;
1718+
actualOptions = options;
1719+
}
1720+
return WebApiRequest.builder(this.getAccessToken())
1721+
.withPath('/v1/episodes/' + episodeId)
1722+
.withQueryParameters(actualOptions)
1723+
.build()
1724+
.execute(HttpManager.get, actualCallback);
1725+
},
1726+
1727+
/**
1728+
* Look up several episodes.
1729+
* @param {string[]} episodeIds The IDs of the episodes.
1730+
* @param {Object} [options] The possible options, currently only market.
1731+
* @param {requestCallback} [callback] Optional callback method to be called instead of the promise.
1732+
* @example getEpisodes(['0oSGxfWSnnOXhD2fKuz2Gy', '3dBVyJ7JuOMt4GE9607Qin']).then(...)
1733+
* @returns {Promise|undefined} A promise that if successful, returns an object containing information
1734+
* about the episodes. Not returned if a callback is given.
1735+
*/
1736+
getEpisodes: function(episodeIds, options, callback) {
1737+
// In case someone is using a version where options parameter did not exist.
1738+
var actualCallback, actualOptions;
1739+
if (typeof options === 'function' && !callback) {
1740+
actualCallback = options;
1741+
actualOptions = {};
1742+
} else {
1743+
actualCallback = callback;
1744+
actualOptions = options;
1745+
}
1746+
return WebApiRequest.builder(this.getAccessToken())
1747+
.withPath('/v1/episodes')
1748+
.withQueryParameters(
1749+
{
1750+
ids: episodeIds.join(',')
1751+
},
1752+
actualOptions
1753+
)
1754+
.build()
1755+
.execute(HttpManager.get, actualCallback);
1756+
},
15421757
};
15431758

1759+
15441760
SpotifyWebApi._addMethods = function(methods) {
15451761
for (var i in methods) {
15461762
if (methods.hasOwnProperty(i)) {

0 commit comments

Comments
 (0)