var http = require('./http')
var sort = require('./sort')
var SpotifyAuthenticator = require('./auth')
/**
* Create a Spotify request handler.
* @constructor
* @param {string} [clientId] - Client ID.
* @param {string} [clientSecret] - Client secret key.
* @param {string} [token] - Access token (if already authenticated).
*/
function SpotifyRequestHandler (clientId, clientSecret, token) {
/**
* Spotify authenticator.
*/
this.auth = new SpotifyAuthenticator(clientId, clientSecret, token)
}
/**
* Fetch album metadata.
*
* [Reference](https://developer.spotify.com/web-api/get-album/#example).
*
* @param {string} id - Album ID.
* @return {Promise | JSON} A JSON response.
*/
SpotifyRequestHandler.prototype.getAlbum = function (id) {
var uri = 'https://api.spotify.com/v1/albums/'
uri += encodeURIComponent(id)
return this.request(uri).then(function (response) {
if (response &&
response.id) {
return Promise.resolve(response)
} else {
return Promise.reject(response)
}
})
}
/**
* Get all albums by an artist.
*
* [Reference](https://developer.spotify.com/web-api/get-artists-albums/#example).
*
* @param {string} id - Artist ID.
* @return {Promise | JSON} A JSON response.
*/
SpotifyRequestHandler.prototype.getAlbumsByArtist = function (id) {
var self = this
var uri = 'https://api.spotify.com/v1/artists/'
uri += encodeURIComponent(id) + '/albums?limit=50'
function getAlbums (uri, result) {
return self.request(uri).then(function (response) {
if (!(response &&
response.items)) {
return Promise.reject(response)
}
if (result) {
result.items = result.items.concat(response.items)
} else {
result = response
}
if (response.next) {
return getAlbums(response.next, result)
} else {
return Promise.resolve(result)
}
})
}
// sort albums by type
function sortAlbums (response) {
if (response && response.items) {
sort(response.items, sort.album)
}
return response
}
return getAlbums(uri).then(sortAlbums)
}
/**
* Fetch a playlist's tracks.
*
* @param {string} [id] - The playlist ID.
* @param {string} [owner] - The owner ID.
*
* [Reference](https://developer.spotify.com/web-api/get-playlists-tracks/#example).
*
* @param {string} id - Album ID.
* @return {Promise | JSON} A JSON response.
*/
SpotifyRequestHandler.prototype.getPlaylist = function (id, owner) {
var self = this
var uri = 'https://api.spotify.com/v1/users/' +
encodeURIComponent(owner) +
'/playlists/' +
encodeURIComponent(id) +
'/tracks'
function getTracks (uri, result) {
return self.request(uri).then(function (response) {
if (!(response &&
response.items)) {
return Promise.reject(response)
}
if (result) {
result.items = result.items.concat(response.items)
} else {
result = response
}
if (response.next) {
return getTracks(response.next, result)
} else {
return Promise.resolve(result)
}
})
}
return getTracks(uri)
}
/**
* Get the top tracks of an artist.
*
* [Reference](https://developer.spotify.com/web-api/get-artists-top-tracks/#example).
*
* @param {string} id - Artist ID.
* @return {Promise | JSON} A JSON response.
*/
SpotifyRequestHandler.prototype.getTopTracks = function (id) {
var uri = 'https://api.spotify.com/v1/artists/'
uri += encodeURIComponent(id) + '/top-tracks?country=US'
return this.request(uri).then(function (response) {
if (response &&
response.tracks) {
sort(response.tracks, sort.popularity)
return Promise.resolve(response)
} else {
return Promise.reject(response)
}
})
}
/**
* Get a track.
*
* [Reference](https://developer.spotify.com/web-api/get-track/#example).
*
* @param {string} id - Track ID.
* @return {Promise | JSON} A JSON response.
*/
SpotifyRequestHandler.prototype.getTrack = function (id) {
var uri = 'https://api.spotify.com/v1/tracks/'
uri += encodeURIComponent(id)
return this.request(uri)
}
/**
* Perform a Spotify request.
* @param {string} uri - The URI to resolve.
* @param {Object} [options] - Request options.
* @return {Promise | JSON} A JSON response.
*/
SpotifyRequestHandler.prototype.request = function (uri, options) {
var self = this
options = options || {}
console.log(uri)
return this.auth.getToken().then(function (token) {
options.headers = options.headers || {}
options.headers.Authorization = 'Bearer ' + token
return http.json(uri, options)
}).catch(function (status) {
return self.refreshToken().then(function (token) {
options.headers.Authorization = 'Bearer ' + token
return http.json(uri, options)
})
})
}
/**
* Search for artist.
*
* [Reference](https://developer.spotify.com/web-api/search-item/#example).
*
* @param {string} artist - The artist to search for.
* @return {Promise | JSON} A JSON response.
*/
SpotifyRequestHandler.prototype.searchForArtist = function (artist) {
var uri = 'https://api.spotify.com/v1/search?type=artist&q='
uri += encodeURIComponent(artist)
return this.request(uri).then(function (response) {
if (response &&
response.artists &&
response.artists.items[0] &&
response.artists.items[0].id) {
// sort results by string similarity
sort(response.artists.items, sort.similarArtist(artist))
return Promise.resolve(response)
} else {
return Promise.reject(response)
}
})
}
/**
* Search for album.
*
* [Reference](https://developer.spotify.com/web-api/search-item/#example).
*
* @param {string} album - The album to search for.
* @param {string} [artist] - The album artist.
* @return {Promise | JSON} A JSON response.
*/
SpotifyRequestHandler.prototype.searchForAlbum = function (album, artist) {
var query = album
if (artist) {
query = 'album:"' + album + '"'
query += artist ? (' artist:"' + artist + '"') : ''
}
var uri = 'https://api.spotify.com/v1/search?type=album&q='
uri += encodeURIComponent(query)
return this.request(uri).then(function (response) {
if (response &&
response.albums &&
response.albums.items[0] &&
response.albums.items[0].id) {
// sort results by string similarity
if (!artist) {
sort(response.albums.items, sort.similarAlbum(album))
}
return Promise.resolve(response)
} else {
return Promise.reject(response)
}
})
}
/**
* Search for playlist.
*
* @param {string} playlist - The playlist to search for.
* [Reference](https://developer.spotify.com/web-api/search-item/#example).
*
* @param {string} playlist - The track to search for.
* @return {Promise | JSON} JSON response.
*/
SpotifyRequestHandler.prototype.searchForPlaylist = function (playlist) {
var uri = 'https://api.spotify.com/v1/search?type=playlist&limit=50&q='
uri += encodeURIComponent(playlist)
return this.request(uri).then(function (response) {
if (response.playlists &&
response.playlists.items[0] &&
response.playlists.items[0].uri) {
return Promise.resolve(response)
} else {
return Promise.reject(response)
}
})
}
/**
* Search for related artists.
*
* [Reference](https://developer.spotify.com/web-api/get-related-artists/#example).
*
* @param {string} id - The album ID.
* @return {Promise | JSON} A JSON response.
*/
SpotifyRequestHandler.prototype.searchForRelatedArtists = function (id) {
var uri = 'https://api.spotify.com/v1/artists/'
uri += encodeURIComponent(id) + '/related-artists'
return this.request(uri).then(function (response) {
if (response &&
response.artists) {
return Promise.resolve(response)
} else {
return Promise.reject(response)
}
})
}
/**
* Search for track.
*
* [Reference](https://developer.spotify.com/web-api/search-item/#example).
*
* @param {string} track - The track to search for.
* @param {string} [artist] - The track artist.
* @param {string} [album] - The track album.
* @return {Promise | JSON} JSON response.
*/
SpotifyRequestHandler.prototype.searchForTrack = function (track, artist, album) {
var query = track
if (artist || album) {
query = 'track:"' + track + '"'
query += artist ? (' artist:"' + artist + '"') : ''
query += album ? (' album:"' + album + '"') : ''
}
var uri = 'https://api.spotify.com/v1/search?type=track&limit=50&q='
uri += encodeURIComponent(query)
return this.request(uri).then(function (response) {
if (response.tracks &&
response.tracks.items[0] &&
response.tracks.items[0].uri) {
// Sort results by string similarity. This takes care of some
// odd cases where a random track from an album of the same name
// is returned as the first hit.
if (!(album && artist)) {
sort(response.tracks.items, sort.track(track))
}
return Promise.resolve(response)
} else {
return Promise.reject(response)
}
})
}
module.exports = SpotifyRequestHandler