mirror of
https://gitlab.com/deeplydrumming/DeemixFix.git
synced 2026-01-15 08:22:59 -03:00
Merge branch 'development' into 'main'
reverted to spotify-web-api-node (local) and applied Buffer fix. See merge request deeplydrumming/DeemixFix!7
This commit is contained in:
@@ -10,7 +10,7 @@ const {
|
||||
const { Convertable, Collection } = require('../types/DownloadObjects.js')
|
||||
const { sep } = require('path')
|
||||
const fs = require('fs')
|
||||
const SpotifyWebApi = require('spotify-web-api-node-plus')
|
||||
const SpotifyWebApi = require('spotify-web-api-node')
|
||||
const got = require('got')
|
||||
const { queue } = require('async')
|
||||
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
"got": "^11.8.2",
|
||||
"html-entities": "^2.3.3",
|
||||
"metaflac-js2": "^1.0.8",
|
||||
"spotify-web-api-node-plus": "../spotify-web-api-node-plus",
|
||||
"spotify-web-api-node": "../spotify-web-api-node",
|
||||
"tough-cookie": "^4.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
||||
@@ -1 +1 @@
|
||||
2024.7.26-r256.c452e2e47d
|
||||
2024.7.31-r258.711fcec286
|
||||
@@ -1,175 +0,0 @@
|
||||
'use strict'
|
||||
|
||||
const {
|
||||
TimeoutError,
|
||||
WebapiError,
|
||||
WebapiRegularError,
|
||||
WebapiAuthenticationError,
|
||||
WebapiPlayerError
|
||||
} = require('./response-error')
|
||||
|
||||
const HttpManager = {}
|
||||
|
||||
/* Create superagent options from the base request */
|
||||
const _getParametersFromRequest = function (request) {
|
||||
const options = {}
|
||||
|
||||
if (request.getQueryParameters()) {
|
||||
options.query = new URLSearchParams(
|
||||
request.getQueryParameters()
|
||||
).toString()
|
||||
}
|
||||
|
||||
if (
|
||||
request.getHeaders() &&
|
||||
request.getHeaders()['Content-Type'] === 'application/json'
|
||||
) {
|
||||
options.data = JSON.stringify(request.getBodyParameters())
|
||||
} else if (request.getBodyParameters()) {
|
||||
options.data = request.getBodyParameters()
|
||||
}
|
||||
|
||||
if (request.getHeaders()) {
|
||||
options.headers = request.getHeaders()
|
||||
}
|
||||
|
||||
if (request.getTimeout()) {
|
||||
options.timeout = request.getTimeout()
|
||||
}
|
||||
|
||||
return options
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Response} response
|
||||
*/
|
||||
const _toError = async function (response) {
|
||||
const body = await response.json()
|
||||
|
||||
if (
|
||||
typeof body === 'object' &&
|
||||
typeof body.error === 'object' &&
|
||||
typeof body.error.reason === 'string'
|
||||
) {
|
||||
return new WebapiPlayerError(body, response.headers, response.status)
|
||||
}
|
||||
|
||||
if (typeof body === 'object' && typeof body.error === 'object') {
|
||||
return new WebapiRegularError(body, response.headers, response.status)
|
||||
}
|
||||
|
||||
if (typeof body === 'object' && typeof body.error === 'string') {
|
||||
return new WebapiAuthenticationError(
|
||||
body,
|
||||
response.headers,
|
||||
response.status
|
||||
)
|
||||
}
|
||||
|
||||
/* Other type of error, or unhandled Web API error format */
|
||||
return new WebapiError(body, response.headers, response.status, body)
|
||||
}
|
||||
|
||||
/* Make the request to the Web API */
|
||||
HttpManager._makeRequest = function (method, options, uri, callback) {
|
||||
const headers = new Headers(options.headers || {})
|
||||
let serializationMethod = JSON.stringify
|
||||
|
||||
if (headers.get('Content-Type') === 'application/x-www-form-urlencoded') {
|
||||
serializationMethod = d => new URLSearchParams(d)
|
||||
}
|
||||
|
||||
const controller = new AbortController()
|
||||
let timeoutId
|
||||
|
||||
if (options.timeout) {
|
||||
setTimeout(() => {
|
||||
controller.abort()
|
||||
}, options.timeout)
|
||||
}
|
||||
|
||||
let body = options.data
|
||||
|
||||
if (body && typeof body !== 'string') {
|
||||
body = serializationMethod(body)
|
||||
}
|
||||
|
||||
fetch(uri + (options.query ? '?' + options.query : ''), {
|
||||
method,
|
||||
headers,
|
||||
body,
|
||||
signal: controller.signal
|
||||
})
|
||||
.then(async resp => {
|
||||
clearTimeout(timeoutId)
|
||||
|
||||
if (!resp.ok) {
|
||||
return callback(await _toError(resp))
|
||||
}
|
||||
|
||||
return callback(null, {
|
||||
body: await resp.json().catch(() => null),
|
||||
headers: resp.headers,
|
||||
statusCode: resp.status
|
||||
})
|
||||
})
|
||||
.catch(err => {
|
||||
if (controller.signal.aborted) {
|
||||
return callback(
|
||||
new TimeoutError(`request took longer than ${options.timeout}ms`)
|
||||
)
|
||||
}
|
||||
|
||||
return callback(err)
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* Make a HTTP GET request.
|
||||
* @param {BaseRequest} The request.
|
||||
* @param {Function} The callback function.
|
||||
*/
|
||||
HttpManager.get = function (request, callback) {
|
||||
const options = _getParametersFromRequest(request)
|
||||
const method = 'GET'
|
||||
|
||||
HttpManager._makeRequest(method, options, request.getURI(), callback)
|
||||
}
|
||||
|
||||
/**
|
||||
* Make a HTTP POST request.
|
||||
* @param {BaseRequest} The request.
|
||||
* @param {Function} The callback function.
|
||||
*/
|
||||
HttpManager.post = function (request, callback) {
|
||||
const options = _getParametersFromRequest(request)
|
||||
const method = 'POST'
|
||||
|
||||
HttpManager._makeRequest(method, options, request.getURI(), callback)
|
||||
}
|
||||
|
||||
/**
|
||||
* Make a HTTP DELETE request.
|
||||
* @param {BaseRequest} The request.
|
||||
* @param {Function} The callback function.
|
||||
*/
|
||||
HttpManager.del = function (request, callback) {
|
||||
const options = _getParametersFromRequest(request)
|
||||
const method = 'DELETE'
|
||||
|
||||
HttpManager._makeRequest(method, options, request.getURI(), callback)
|
||||
}
|
||||
|
||||
/**
|
||||
* Make a HTTP PUT request.
|
||||
* @param {BaseRequest} The request.
|
||||
* @param {Function} The callback function.
|
||||
*/
|
||||
HttpManager.put = function (request, callback) {
|
||||
const options = _getParametersFromRequest(request)
|
||||
const method = 'PUT'
|
||||
|
||||
HttpManager._makeRequest(method, options, request.getURI(), callback)
|
||||
}
|
||||
|
||||
module.exports = HttpManager
|
||||
5
spotify-web-api-node/.travis.yml
Normal file
5
spotify-web-api-node/.travis.yml
Normal file
@@ -0,0 +1,5 @@
|
||||
language: node_js
|
||||
node_js:
|
||||
- 14
|
||||
after_success:
|
||||
- npm run travis
|
||||
@@ -1,62 +1,47 @@
|
||||
## Change log
|
||||
|
||||
#### 7.0.0 (Jan 2024)
|
||||
|
||||
* Added [getQueue](https://developer.spotify.com/documentation/web-api/reference/get-queue) endpoint
|
||||
* Added [getPlaylistCoverImage](https://developer.spotify.com/documentation/web-api/reference/get-playlist-cover) endpoint
|
||||
* Added [addToQueue](https://developer.spotify.com/documentation/web-api/reference/add-to-queue) endpoint
|
||||
* Added [getAvailableMarkets](https://developer.spotify.com/documentation/web-api/reference/get-available-markets) endpoint
|
||||
* Updated Readme with new endpoints
|
||||
|
||||
#### 6.0.0
|
||||
|
||||
* **BREAKING CHANGES**
|
||||
* This release replaces superagent with `fetch` when making HTTP calls. This should result in no changes for consumers
|
||||
of this library except that the `headers` returned in the responses are now `Headers` objects instead of plain objects.
|
||||
Headers are case insensitive and must be treated as such.
|
||||
|
||||
#### 5.0.2 (Jan 2021)
|
||||
|
||||
* Fix: Make `transferMyPlayback` not require the `options` object, since it should be optional. Thanks for the heads-up [@Simber1](https://github.com/Simber1)!
|
||||
* Fix: Make `transferMyPlayback` not require the `options` object, since it should be optional. Thanks for the heads-up [@Simber1](https://github.com/Simber1)!
|
||||
|
||||
#### 5.0.1 (Jan 2021)
|
||||
|
||||
* Fix error handling in the HTTP client. Thanks [@yamadapc](https://github.com/yamadapc)!
|
||||
* This package can currently not be built on **Node 15 on Linux**, due to a dependency not being available yet. Issue can be followed on the [node-canvas](https://github.com/Automattic/node-canvas/issues/1688) issue tracker. In the mean time, Travis CI will run on earlier versions of Node.
|
||||
* This package can currently not be built on **Node 15 on Linux**, due to a dependency not being available yet. Issue can be followed on the [node-canvas](https://github.com/Automattic/node-canvas/issues/1688) issue tracker. In the mean time, Travis CI will run on earlier versions of Node.
|
||||
|
||||
#### 5.0.0 (Oct 2020)
|
||||
|
||||
* **BREAKING CHANGES**.
|
||||
* **BREAKING CHANGES**.
|
||||
* Arguments for some API methods have changed, causing incorrect behaviour using argument order from version 4.x. See the `README.md` for examples of how the methods can be used.
|
||||
* Create Playlist (`createPlaylist`) method no longer accepts a `userId` string as its first argument.
|
||||
* Transfer A User's Playback (`transferMyPlayback`) method takes a `deviceIds` array as its first argument.
|
||||
* Create Playlist (`createPlaylist`) method no longer accepts a `userId` string as its first argument.
|
||||
* Transfer A User's Playback (`transferMyPlayback`) method takes a `deviceIds` array as its first argument.
|
||||
* Skip to Previous (`skipToPrevious`) method takes an `options` object as its first argument.
|
||||
* Skip to Next (`skipToNext`) method takes an `options` object as its first argument.
|
||||
* Set Repeat Mode on the Current User's Playback (`setRepeat`) method takes a `state` string as its first argument.
|
||||
* Set Shuffle Mode on the Current User's Playback (`setShuffle`) method takes a `state` string as its first argument.
|
||||
|
||||
|
||||
Cheers [@marinacrachi](https://github.com/marinacrachi) for the createPlaylist update.
|
||||
* Removed legacy support for not passing an `options` object while providing a callback method. This was only supported on a few of the older endpoints, and could lead to tricky bugs. The affected endpoints are `getTrack`, `getTracks`, `getAlbum`, `getAlbums`, and `createPlaylist`. Again, check the `README.md` for examples on how these methods can be used if needed.
|
||||
* Removed `options` argument for retrieving an access token using the Client Credentials flow, `clientCredentialsGrant`.
|
||||
* API errors come in five different flavours.
|
||||
* WebapiRegularError - For errors returned by most API endpoints.
|
||||
* WebapiPlayerError - For errors returned by the Player API. These contain a bit more information.
|
||||
* WebapiPlayerError - For errors returned by the Player API. These contain a bit more information.
|
||||
* WebapiAuthenticationError - For errors related to authentication.
|
||||
* WebapiError - For errors that come from the Web API that didn't fit into one of the above.
|
||||
* TimeoutError - For network timeout errors.
|
||||
|
||||
|
||||
More importantly, errors now contain the response body, headers, and status code. One side-effect of this is that rate limited requests can be handled by checking the `Retry-After` header. Thanks for the PRs [@kauffecup](https://github.com/kauffecup), [@lantelyes](https://github.com/lantelyes), [@dkliemsch](https://github.com/dkliemsch), and [@erezny](https://github.com/erezny).
|
||||
|
||||
|
||||
Much appreciated [@konstantinjdobler](https://github.com/konstantinjdobler) for updates to the Player API errors.
|
||||
* 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)!
|
||||
* Starts or Resumes the Current User's Playback (`play`) method now supports the `position_ms` option. Thanks [@alqubo](https://github.com/alqubo), [@koflin](https://github.com/koflin), [@DoctorFishy](https://github.com/DoctorFishy). Thanks [@carmilso](https://github.com/carmilso) for general improvements to the Player API methods.
|
||||
* Binding for [Add an Item to the User's Playback Queue](https://developer.spotify.com/documentation/web-api/reference/player/add-to-queue/) endpoint added. Thanks [@thattomperson](https://github.com/thattomperson) and [@AriciducaZagaria](https://github.com/AriciducaZagaria)!
|
||||
* Binding for all [Shows and Episodes endpoints](https://developer.spotify.com/console/shows/). Thanks a _lot_ [@andyruwruw](https://github.com/andyruwruw)!
|
||||
* Binding for all [Shows and Episodes endpoints](https://developer.spotify.com/console/shows/). Thanks a _lot_ [@andyruwruw](https://github.com/andyruwruw)!
|
||||
* Documentation updates to keep up to date with ES6, thanks [@dandv](https://github.com/dandv)! Other documentation improvements by [@terensu-desu](https://github.com/terensu-desu), and examples by [@dersimn](https://github.com/dersimn). Thanks!
|
||||
* Bumped dependencies to resolve critical security issues.
|
||||
* Finally, hat off to [@dersimn](https://github.com/dersimn). Thanks for collecting all of the lingering PRs and merging them into a working and up-to-date fork. You really stepped up.
|
||||
* Bumped dependencies to resolve critical security issues.
|
||||
* Finally, hat off to [@dersimn](https://github.com/dersimn). Thanks for collecting all of the lingering PRs and merging them into a working and up-to-date fork. You really stepped up.
|
||||
|
||||
Likely more changes coming before release to npm, which will happen shortly.
|
||||
Likely more changes coming before release to npm, which will happen shortly.
|
||||
|
||||
#### 4.0.0 (14 Sep 2018)
|
||||
|
||||
@@ -91,11 +76,11 @@ Likely more changes coming before release to npm, which will happen shortly.
|
||||
#### 2.4.0 (2 May 2017)
|
||||
|
||||
* Change `addTracksToPlaylist` to pass the data in the body, preventing an issue with a long URL when passing many tracks. Thanks [@dolcalmi](https://github.com/dolcalmi) for [the PR](https://github.com/thelinmichael/spotify-web-api-node/pull/117)
|
||||
* Add support for fetching [recently played tracks](https://developer.spotify.com/documentation/web-api/reference/get-recently-played/). Thanks [@jeremyboles](https://github.com/jeremyboles) for [the PR](https://github.com/thelinmichael/spotify-web-api-node/pull/111).
|
||||
* Add support for fetching [recently played tracks](https://developer.spotify.com/web-api/console/get-recently-played/). Thanks [@jeremyboles](https://github.com/jeremyboles) for [the PR](https://github.com/thelinmichael/spotify-web-api-node/pull/111).
|
||||
|
||||
#### 2.3.6 (15 October 2016)
|
||||
|
||||
* Add language bindings for the **[Get Audio Analysis for a Track](https://developer.spotify.com/documentation/web-api/reference/get-audio-analysis/)** endpoint.
|
||||
* Add language bindings for the **[Get Audio Analysis for a Track](https://developer.spotify.com/web-api/get-audio-analysis/)** endpoint.
|
||||
|
||||
#### 2.3.5 (20 July 2016)
|
||||
|
||||
@@ -111,7 +96,7 @@ Likely more changes coming before release to npm, which will happen shortly.
|
||||
|
||||
#### 2.3.2 (10 July 2016)
|
||||
|
||||
* Add language bindings for **[Get a List of Current User's Playlists](https://developer.spotify.com/documentation/web-api/reference/get-a-list-of-current-users-playlists/)**. Thanks [@JMPerez](https://github.com/JMPerez) and [@vinialbano](https://github.com/vinialbano).
|
||||
* Add language bindings for **[Get a List of Current User's Playlists](https://developer.spotify.com/web-api/get-a-list-of-current-users-playlists/)**. Thanks [@JMPerez](https://github.com/JMPerez) and [@vinialbano](https://github.com/vinialbano).
|
||||
|
||||
#### 2.3.1 (3 July 2016)
|
||||
|
||||
@@ -119,12 +104,12 @@ Likely more changes coming before release to npm, which will happen shortly.
|
||||
|
||||
#### 2.3.0 (2 April 2016)
|
||||
|
||||
* Add language bindings for **[Get Recommendations Based on Seeds](https://developer.spotify.com/documentation/web-api/reference/get-recommendations/)**, **[Get a User's Top Artists and Tracks](https://developer.spotify.com/documentation/web-api/reference/get-users-top-artists-and-tracks/)**, **[Get Audio Features for a Track](https://developer.spotify.com/documentation/web-api/reference/get-audio-features/)**, and **[Get Audio Features for Several Tracks](https://developer.spotify.com/documentation/web-api/reference/get-several-audio-features/)**. Read more about the endpoints in the links above or in this [blog post](https://developer.spotify.com/news-stories/2016/03/29/api-improvements-update/).
|
||||
* Add language bindings for **[Get Recommendations Based on Seeds](https://developer.spotify.com/web-api/get-recommendations/)**, **[Get a User's Top Artists and Tracks](https://developer.spotify.com/web-api/get-users-top-artists-and-tracks/)**, **[Get Audio Features for a Track](https://developer.spotify.com/web-api/get-audio-features/)**, and **[Get Audio Features for Several Tracks](https://developer.spotify.com/web-api/get-several-audio-features/)**. Read more about the endpoints in the links above or in this [blog post](https://developer.spotify.com/news-stories/2016/03/29/api-improvements-update/).
|
||||
* Add generic search method enabling searches for several types at once, e.g. search for both tracks and albums in a single request, instead of one request for track results and one request for album results.
|
||||
|
||||
#### 2.2.0 (23 November 2015)
|
||||
|
||||
* Add language bindings for **[Get User's Saved Albums](https://developer.spotify.com/documentation/web-api/reference/get-users-saved-albums/)** and other endpoints related to the user's saved albums.
|
||||
* Add language bindings for **[Get User's Saved Albums](https://developer.spotify.com/web-api/get-users-saved-albums/)** and other endpoints related to the user's saved albums.
|
||||
|
||||
#### 2.1.1 (23 November 2015)
|
||||
|
||||
@@ -132,7 +117,7 @@ Likely more changes coming before release to npm, which will happen shortly.
|
||||
|
||||
#### 2.1.0 (16 July 2015)
|
||||
|
||||
* Add language binding for **[Get Followed Artists](https://developer.spotify.com/documentation/web-api/reference/get-followed-artists/)**
|
||||
* Add language binding for **[Get Followed Artists](https://developer.spotify.com/web-api/get-followed-artists/)**
|
||||
|
||||
#### 2.0.2 (11 May 2015)
|
||||
|
||||
@@ -149,28 +134,28 @@ Likely more changes coming before release to npm, which will happen shortly.
|
||||
|
||||
#### 1.3.13 (26 Feb 2015)
|
||||
|
||||
* Add language binding for **[Reorder tracks in a Playlist](https://developer.spotify.com/documentation/web-api/reference/reorder-playlists-tracks/)**
|
||||
* Add language binding for **[Reorder tracks in a Playlist](https://developer.spotify.com/web-api/reorder-playlists-tracks/)**
|
||||
|
||||
#### 1.3.12 (22 Feb 2015)
|
||||
|
||||
* Add language binding for **[Remove tracks in a Playlist by Position](https://developer.spotify.com/documentation/web-api/reference/remove-tracks-playlist/)**
|
||||
* Add language binding for **[Remove tracks in a Playlist by Position](https://developer.spotify.com/web-api/remove-tracks-playlist/)**
|
||||
|
||||
#### 1.3.11
|
||||
|
||||
* Add **[Search for Playlists](https://developer.spotify.com/documentation/web-api/reference/search-item/)** endpoint.
|
||||
* Add **[Search for Playlists](https://developer.spotify.com/web-api/search-item/)** endpoint.
|
||||
|
||||
#### 1.3.10
|
||||
|
||||
* Add market parameter to endpoints supporting **[Track Relinking](https://developer.spotify.com/documentation/web-api/reference/track-relinking-guide/)**.
|
||||
* Add market parameter to endpoints supporting **[Track Relinking](https://developer.spotify.com/web-api/track-relinking-guide/)**.
|
||||
* Improve SEO by adding keywords to the package.json file. ;-)
|
||||
|
||||
#### 1.3.8
|
||||
|
||||
* Add **[Get a List of Categories](https://developer.spotify.com/documentation/web-api/reference/get-list-categories/)**, **[Get a Category](https://developer.spotify.com/documentation/web-api/reference/get-category/)**, and **[Get A Category's Playlists](https://developer.spotify.com/documentation/web-api/reference/get-categorys-playlists/)** endpoints.
|
||||
* Add **[Get a List of Categories](https://developer.spotify.com/web-api/get-list-categories/)**, **[Get a Category](https://developer.spotify.com/web-api/get-category/)**, and **[Get A Category's Playlists](https://developer.spotify.com/web-api/get-categorys-playlists/)** endpoints.
|
||||
|
||||
#### 1.3.7
|
||||
|
||||
* Add **[Check if Users are Following Playlist](https://developer.spotify.com/documentation/web-api/reference/check-user-following-playlist/)** endpoint.
|
||||
* Add **[Check if Users are Following Playlist](https://developer.spotify.com/web-api/check-user-following-playlist/)** endpoint.
|
||||
|
||||
#### 1.3.5
|
||||
|
||||
@@ -178,7 +163,7 @@ Likely more changes coming before release to npm, which will happen shortly.
|
||||
|
||||
#### 1.3.4
|
||||
|
||||
* Add **[Follow Playlist](https://developer.spotify.com/documentation/web-api/reference/follow-playlist/)** and **[Unfollow Playlist](https://developer.spotify.com/documentation/web-api/reference/unfollow-playlist/)** endpoints.
|
||||
* Add **[Follow Playlist](https://developer.spotify.com/web-api/follow-playlist/)** and **[Unfollow Playlist](https://developer.spotify.com/web-api/unfollow-playlist/)** endpoints.
|
||||
|
||||
#### 1.3.3
|
||||
|
||||
@@ -194,11 +179,11 @@ Likely more changes coming before release to npm, which will happen shortly.
|
||||
|
||||
#### 1.2.1
|
||||
|
||||
* Add **[Follow endpoints](https://developer.spotify.com/documentation/web-api/reference/web-api-follow-endpoints/)**. Great work [JMPerez](https://github.com/JMPerez).
|
||||
* Add **[Follow endpoints](https://developer.spotify.com/web-api/web-api-follow-endpoints/)**. Great work [JMPerez](https://github.com/JMPerez).
|
||||
|
||||
#### 1.1.0
|
||||
|
||||
* Add **[Browse endpoints](https://developer.spotify.com/documentation/web-api/reference/browse-endpoints/)**. Thanks [fsahin](https://github.com/fsahin).
|
||||
* Add **[Browse endpoints](https://developer.spotify.com/web-api/browse-endpoints/)**. Thanks [fsahin](https://github.com/fsahin).
|
||||
|
||||
#### 1.0.2
|
||||
|
||||
@@ -210,19 +195,19 @@ Likely more changes coming before release to npm, which will happen shortly.
|
||||
|
||||
#### 1.0.0
|
||||
|
||||
* Add **[Replace tracks in a Playlist](https://developer.spotify.com/documentation/web-api/reference/replace-playlists-tracks/)** endpoint
|
||||
* Add **[Remove tracks in a Playlist](https://developer.spotify.com/documentation/web-api/reference/remove-tracks-playlist/)** endpoint
|
||||
* Add **[Replace tracks in a Playlist](https://developer.spotify.com/web-api/replace-playlists-tracks/)** endpoint
|
||||
* Add **[Remove tracks in a Playlist](https://developer.spotify.com/web-api/remove-tracks-playlist/)** endpoint
|
||||
* Return errors as Error objects instead of unparsed JSON. Thanks [niftylettuce](https://github.com/niftylettuce).
|
||||
|
||||
#### 0.0.11
|
||||
|
||||
* Add **[Change Playlist details](https://developer.spotify.com/documentation/web-api/reference/change-playlist-details/)** endpoint (change published status and name). Gracias [JMPerez](https://github.com/JMPerez).
|
||||
* Add **[Change Playlist details](https://developer.spotify.com/web-api/change-playlist-details/)** endpoint (change published status and name). Gracias [JMPerez](https://github.com/JMPerez).
|
||||
|
||||
#### 0.0.10
|
||||
|
||||
* Add Your Music Endpoints (**[Add tracks](https://developer.spotify.com/documentation/web-api/reference/save-tracks-user/)**, **[Remove tracks](https://developer.spotify.com/documentation/web-api/reference/remove-tracks-user/)**, **[Contains tracks](https://developer.spotify.com/documentation/web-api/reference/check-users-saved-tracks/)**, **[Get tracks](https://developer.spotify.com/documentation/web-api/reference/get-users-saved-tracks/)**).
|
||||
* Add Your Music Endpoints (**[Add tracks](https://developer.spotify.com/web-api/save-tracks-user/)**, **[Remove tracks](https://developer.spotify.com/web-api/remove-tracks-user/)**, **[Contains tracks](https://developer.spotify.com/web-api/check-users-saved-tracks/)**, **[Get tracks](https://developer.spotify.com/web-api/get-users-saved-tracks/)**).
|
||||
* Documentation updates (change scope name of playlist-modify to playlist-modify-public, and a fix to a parameter type). Thanks [JMPerez](https://github.com/JMPerez) and [matiassingers](https://github.com/matiassingers).
|
||||
|
||||
#### 0.0.9
|
||||
|
||||
* Add **[Related artists](https://developer.spotify.com/documentation/web-api/reference/get-related-artists/)** endpoint
|
||||
* Add **[Related artists](https://developer.spotify.com/web-api/get-related-artists/)** endpoint
|
||||
@@ -1,9 +1,16 @@
|
||||
# Spotify Web API Node
|
||||
|
||||
[](https://travis-ci.org/thelinmichael/spotify-web-api-node)
|
||||
[](https://coveralls.io/r/thelinmichael/spotify-web-api-node)
|
||||
[](https://bundlephobia.com/result?p=spotify-web-api-node)
|
||||
|
||||
This is a universal wrapper/client for the [Spotify Web API](https://developer.spotify.com/web-api/) that runs on Node.JS and the browser, using [browserify](http://browserify.org/)/[webpack](https://webpack.github.io/)/[rollup](http://rollupjs.org/). A list of selected wrappers for different languages and environments is available at the Developer site's [Libraries page](https://developer.spotify.com/documentation/web-api/libraries/).
|
||||
|
||||
This library is a fork of [spotify-web-api-node](https://github.com/thelinmichael/spotify-web-api-node) with the goal of
|
||||
the library becoming dependency free and actively maintained.
|
||||
Project owners are [thelinmichael](https://github.com/thelinmichael) and [JMPerez](https://github.com/JMPerez), with help from [a lot of awesome contributors](https://github.com/thelinmichael/spotify-web-api-node/network/members).
|
||||
|
||||
## Version 5
|
||||
|
||||
> :warning: Since the last release (4.0.0, released over year ago) a lot of new functionality has been added by a lot of different contributors. **Thank you.** In order to implement some of the feature requests, some **breaking changes** had to be made. A list of them, along with a list of the new functionality, can be found in the [CHANGELOG](https://github.com/thelinmichael/spotify-web-api-node/blob/master/CHANGELOG.md).
|
||||
|
||||
## Table of contents
|
||||
|
||||
@@ -45,7 +52,7 @@ The library includes helper functions to do the following:
|
||||
#### Your Music library
|
||||
|
||||
* Add, remove, and get tracks and albums that are in the signed in user's Your Music library
|
||||
* Check if a track or album is in the signed in user's Your Music library
|
||||
* Check if a track or album is in the signed in user's Your Music library
|
||||
|
||||
#### Personalization
|
||||
|
||||
@@ -66,14 +73,14 @@ The library includes helper functions to do the following:
|
||||
* Get a User's Available Devices
|
||||
* Get Information About The User's Current Playback State
|
||||
* Get Current User's Recently Played Tracks
|
||||
* Get the User's Currently Playing Track
|
||||
* Get the User's Currently Playing Track
|
||||
* Pause a User's Playback
|
||||
* Seek To Position In Currently Playing Track
|
||||
* Set Repeat Mode On User’s Playback
|
||||
* Set Volume For User's Playback
|
||||
* Skip User’s Playback To Next Track
|
||||
* Skip User’s Playback To Previous Track
|
||||
* Start/Resume a User's Playback
|
||||
* Skip User’s Playback To Previous Track
|
||||
* Start/Resume a User's Playback
|
||||
* Toggle Shuffle For User’s Playback
|
||||
* Transfer a User's Playback
|
||||
|
||||
@@ -120,12 +127,7 @@ This project depends on [superagent](https://github.com/visionmedia/superagent)
|
||||
|
||||
## Installation
|
||||
|
||||
```bash
|
||||
$ npm install spotify-web-api-node --save
|
||||
# If you are using this library in a Node version that does not have the fetch function (Node < v17), you will need
|
||||
# to install and configure a fetch polyfill
|
||||
$ npm install node-fetch --save
|
||||
```
|
||||
$ npm install spotify-web-api-node --save
|
||||
|
||||
## Usage
|
||||
|
||||
@@ -199,7 +201,7 @@ spotifyApi
|
||||
|
||||
### Responses and errors
|
||||
|
||||
This exposes the response headers, status code and body.
|
||||
This exposes the response headers, status code and body.
|
||||
|
||||
```json
|
||||
{
|
||||
@@ -213,7 +215,7 @@ This exposes the response headers, status code and body.
|
||||
}
|
||||
```
|
||||
|
||||
Errors have same fields, as well as a human readable `message`. This is especially useful since
|
||||
Errors have same fields, as well as a human readable `message`. This is especially useful since
|
||||
Spotify's Web API returns different types of error objects depending on the endpoint being called.
|
||||
|
||||
#### Example of a response
|
||||
@@ -242,7 +244,7 @@ Retrieving a track's metadata in `spotify-web-api-node` version 1.4.0 and later:
|
||||
|
||||
### More examples
|
||||
|
||||
Below are examples for all helper functions. Longer examples of some requests can be found in the [examples folder](examples/).
|
||||
Below are examples for all helper functions. Longer examples of some requests can be found in the [examples folder](examples/).
|
||||
|
||||
```javascript
|
||||
var SpotifyWebApi = require('spotify-web-api-node');
|
||||
@@ -253,22 +255,6 @@ var spotifyApi = new SpotifyWebApi();
|
||||
* Get metadata of tracks, albums, artists, shows, and episodes
|
||||
*/
|
||||
|
||||
// Get track
|
||||
spotifyApi.getTrack("28s5iRbX62GZG2ReZTLKDa")
|
||||
.then(function (data) {
|
||||
console.log("Track information", data.body);
|
||||
}, function (err) {
|
||||
console.error(err);
|
||||
});
|
||||
|
||||
// Get multiple tracks
|
||||
spotifyApi.getTracks(["6Rb4xFCy3Hh5MJ88ehLXdc", "5oOoQn1bhg6nbuvd54URPF"])
|
||||
.then(function (data) {
|
||||
console.log("Tracks information", track);
|
||||
},function (err) {
|
||||
console.error(err);
|
||||
});
|
||||
|
||||
// Get album
|
||||
spotifyApi.getAlbum('5U4W9E5WsYb2jUQWePT8Xm')
|
||||
.then(function(data) {
|
||||
@@ -834,7 +820,7 @@ spotifyApi.getMyRecentlyPlayedTracks({
|
||||
console.log('Something went wrong!', err);
|
||||
});
|
||||
|
||||
// Get the User's Currently Playing Track
|
||||
// Get the User's Currently Playing Track
|
||||
spotifyApi.getMyCurrentPlayingTrack()
|
||||
.then(function(data) {
|
||||
console.log('Now playing: ' + data.body.item.name);
|
||||
@@ -887,7 +873,7 @@ spotifyApi.skipToNext()
|
||||
console.log('Something went wrong!', err);
|
||||
});
|
||||
|
||||
// Skip User’s Playback To Previous Track
|
||||
// Skip User’s Playback To Previous Track
|
||||
spotifyApi.skipToPrevious()
|
||||
.then(function() {
|
||||
console.log('Skip to previous');
|
||||
@@ -896,7 +882,7 @@ spotifyApi.skipToPrevious()
|
||||
console.log('Something went wrong!', err);
|
||||
});
|
||||
|
||||
// Start/Resume a User's Playback
|
||||
// Start/Resume a User's Playback
|
||||
spotifyApi.play()
|
||||
.then(function() {
|
||||
console.log('Playback started');
|
||||
@@ -1252,7 +1238,7 @@ api
|
||||
|
||||
## Development
|
||||
|
||||
See something you think can be improved? [Open an issue](https://github.com/eligundry/spotify-web-api-fetch/issues/new) or clone the project and send a pull request with your changes.
|
||||
See something you think can be improved? [Open an issue](https://github.com/thelinmichael/spotify-web-api-node/issues/new) or clone the project and send a pull request with your changes.
|
||||
|
||||
### Running tests
|
||||
|
||||
86
spotify-web-api-node/examples/access-token-refresh.js
Normal file
86
spotify-web-api-node/examples/access-token-refresh.js
Normal file
@@ -0,0 +1,86 @@
|
||||
const SpotifyWebApi = require('../');
|
||||
|
||||
/**
|
||||
* This example refreshes an access token. Refreshing access tokens is only possible access tokens received using the
|
||||
* Authorization Code flow, documented here: https://developer.spotify.com/spotify-web-api/authorization-guide/#authorization_code_flow
|
||||
*/
|
||||
|
||||
/* Retrieve an authorization code as documented here:
|
||||
* https://developer.spotify.com/documentation/general/guides/authorization-guide/#authorization-code-flow
|
||||
* or in the Authorization section of the README.
|
||||
*
|
||||
* Codes are given for a set of scopes. For this example, the scopes are user-read-private and user-read-email.
|
||||
* Scopes are documented here:
|
||||
* https://developer.spotify.com/documentation/general/guides/scopes/
|
||||
*/
|
||||
const authorizationCode =
|
||||
'<insert authorization code with user-read-private and user-read-email scopes>';
|
||||
|
||||
/**
|
||||
* Get the credentials from Spotify's Dashboard page.
|
||||
* https://developer.spotify.com/dashboard/applications
|
||||
*/
|
||||
const spotifyApi = new SpotifyWebApi({
|
||||
clientId: '<insert client id>',
|
||||
clientSecret: '<insert client secret>',
|
||||
redirectUri: '<insert redirect URI>'
|
||||
});
|
||||
|
||||
// When our access token will expire
|
||||
let tokenExpirationEpoch;
|
||||
|
||||
// First retrieve an access token
|
||||
spotifyApi.authorizationCodeGrant(authorizationCode).then(
|
||||
function(data) {
|
||||
// Set the access token and refresh token
|
||||
spotifyApi.setAccessToken(data.body['access_token']);
|
||||
spotifyApi.setRefreshToken(data.body['refresh_token']);
|
||||
|
||||
// Save the amount of seconds until the access token expired
|
||||
tokenExpirationEpoch =
|
||||
new Date().getTime() / 1000 + data.body['expires_in'];
|
||||
console.log(
|
||||
'Retrieved token. It expires in ' +
|
||||
Math.floor(tokenExpirationEpoch - new Date().getTime() / 1000) +
|
||||
' seconds!'
|
||||
);
|
||||
},
|
||||
function(err) {
|
||||
console.log(
|
||||
'Something went wrong when retrieving the access token!',
|
||||
err.message
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
// Continually print out the time left until the token expires..
|
||||
let numberOfTimesUpdated = 0;
|
||||
|
||||
setInterval(function() {
|
||||
console.log(
|
||||
'Time left: ' +
|
||||
Math.floor(tokenExpirationEpoch - new Date().getTime() / 1000) +
|
||||
' seconds left!'
|
||||
);
|
||||
|
||||
// OK, we need to refresh the token. Stop printing and refresh.
|
||||
if (++numberOfTimesUpdated > 5) {
|
||||
clearInterval(this);
|
||||
|
||||
// Refresh token and print the new time to expiration.
|
||||
spotifyApi.refreshAccessToken().then(
|
||||
function(data) {
|
||||
tokenExpirationEpoch =
|
||||
new Date().getTime() / 1000 + data.body['expires_in'];
|
||||
console.log(
|
||||
'Refreshed token. It now expires in ' +
|
||||
Math.floor(tokenExpirationEpoch - new Date().getTime() / 1000) +
|
||||
' seconds!'
|
||||
);
|
||||
},
|
||||
function(err) {
|
||||
console.log('Could not refresh the token!', err.message);
|
||||
}
|
||||
);
|
||||
}
|
||||
}, 1000);
|
||||
@@ -0,0 +1,32 @@
|
||||
const SpotifyWebApi = require('../');
|
||||
|
||||
/**
|
||||
* This example retrieves an access token using the Client Credentials Flow, documented at:
|
||||
* https://developer.spotify.com/documentation/general/guides/authorization-guide/#client-credentials-flow
|
||||
*/
|
||||
|
||||
/**
|
||||
* Get the credentials from Spotify's Dashboard page.
|
||||
* https://developer.spotify.com/dashboard/applications
|
||||
*/
|
||||
const spotifyApi = new SpotifyWebApi({
|
||||
clientId: '<insert client id>',
|
||||
clientSecret: '<insert client secret>'
|
||||
});
|
||||
|
||||
// Retrieve an access token
|
||||
spotifyApi.clientCredentialsGrant().then(
|
||||
function(data) {
|
||||
console.log('The access token expires in ' + data.body['expires_in']);
|
||||
console.log('The access token is ' + data.body['access_token']);
|
||||
|
||||
// Save the access token so that it's used in future calls
|
||||
spotifyApi.setAccessToken(data.body['access_token']);
|
||||
},
|
||||
function(err) {
|
||||
console.log(
|
||||
'Something went wrong when retrieving an access token',
|
||||
err.message
|
||||
);
|
||||
}
|
||||
);
|
||||
@@ -0,0 +1,84 @@
|
||||
const SpotifyWebApi = require('../');
|
||||
|
||||
/**
|
||||
* This example demonstrates adding tracks, removing tracks, and replacing tracks in a playlist. At the time of writing this
|
||||
* documentation, this is the available playlist track modification feature in the Spotify Web API.
|
||||
*
|
||||
* Since authorization is required, this example retrieves an access token using the Authorization Code Grant flow,
|
||||
* documented here: https://developer.spotify.com/documentation/general/guides/authorization-guide/#authorization-code-flow
|
||||
*
|
||||
* Codes are given for a set of scopes. For this example, the scopes are playlist-modify-public.
|
||||
* Scopes are documented here:
|
||||
* https://developer.spotify.com/documentation/general/guides/scopes/
|
||||
*/
|
||||
|
||||
/* Obtain the `authorizationCode` below as described in the Authorization section of the README.
|
||||
*/
|
||||
const authorizationCode =
|
||||
'<insert authorization code with playlist-modify-public scope>';
|
||||
|
||||
/**
|
||||
* Get the credentials from Spotify's Dashboard page.
|
||||
* https://developer.spotify.com/dashboard/applications
|
||||
*/
|
||||
const spotifyApi = new SpotifyWebApi({
|
||||
clientId: '<insert client id>',
|
||||
clientSecret: '<insert client secret>',
|
||||
redirectUri: '<insert redirect URI>'
|
||||
});
|
||||
|
||||
let playlistId;
|
||||
|
||||
// First retrieve an access token
|
||||
spotifyApi
|
||||
.authorizationCodeGrant(authorizationCode)
|
||||
.then(function(data) {
|
||||
// Save the access token so that it's used in future requests
|
||||
spotifyApi.setAccessToken(data['access_token']);
|
||||
|
||||
// Create a playlist
|
||||
return spotifyApi.createPlaylist(
|
||||
'thelinmichael',
|
||||
'My New Awesome Playlist'
|
||||
);
|
||||
})
|
||||
.then(function(data) {
|
||||
console.log('Ok. Playlist created!');
|
||||
playlistId = data.body['id'];
|
||||
|
||||
// Add tracks to the playlist
|
||||
return spotifyApi.addTracksToPlaylist(playlistId, [
|
||||
'spotify:track:4iV5W9uYEdYUVa79Axb7Rh',
|
||||
'spotify:track:6tcfwoGcDjxnSc6etAkDRR',
|
||||
'spotify:track:4iV5W9uYEdYUVa79Axb7Rh'
|
||||
]);
|
||||
})
|
||||
.then(function(data) {
|
||||
console.log('Ok. Tracks added!');
|
||||
|
||||
// Woops! Made a duplicate. Remove one of the duplicates from the playlist
|
||||
return spotifyApi.removeTracksFromPlaylist('thelinmichael', playlistId, [
|
||||
{
|
||||
uri: 'spotify:track:4iV5W9uYEdYUVa79Axb7Rh',
|
||||
positions: [0]
|
||||
}
|
||||
]);
|
||||
})
|
||||
.then(function(data) {
|
||||
console.log('Ok. Tracks removed!');
|
||||
|
||||
// Actually, lets just replace all tracks in the playlist with something completely different
|
||||
return spotifyApi.replaceTracksInPlaylist('thelinmichael', playlistId, [
|
||||
'spotify:track:5Wd2bfQ7wc6GgSa32OmQU3',
|
||||
'spotify:track:4r8lRYnoOGdEi6YyI5OC1o',
|
||||
'spotify:track:4TZZvblv2yzLIBk2JwJ6Un',
|
||||
'spotify:track:2IA4WEsWAYpV9eKkwR2UYv',
|
||||
'spotify:track:6hDH3YWFdcUNQjubYztIsG'
|
||||
]);
|
||||
})
|
||||
.then(function(data) {
|
||||
console.log('Ok. Tracks replaced!');
|
||||
})
|
||||
.catch(function(err) {
|
||||
console.log('Something went wrong:', err.message);
|
||||
});
|
||||
49
spotify-web-api-node/examples/add-tracks-to-a-playlist.js
Normal file
49
spotify-web-api-node/examples/add-tracks-to-a-playlist.js
Normal file
@@ -0,0 +1,49 @@
|
||||
const SpotifyWebApi = require('../');
|
||||
|
||||
/**
|
||||
* This example demonstrates adding tracks to a specified position in a playlist.
|
||||
*
|
||||
* Since authorization is required, this example retrieves an access token using the Authorization Code Grant flow,
|
||||
* documented here: https://developer.spotify.com/documentation/general/guides/authorization-guide/#authorization-code-flow
|
||||
*
|
||||
* Codes are given for a set of scopes. For this example, the scopes are playlist-modify-public.
|
||||
* Scopes are documented here:
|
||||
* https://developer.spotify.com/documentation/general/guides/scopes/
|
||||
*/
|
||||
|
||||
/* Obtain the `authorizationCode` below as described in the Authorization section of the README.
|
||||
*/
|
||||
const authorizationCode = '<insert authorization code>';
|
||||
|
||||
/**
|
||||
* Get the credentials from Spotify's Dashboard page.
|
||||
* https://developer.spotify.com/dashboard/applications
|
||||
*/
|
||||
const spotifyApi = new SpotifyWebApi({
|
||||
clientId: '<insert client id>',
|
||||
clientSecret: '<insert client secret>',
|
||||
redirectUri: '<insert redirect URI>'
|
||||
});
|
||||
|
||||
// First retrieve an access token
|
||||
spotifyApi
|
||||
.authorizationCodeGrant(authorizationCode)
|
||||
.then(function(data) {
|
||||
spotifyApi.setAccessToken(data.body['access_token']);
|
||||
return spotifyApi.addTracksToPlaylist(
|
||||
'5ieJqeLJjjI8iJWaxeBLuK',
|
||||
[
|
||||
'spotify:track:4iV5W9uYEdYUVa79Axb7Rh',
|
||||
'spotify:track:1301WleyT98MSxVHPZCA6M'
|
||||
],
|
||||
{
|
||||
position: 10
|
||||
}
|
||||
);
|
||||
})
|
||||
.then(function(data) {
|
||||
console.log('Added tracks to the playlist!');
|
||||
})
|
||||
.catch(function(err) {
|
||||
console.log('Something went wrong:', err.message);
|
||||
});
|
||||
26
spotify-web-api-node/examples/client-credentials.js
Normal file
26
spotify-web-api-node/examples/client-credentials.js
Normal file
@@ -0,0 +1,26 @@
|
||||
const { util } = require('prettier');
|
||||
var SpotifyWebApi = require('../');
|
||||
|
||||
/**
|
||||
* This example uses the Client Credentials authorization flow.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Get the credentials from Spotify's Dashboard page.
|
||||
* https://developer.spotify.com/dashboard/applications
|
||||
*/
|
||||
const spotifyApi = new SpotifyWebApi({
|
||||
clientId: '<Client ID>',
|
||||
clientSecret: '<Client Secret>'
|
||||
});
|
||||
|
||||
// Retrieve an access token using your credentials
|
||||
spotifyApi.clientCredentialsGrant().
|
||||
then(function(result) {
|
||||
console.log('It worked! Your access token is: ' + result.body.access_token);
|
||||
}).catch(function(err) {
|
||||
console.log('If this is printed, it probably means that you used invalid ' +
|
||||
'clientId and clientSecret values. Please check!');
|
||||
console.log('Hint: ');
|
||||
console.log(err);
|
||||
});
|
||||
54
spotify-web-api-node/examples/get-info-about-current-user.js
Normal file
54
spotify-web-api-node/examples/get-info-about-current-user.js
Normal file
@@ -0,0 +1,54 @@
|
||||
const SpotifyWebApi = require('../');
|
||||
|
||||
/**
|
||||
* This example retrieves information about the 'current' user. The current user is the user that has
|
||||
* authorized the application to access its data.
|
||||
*/
|
||||
|
||||
/* Retrieve a code as documented here:
|
||||
* https://developer.spotify.com/documentation/general/guides/authorization-guide/#authorization-code-flow
|
||||
*
|
||||
* Codes are given for a set of scopes. For this example, the scopes are user-read-private and user-read-email.
|
||||
* Scopes are documented here:
|
||||
* https://developer.spotify.com/documentation/general/guides/scopes/
|
||||
*/
|
||||
const authorizationCode =
|
||||
'<insert authorization code with user-read-private and user-read-email scopes>';
|
||||
|
||||
/* Get the credentials from Spotify's Dashboard page.
|
||||
* https://developer.spotify.com/dashboard/applications
|
||||
*/
|
||||
const spotifyApi = new SpotifyWebApi({
|
||||
clientId: '<insert client id>',
|
||||
clientSecret: '<insert client secret>',
|
||||
redirectUri: '<insert redirect URI>'
|
||||
});
|
||||
|
||||
// First retrieve an access token
|
||||
spotifyApi
|
||||
.authorizationCodeGrant(authorizationCode)
|
||||
.then(function(data) {
|
||||
console.log('Retrieved access token', data.body['access_token']);
|
||||
|
||||
// Set the access token
|
||||
spotifyApi.setAccessToken(data.body['access_token']);
|
||||
|
||||
// Use the access token to retrieve information about the user connected to it
|
||||
return spotifyApi.getMe();
|
||||
})
|
||||
.then(function(data) {
|
||||
// "Retrieved data for Faruk Sahin"
|
||||
console.log('Retrieved data for ' + data.body['display_name']);
|
||||
|
||||
// "Email is farukemresahin@gmail.com"
|
||||
console.log('Email is ' + data.body.email);
|
||||
|
||||
// "Image URL is http://media.giphy.com/media/Aab07O5PYOmQ/giphy.gif"
|
||||
console.log('Image URL is ' + data.body.images[0].url);
|
||||
|
||||
// "This user has a premium account"
|
||||
console.log('This user has a ' + data.body.product + ' account');
|
||||
})
|
||||
.catch(function(err) {
|
||||
console.log('Something went wrong:', err.message);
|
||||
});
|
||||
49
spotify-web-api-node/examples/get-related-artists.js
Normal file
49
spotify-web-api-node/examples/get-related-artists.js
Normal file
@@ -0,0 +1,49 @@
|
||||
var SpotifyWebApi = require('../');
|
||||
|
||||
/*
|
||||
* This example shows how to get artists related to another artists. The endpoint is documented here:
|
||||
* https://developer.spotify.com/web-api/get-related-artists/
|
||||
|
||||
* Please note that authorization is now required and so this example retrieves an access token using the Authorization Code Flow,
|
||||
* documented here: https://developer.spotify.com/documentation/general/guides/authorization-guide/#authorization-code-flow
|
||||
*/
|
||||
|
||||
var authorizationCode =
|
||||
'AQAgjS78s64u1axMCBCRA0cViW_ZDDU0pbgENJ_-WpZr3cEO7V5O-JELcEPU6pGLPp08SfO3dnHmu6XJikKqrU8LX9W6J11NyoaetrXtZFW-Y58UGeV69tuyybcNUS2u6eyup1EgzbTEx4LqrP_eCHsc9xHJ0JUzEhi7xcqzQG70roE4WKM_YrlDZO-e7GDRMqunS9RMoSwF_ov-gOMpvy9OMb7O58nZoc3LSEdEwoZPCLU4N4TTJ-IF6YsQRhQkEOJK';
|
||||
|
||||
/* Set the credentials given on Spotify's My Applications page.
|
||||
* https://developer.spotify.com/my-applications
|
||||
*/
|
||||
var spotifyApi = new SpotifyWebApi({
|
||||
clientId: '<insert client id>',
|
||||
clientSecret: '<insert client secret>',
|
||||
redirectUri: '<insert redirect URI>'
|
||||
});
|
||||
|
||||
var artistId = '0qeei9KQnptjwb8MgkqEoy';
|
||||
|
||||
spotifyApi
|
||||
.authorizationCodeGrant(authorizationCode)
|
||||
.then(function(data) {
|
||||
console.log('Retrieved access token', data.body['access_token']);
|
||||
|
||||
// Set the access token
|
||||
spotifyApi.setAccessToken(data.body['access_token']);
|
||||
|
||||
// Use the access token to retrieve information about the user connected to it
|
||||
return spotifyApi.getArtistRelatedArtists(artistId);
|
||||
})
|
||||
.then(function(data) {
|
||||
if (data.body.artists.length) {
|
||||
// Print the number of similar artists
|
||||
console.log('I got ' + data.body.artists.length + ' similar artists!');
|
||||
|
||||
console.log('The most similar one is ' + data.body.artists[0].name);
|
||||
} else {
|
||||
console.log("I didn't find any similar artists.. Sorry.");
|
||||
}
|
||||
},
|
||||
function(err) {
|
||||
console.log('Something went wrong:', err.message);
|
||||
}
|
||||
);
|
||||
56
spotify-web-api-node/examples/get-top-tracks-for-artist.js
Normal file
56
spotify-web-api-node/examples/get-top-tracks-for-artist.js
Normal file
@@ -0,0 +1,56 @@
|
||||
const SpotifyWebApi = require('../');
|
||||
|
||||
/**
|
||||
* This example retrieves the top tracks for an artist.
|
||||
* https://developer.spotify.com/documentation/web-api/reference/artists/get-artists-top-tracks/
|
||||
*/
|
||||
|
||||
/**
|
||||
* This endpoint doesn't require an access token, but it's beneficial to use one as it
|
||||
* gives the application a higher rate limit.
|
||||
*
|
||||
* Since it's not necessary to get an access token connected to a specific user, this example
|
||||
* uses the Client Credentials flow. This flow uses only the client ID and the client secret.
|
||||
* https://developer.spotify.com/documentation/general/guides/authorization-guide/#client-credentials-flow
|
||||
*/
|
||||
const spotifyApi = new SpotifyWebApi({
|
||||
clientId: '<insert client id>',
|
||||
clientSecret: '<insert client secret>'
|
||||
});
|
||||
|
||||
// Retrieve an access token
|
||||
spotifyApi
|
||||
.clientCredentialsGrant()
|
||||
.then(function(data) {
|
||||
// Set the access token on the API object so that it's used in all future requests
|
||||
spotifyApi.setAccessToken(data.body['access_token']);
|
||||
|
||||
// Get the most popular tracks by David Bowie in Great Britain
|
||||
return spotifyApi.getArtistTopTracks('0oSGxfWSnnOXhD2fKuz2Gy', 'GB');
|
||||
})
|
||||
.then(function(data) {
|
||||
console.log('The most popular tracks for David Bowie is..');
|
||||
console.log('Drum roll..');
|
||||
console.log('...');
|
||||
|
||||
/*
|
||||
* 1. Space Oddity - 2009 Digital Remaster (popularity is 51)
|
||||
* 2. Heroes - 1999 Digital Remaster (popularity is 33)
|
||||
* 3. Let's Dance - 1999 Digital Remaster (popularity is 20)
|
||||
* 4. ...
|
||||
*/
|
||||
data.body.tracks.forEach(function(track, index) {
|
||||
console.log(
|
||||
index +
|
||||
1 +
|
||||
'. ' +
|
||||
track.name +
|
||||
' (popularity is ' +
|
||||
track.popularity +
|
||||
')'
|
||||
);
|
||||
});
|
||||
})
|
||||
.catch(function(err) {
|
||||
console.log('Unfortunately, something has gone wrong.', err.message);
|
||||
});
|
||||
55
spotify-web-api-node/examples/search-for-tracks.js
Normal file
55
spotify-web-api-node/examples/search-for-tracks.js
Normal file
@@ -0,0 +1,55 @@
|
||||
const SpotifyWebApi = require('../');
|
||||
|
||||
/*
|
||||
* This example shows how to search for a track. The endpoint is documented here:
|
||||
* https://developer.spotify.com/documentation/web-api/reference/search/
|
||||
|
||||
* Since authorization is now required, this example retrieves an access token using the Authorization Code Grant flow,
|
||||
* documented here: https://developer.spotify.com/documentation/general/guides/authorization-guide/#authorization-code-flow
|
||||
*
|
||||
* Obtain the `authorizationCode` below as described in the Authorization section of the README.
|
||||
*/
|
||||
|
||||
const authorizationCode = '<insert authorization code>';
|
||||
|
||||
/**
|
||||
* Get the credentials from Spotify's Dashboard page.
|
||||
* https://developer.spotify.com/dashboard/applications
|
||||
*/
|
||||
const spotifyApi = new SpotifyWebApi({
|
||||
clientId: '<insert client id>',
|
||||
clientSecret: '<insert client secret>',
|
||||
redirectUri: '<insert redirect URI>'
|
||||
});
|
||||
|
||||
spotifyApi
|
||||
.authorizationCodeGrant(authorizationCode)
|
||||
.then(function(data) {
|
||||
console.log('Retrieved access token', data.body['access_token']);
|
||||
|
||||
// Set the access token
|
||||
spotifyApi.setAccessToken(data.body['access_token']);
|
||||
|
||||
// Use the access token to retrieve information about the user connected to it
|
||||
return spotifyApi.searchTracks('Love');
|
||||
})
|
||||
.then(function(data) {
|
||||
// Print some information about the results
|
||||
console.log('I got ' + data.body.tracks.total + ' results!');
|
||||
|
||||
// Go through the first page of results
|
||||
var firstPage = data.body.tracks.items;
|
||||
console.log('The tracks in the first page are (popularity in parentheses):');
|
||||
|
||||
/*
|
||||
* 0: All of Me (97)
|
||||
* 1: My Love (91)
|
||||
* 2: I Love This Life (78)
|
||||
* ...
|
||||
*/
|
||||
firstPage.forEach(function(track, index) {
|
||||
console.log(index + ': ' + track.name + ' (' + track.popularity + ')');
|
||||
});
|
||||
}).catch(function(err) {
|
||||
console.log('Something went wrong:', err.message);
|
||||
});
|
||||
101
spotify-web-api-node/examples/tutorial/00-get-access-token.js
Normal file
101
spotify-web-api-node/examples/tutorial/00-get-access-token.js
Normal file
@@ -0,0 +1,101 @@
|
||||
/**
|
||||
* This example is using the Authorization Code flow.
|
||||
*
|
||||
* In root directory run
|
||||
*
|
||||
* npm install express
|
||||
*
|
||||
* then run with the followinng command. If you don't have a client_id and client_secret yet,
|
||||
* create an application on Create an application here: https://developer.spotify.com/my-applications to get them.
|
||||
* Make sure you whitelist the correct redirectUri in line 26.
|
||||
*
|
||||
* node access-token-server.js "<Client ID>" "<Client Secret>"
|
||||
*
|
||||
* and visit <http://localhost:8888/login> in your Browser.
|
||||
*/
|
||||
const SpotifyWebApi = require('../../');
|
||||
const express = require('../../node_modules/express');
|
||||
|
||||
const scopes = [
|
||||
'ugc-image-upload',
|
||||
'user-read-playback-state',
|
||||
'user-modify-playback-state',
|
||||
'user-read-currently-playing',
|
||||
'streaming',
|
||||
'app-remote-control',
|
||||
'user-read-email',
|
||||
'user-read-private',
|
||||
'playlist-read-collaborative',
|
||||
'playlist-modify-public',
|
||||
'playlist-read-private',
|
||||
'playlist-modify-private',
|
||||
'user-library-modify',
|
||||
'user-library-read',
|
||||
'user-top-read',
|
||||
'user-read-playback-position',
|
||||
'user-read-recently-played',
|
||||
'user-follow-read',
|
||||
'user-follow-modify'
|
||||
];
|
||||
|
||||
const spotifyApi = new SpotifyWebApi({
|
||||
redirectUri: 'http://localhost:8888/callback',
|
||||
clientId: process.argv.slice(2)[0],
|
||||
clientSecret: process.argv.slice(2)[1]
|
||||
});
|
||||
|
||||
const app = express();
|
||||
|
||||
app.get('/login', (req, res) => {
|
||||
res.redirect(spotifyApi.createAuthorizeURL(scopes));
|
||||
});
|
||||
|
||||
app.get('/callback', (req, res) => {
|
||||
const error = req.query.error;
|
||||
const code = req.query.code;
|
||||
const state = req.query.state;
|
||||
|
||||
if (error) {
|
||||
console.error('Callback Error:', error);
|
||||
res.send(`Callback Error: ${error}`);
|
||||
return;
|
||||
}
|
||||
|
||||
spotifyApi
|
||||
.authorizationCodeGrant(code)
|
||||
.then(data => {
|
||||
const access_token = data.body['access_token'];
|
||||
const refresh_token = data.body['refresh_token'];
|
||||
const expires_in = data.body['expires_in'];
|
||||
|
||||
spotifyApi.setAccessToken(access_token);
|
||||
spotifyApi.setRefreshToken(refresh_token);
|
||||
|
||||
console.log('access_token:', access_token);
|
||||
console.log('refresh_token:', refresh_token);
|
||||
|
||||
console.log(
|
||||
`Sucessfully retreived access token. Expires in ${expires_in} s.`
|
||||
);
|
||||
res.send('Success! You can now close the window.');
|
||||
|
||||
setInterval(async () => {
|
||||
const data = await spotifyApi.refreshAccessToken();
|
||||
const access_token = data.body['access_token'];
|
||||
|
||||
console.log('The access token has been refreshed!');
|
||||
console.log('access_token:', access_token);
|
||||
spotifyApi.setAccessToken(access_token);
|
||||
}, expires_in / 2 * 1000);
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('Error getting Tokens:', error);
|
||||
res.send(`Error getting Tokens: ${error}`);
|
||||
});
|
||||
});
|
||||
|
||||
app.listen(8888, () =>
|
||||
console.log(
|
||||
'HTTP Server up. Now go to http://localhost:8888/login in your browser.'
|
||||
)
|
||||
);
|
||||
@@ -0,0 +1,11 @@
|
||||
const SpotifyWebApi = require('../../../');
|
||||
|
||||
const spotifyApi = new SpotifyWebApi();
|
||||
spotifyApi.setAccessToken(process.env.SPOTIFY_ACCESS_TOKEN);
|
||||
|
||||
(async () => {
|
||||
const me = await spotifyApi.getMe();
|
||||
console.log(me);
|
||||
})().catch(e => {
|
||||
console.error(e);
|
||||
});
|
||||
17
spotify-web-api-node/examples/tutorial/README.md
Normal file
17
spotify-web-api-node/examples/tutorial/README.md
Normal file
@@ -0,0 +1,17 @@
|
||||
Execute all commands from the root folder of this repository.
|
||||
|
||||
Start with
|
||||
|
||||
git clone <this repo url>
|
||||
cd spotify-web-api-node
|
||||
npm install
|
||||
npm install express
|
||||
node examples/tutorial/00-get-access-token.js "<Client ID>" "<Client Secret>"
|
||||
|
||||
and visit <http://localhost:8888/login> in your browser to get an `access_token`.
|
||||
If you don't have a `client_id` and `client_secret` yet, create an application here: <https://developer.spotify.com/my-applications> to get them. Make sure you whitelist the correct redirectUri when creating your application, which is `http://localhost:8888/callback`.
|
||||
|
||||
After you got the `access_token`, call all other examples with this token in ENV variable `SPOTIFY_ACCESS_TOKEN`. The easiest way is to call:
|
||||
|
||||
export SPOTIFY_ACCESS_TOKEN="<Token content here>"
|
||||
node examples/tutorial/01-basics/01-get-info-about-current-user.js
|
||||
@@ -1,14 +1,14 @@
|
||||
{
|
||||
"name": "spotify-web-api-node-plus",
|
||||
"version": "7.0.1",
|
||||
"homepage": "https://github.com/manhbi18112005/spotify-web-api-node-plus",
|
||||
"name": "spotify-web-api-node",
|
||||
"version": "5.0.3",
|
||||
"homepage": "https://github.com/thelinmichael/spotify-web-api-node",
|
||||
"description": "A Node.js wrapper for Spotify's Web API",
|
||||
"main": "./src/server.js",
|
||||
"author": "Michael Thelin",
|
||||
"contributors": [
|
||||
{
|
||||
"name": "Le Ngo Duc Manh",
|
||||
"url": "https://github.com/manhbi18112005"
|
||||
"name": "José M. Perez",
|
||||
"url": "https://github.com/JMPerez"
|
||||
},
|
||||
{
|
||||
"name": "Deeplydrumming",
|
||||
@@ -18,20 +18,16 @@
|
||||
"license": "MIT",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/manhbi18112005/spotify-web-api-node-plus.git"
|
||||
"url": "https://github.com/thelinmichael/spotify-web-api-node.git"
|
||||
},
|
||||
"scripts": {
|
||||
"test": "jest",
|
||||
"travis": "npm test -- --coverage && cat ./coverage/lcov.info | ./node_modules/coveralls/bin/coveralls.js",
|
||||
"precommit": "lint-staged",
|
||||
"prettier": "prettier . --write"
|
||||
"precommit": "lint-staged"
|
||||
},
|
||||
"jest": {
|
||||
"verbose": true,
|
||||
"testURL": "http://localhost/",
|
||||
"setupFiles": [
|
||||
"./setupJest.js"
|
||||
]
|
||||
"testURL": "http://localhost/"
|
||||
},
|
||||
"lint-staged": {
|
||||
"*.{js,json,css,md}": [
|
||||
@@ -39,15 +35,24 @@
|
||||
"git add"
|
||||
]
|
||||
},
|
||||
"dependencies": {
|
||||
"superagent": "^6.1.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"coveralls": "^3.1.0",
|
||||
"husky": "^4.3.0",
|
||||
"jest": "^26.6.3",
|
||||
"jest-fetch-mock": "^3.0.3",
|
||||
"jest-resolve": "^26.6.2",
|
||||
"lint-staged": "^10.4.0",
|
||||
"node-fetch": "^2.6.12",
|
||||
"prettier": "^2.1.2"
|
||||
"prettier": "^2.1.2",
|
||||
"sinon": "^9.0.3",
|
||||
"canvas": "^2.6.1",
|
||||
"bufferutil": "^4.0.1",
|
||||
"utf-8-validate": "^5.0.2",
|
||||
"jest-resolve": "^26.6.2",
|
||||
"minimist": "^1.2.5",
|
||||
"set-value": ">=2.0.1",
|
||||
"mixin-deep": ">=1.3.2",
|
||||
"ini": ">=1.3.6"
|
||||
},
|
||||
"keywords": [
|
||||
"spotify",
|
||||
@@ -60,20 +65,5 @@
|
||||
],
|
||||
"browser": {
|
||||
"./src/server.js": "./src/client.js"
|
||||
},
|
||||
"files": [
|
||||
"./src",
|
||||
"./LICENSE",
|
||||
"./package.json",
|
||||
"./README.md",
|
||||
"./CHANGELOG.md"
|
||||
],
|
||||
"prettier": {
|
||||
"trailingComma": "none",
|
||||
"tabWidth": 2,
|
||||
"semi": true,
|
||||
"singleQuote": true,
|
||||
"bracketSpacing": true,
|
||||
"arrowParens": "avoid"
|
||||
}
|
||||
}
|
||||
@@ -12,7 +12,6 @@ const Request = function (builder) {
|
||||
this.bodyParameters = builder.bodyParameters
|
||||
this.headers = builder.headers
|
||||
this.path = builder.path
|
||||
this.timeout = builder.timeout
|
||||
}
|
||||
|
||||
Request.prototype._getter = function (key) {
|
||||
@@ -39,8 +38,6 @@ Request.prototype.getBodyParameters = Request.prototype._getter(
|
||||
|
||||
Request.prototype.getHeaders = Request.prototype._getter('headers')
|
||||
|
||||
Request.prototype.getTimeout = Request.prototype._getter('timeout')
|
||||
|
||||
Request.prototype.getURI = function () {
|
||||
if (!this.scheme || !this.host || !this.port) {
|
||||
throw new Error('Missing components necessary to construct URI')
|
||||
@@ -139,8 +136,6 @@ Builder.prototype.withBodyParameters = Builder.prototype._assigner(
|
||||
|
||||
Builder.prototype.withHeaders = Builder.prototype._assigner('headers')
|
||||
|
||||
Builder.prototype.withTimeout = Builder.prototype._setter('timeout')
|
||||
|
||||
Builder.prototype.withAuth = function (accessToken) {
|
||||
if (accessToken) {
|
||||
this.withHeaders({ Authorization: 'Bearer ' + accessToken })
|
||||
134
spotify-web-api-node/src/http-manager.js
Normal file
134
spotify-web-api-node/src/http-manager.js
Normal file
@@ -0,0 +1,134 @@
|
||||
'use strict'
|
||||
|
||||
const superagent = require('superagent')
|
||||
const {
|
||||
TimeoutError,
|
||||
WebapiError,
|
||||
WebapiRegularError,
|
||||
WebapiAuthenticationError,
|
||||
WebapiPlayerError
|
||||
} = require('./response-error')
|
||||
|
||||
const HttpManager = {}
|
||||
|
||||
/* Create superagent options from the base request */
|
||||
const _getParametersFromRequest = function (request) {
|
||||
const options = {}
|
||||
|
||||
if (request.getQueryParameters()) {
|
||||
options.query = request.getQueryParameters()
|
||||
}
|
||||
|
||||
if (request.getHeaders() && request.getHeaders()['Content-Type'] === 'application/json') {
|
||||
options.data = JSON.stringify(request.getBodyParameters())
|
||||
} else if (request.getBodyParameters()) {
|
||||
options.data = request.getBodyParameters()
|
||||
}
|
||||
|
||||
if (request.getHeaders()) {
|
||||
options.headers = request.getHeaders()
|
||||
}
|
||||
return options
|
||||
}
|
||||
|
||||
const _toError = function (response) {
|
||||
if (typeof response.body === 'object' && response.body.error && typeof response.body.error === 'object' && response.body.error.reason) {
|
||||
return new WebapiPlayerError(response.body, response.headers, response.statusCode)
|
||||
}
|
||||
|
||||
if (typeof response.body === 'object' && response.body.error && typeof response.body.error === 'object') {
|
||||
return new WebapiRegularError(response.body, response.headers, response.statusCode)
|
||||
}
|
||||
|
||||
if (typeof response.body === 'object' && response.body.error && typeof response.body.error === 'string') {
|
||||
return new WebapiAuthenticationError(response.body, response.headers, response.statusCode)
|
||||
}
|
||||
|
||||
/* Other type of error, or unhandled Web API error format */
|
||||
return new WebapiError(response.body, response.headers, response.statusCode, response.body)
|
||||
}
|
||||
|
||||
/* Make the request to the Web API */
|
||||
HttpManager._makeRequest = function (method, options, uri, callback) {
|
||||
const req = method.bind(superagent)(uri)
|
||||
|
||||
if (options.query) {
|
||||
req.query(options.query)
|
||||
}
|
||||
|
||||
if (options.headers) {
|
||||
req.set(options.headers)
|
||||
}
|
||||
|
||||
if (options.data) {
|
||||
req.send(options.data)
|
||||
}
|
||||
|
||||
req.end(function (err, response) {
|
||||
if (err) {
|
||||
if (err.timeout) {
|
||||
return callback(new TimeoutError())
|
||||
} else if (err.response) {
|
||||
return callback(_toError(err.response))
|
||||
} else {
|
||||
return callback(err)
|
||||
}
|
||||
}
|
||||
|
||||
return callback(null, {
|
||||
body: response.body,
|
||||
headers: response.headers,
|
||||
statusCode: response.statusCode
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* Make a HTTP GET request.
|
||||
* @param {BaseRequest} The request.
|
||||
* @param {Function} The callback function.
|
||||
*/
|
||||
HttpManager.get = function (request, callback) {
|
||||
const options = _getParametersFromRequest(request)
|
||||
const method = superagent.get
|
||||
|
||||
HttpManager._makeRequest(method, options, request.getURI(), callback)
|
||||
}
|
||||
|
||||
/**
|
||||
* Make a HTTP POST request.
|
||||
* @param {BaseRequest} The request.
|
||||
* @param {Function} The callback function.
|
||||
*/
|
||||
HttpManager.post = function (request, callback) {
|
||||
const options = _getParametersFromRequest(request)
|
||||
const method = superagent.post
|
||||
|
||||
HttpManager._makeRequest(method, options, request.getURI(), callback)
|
||||
}
|
||||
|
||||
/**
|
||||
* Make a HTTP DELETE request.
|
||||
* @param {BaseRequest} The request.
|
||||
* @param {Function} The callback function.
|
||||
*/
|
||||
HttpManager.del = function (request, callback) {
|
||||
const options = _getParametersFromRequest(request)
|
||||
const method = superagent.del
|
||||
|
||||
HttpManager._makeRequest(method, options, request.getURI(), callback)
|
||||
}
|
||||
|
||||
/**
|
||||
* Make a HTTP PUT request.
|
||||
* @param {BaseRequest} The request.
|
||||
* @param {Function} The callback function.
|
||||
*/
|
||||
HttpManager.put = function (request, callback) {
|
||||
const options = _getParametersFromRequest(request)
|
||||
const method = superagent.put
|
||||
|
||||
HttpManager._makeRequest(method, options, request.getURI(), callback)
|
||||
}
|
||||
|
||||
module.exports = HttpManager
|
||||
@@ -7,8 +7,7 @@ class NamedError extends Error {
|
||||
|
||||
class TimeoutError extends NamedError {
|
||||
constructor () {
|
||||
const message =
|
||||
"A timeout occurred while communicating with Spotify's Web API."
|
||||
const message = 'A timeout occurred while communicating with Spotify\'s Web API.'
|
||||
super(message)
|
||||
}
|
||||
}
|
||||
@@ -29,11 +28,8 @@ class WebapiError extends NamedError {
|
||||
*/
|
||||
class WebapiRegularError extends WebapiError {
|
||||
constructor (body, headers, statusCode) {
|
||||
const message =
|
||||
"An error occurred while communicating with Spotify's Web API.\n" +
|
||||
'Details: ' +
|
||||
body.error.message +
|
||||
'.'
|
||||
const message = 'An error occurred while communicating with Spotify\'s Web API.\n' +
|
||||
'Details: ' + body.error.message + '.'
|
||||
|
||||
super(body, headers, statusCode, message)
|
||||
}
|
||||
@@ -45,11 +41,8 @@ class WebapiRegularError extends WebapiError {
|
||||
*/
|
||||
class WebapiAuthenticationError extends WebapiError {
|
||||
constructor (body, headers, statusCode) {
|
||||
const message =
|
||||
"An authentication error occurred while communicating with Spotify's Web API.\n" +
|
||||
'Details: ' +
|
||||
body.error +
|
||||
(body.error_description ? ' ' + body.error_description + '.' : '.')
|
||||
const message = 'An authentication error occurred while communicating with Spotify\'s Web API.\n' +
|
||||
'Details: ' + body.error + (body.error_description ? ' ' + body.error_description + '.' : '.')
|
||||
|
||||
super(body, headers, statusCode, message)
|
||||
}
|
||||
@@ -61,20 +54,11 @@ class WebapiAuthenticationError extends WebapiError {
|
||||
*/
|
||||
class WebapiPlayerError extends WebapiError {
|
||||
constructor (body, headers, statusCode) {
|
||||
const message =
|
||||
"An error occurred while communicating with Spotify's Web API.\n" +
|
||||
'Details: ' +
|
||||
body.error.message +
|
||||
(body.error.reason ? ' ' + body.error.reason + '.' : '.')
|
||||
const message = 'An error occurred while communicating with Spotify\'s Web API.\n' +
|
||||
'Details: ' + body.error.message + (body.error.reason ? ' ' + body.error.reason + '.' : '.')
|
||||
|
||||
super(body, headers, statusCode, message)
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
WebapiError,
|
||||
TimeoutError,
|
||||
WebapiRegularError,
|
||||
WebapiAuthenticationError,
|
||||
WebapiPlayerError
|
||||
}
|
||||
module.exports = { WebapiError, TimeoutError, WebapiRegularError, WebapiAuthenticationError, WebapiPlayerError }
|
||||
@@ -4,6 +4,7 @@ const AuthenticationRequest = require('./authentication-request')
|
||||
const HttpManager = require('./http-manager')
|
||||
|
||||
module.exports = {
|
||||
|
||||
/**
|
||||
* Retrieve a URL where the user can give the application permissions.
|
||||
* @param {string[]} scopes The scopes corresponding to the permissions the application needs.
|
||||
@@ -12,12 +13,7 @@ module.exports = {
|
||||
* @param {string} responseType An optional parameter that you can use to specify the code response based on the authentication type - can be set to 'code' or 'token'. Default 'code' to ensure backwards compatability.
|
||||
* @returns {string} The URL where the user can give application permissions.
|
||||
*/
|
||||
createAuthorizeURL: function (
|
||||
scopes,
|
||||
state,
|
||||
showDialog,
|
||||
responseType = 'code'
|
||||
) {
|
||||
createAuthorizeURL: function (scopes, state, showDialog, responseType = 'code') {
|
||||
return AuthenticationRequest.builder()
|
||||
.withPath('/authorize')
|
||||
.withQueryParameters({
|
||||
@@ -46,7 +42,11 @@ module.exports = {
|
||||
grant_type: 'client_credentials'
|
||||
})
|
||||
.withHeaders({
|
||||
Authorization: 'Basic ' + Buffer.from(this.getClientId() + ':' + this.getClientSecret()).toString('base64'),
|
||||
Authorization:
|
||||
'Basic ' +
|
||||
Buffer.from(
|
||||
this.getClientId() + ':' + this.getClientSecret()
|
||||
).toString('base64'),
|
||||
'Content-Type': 'application/x-www-form-urlencoded'
|
||||
})
|
||||
.build()
|
||||
@@ -94,7 +94,10 @@ module.exports = {
|
||||
})
|
||||
.withHeaders({
|
||||
Authorization:
|
||||
'Basic ' + Buffer.from(this.getClientId() + ':' + this.getClientSecret()).toString('base64'),
|
||||
'Basic ' +
|
||||
Buffer.from(
|
||||
this.getClientId() + ':' + this.getClientSecret()
|
||||
).toString('base64'),
|
||||
'Content-Type': 'application/x-www-form-urlencoded'
|
||||
})
|
||||
.build()
|
||||
@@ -1,6 +1,6 @@
|
||||
'use strict'
|
||||
|
||||
/* const AuthenticationRequest = require('./authentication-request') */
|
||||
const AuthenticationRequest = require('./authentication-request')
|
||||
const WebApiRequest = require('./webapi-request')
|
||||
const HttpManager = require('./http-manager')
|
||||
|
||||
@@ -91,13 +91,17 @@ SpotifyWebApi.prototype = {
|
||||
},
|
||||
|
||||
_getCredential: function (credentialKey) {
|
||||
if (this._credentials) {
|
||||
if (!this._credentials) {
|
||||
|
||||
} else {
|
||||
return this._credentials[credentialKey]
|
||||
}
|
||||
},
|
||||
|
||||
_resetCredential: function (credentialKey) {
|
||||
if (this._credentials) {
|
||||
if (!this._credentials) {
|
||||
|
||||
} else {
|
||||
this._credentials[credentialKey] = null
|
||||
}
|
||||
},
|
||||
@@ -180,27 +184,6 @@ SpotifyWebApi.prototype = {
|
||||
.execute(HttpManager.get, callback)
|
||||
},
|
||||
|
||||
getPlaylistCoverImage: function (playlistId, callback) {
|
||||
return WebApiRequest.builder(this.getAccessToken())
|
||||
.withPath('/v1/playlists/' + playlistId + '/images')
|
||||
.withHeaders({ 'Content-Type': 'application/json' })
|
||||
.build()
|
||||
.execute(HttpManager.get, callback)
|
||||
},
|
||||
|
||||
/** Get available markets that Spotify support
|
||||
* @param {requestCallback} callback
|
||||
* @returns {Promise|undefined} A promise that if successful, returns an object containing the user's devices. Not returned if a callback is given.
|
||||
*/
|
||||
getAvailableMarkets: function (callback) {
|
||||
const path = '/v1/markets'
|
||||
return WebApiRequest.builder(this.getAccessToken())
|
||||
.withPath(path)
|
||||
.withHeaders({ 'Content-Type': 'application/json' })
|
||||
.build()
|
||||
.execute(HttpManager.get, callback)
|
||||
},
|
||||
|
||||
/**
|
||||
* Look up an artist.
|
||||
* @param {string} artistId The artist's ID.
|
||||
@@ -496,12 +479,9 @@ SpotifyWebApi.prototype = {
|
||||
return WebApiRequest.builder(this.getAccessToken())
|
||||
.withPath('/v1/me/playlists')
|
||||
.withHeaders({ 'Content-Type': 'application/json' })
|
||||
.withBodyParameters(
|
||||
{
|
||||
name
|
||||
},
|
||||
options
|
||||
)
|
||||
.withBodyParameters({
|
||||
name
|
||||
}, options)
|
||||
.build()
|
||||
.execute(HttpManager.post, callback)
|
||||
},
|
||||
@@ -574,16 +554,16 @@ SpotifyWebApi.prototype = {
|
||||
},
|
||||
|
||||
/**
|
||||
* Add tracks to a playlist.
|
||||
* @param {string} playlistId The playlist's ID
|
||||
* @param {string[]} tracks URIs of the tracks to add to the playlist.
|
||||
* @param {Object} [options] Options, position being the only one.
|
||||
* @param {requestCallback} [callback] Optional callback method to be called instead of the promise.
|
||||
* @example addTracksToPlaylist('3EsfV6XzCHU8SPNdbnFogK',
|
||||
'["spotify:track:4iV5W9uYEdYUVa79Axb7Rh", "spotify:track:1301WleyT98MSxVHPZCA6M"]').then(...)
|
||||
* @returns {Promise|undefined} A promise that if successful returns an object containing a snapshot_id. If rejected,
|
||||
* it contains an error object. Not returned if a callback is given.
|
||||
*/
|
||||
* Add tracks to a playlist.
|
||||
* @param {string} playlistId The playlist's ID
|
||||
* @param {string[]} tracks URIs of the tracks to add to the playlist.
|
||||
* @param {Object} [options] Options, position being the only one.
|
||||
* @param {requestCallback} [callback] Optional callback method to be called instead of the promise.
|
||||
* @example addTracksToPlaylist('3EsfV6XzCHU8SPNdbnFogK',
|
||||
'["spotify:track:4iV5W9uYEdYUVa79Axb7Rh", "spotify:track:1301WleyT98MSxVHPZCA6M"]').then(...)
|
||||
* @returns {Promise|undefined} A promise that if successful returns an object containing a snapshot_id. If rejected,
|
||||
* it contains an error object. Not returned if a callback is given.
|
||||
*/
|
||||
addTracksToPlaylist: function (playlistId, tracks, options, callback) {
|
||||
return WebApiRequest.builder(this.getAccessToken())
|
||||
.withPath('/v1/playlists/' + playlistId + '/tracks')
|
||||
@@ -1359,15 +1339,22 @@ SpotifyWebApi.prototype = {
|
||||
|
||||
/**
|
||||
* Check if users are following a playlist.
|
||||
* @param {String[]} followerIds IDs of the following users
|
||||
* @param {string} userId The playlist's owner's user ID
|
||||
* @param {string} playlistId The playlist's ID
|
||||
* @param {String[]} User IDs of the following users
|
||||
* @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 booleans. If rejected,
|
||||
* it contains an error object. Not returned if a callback is given.
|
||||
*/
|
||||
areFollowingPlaylist: function (playlistId, followerIds, callback) {
|
||||
areFollowingPlaylist: function (userId, playlistId, followerIds, callback) {
|
||||
return WebApiRequest.builder(this.getAccessToken())
|
||||
.withPath('/v1/playlists/' + playlistId + '/followers/contains')
|
||||
.withPath(
|
||||
'/v1/users/' +
|
||||
encodeURIComponent(userId) +
|
||||
'/playlists/' +
|
||||
playlistId +
|
||||
'/followers/contains'
|
||||
)
|
||||
.withQueryParameters({
|
||||
ids: followerIds.join(',')
|
||||
})
|
||||
@@ -1542,9 +1529,7 @@ SpotifyWebApi.prototype = {
|
||||
return WebApiRequest.builder(this.getAccessToken())
|
||||
.withPath('/v1/me/shows')
|
||||
.withHeaders({ 'Content-Type': 'application/json' })
|
||||
.withQueryParameters({
|
||||
ids: showIds.join(',')
|
||||
})
|
||||
.withBodyParameters(showIds)
|
||||
.build()
|
||||
.execute(HttpManager.del, callback)
|
||||
},
|
||||
@@ -1662,21 +1647,7 @@ SpotifyWebApi.prototype = {
|
||||
)
|
||||
.build()
|
||||
.execute(HttpManager.get, callback)
|
||||
},
|
||||
|
||||
/** Get current Queue
|
||||
* @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 information
|
||||
* about the episodes. Not returned if a callback is given.
|
||||
*/
|
||||
|
||||
getQueue: function (callback) {
|
||||
return WebApiRequest.builder(this.getAccessToken())
|
||||
.withPath('/v1/me/player/queue')
|
||||
.build()
|
||||
.execute(HttpManager.get, callback)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
SpotifyWebApi._addMethods = function (methods) {
|
||||
@@ -37,6 +37,10 @@
|
||||
|
||||
<h2>Changelog</h2>
|
||||
<ul class="no-dots" style="font-size: 15px;">
|
||||
<h3>31/07/2024</h3>
|
||||
- Reverted to spotify-web-api-node<br>
|
||||
- Fixed (again) the Buffer method in spotify-web-api-node<br>
|
||||
<br>
|
||||
<h3>26/07/2024</h3>
|
||||
- Moved all scripts to pnpm<br>
|
||||
- Fixed a few dependencies<br>
|
||||
@@ -128,7 +132,7 @@
|
||||
</span>
|
||||
</h2>
|
||||
<ul>
|
||||
<!-- <li>
|
||||
<!-- <li>
|
||||
{{ $t('about.acceptFeatures') }}
|
||||
</li> -->
|
||||
<i18n path="about.contributeWebUI.text" tag="li">
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<template>
|
||||
<div id="home_tab">
|
||||
<h1 class="mb-8 text-5xl">{{ $t('globals.welcome') }}</h1>
|
||||
Version published 26/07/2024, see About section for changelog.
|
||||
Version published 31/07/2024, see About section for changelog.
|
||||
<section v-if="!isLoggedIn" ref="notLogged" class="py-6 border-0 border-t border-solid border-grayscale-500">
|
||||
<p id="home_not_logged_text" class="mb-4">{{ $t('home.needTologin') }}</p>
|
||||
<router-link custom v-slot="{ navigate }" class="btn btn-primary" name="button" :to="{ name: 'Settings' }">
|
||||
|
||||
Reference in New Issue
Block a user