From 2f0375fb5d52dd16cdcc204d10af119bdc1207ee Mon Sep 17 00:00:00 2001 From: Lucas Augusto Deters Date: Wed, 4 Apr 2018 00:20:30 -0300 Subject: [PATCH 01/22] Playlist manipulation - prototype --- lib/client.js | 119 +++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 117 insertions(+), 2 deletions(-) diff --git a/lib/client.js b/lib/client.js index bc818c5..8faf1d9 100644 --- a/lib/client.js +++ b/lib/client.js @@ -278,6 +278,42 @@ TidalAPI.prototype.getPlaylistTracks = function (query, callback){ countryCode: _countryCode }, 'albums', callback); } +/** +* Get user playlists +* @param {{id: String, limit: Number, filter: String, offset: Number}} +*/ +TidalAPI.prototype.getUserPlaylists = function (user, callback){ + var self = this; + self._baseRequest('/users/' + user + '/playlists', { + limit: 9999, + countryCode: _countryCode + }, '', callback); +} + +/** +* Add tracks to a playlist. +* @param {{id: String, limit: Number, filter: String, offset: Number}} +*/ +TidalAPI.prototype.addPlaylistTracks = function (playlist, tracks, etag, callback){ + var self = this; + self._basePost('/playlists/' + playlist + '/items', { + countryCode: _countryCode + }, {trackIds: tracks, toIndex: 0}, 'playlists', etag, callback); +} + +/** +* Delete tracks from a playlist, based on their positions +* @param {{id: String, limit: Number, filter: String, offset: Number}} +*/ +TidalAPI.prototype.deletePlaylistTracks = function (playlist, tracks, etag, callback){ + var self = this; + self._baseDelete('/playlists/' + playlist + '/items/'+tracks, { + countryCode: _countryCode, + orderDirection: 'ASC', + order: 'INDEX' + }, {/*trackIds: tracks, toIndex: 1*/}, '', etag, callback); +} + /** * Get track info. * @param {{id: Number, quality: String}} @@ -409,10 +445,89 @@ TidalAPI.prototype._baseRequest = function(method, params, type, callback) { if(params.types.indexOf('playlists') > -1) { newBody['playlists'] = body.playlists; } - callback(newBody); + callback(newBody, res.headers); } else - callback(body); + callback(body, res.headers); + }); +} + + + +/** +* Base delete function. +* @param {{method: String, params: Object, type: String, callback: Function}} +*/ +TidalAPI.prototype._baseDelete = function(method, params, formdata, type, etag, callback) { + var self = this; + + if (!loggedIn) { + return tryLogin(this.authData, function() { + self._baseRequest(method, params, type, callback); + }); + } + + params.countryCode = params.countryCode ? params.countryCode : _countryCode; + request({ + method: 'DELETE', + uri: method, + headers: { + 'Origin': 'https://listen.tidal.com', + 'If-None-Match': etag, + 'X-Tidal-SessionId': _sessionID + }, + form: formdata + }, function(err, res, data) { + if(!err){ + if (data && res && res.statusCode !== 200 || err) { + throw new Error(data) + } + //data = JSON.parse(data); + if (callback) { + callback(data); + } + } }); + + +} + + +/** +* Base post function. +* @param {{method: String, params: Object, type: String, callback: Function}} +*/ +TidalAPI.prototype._basePost = function(method, params, formdata, type, etag, callback) { + var self = this; + + if (!loggedIn) { + return tryLogin(this.authData, function() { + self._baseRequest(method, params, type, callback); + }); + } + params.countryCode = params.countryCode ? params.countryCode : _countryCode; + + request({ + method: 'POST', + uri: method, + headers: { + 'Origin': 'https://listen.tidal.com', + 'If-None-Match': etag, + 'X-Tidal-SessionId': _sessionID + }, + form: formdata + }, function(err, res, data) { + if(!err){ + if (data && res && res.statusCode !== 200 || err) { + throw new Error(data) + } + //data = JSON.parse(data); + if (callback) { + callback(data); + } + } + }); + + } module.exports = TidalAPI; From 5631442dfa66580cad95d5a8e99819f1e677ca44 Mon Sep 17 00:00:00 2001 From: Lucas Augusto Deters Date: Wed, 4 Apr 2018 10:46:49 -0300 Subject: [PATCH 02/22] Promisifying --- lib/client.js | 558 ++++++++++++++++++++++++-------------------------- package.json | 3 +- 2 files changed, 274 insertions(+), 287 deletions(-) diff --git a/lib/client.js b/lib/client.js index 93b0d86..f186866 100644 --- a/lib/client.js +++ b/lib/client.js @@ -3,8 +3,8 @@ //Node.js modules -var request = require('request').defaults({ - baseUrl: 'https://api.tidalhifi.com/v1' +var request = require('request-promise-native').defaults({ + baseUrl: 'https://api.tidalhifi.com/v1' }); /** @@ -63,26 +63,25 @@ var loggedIn = false; var authData = {}; /** -* Create TidalAPI instance -* @param {{username: String, password: String, token: String, quality: String}} -* @Constructor -*/ + * Create TidalAPI instance + * @param {{username: String, password: String, token: String, quality: String}} + * @Constructor + */ function TidalAPI(authData) { - if(typeof authData !== 'object') - { + if (typeof authData !== 'object') { throw new Error('You must pass auth data into the TidalAPI object correctly'); } else { - if(typeof authData.username !== 'string') { + if (typeof authData.username !== 'string') { throw new Error('Username invalid or missing'); } - if(typeof authData.password !== 'string') { + if (typeof authData.password !== 'string') { throw new Error('Password invalid or missing'); } - if(typeof authData.token !== 'string') { + if (typeof authData.token !== 'string') { throw new Error('Token invalid or missing'); } - if(typeof authData.quality !== 'string') { + if (typeof authData.quality !== 'string') { throw new Error('Stream quality invalid or missing'); } } @@ -94,16 +93,16 @@ function TidalAPI(authData) { } /** -* Try login using credentials. -* @param {{username: String, password: String}} -*/ -function tryLogin(authInfo, cb) { + * Try login using credentials. + * @param {{username: String, password: String}} + */ +function tryLogin(authInfo) { /** - * Logging? - * @type {boolean} - */ + * Logging? + * @type {boolean} + */ var loggingIn = true; - request({ + return request({ method: 'POST', uri: '/login/username', headers: { @@ -114,11 +113,7 @@ function tryLogin(authInfo, cb) { password: authInfo.password, clientUniqueKey: "vjknfvjbnjhbgjhbbg" } - }, function(err, res, data) { - if(!err){ - if (data && res && res.statusCode !== 200 || err) { - throw new Error(data) - } + }).then( (data) => { data = JSON.parse(data); _sessionID = data.sessionId; _userID = data.userId; @@ -126,254 +121,254 @@ function tryLogin(authInfo, cb) { _streamQuality = authInfo.quality; loggingIn = false; loggedIn = true; - if (cb) { - cb(); - } - } + return data; }); } /** -* Return userID. -*/ -TidalAPI.prototype.getMyID = function () { + * Return userID. + */ +TidalAPI.prototype.getMyID = function() { return _userID; } /** -* Global search. -* @param {{query: String, limit: Number, types: String, offset: Number}} -*/ -TidalAPI.prototype.search = function (query, callback) { + * Global search. + * @param {{query: String, limit: Number, types: String, offset: Number}} + */ +TidalAPI.prototype.search = function(query) { var self = this; - self._baseRequest('/search', { - query: query.query || query, - limit: query.limit || 999, - types: query.type || 'ARTISTS,ALBUMS,TRACKS,VIDEOS,PLAYLISTS', - offset: query.offset || 0, - countryCode: _countryCode - }, 'search', callback); + return self._baseRequest('/search', { + query: query.query || query, + limit: query.limit || 999, + types: query.type || 'ARTISTS,ALBUMS,TRACKS,VIDEOS,PLAYLISTS', + offset: query.offset || 0, + countryCode: _countryCode + }, 'search'); } /** -* Get artist info. -* @param {{id: Number, limit: Number, filter: String, offset: Number}} -*/ -TidalAPI.prototype.getArtist = function (query, callback) { + * Get artist info. + * @param {{id: Number, limit: Number, filter: String, offset: Number}} + */ +TidalAPI.prototype.getArtist = function(query) { var self = this; - self._baseRequest('/artists/' + (query.id || query), { - limit: query.limit || 999, - filter: query.filter || 'ALL', - offset: query.offset || 0, - countryCode: _countryCode - }, 'artist', callback); + return self._baseRequest('/artists/' + (query.id || query), { + limit: query.limit || 999, + filter: query.filter || 'ALL', + offset: query.offset || 0, + countryCode: _countryCode + }, 'artist'); } /** -* Get artist top tracks. -* @param {{id: Number, limit: Number, filter: String, offset: Number}} -*/ -TidalAPI.prototype.getTopTracks = function (query, callback) { + * Get artist top tracks. + * @param {{id: Number, limit: Number, filter: String, offset: Number}} + */ +TidalAPI.prototype.getTopTracks = function(query) { var self = this; - self._baseRequest('/artists/' + (query.id || query) + '/toptracks', { - limit: query.limit || 999, - filter: query.filter || 'ALL', - offset: query.offset || 0, - countryCode: _countryCode - }, 'toptracks', callback); + return self._baseRequest('/artists/' + (query.id || query) + '/toptracks', { + limit: query.limit || 999, + filter: query.filter || 'ALL', + offset: query.offset || 0, + countryCode: _countryCode + }, 'toptracks'); } /** -* Get artist videos. -* @param {{id: Number, limit: Number, filter: String, offset: Number}} -*/ -TidalAPI.prototype.getArtistVideos = function (query, callback) { + * Get artist videos. + * @param {{id: Number, limit: Number, filter: String, offset: Number}} + */ +TidalAPI.prototype.getArtistVideos = function(query) { var self = this; - self._baseRequest('/artists/' + (query.id || query) + '/videos', { - limit: query.limit || 999, - filter: query.filter || 'ALL', - offset: query.offset || 0, - countryCode: _countryCode - }, 'videos', callback); + return self._baseRequest('/artists/' + (query.id || query) + '/videos', { + limit: query.limit || 999, + filter: query.filter || 'ALL', + offset: query.offset || 0, + countryCode: _countryCode + }, 'videos'); } /** -* Get artist bio. -* @param {{id: Number}} -*/ -TidalAPI.prototype.getArtistBio = function (query, callback) { + * Get artist bio. + * @param {{id: Number}} + */ +TidalAPI.prototype.getArtistBio = function(query) { var self = this; - self._baseRequest('/artists/' + (query.id || query) + '/bio', { - countryCode: _countryCode - }, 'bio', callback); + return self._baseRequest('/artists/' + (query.id || query) + '/bio', { + countryCode: _countryCode + }, 'bio'); } /** -* Get similar artists. -* @param {{id: Number, limit: Number, filter: String, offset: Number}} -*/ -TidalAPI.prototype.getSimilarArtists = function (query, callback) { + * Get similar artists. + * @param {{id: Number, limit: Number, filter: String, offset: Number}} + */ +TidalAPI.prototype.getSimilarArtists = function(query) { var self = this; - self._baseRequest('/artists/' + (query.id || query) + '/similar', { - limit: query.limit || 999, - filter: query.filter || 'ALL', - offset: query.offset || 0, - countryCode: _countryCode - }, 'similar', callback); + return self._baseRequest('/artists/' + (query.id || query) + '/similar', { + limit: query.limit || 999, + filter: query.filter || 'ALL', + offset: query.offset || 0, + countryCode: _countryCode + }, 'similar'); } /** -* Get artist albums. -* @param {{id: Number, limit: Number, filter: String, offset: Number}} -*/ -TidalAPI.prototype.getArtistAlbums = function (query, callback) { + * Get artist albums. + * @param {{id: Number, limit: Number, filter: String, offset: Number}} + */ +TidalAPI.prototype.getArtistAlbums = function(query) { var self = this; - self._baseRequest('/artists/' + (query.id || query) + '/albums', { - limit: query.limit || 999, - filter: query.filter || 'ALL', - offset: query.offset || 0, - countryCode: _countryCode - }, 'albums', callback); + return self._baseRequest('/artists/' + (query.id || query) + '/albums', { + limit: query.limit || 999, + filter: query.filter || 'ALL', + offset: query.offset || 0, + countryCode: _countryCode + }, 'albums'); } /** -* Get album info. -* @param {{id: Number, limit: Number, filter: String, offset: Number}} -*/ -TidalAPI.prototype.getAlbum = function (query, callback) { + * Get album info. + * @param {{id: Number, limit: Number, filter: String, offset: Number}} + */ +TidalAPI.prototype.getAlbum = function(query) { var self = this; - self._baseRequest('/albums/' + (query.id || query), { - limit: query.limit || 999, - filter: query.filter || 'ALL', - offset: query.offset || 0, - countryCode: _countryCode - }, 'album', callback); + return self._baseRequest('/albums/' + (query.id || query), { + limit: query.limit || 999, + filter: query.filter || 'ALL', + offset: query.offset || 0, + countryCode: _countryCode + }, 'album'); } /** -* Get album tracks. -* @param {{id: Number, limit: Number, filter: String, offset: Number}} -*/ -TidalAPI.prototype.getAlbumTracks = function (query, callback) { + * Get album tracks. + * @param {{id: Number, limit: Number, filter: String, offset: Number}} + */ +TidalAPI.prototype.getAlbumTracks = function(query) { var self = this; - self._baseRequest('/albums/' + (query.id || query) + '/tracks', { - limit: query.limit || 999, - filter: query.filter || 'ALL', - offset: query.offset || 0, - countryCode: _countryCode - }, 'albums', callback); + return self._baseRequest('/albums/' + (query.id || query) + '/tracks', { + limit: query.limit || 999, + filter: query.filter || 'ALL', + offset: query.offset || 0, + countryCode: _countryCode + }, 'albums'); } /** -* Get playlist info. -* @param {{id: String, limit: Number, filter: String, offset: Number}} -*/ -TidalAPI.prototype.getPlaylist = function (query, callback){ + * Get playlist info. + * @param {{id: String, limit: Number, filter: String, offset: Number}} + */ +TidalAPI.prototype.getPlaylist = function(query) { var self = this; - self._baseRequest('/playlists/' + (query.id || query), { - limit: query.limit || 999, - filter: query.filter || 'ALL', - offset: query.offset || 0, - countryCode: _countryCode - }, 'album', callback); + return self._baseRequest('/playlists/' + (query.id || query), { + limit: query.limit || 999, + filter: query.filter || 'ALL', + offset: query.offset || 0, + countryCode: _countryCode + }, 'album'); } /** -* Get tracks from a playlist. -* @param {{uuid: String, limit: Number, filter: String, offset: Number}} -*/ -TidalAPI.prototype.getPlaylistTracks = function (query, callback){ + * Get tracks from a playlist. + * @param {{uuid: String, limit: Number, filter: String, offset: Number}} + */ +TidalAPI.prototype.getPlaylistTracks = function(query) { var self = this; - self._baseRequest('/playlists/' + (query.uuid || query) + '/tracks', { - limit: query.limit || 999, - filter: query.filter || 'ALL', - offset: query.offset || 0, - countryCode: _countryCode - }, 'albums', callback); + return self._baseRequest('/playlists/' + (query.uuid || query) + '/tracks', { + limit: query.limit || 999, + filter: query.filter || 'ALL', + offset: query.offset || 0, + countryCode: _countryCode + }, 'albums'); } /** -* Add tracks to a playlist. -* @param {{uuid: String, trackIds: List, toIndex: Number}} -*/ -TidalAPI.prototype.addPlaylistTracks = function (data, callback){ + * Add tracks to a playlist. + * @param {{uuid: String, trackIds: List, toIndex: Number}} + */ +TidalAPI.prototype.addPlaylistTracks = function(data) { var self = this; - self._basePost('/playlists/' + data.uuid + '/items', { - countryCode: _countryCode - }, {trackIds: data.trackIds.join(','), toIndex: data.toIndex || 0}, 'playlists', callback); + return self._basePost('/playlists/' + data.uuid + '/items', { + countryCode: _countryCode + }, { + trackIds: data.trackIds.join(','), + toIndex: data.toIndex || 0 + }, 'playlists'); } /** -* Delete tracks from a playlist, based on their positions -* @param {{uuid: String, trackPositions: List, orderDirection: String, order: String}} -*/ -TidalAPI.prototype.deletePlaylistTracks = function (data, callback){ + * Delete tracks from a playlist, based on their positions + * @param {{uuid: String, trackPositions: List, orderDirection: String, order: String}} + */ +TidalAPI.prototype.deletePlaylistTracks = function(data) { var self = this; - self._baseDelete('/playlists/' + data.uuid + '/items/'+(data.trackPositions.join(',')), { - countryCode: _countryCode, - orderDirection: data.orderDirection || 'ASC', - order: data.order || 'INDEX' - }, {/*trackIds: tracks, toIndex: 1*/}, '', callback); + return self._baseDelete('/playlists/' + data.uuid + '/items/' + (data.trackPositions.join(',')), { + countryCode: _countryCode, + orderDirection: data.orderDirection || 'ASC', + order: data.order || 'INDEX' + }, { /*trackIds: tracks, toIndex: 1*/ }, ''); } /** -* Get track info. -* @param {{id: Number, quality: String}} -*/ -TidalAPI.prototype.getTrackInfo = function (track, callback){ + * Get track info. + * @param {{id: Number, quality: String}} + */ +TidalAPI.prototype.getTrackInfo = function(track) { var self = this; - self._baseRequest('/tracks/' + (track.id || track), { - countryCode: _countryCode - }, 'trackInfo', callback); + return self._baseRequest('/tracks/' + (track.id || track), { + countryCode: _countryCode + }, 'trackInfo'); } /** -* Get track stream URL. -* @param {{id: Number, quality: String}} -*/ -TidalAPI.prototype.getStreamURL = function (track, callback) { + * Get track stream URL. + * @param {{id: Number, quality: String}} + */ +TidalAPI.prototype.getStreamURL = function(track) { var self = this; - self._baseRequest('/tracks/' + (track.id || track) + '/streamUrl', { - soundQuality: track.quality || _streamQuality, - countryCode: _countryCode - }, 'streamURL', callback); + return self._baseRequest('/tracks/' + (track.id || track) + '/streamUrl', { + soundQuality: track.quality || _streamQuality, + countryCode: _countryCode + }, 'streamURL'); } /** -* Get track stream URL. -* @param {{id: Number, quality: String}} -*/ -TidalAPI.prototype.getOfflineURL = function (track, callback) { + * Get track stream URL. + * @param {{id: Number, quality: String}} + */ +TidalAPI.prototype.getOfflineURL = function(track) { var self = this; - self._baseRequest('/tracks/' + (track.id || track) + '/offlineUrl', { - soundQuality: track.quality || _streamQuality, - countryCode: _countryCode - }, 'streamURL', callback); + return self._baseRequest('/tracks/' + (track.id || track) + '/offlineUrl', { + soundQuality: track.quality || _streamQuality, + countryCode: _countryCode + }, 'streamURL'); } /** -* Get video stream URL. -* @param {{id: Number}} -*/ -TidalAPI.prototype.getVideoStreamURL = function (track, callback) { + * Get video stream URL. + * @param {{id: Number}} + */ +TidalAPI.prototype.getVideoStreamURL = function(track) { var self = this; - self._baseRequest('/videos/' + (track.id || track) + '/streamUrl', { - countryCode: _countryCode - }, 'streamURL', callback); + return self._baseRequest('/videos/' + (track.id || track) + '/streamUrl', { + countryCode: _countryCode + }, 'streamURL'); } /** -* Get user info. -* @param {{id: Number}} -*/ -TidalAPI.prototype.getUser = function (user, callback) { + * Get user info. + * @param {{id: Number}} + */ +TidalAPI.prototype.getUser = function(user) { var self = this; - self._baseRequest('/users/' + (user.id || user), { - limit: user.limit || 999, - offset: user.offset || 0 - }, 'user', callback); + return self._baseRequest('/users/' + (user.id || user), { + limit: user.limit || 999, + offset: user.offset || 0 + }, 'user'); } /** * Get user playlists. * @param {{id: Number}} */ -TidalAPI.prototype.getPlaylists = function (user, callback) { - var self = this; - self._baseRequest('/users/' + (user.id || user) + "/playlists", { - limit: user.limit || 999, - offset: user.offset || 0, - countryCode: _countryCode - }, 'userPlaylists', callback); +TidalAPI.prototype.getPlaylists = function(user) { + var self = this; + return self._baseRequest('/users/' + (user.id || user) + "/playlists", { + limit: user.limit || 999, + offset: user.offset || 0, + countryCode: _countryCode + }, 'userPlaylists'); } /** -* Get track stream URL. -* @param {id: String, res: Number} -*/ + * Get track stream URL. + * @param {id: String, res: Number} + */ TidalAPI.prototype.getArtURL = function(id, width, height) { width = width || 1280; @@ -381,96 +376,106 @@ TidalAPI.prototype.getArtURL = function(id, width, height) { return 'https://resources.tidal.com/images/' + id.replace(/-/g, '/') + '/' + width + 'x' + height + '.jpg'; } /** -* Generate Metaflac tags. -* @param {{id: Number}} -*/ -TidalAPI.prototype.genMetaflacTags = function(track, callback) { + * Generate Metaflac tags. + * @param {{id: Number}} + */ +TidalAPI.prototype.genMetaflacTags = function(track) { var self = this; - self.getTrackInfo({id: track.id || track}, function(data) { - self.getAlbum({id: data.album.id }, function(albumData) { + return self.getTrackInfo({ + id: track.id || track + }).then ( (data) => { + self.getAlbum({ + id: data.album.id + }).then( (albumData) => { var metaflacTag; - metaflacTag = '--remove-all-tags '; + metaflacTag = '--remove-all-tags '; metaflacTag += '--set-tag=\"ARTIST=' + data.artist.name + '\" '; metaflacTag += '--set-tag=\"TITLE=' + data.title + '\" '; metaflacTag += '--set-tag=\"ALBUM=' + data.album.title + '\" '; metaflacTag += '--set-tag=\"TRACKNUMBER=' + data.trackNumber + '\" '; metaflacTag += '--set-tag=\"COPYRIGHT=' + data.copyright + '\" '; metaflacTag += '-set-tag="DATE=' + albumData.releaseDate.split("-")[0] + '" '; - if(track.coverPath){ - metaflacTag += '--import-picture-from=' + '\"' + track.coverPath + '\" '; + if (track.coverPath) { + metaflacTag += '--import-picture-from=' + '\"' + track.coverPath + '\" '; } - if(track.songPath){ + if (track.songPath) { metaflacTag += '\"' + track.songPath + '\" '; } metaflacTag += '--add-replay-gain'; - callback(metaflacTag); + return metaflacTag; }) }); } /** -* Base request function. -* @param {{method: String, params: Object, type: String, callback: Function}} -*/ -TidalAPI.prototype._baseRequest = function(method, params, type, callback) { + * Base request function. + * @param {{method: String, params: Object, type: String}} + */ +TidalAPI.prototype._baseRequest = function(method, params, type) { var self = this; if (!loggedIn) { - return tryLogin(this.authData, function() { - self._baseRequest(method, params, type, callback); + return tryLogin(this.authData).then( () => { + + return self._baseRequest(method, params, type); }); } params.countryCode = params.countryCode ? params.countryCode : _countryCode; - request.get({ + return request.get({ uri: method, headers: { 'Origin': 'http://listen.tidal.com', 'X-Tidal-SessionId': _sessionID }, qs: params - }, function(err, res, body) { - body = JSON.parse(body); - if(params.types) { - var newBody = {}; - if(params.types.indexOf('tracks') > -1) { - newBody['tracks'] = body.tracks; - } - if(params.types.indexOf('artists') > -1) { - newBody['artists'] = body.artists; - } - if(params.types.indexOf('albums') > -1) { - newBody['albums'] = body.albums; - } - if(params.types.indexOf('videos') > -1) { - newBody['videos'] = body.videos; - } - if(params.types.indexOf('playlists') > -1) { - newBody['playlists'] = body.playlists; - } - callback(newBody, res.headers); - } else - callback(body, res.headers); - }); + }).then( (data) => { + let body = JSON.parse(data); + if (params.types) { + var newBody = {}; + if (params.types.indexOf('tracks') > -1) { + newBody['tracks'] = body.tracks; + } + if (params.types.indexOf('artists') > -1) { + newBody['artists'] = body.artists; + } + if (params.types.indexOf('albums') > -1) { + newBody['albums'] = body.albums; + } + if (params.types.indexOf('videos') > -1) { + newBody['videos'] = body.videos; + } + if (params.types.indexOf('playlists') > -1) { + newBody['playlists'] = body.playlists; + } + return newBody; + } else { + return body; + } + }) + } /** -* Base delete function. -* @param {{method: String, params: Object, type: String, callback: Function}} -*/ -TidalAPI.prototype._baseDelete = function(method, params, formdata, type, callback) { + * Base delete function. + * @param {{method: String, params: Object, type: String}} + */ +TidalAPI.prototype._baseDelete = function(method, params, formdata) { var self = this; if (!loggedIn) { - return tryLogin(this.authData, function() { - self._baseRequest(method, params, type, callback); - }); + + return tryLogin(this.authData) + .then(() => { + return self._baseDelete(method, params, formdata, type); + }) + } params.countryCode = params.countryCode ? params.countryCode : _countryCode; - request({ + return request({ method: 'DELETE', uri: method, headers: { @@ -479,37 +484,29 @@ TidalAPI.prototype._baseDelete = function(method, params, formdata, type, callba 'X-Tidal-SessionId': _sessionID }, form: formdata - }, function(err, res, data) { - if(!err){ - if (data && res && res.statusCode !== 200 || err) { - throw new Error(data) - } - //data = JSON.parse(data); - if (callback) { - callback(data); - } - } - }); - - + }) } /** -* Base post function. -* @param {{method: String, params: Object, type: String, callback: Function}} -*/ -TidalAPI.prototype._basePost = function(method, params, formdata, type, callback) { + * Base post function. + * @param {{method: String, params: Object}} + */ +TidalAPI.prototype._basePost = function(method, params, formdata) { var self = this; if (!loggedIn) { - return tryLogin(this.authData, function() { - self._baseRequest(method, params, type, callback); - }); + + return tryLogin(this.authData) + .then(() => { + return self._basePost(method, params, formdata); + }) + } + params.countryCode = params.countryCode ? params.countryCode : _countryCode; - request({ + return request({ method: 'POST', uri: method, headers: { @@ -518,18 +515,7 @@ TidalAPI.prototype._basePost = function(method, params, formdata, type, callback 'X-Tidal-SessionId': _sessionID }, form: formdata - }, function(err, res, data) { - if(!err){ - if (data && res && res.statusCode !== 200 || err) { - throw new Error(data) - } - //data = JSON.parse(data); - if (callback) { - callback(data); - } - } - }); - + }) } diff --git a/package.json b/package.json index ce4619a..d4fd23f 100644 --- a/package.json +++ b/package.json @@ -24,7 +24,8 @@ }, "homepage": "https://github.com/lucaslg26/TidalAPI#readme", "dependencies": { - "request": "^2.69.0" + "request": "^2.69.0", + "request-promise-native": "^1.0.5" }, "devDependencies": { "mocha": "^2.4.5" From ee665fb3c14f3c6b788b4ce2894dc1ae2dca9879 Mon Sep 17 00:00:00 2001 From: Lucas Augusto Deters Date: Wed, 4 Apr 2018 12:31:56 -0300 Subject: [PATCH 03/22] Added playlist delete --- examples/.config.json | 8 +++++ examples/search.js | 79 ++++++++++++++++++++++--------------------- lib/client.js | 60 +++++++++++++++++++++++++------- 3 files changed, 97 insertions(+), 50 deletions(-) create mode 100644 examples/.config.json diff --git a/examples/.config.json b/examples/.config.json new file mode 100644 index 0000000..7b0ebd4 --- /dev/null +++ b/examples/.config.json @@ -0,0 +1,8 @@ +{ + "tidal": { + "username": "", + "password": "", + "token": "", + "quality": "LOSSLESS" + } +} diff --git a/examples/search.js b/examples/search.js index f95bb8c..93fa4f9 100644 --- a/examples/search.js +++ b/examples/search.js @@ -1,50 +1,53 @@ -var TidalAPI = require('../'); +let credentials = require('./.config.json'); +let TidalClient = require('./client.js'); +let api = new TidalClient(credentials.tidal); -var api = new TidalAPI({ - username: '', - password: '', - token: '_KM2HixcUBZtmktH', - clientVersion: '2.2.1--7', - quality: 'LOSSLESS' -}); +async function test_search(playlist_name, query_musics) { -api.search({type: 'artists', query: 'Dream Theater', limit: 1}, function(data){ - console.log(data.artists); -}) -api.search({type: 'albums', query: 'Dream Theater', limit: 1}, function(data){ - console.log(data.albums); -}) + api.search({type: 'artists', query: 'Dream Theater', limit: 1}).then( data => { + console.log(data.artists); + }) -api.search({type: 'tracks', query: 'Dream Theater', limit: 1}, function(data){ - console.log(data.tracks); -}) + api.search({type: 'albums', query: 'Dream Theater', limit: 1}).then( data => { + console.log(data.albums); + }) -api.search({type: 'tracks,albums,artists', query: 'Dream Theater', limit: 1}, function(data){ - console.log(data.tracks); - console.log(data.albums); - console.log(data.artists); -}) + api.search({type: 'tracks', query: 'Dream Theater', limit: 1}).then( data => { + console.log(data.tracks); + }) -api.getTrackInfo({id: 22560696 }, function(data){ - console.log(data) -}) + api.search({type: 'tracks,albums,artists', query: 'Dream Theater', limit: 1}).then( data => { + console.log(data.tracks); + console.log(data.albums); + console.log(data.artists); + }) -api.getStreamURL({id: 22560696}, function(data){ - console.log(data) -}) + api.getTrackInfo({id: 22560696 }).then( data => { + console.log(data) + }) -api.getVideoStreamURL({id: 25470315}, function(data){ - console.log(data) -}) + api.getStreamURL({id: 22560696}).then( data => { + console.log(data) + }) -console.log(api.getArtURL('24f52ab0-e7d6-414d-a650-20a4c686aa57', 1280)) //coverid + api.getVideoStreamURL({id: 25470315}).then( data => { + console.log(data) + }) -api.getArtistVideos({id: 14670, limit: 2}, function(data){ - console.log(data) -}) + console.log(api.getArtURL('24f52ab0-e7d6-414d-a650-20a4c686aa57', 1280)) //coverid -api.genMetaflacTags({id: 22560696, coverPath: './albumart.jpg', songPath: './song.flac'}, function(data){ - console.log(data) -}) + api.getArtistVideos({id: 14670, limit: 2}).then( data => { + console.log(data) + }) + + api.genMetaflacTags({id: 22560696, coverPath: './albumart.jpg', songPath: './song.flac'}).then( data => { + console.log(data) + }) + + + +} + +test_search(); diff --git a/lib/client.js b/lib/client.js index f186866..a998089 100644 --- a/lib/client.js +++ b/lib/client.js @@ -128,6 +128,15 @@ function tryLogin(authInfo) { * Return userID. */ TidalAPI.prototype.getMyID = function() { + var self = this; + + if (!loggedIn) { + return tryLogin(this.authData).then( () => { + + return self.getMyID(); + }); + } + return _userID; } /** @@ -260,11 +269,11 @@ TidalAPI.prototype.getPlaylist = function(query) { } /** * Get tracks from a playlist. - * @param {{uuid: String, limit: Number, filter: String, offset: Number}} + * @param {{playlist: { uuid : String }, limit: Number, filter: String, offset: Number}} */ TidalAPI.prototype.getPlaylistTracks = function(query) { var self = this; - return self._baseRequest('/playlists/' + (query.uuid || query) + '/tracks', { + return self._baseRequest('/playlists/' + (query.playlist.uuid || query) + '/tracks', { limit: query.limit || 999, filter: query.filter || 'ALL', offset: query.offset || 0, @@ -273,30 +282,56 @@ TidalAPI.prototype.getPlaylistTracks = function(query) { } /** - * Add tracks to a playlist. - * @param {{uuid: String, trackIds: List, toIndex: Number}} + * Create playlist. + * @param {{title: String, description: String}} + */ +TidalAPI.prototype.createPlaylist = function(data) { + var self = this; + return self._basePost('/users/'+ this.getMyID() +'/playlists', { + countryCode: _countryCode + }, { + title: data.title, + description: data.description + }).then(JSON.parse); +} + +/** + * Delete a playlist + * @param {{playlist: {uuid : String}}} + */ +TidalAPI.prototype.deletePlaylist = function(data) { + var self = this; + return self._baseDelete('/playlists/' + data.uuid, { + countryCode: _countryCode + }, {}); +} + +/** + * Add tracks to a playlist + * @param {{playlist: {uuid: String}, tracks: {id : Number}, toIndex: Number}} */ TidalAPI.prototype.addPlaylistTracks = function(data) { var self = this; - return self._basePost('/playlists/' + data.uuid + '/items', { + + return self._basePost('/playlists/' + data.playlist.uuid + '/items', { countryCode: _countryCode }, { - trackIds: data.trackIds.join(','), + trackIds: data.tracks.map(v => v.id ).join(','), toIndex: data.toIndex || 0 - }, 'playlists'); + }); } /** * Delete tracks from a playlist, based on their positions - * @param {{uuid: String, trackPositions: List, orderDirection: String, order: String}} + * @param {{playlist: {uuid : String}, trackPositions: List, orderDirection: String, order: String}} */ TidalAPI.prototype.deletePlaylistTracks = function(data) { var self = this; - return self._baseDelete('/playlists/' + data.uuid + '/items/' + (data.trackPositions.join(',')), { + return self._baseDelete('/playlists/' + data.playlist.uuid + '/items/' + (data.trackPositions.join(',')), { countryCode: _countryCode, orderDirection: data.orderDirection || 'ASC', order: data.order || 'INDEX' - }, { /*trackIds: tracks, toIndex: 1*/ }, ''); + }, {}).then(JSON.parse); } /** @@ -426,7 +461,8 @@ TidalAPI.prototype._baseRequest = function(method, params, type) { uri: method, headers: { 'Origin': 'http://listen.tidal.com', - 'X-Tidal-SessionId': _sessionID + 'X-Tidal-SessionId': _sessionID, + 'Pragma': 'no-cache' }, qs: params }).then( (data) => { @@ -515,7 +551,7 @@ TidalAPI.prototype._basePost = function(method, params, formdata) { 'X-Tidal-SessionId': _sessionID }, form: formdata - }) + }); } From ccaf716aef13dba2387aab76a19101aba148aae1 Mon Sep 17 00:00:00 2001 From: Lucas Augusto Deters Date: Wed, 4 Apr 2018 18:28:26 -0300 Subject: [PATCH 04/22] Fixed small bug and finished playlist samples. --- examples/playlists.js | 72 +++++++++++++++++++++++++++++++++++++++++++ examples/search.js | 2 +- lib/client.js | 4 +-- 3 files changed, 75 insertions(+), 3 deletions(-) create mode 100644 examples/playlists.js diff --git a/examples/playlists.js b/examples/playlists.js new file mode 100644 index 0000000..f743539 --- /dev/null +++ b/examples/playlists.js @@ -0,0 +1,72 @@ +let TidalClient = require('../'); +let credentials = require('./.config.json'); + +let api = new TidalClient(credentials.tidal); + +async function test_playlists(delete_playlist_after_testing) { + + // get the id of the current user + let user_id = await api.getMyID(); + console.log(user_id); + + // query more information about current user + let user = await api.getUser({id: user_id}); + console.log(user); + + // get all playlists of current user + let result = await api.getPlaylists({id: user_id}); + let current_playlists = result.items; + let playlists_resume = current_playlists.map(playlist => playlist.title).filter((value, index) => index < 5); + console.log('listing first 5 playlists of current user: \n',playlists_resume) + + // search some musics + let track_results = await api.search({type: 'tracks', query: 'The Beatles', limit: 10}); + let beatles_tracks = track_results.tracks.items; + let beatles_tracks_resume = beatles_tracks.map(playlist => playlist.title); + console.log('list of beatles tracks:',beatles_tracks_resume); + + // lookup for a specific playlist + let TEST_PLAYLIST = 'Test playlist' + let filtered_playlists = current_playlists.filter( playlist => playlist.title == TEST_PLAYLIST ); + let test_playlist = filtered_playlists[0] + + // create a new playlist if necessary + if (test_playlist == undefined){ + test_playlist = await api.createPlaylist({title: TEST_PLAYLIST, description: 'Automatically created playlist.'}); + console.log('created a new playlist.') + } + console.log('test playlist uuid is:' + test_playlist.uuid) + + // add musics to the beginning of the playlist + result = await api.addPlaylistTracks({playlist: test_playlist, tracks: beatles_tracks, toIndex: 0}); + console.log(beatles_tracks.length + ' tracks added to playlist ', result); + + // get tracks in the playlist + result = await api.getPlaylistTracks({playlist: test_playlist}) + let musics_on_test_playlist = result.items; + let number_of_musics_on_test_playlist = result.totalNumberOfItems; + console.log('Musics on the playlist now : \n',number_of_musics_on_test_playlist); + + // we added new music to the beginning. so we can delete old musics from the end. + let number_of_musics_to_keep = beatles_tracks.length; + let number_of_musics_to_delete = number_of_musics_on_test_playlist - number_of_musics_to_keep; + let positions_to_delete = [...Array(number_of_musics_to_delete).keys()].map(v => v+number_of_musics_to_keep); + result = await api.deletePlaylistTracks({playlist: test_playlist, trackPositions: positions_to_delete}); + console.log(number_of_musics_to_delete + ' tracks deleted from the playlist'); + + // get tracks in the playlist again + result = await api.getPlaylistTracks({playlist: test_playlist}) + musics_on_test_playlist = result.items; + number_of_musics_on_test_playlist = result.totalNumberOfItems; + console.log('Musics on the playlist now : \n',number_of_musics_on_test_playlist); + + if (delete_playlist_after_testing) { + result = await api.deletePlaylist(test_playlist); + console.log('Playlist deleted. \n') + } + +} + +let DELETE_PLAYLIST_AFTER_TEST = true; + +test_playlists(DELETE_PLAYLIST_AFTER_TEST); diff --git a/examples/search.js b/examples/search.js index 93fa4f9..bd232a9 100644 --- a/examples/search.js +++ b/examples/search.js @@ -1,5 +1,5 @@ +let TidalClient = require('../'); let credentials = require('./.config.json'); -let TidalClient = require('./client.js'); let api = new TidalClient(credentials.tidal); diff --git a/lib/client.js b/lib/client.js index a998089..1c0ef1d 100644 --- a/lib/client.js +++ b/lib/client.js @@ -331,7 +331,7 @@ TidalAPI.prototype.deletePlaylistTracks = function(data) { countryCode: _countryCode, orderDirection: data.orderDirection || 'ASC', order: data.order || 'INDEX' - }, {}).then(JSON.parse); + }, {}); } /** @@ -397,7 +397,7 @@ TidalAPI.prototype.getPlaylists = function(user) { limit: user.limit || 999, offset: user.offset || 0, countryCode: _countryCode - }, 'userPlaylists'); + }); } /** From aab9f83f55ed4ab2011531238392d7dac8567a76 Mon Sep 17 00:00:00 2001 From: Lucas Augusto Deters Date: Wed, 4 Apr 2018 20:12:06 -0300 Subject: [PATCH 05/22] Limiting requests per secound and fixed small bug while deleting. --- lib/client.js | 47 ++++++++++++++++++++++++++++++++++------------- package.json | 3 ++- 2 files changed, 36 insertions(+), 14 deletions(-) diff --git a/lib/client.js b/lib/client.js index 1c0ef1d..65e6a6e 100644 --- a/lib/client.js +++ b/lib/client.js @@ -1,12 +1,13 @@ 'use strict'; - //Node.js modules var request = require('request-promise-native').defaults({ baseUrl: 'https://api.tidalhifi.com/v1' }); +var Semaphore = require('semaphore'); + /** * Package.json of TidalAPI * @type {exports} @@ -64,7 +65,7 @@ var authData = {}; /** * Create TidalAPI instance - * @param {{username: String, password: String, token: String, quality: String}} + * @param {{username: String, password: String, token: String, quality: String, requests_per_secound: Number}} * @Constructor */ @@ -84,9 +85,11 @@ function TidalAPI(authData) { if (typeof authData.quality !== 'string') { throw new Error('Stream quality invalid or missing'); } + } this.authData = authData; + this.sem1 = Semaphore(authData.requests_per_secound || 10); /* try log in */ // tryLogin(authData); @@ -256,16 +259,13 @@ TidalAPI.prototype.getAlbumTracks = function(query) { } /** * Get playlist info. - * @param {{id: String, limit: Number, filter: String, offset: Number}} + * @param {{uuid: String, limit: Number, filter: String, offset: Number}} */ TidalAPI.prototype.getPlaylist = function(query) { var self = this; - return self._baseRequest('/playlists/' + (query.id || query), { - limit: query.limit || 999, - filter: query.filter || 'ALL', - offset: query.offset || 0, + return self._baseRequest('/playlists/' + query.uuid, { countryCode: _countryCode - }, 'album'); + }); } /** * Get tracks from a playlist. @@ -297,7 +297,7 @@ TidalAPI.prototype.createPlaylist = function(data) { /** * Delete a playlist - * @param {{playlist: {uuid : String}}} + * @param {{uuid : String}} */ TidalAPI.prototype.deletePlaylist = function(data) { var self = this; @@ -313,6 +313,10 @@ TidalAPI.prototype.deletePlaylist = function(data) { TidalAPI.prototype.addPlaylistTracks = function(data) { var self = this; + if (data.tracks.length == 0) { + return; + } + return self._basePost('/playlists/' + data.playlist.uuid + '/items', { countryCode: _countryCode }, { @@ -327,6 +331,12 @@ TidalAPI.prototype.addPlaylistTracks = function(data) { */ TidalAPI.prototype.deletePlaylistTracks = function(data) { var self = this; + + if (data.trackPositions == undefined || data.trackPositions.length == 0) { + return; + } + + return self._baseDelete('/playlists/' + data.playlist.uuid + '/items/' + (data.trackPositions.join(',')), { countryCode: _countryCode, orderDirection: data.orderDirection || 'ASC', @@ -455,6 +465,10 @@ TidalAPI.prototype._baseRequest = function(method, params, type) { }); } + this.sem1.take( () => { + setTimeout(this.sem1.leave, 1000); + }); + params.countryCode = params.countryCode ? params.countryCode : _countryCode; return request.get({ @@ -492,8 +506,6 @@ TidalAPI.prototype._baseRequest = function(method, params, type) { } - - /** * Base delete function. * @param {{method: String, params: Object, type: String}} @@ -511,6 +523,11 @@ TidalAPI.prototype._baseDelete = function(method, params, formdata) { } params.countryCode = params.countryCode ? params.countryCode : _countryCode; + + this.sem1.take( () => { + setTimeout(this.sem1.leave, 1000); + }); + return request({ method: 'DELETE', uri: method, @@ -523,12 +540,12 @@ TidalAPI.prototype._baseDelete = function(method, params, formdata) { }) } - /** * Base post function. * @param {{method: String, params: Object}} */ TidalAPI.prototype._basePost = function(method, params, formdata) { + var self = this; if (!loggedIn) { @@ -542,6 +559,10 @@ TidalAPI.prototype._basePost = function(method, params, formdata) { params.countryCode = params.countryCode ? params.countryCode : _countryCode; + this.sem1.take( () => { + setTimeout(this.sem1.leave, 1000); + }); + return request({ method: 'POST', uri: method, @@ -551,7 +572,7 @@ TidalAPI.prototype._basePost = function(method, params, formdata) { 'X-Tidal-SessionId': _sessionID }, form: formdata - }); + }) } diff --git a/package.json b/package.json index d4fd23f..176c44d 100644 --- a/package.json +++ b/package.json @@ -25,7 +25,8 @@ "homepage": "https://github.com/lucaslg26/TidalAPI#readme", "dependencies": { "request": "^2.69.0", - "request-promise-native": "^1.0.5" + "request-promise-native": "^1.0.5", + "semaphore": "^1.1.0" }, "devDependencies": { "mocha": "^2.4.5" From 24bbbf395dbc42b832fbe9d28fc7812964b7cc3b Mon Sep 17 00:00:00 2001 From: Lucas Augusto Deters Date: Thu, 5 Apr 2018 14:53:00 -0300 Subject: [PATCH 06/22] First version of the package --- README.md | 109 +++++++++++++++++++++++++++++--------- lib/{client.js => api.js} | 0 package.json | 14 ++--- 3 files changed, 92 insertions(+), 31 deletions(-) rename lib/{client.js => api.js} (100%) diff --git a/README.md b/README.md index d1e0abc..87c529d 100644 --- a/README.md +++ b/README.md @@ -1,12 +1,13 @@ -# TidalAPI +# TidalPromise -[![Build Status](https://img.shields.io/travis/lucaslg26/TidalAPI.svg)](https://travis-ci.org/lucaslg26/TidalAPI) [![npm version](http://img.shields.io/npm/v/tidalapi.svg)](https://npmjs.org/package/tidalapi) [![npm downloads](https://img.shields.io/npm/dm/tidalapi.svg)](https://npmjs.org/package/tidalapi) [![NPM](https://img.shields.io/npm/l/tidalapi.svg)](https://github.com/lucaslg26/TidalAPI/blob/master/LICENSE.md) [![David](https://img.shields.io/david/lucaslg26/TidalAPI.svg)](https://david-dm.org/lucaslg26/TidalAPI) +[![Build Status](https://img.shields.io/travis/deters/TidalPromise.svg)](https://travis-ci.org/deters/TidalPromise) [![npm version](http://img.shields.io/npm/v/deters.svg)](https://npmjs.org/package/tidalpromise) [![npm downloads](https://img.shields.io/npm/dm/deters.svg)](https://npmjs.org/package/tidalpromise) [![NPM](https://img.shields.io/npm/l/deters.svg)](https://github.com/deters/TidalPromise/blob/master/LICENSE.md) [![David](https://img.shields.io/david/lucaslg26/TidalAPI.svg)](https://david-dm.org/lucaslg26/TidalAPI) ## About -node.js TIDAL API. Use the TIDAL Web API simply using this module ;) +node.js TIDAL API, with Promises and playlist manipulation support. -Created by [Lucas Vasconcelos](https://github.com/lucaslg26) +Mantainer [Lucas Deters](https://github.com/deters) +This is a fork of node.js Tidal API by [Lucas Vasconcelos](https://github.com/lucaslg26) **NOTE:** Currently not supporting facebook login. @@ -14,7 +15,7 @@ Created by [Lucas Vasconcelos](https://github.com/lucaslg26) Run the following: ``` javascript -npm install tidalapi +npm install tidalpromise ``` ## Obtain the Tidal token needed to use this API @@ -35,7 +36,7 @@ As well as a TIDAL username and password, the Tidal API needs an API `token` whi Simple usage searching and querying a track list ```javascript -var TidalAPI = require('tidalapi'); +var TidalAPI = require('tidalpromise'); var api = new TidalAPI({ username: 'your-username-here', @@ -49,43 +50,43 @@ var api = new TidalAPI({ ### Search ```javascript -api.search({type: 'artists', query: 'Dream Theater', limit: 1}, function(data){ +api.search({type: 'artists', query: 'Dream Theater', limit: 1}).then( function(data){ console.log(data.artists); -}) +}).catch(console.log) -api.search({type: 'albums', query: 'Dream Theater', limit: 1}, function(data){ +api.search({type: 'albums', query: 'Dream Theater', limit: 1}).then( function(data){ console.log(data.albums); -}) +}).catch(console.log) -api.search({type: 'tracks', query: 'Dream Theater', limit: 1}, function(data){ +api.search({type: 'tracks', query: 'Dream Theater', limit: 1}).then( function(data){ console.log(data.tracks); -}) +}).catch(console.log) -api.search({type: 'tracks,albums,artists', query: 'Dream Theater', limit: 1}, function(data){ +api.search({type: 'tracks,albums,artists', query: 'Dream Theater', limit: 1}).then( function(data){ console.log(data.tracks); console.log(data.albums); console.log(data.artists); -}) +}).catch(console.log) ``` ### Track info ```javascript -api.getTrackInfo({id: 22560696 }, function(data){ +api.getTrackInfo({id: 22560696 }).then( function(data){ console.log(data) -}) +}).catch(console.log) ``` ### Streams ```javascript -api.getStreamURL({id: 22560696}, function(data){ +api.getStreamURL({id: 22560696}).then( function(data){ console.log(data) -}) +}).catch(console.log) -api.getVideoStreamURL({id: 25470315}, function(data){ +api.getVideoStreamURL({id: 25470315}).then( function(data){ console.log(data) -}) +}).catch(console.log) ``` ### Album Art @@ -97,20 +98,80 @@ console.log(api.getArtURL('24f52ab0-e7d6-414d-a650-20a4c686aa57', 1280)) //cover ### Videos ```javascript -api.getArtistVideos({id: 14670, limit: 2}, function(data){ +api.getArtistVideos({id: 14670, limit: 2}).then( function(data){ console.log(data) -}) +}).catch(console.log) ``` ### FLAC tags ```javascript -api.genMetaflacTags({id: 22560696, coverPath: './albumart.jpg', songPath: './song.flac'}, function(data){ +api.genMetaflacTags({id: 22560696, coverPath: './albumart.jpg', songPath: './song.flac'}).then( function(data){ console.log(data) /* --remove-all-tags --set-tag="ARTIST=Dream Theater" --set-tag="TITLE=Along For The Ride" --set-tag="ALBUM=Dream Theater" --set-tag="TRACKNUMBER=8" --set-tag="COPYRIGHT=2013 Roadrunner Records, Inc." -set-tag="DATE=2013" --import-picture-from="./albumart.jpg" "./song.flac" --add-replay-gain */ -}) +}).catch(console.log) ``` +### Playlist manipulation (example using async/await for clarity) + +// get the id of the current user +let user_id = await api.getMyID(); +console.log(user_id); + +// query more information about current user +let user = await api.getUser({id: user_id}); +console.log(user); + +// get all playlists of current user +let result = await api.getPlaylists({id: user_id}); +let current_playlists = result.items; +let playlists_resume = current_playlists.map(playlist => playlist.title).filter((value, index) => index < 5); +console.log('listing first 5 playlists of current user: \n',playlists_resume) + +// search some musics +let track_results = await api.search({type: 'tracks', query: 'The Beatles', limit: 10}); +let beatles_tracks = track_results.tracks.items; +let beatles_tracks_resume = beatles_tracks.map(playlist => playlist.title); +console.log('list of beatles tracks:',beatles_tracks_resume); + +// lookup for a specific playlist +let TEST_PLAYLIST = 'Test playlist' +let filtered_playlists = current_playlists.filter( playlist => playlist.title == TEST_PLAYLIST ); +let test_playlist = filtered_playlists[0] + +// create a new playlist if necessary +if (test_playlist == undefined){ + test_playlist = await api.createPlaylist({title: TEST_PLAYLIST, description: 'Automatically created playlist.'}); + console.log('created a new playlist.') +} +console.log('test playlist uuid is:' + test_playlist.uuid) + +// add musics to the beginning of the playlist +result = await api.addPlaylistTracks({playlist: test_playlist, tracks: beatles_tracks, toIndex: 0}); +console.log(beatles_tracks.length + ' tracks added to playlist ', result); + +// get tracks in the playlist +result = await api.getPlaylistTracks({playlist: test_playlist}) +let musics_on_test_playlist = result.items; +let number_of_musics_on_test_playlist = result.totalNumberOfItems; +console.log('Musics on the playlist now : \n',number_of_musics_on_test_playlist); + +// we added new music to the beginning. so we can delete old musics from the end. +let number_of_musics_to_keep = beatles_tracks.length; +let number_of_musics_to_delete = number_of_musics_on_test_playlist - number_of_musics_to_keep; +let positions_to_delete = [...Array(number_of_musics_to_delete).keys()].map(v => v+number_of_musics_to_keep); +result = await api.deletePlaylistTracks({playlist: test_playlist, trackPositions: positions_to_delete}); +console.log(number_of_musics_to_delete + ' tracks deleted from the playlist'); + +// get tracks in the playlist again +result = await api.getPlaylistTracks({playlist: test_playlist}) +musics_on_test_playlist = result.items; +number_of_musics_on_test_playlist = result.totalNumberOfItems; +console.log('Musics on the playlist now : \n',number_of_musics_on_test_playlist); + +result = await api.deletePlaylist(test_playlist); +console.log('Playlist deleted. \n') + ## Troubleshooting ### 500 error with 'Ooops, an unexpected error occurred' diff --git a/lib/client.js b/lib/api.js similarity index 100% rename from lib/client.js rename to lib/api.js diff --git a/package.json b/package.json index 176c44d..a08e391 100644 --- a/package.json +++ b/package.json @@ -1,14 +1,14 @@ { - "name": "tidalapi", + "name": "tidalpromise", "version": "0.2.3", - "description": "Unofficial Node.js TIDAL API", - "main": "./lib/client.js", + "description": "Unofficial Node.js TIDAL Promise API", + "main": "./lib/api.js", "scripts": { "test": "mocha" }, "repository": { "type": "git", - "url": "git+https://github.com/lucaslg26/TidalAPI.git" + "url": "git+https://github.com/deters/TidalPromise.git" }, "keywords": [ "node", @@ -17,12 +17,12 @@ "music", "flac" ], - "author": "Lucas Vasconcelos (lucaslg26@gmail.com)", + "author": "Lucas Deters (lucasdeters@gmail.com)", "license": "MIT", "bugs": { - "url": "https://github.com/lucaslg26/TidalAPI/issues" + "url": "https://github.com/deters/TidalPromise/issues" }, - "homepage": "https://github.com/lucaslg26/TidalAPI#readme", + "homepage": "https://github.com/deters/TidalPromise#readme", "dependencies": { "request": "^2.69.0", "request-promise-native": "^1.0.5", From 537f724293b4d0cb7b4187131fd8fcf894086a63 Mon Sep 17 00:00:00 2001 From: Lucas Augusto Deters Date: Thu, 5 Apr 2018 15:04:38 -0300 Subject: [PATCH 07/22] Fixed README.md --- README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/README.md b/README.md index 87c529d..4f73929 100644 --- a/README.md +++ b/README.md @@ -7,6 +7,7 @@ node.js TIDAL API, with Promises and playlist manipulation support. Mantainer [Lucas Deters](https://github.com/deters) + This is a fork of node.js Tidal API by [Lucas Vasconcelos](https://github.com/lucaslg26) **NOTE:** Currently not supporting facebook login. @@ -114,6 +115,7 @@ api.genMetaflacTags({id: 22560696, coverPath: './albumart.jpg', songPath: './son ### Playlist manipulation (example using async/await for clarity) +```javascript // get the id of the current user let user_id = await api.getMyID(); console.log(user_id); @@ -171,6 +173,7 @@ console.log('Musics on the playlist now : \n',number_of_musics_on_test_playlist) result = await api.deletePlaylist(test_playlist); console.log('Playlist deleted. \n') +``` ## Troubleshooting From 136587ff286ccc42a96e6601b5a1d9e61e7a1532 Mon Sep 17 00:00:00 2001 From: Lucas Augusto Deters Date: Fri, 6 Apr 2018 05:28:35 -0300 Subject: [PATCH 08/22] 0.2.4 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index a08e391..00e0611 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "tidalpromise", - "version": "0.2.3", + "version": "0.2.4", "description": "Unofficial Node.js TIDAL Promise API", "main": "./lib/api.js", "scripts": { From fbfadde4a3acb716d348d301c2f4b2bd93ce0aa0 Mon Sep 17 00:00:00 2001 From: Lucas Augusto Deters Date: Fri, 23 Aug 2019 10:39:36 -0300 Subject: [PATCH 09/22] fixed playlist create --- lib/api.js | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/lib/api.js b/lib/api.js index 65e6a6e..d0fc90c 100644 --- a/lib/api.js +++ b/lib/api.js @@ -287,12 +287,17 @@ TidalAPI.prototype.getPlaylistTracks = function(query) { */ TidalAPI.prototype.createPlaylist = function(data) { var self = this; - return self._basePost('/users/'+ this.getMyID() +'/playlists', { - countryCode: _countryCode - }, { - title: data.title, - description: data.description - }).then(JSON.parse); + return this.getMyID().then(id => { + + return self._basePost('/users/'+ id +'/playlists', { + countryCode: _countryCode + }, { + title: data.title, + description: data.description + }).then(JSON.parse); + + + }) } /** From b6c26ec4b444f1a5880aa9c442ba06fb06d01348 Mon Sep 17 00:00:00 2001 From: Lucas Augusto Deters Date: Fri, 23 Aug 2019 10:39:53 -0300 Subject: [PATCH 10/22] 0.2.5 --- package-lock.json | 560 ++++++++++++++++++++++++++++++++++++++++++++++ package.json | 2 +- 2 files changed, 561 insertions(+), 1 deletion(-) create mode 100644 package-lock.json diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..35b3e3c --- /dev/null +++ b/package-lock.json @@ -0,0 +1,560 @@ +{ + "name": "tidalpromise", + "version": "0.2.5", + "lockfileVersion": 1, + "requires": true, + "dependencies": { + "ajv": { + "version": "5.5.2", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-5.5.2.tgz", + "integrity": "sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU=", + "requires": { + "co": "4.6.0", + "fast-deep-equal": "1.1.0", + "fast-json-stable-stringify": "2.0.0", + "json-schema-traverse": "0.3.1" + } + }, + "asn1": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.3.tgz", + "integrity": "sha1-2sh4dxPJlmhJ/IGAd36+nB3fO4Y=" + }, + "assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=" + }, + "asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=" + }, + "aws-sign2": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", + "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=" + }, + "aws4": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.6.0.tgz", + "integrity": "sha1-g+9cqGCysy5KDe7e6MdxudtXRx4=" + }, + "bcrypt-pbkdf": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.1.tgz", + "integrity": "sha1-Y7xdy2EzG5K8Bf1SiVPDNGKgb40=", + "optional": true, + "requires": { + "tweetnacl": "0.14.5" + } + }, + "boom": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/boom/-/boom-4.3.1.tgz", + "integrity": "sha1-T4owBctKfjiJ90kDD9JbluAdLjE=", + "requires": { + "hoek": "4.2.1" + } + }, + "caseless": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", + "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=" + }, + "co": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", + "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=" + }, + "combined-stream": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.6.tgz", + "integrity": "sha1-cj599ugBrFYTETp+RFqbactjKBg=", + "requires": { + "delayed-stream": "1.0.0" + } + }, + "commander": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.3.0.tgz", + "integrity": "sha1-/UMOiJgy7DU7ms0d4hfBHLPu+HM=", + "dev": true + }, + "core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" + }, + "cryptiles": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/cryptiles/-/cryptiles-3.1.2.tgz", + "integrity": "sha1-qJ+7Ig9c4l7FboxKqKT9e1sNKf4=", + "requires": { + "boom": "5.2.0" + }, + "dependencies": { + "boom": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/boom/-/boom-5.2.0.tgz", + "integrity": "sha512-Z5BTk6ZRe4tXXQlkqftmsAUANpXmuwlsF5Oov8ThoMbQRzdGTA1ngYRW160GexgOgjsFOKJz0LYhoNi+2AMBUw==", + "requires": { + "hoek": "4.2.1" + } + } + } + }, + "dashdash": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", + "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", + "requires": { + "assert-plus": "1.0.0" + } + }, + "debug": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz", + "integrity": "sha1-+HBX6ZWxofauaklgZkE3vFbwOdo=", + "dev": true, + "requires": { + "ms": "0.7.1" + } + }, + "delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=" + }, + "diff": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-1.4.0.tgz", + "integrity": "sha1-fyjS657nsVqX79ic5j3P2qPMur8=", + "dev": true + }, + "ecc-jsbn": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.1.tgz", + "integrity": "sha1-D8c6ntXw1Tw4GTOYUj735UN3dQU=", + "optional": true, + "requires": { + "jsbn": "0.1.1" + } + }, + "escape-string-regexp": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.2.tgz", + "integrity": "sha1-Tbwv5nTnGUnK8/smlc5/LcHZqNE=", + "dev": true + }, + "extend": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.1.tgz", + "integrity": "sha1-p1Xqe8Gt/MWjHOfnYtuq3F5jZEQ=" + }, + "extsprintf": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", + "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=" + }, + "fast-deep-equal": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz", + "integrity": "sha1-wFNHeBfIa1HaqFPIHgWbcz0CNhQ=" + }, + "fast-json-stable-stringify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz", + "integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I=" + }, + "forever-agent": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", + "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=" + }, + "form-data": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.2.tgz", + "integrity": "sha1-SXBJi+YEwgwAXU9cI67NIda0kJk=", + "requires": { + "asynckit": "0.4.0", + "combined-stream": "1.0.6", + "mime-types": "2.1.18" + } + }, + "getpass": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", + "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", + "requires": { + "assert-plus": "1.0.0" + } + }, + "glob": { + "version": "3.2.11", + "resolved": "https://registry.npmjs.org/glob/-/glob-3.2.11.tgz", + "integrity": "sha1-Spc/Y1uRkPcV0QmH1cAP0oFevj0=", + "dev": true, + "requires": { + "inherits": "2.0.3", + "minimatch": "0.3.0" + } + }, + "growl": { + "version": "1.9.2", + "resolved": "https://registry.npmjs.org/growl/-/growl-1.9.2.tgz", + "integrity": "sha1-Dqd0NxXbjY3ixe3hd14bRayFwC8=", + "dev": true + }, + "har-schema": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", + "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=" + }, + "har-validator": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.0.3.tgz", + "integrity": "sha1-ukAsJmGU8VlW7xXg/PJCmT9qff0=", + "requires": { + "ajv": "5.5.2", + "har-schema": "2.0.0" + } + }, + "hawk": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/hawk/-/hawk-6.0.2.tgz", + "integrity": "sha512-miowhl2+U7Qle4vdLqDdPt9m09K6yZhkLDTWGoUiUzrQCn+mHHSmfJgAyGaLRZbPmTqfFFjRV1QWCW0VWUJBbQ==", + "requires": { + "boom": "4.3.1", + "cryptiles": "3.1.2", + "hoek": "4.2.1", + "sntp": "2.1.0" + } + }, + "hoek": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/hoek/-/hoek-4.2.1.tgz", + "integrity": "sha512-QLg82fGkfnJ/4iy1xZ81/9SIJiq1NGFUMGs6ParyjBZr6jW2Ufj/snDqTHixNlHdPNwN2RLVD0Pi3igeK9+JfA==" + }, + "http-signature": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", + "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", + "requires": { + "assert-plus": "1.0.0", + "jsprim": "1.4.1", + "sshpk": "1.14.1" + } + }, + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", + "dev": true + }, + "is-typedarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", + "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=" + }, + "isstream": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", + "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=" + }, + "jade": { + "version": "0.26.3", + "resolved": "https://registry.npmjs.org/jade/-/jade-0.26.3.tgz", + "integrity": "sha1-jxDXl32NefL2/4YqgbBRPMslaGw=", + "dev": true, + "requires": { + "commander": "0.6.1", + "mkdirp": "0.3.0" + }, + "dependencies": { + "commander": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-0.6.1.tgz", + "integrity": "sha1-+mihT2qUXVTbvlDYzbMyDp47GgY=", + "dev": true + }, + "mkdirp": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.3.0.tgz", + "integrity": "sha1-G79asbqCevI1dRQ0kEJkVfSB/h4=", + "dev": true + } + } + }, + "jsbn": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", + "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=", + "optional": true + }, + "json-schema": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", + "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=" + }, + "json-schema-traverse": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz", + "integrity": "sha1-NJptRMU6Ud6JtAgFxdXlm0F9M0A=" + }, + "json-stringify-safe": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", + "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=" + }, + "jsprim": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", + "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=", + "requires": { + "assert-plus": "1.0.0", + "extsprintf": "1.3.0", + "json-schema": "0.2.3", + "verror": "1.10.0" + } + }, + "lodash": { + "version": "4.17.5", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.5.tgz", + "integrity": "sha512-svL3uiZf1RwhH+cWrfZn3A4+U58wbP0tGVTLQPbjplZxZ8ROD9VLuNgsRniTlLe7OlSqR79RUehXgpBW/s0IQw==" + }, + "lru-cache": { + "version": "2.7.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-2.7.3.tgz", + "integrity": "sha1-bUUk6LlV+V1PW1iFHOId1y+06VI=", + "dev": true + }, + "mime-db": { + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.33.0.tgz", + "integrity": "sha512-BHJ/EKruNIqJf/QahvxwQZXKygOQ256myeN/Ew+THcAa5q+PjyTTMMeNQC4DZw5AwfvelsUrA6B67NKMqXDbzQ==" + }, + "mime-types": { + "version": "2.1.18", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.18.tgz", + "integrity": "sha512-lc/aahn+t4/SWV/qcmumYjymLsWfN3ELhpmVuUFjgsORruuZPVSwAQryq+HHGvO/SI2KVX26bx+En+zhM8g8hQ==", + "requires": { + "mime-db": "1.33.0" + } + }, + "minimatch": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-0.3.0.tgz", + "integrity": "sha1-J12O2qxPG7MyZHIInnlJyDlGmd0=", + "dev": true, + "requires": { + "lru-cache": "2.7.3", + "sigmund": "1.0.1" + } + }, + "minimist": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", + "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", + "dev": true + }, + "mkdirp": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", + "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", + "dev": true, + "requires": { + "minimist": "0.0.8" + } + }, + "mocha": { + "version": "2.5.3", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-2.5.3.tgz", + "integrity": "sha1-FhvlvetJZ3HrmzV0UFC2IrWu/Fg=", + "dev": true, + "requires": { + "commander": "2.3.0", + "debug": "2.2.0", + "diff": "1.4.0", + "escape-string-regexp": "1.0.2", + "glob": "3.2.11", + "growl": "1.9.2", + "jade": "0.26.3", + "mkdirp": "0.5.1", + "supports-color": "1.2.0", + "to-iso-string": "0.0.2" + } + }, + "ms": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz", + "integrity": "sha1-nNE8A62/8ltl7/3nzoZO6VIBcJg=", + "dev": true + }, + "oauth-sign": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.8.2.tgz", + "integrity": "sha1-Rqarfwrq2N6unsBWV4C31O/rnUM=" + }, + "performance-now": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", + "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=" + }, + "punycode": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", + "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=" + }, + "qs": { + "version": "6.5.1", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.1.tgz", + "integrity": "sha512-eRzhrN1WSINYCDCbrz796z37LOe3m5tmW7RQf6oBntukAG1nmovJvhnwHHRMAfeoItc1m2Hk02WER2aQ/iqs+A==" + }, + "request": { + "version": "2.85.0", + "resolved": "https://registry.npmjs.org/request/-/request-2.85.0.tgz", + "integrity": "sha512-8H7Ehijd4js+s6wuVPLjwORxD4zeuyjYugprdOXlPSqaApmL/QOy+EB/beICHVCHkGMKNh5rvihb5ov+IDw4mg==", + "requires": { + "aws-sign2": "0.7.0", + "aws4": "1.6.0", + "caseless": "0.12.0", + "combined-stream": "1.0.6", + "extend": "3.0.1", + "forever-agent": "0.6.1", + "form-data": "2.3.2", + "har-validator": "5.0.3", + "hawk": "6.0.2", + "http-signature": "1.2.0", + "is-typedarray": "1.0.0", + "isstream": "0.1.2", + "json-stringify-safe": "5.0.1", + "mime-types": "2.1.18", + "oauth-sign": "0.8.2", + "performance-now": "2.1.0", + "qs": "6.5.1", + "safe-buffer": "5.1.1", + "stringstream": "0.0.5", + "tough-cookie": "2.3.4", + "tunnel-agent": "0.6.0", + "uuid": "3.2.1" + } + }, + "request-promise-core": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/request-promise-core/-/request-promise-core-1.1.1.tgz", + "integrity": "sha1-Pu4AssWqgyOc+wTFcA2jb4HNCLY=", + "requires": { + "lodash": "4.17.5" + } + }, + "request-promise-native": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/request-promise-native/-/request-promise-native-1.0.5.tgz", + "integrity": "sha1-UoF3D2jgyXGeUWP9P6tIIhX0/aU=", + "requires": { + "request-promise-core": "1.1.1", + "stealthy-require": "1.1.1", + "tough-cookie": "2.3.4" + } + }, + "safe-buffer": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz", + "integrity": "sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg==" + }, + "semaphore": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/semaphore/-/semaphore-1.1.0.tgz", + "integrity": "sha512-O4OZEaNtkMd/K0i6js9SL+gqy0ZCBMgUvlSqHKi4IBdjhe7wB8pwztUk1BbZ1fmrvpwFrPbHzqd2w5pTcJH6LA==" + }, + "sigmund": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/sigmund/-/sigmund-1.0.1.tgz", + "integrity": "sha1-P/IfGYytIXX587eBhT/ZTQ0ZtZA=", + "dev": true + }, + "sntp": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/sntp/-/sntp-2.1.0.tgz", + "integrity": "sha512-FL1b58BDrqS3A11lJ0zEdnJ3UOKqVxawAkF3k7F0CVN7VQ34aZrV+G8BZ1WC9ZL7NyrwsW0oviwsWDgRuVYtJg==", + "requires": { + "hoek": "4.2.1" + } + }, + "sshpk": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.14.1.tgz", + "integrity": "sha1-Ew9Zde3a2WPx1W+SuaxsUfqfg+s=", + "requires": { + "asn1": "0.2.3", + "assert-plus": "1.0.0", + "bcrypt-pbkdf": "1.0.1", + "dashdash": "1.14.1", + "ecc-jsbn": "0.1.1", + "getpass": "0.1.7", + "jsbn": "0.1.1", + "tweetnacl": "0.14.5" + } + }, + "stealthy-require": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/stealthy-require/-/stealthy-require-1.1.1.tgz", + "integrity": "sha1-NbCYdbT/SfJqd35QmzCQoyJr8ks=" + }, + "stringstream": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/stringstream/-/stringstream-0.0.5.tgz", + "integrity": "sha1-TkhM1N5aC7vuGORjB3EKioFiGHg=" + }, + "supports-color": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-1.2.0.tgz", + "integrity": "sha1-/x7R5hFp0Gs88tWI4YixjYhH4X4=", + "dev": true + }, + "to-iso-string": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/to-iso-string/-/to-iso-string-0.0.2.tgz", + "integrity": "sha1-TcGeZk38y+Jb2NtQiwDG2hWCVdE=", + "dev": true + }, + "tough-cookie": { + "version": "2.3.4", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.3.4.tgz", + "integrity": "sha512-TZ6TTfI5NtZnuyy/Kecv+CnoROnyXn2DN97LontgQpCwsX2XyLYCC0ENhYkehSOwAp8rTQKc/NUIF7BkQ5rKLA==", + "requires": { + "punycode": "1.4.1" + } + }, + "tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", + "requires": { + "safe-buffer": "5.1.1" + } + }, + "tweetnacl": { + "version": "0.14.5", + "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", + "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=", + "optional": true + }, + "uuid": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.2.1.tgz", + "integrity": "sha512-jZnMwlb9Iku/O3smGWvZhauCf6cvvpKi4BKRiliS3cxnI+Gz9j5MEpTz2UFuXiKPJocb7gnsLHwiS05ige5BEA==" + }, + "verror": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", + "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", + "requires": { + "assert-plus": "1.0.0", + "core-util-is": "1.0.2", + "extsprintf": "1.3.0" + } + } + } +} diff --git a/package.json b/package.json index 00e0611..c5e6d7f 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "tidalpromise", - "version": "0.2.4", + "version": "0.2.5", "description": "Unofficial Node.js TIDAL Promise API", "main": "./lib/api.js", "scripts": { From 005eae5df3f2c6d7ecd67b5a73934e4f7f90448b Mon Sep 17 00:00:00 2001 From: Lucas Augusto Deters Date: Sat, 24 Aug 2019 19:17:33 -0300 Subject: [PATCH 11/22] Fixed bug getting user id --- lib/api.js | 396 +++++++++++++++++++++++++++-------------------------- 1 file changed, 200 insertions(+), 196 deletions(-) diff --git a/lib/api.js b/lib/api.js index d0fc90c..c9257db 100644 --- a/lib/api.js +++ b/lib/api.js @@ -116,15 +116,15 @@ function tryLogin(authInfo) { password: authInfo.password, clientUniqueKey: "vjknfvjbnjhbgjhbbg" } - }).then( (data) => { - data = JSON.parse(data); - _sessionID = data.sessionId; - _userID = data.userId; - _countryCode = data.countryCode; - _streamQuality = authInfo.quality; - loggingIn = false; - loggedIn = true; - return data; + }).then((data) => { + data = JSON.parse(data); + _sessionID = data.sessionId; + _userID = data.userId; + _countryCode = data.countryCode; + _streamQuality = authInfo.quality; + loggingIn = false; + loggedIn = true; + return data; }); } /** @@ -134,7 +134,7 @@ TidalAPI.prototype.getMyID = function() { var self = this; if (!loggedIn) { - return tryLogin(this.authData).then( () => { + return tryLogin(this.authData).then(() => { return self.getMyID(); }); @@ -289,7 +289,7 @@ TidalAPI.prototype.createPlaylist = function(data) { var self = this; return this.getMyID().then(id => { - return self._basePost('/users/'+ id +'/playlists', { + return self._basePost('/users/' + id + '/playlists', { countryCode: _countryCode }, { title: data.title, @@ -325,7 +325,7 @@ TidalAPI.prototype.addPlaylistTracks = function(data) { return self._basePost('/playlists/' + data.playlist.uuid + '/items', { countryCode: _countryCode }, { - trackIds: data.tracks.map(v => v.id ).join(','), + trackIds: data.tracks.map(v => v.id).join(','), toIndex: data.toIndex || 0 }); } @@ -396,189 +396,193 @@ TidalAPI.prototype.getVideoStreamURL = function(track) { * @param {{id: Number}} */ TidalAPI.prototype.getUser = function(user) { - var self = this; - return self._baseRequest('/users/' + (user.id || user), { - limit: user.limit || 999, - offset: user.offset || 0 - }, 'user'); -} -/** - * Get user playlists. - * @param {{id: Number}} - */ -TidalAPI.prototype.getPlaylists = function(user) { - var self = this; - return self._baseRequest('/users/' + (user.id || user) + "/playlists", { - limit: user.limit || 999, - offset: user.offset || 0, - countryCode: _countryCode - }); -} - -/** - * Get track stream URL. - * @param {id: String, res: Number} - */ - -TidalAPI.prototype.getArtURL = function(id, width, height) { - width = width || 1280; - height = height || 1280; - return 'https://resources.tidal.com/images/' + id.replace(/-/g, '/') + '/' + width + 'x' + height + '.jpg'; -} -/** - * Generate Metaflac tags. - * @param {{id: Number}} - */ -TidalAPI.prototype.genMetaflacTags = function(track) { - var self = this; - return self.getTrackInfo({ - id: track.id || track - }).then ( (data) => { - self.getAlbum({ - id: data.album.id - }).then( (albumData) => { - var metaflacTag; - metaflacTag = '--remove-all-tags '; - metaflacTag += '--set-tag=\"ARTIST=' + data.artist.name + '\" '; - metaflacTag += '--set-tag=\"TITLE=' + data.title + '\" '; - metaflacTag += '--set-tag=\"ALBUM=' + data.album.title + '\" '; - metaflacTag += '--set-tag=\"TRACKNUMBER=' + data.trackNumber + '\" '; - metaflacTag += '--set-tag=\"COPYRIGHT=' + data.copyright + '\" '; - metaflacTag += '-set-tag="DATE=' + albumData.releaseDate.split("-")[0] + '" '; - if (track.coverPath) { - metaflacTag += '--import-picture-from=' + '\"' + track.coverPath + '\" '; - } - if (track.songPath) { - metaflacTag += '\"' + track.songPath + '\" '; - } - metaflacTag += '--add-replay-gain'; - return metaflacTag; - }) - }); -} -/** - * Base request function. - * @param {{method: String, params: Object, type: String}} - */ -TidalAPI.prototype._baseRequest = function(method, params, type) { - var self = this; - - if (!loggedIn) { - return tryLogin(this.authData).then( () => { - - return self._baseRequest(method, params, type); - }); - } - - this.sem1.take( () => { - setTimeout(this.sem1.leave, 1000); - }); - - params.countryCode = params.countryCode ? params.countryCode : _countryCode; - - return request.get({ - uri: method, - headers: { - 'Origin': 'http://listen.tidal.com', - 'X-Tidal-SessionId': _sessionID, - 'Pragma': 'no-cache' - }, - qs: params - }).then( (data) => { - let body = JSON.parse(data); - if (params.types) { - var newBody = {}; - if (params.types.indexOf('tracks') > -1) { - newBody['tracks'] = body.tracks; + var self = this; + return this.getMyID().then(id => { + return self._baseRequest('/users/' + (id || user), { + limit: user.limit || 999, + offset: user.offset || 0 + }, 'user'); } - if (params.types.indexOf('artists') > -1) { - newBody['artists'] = body.artists; - } - if (params.types.indexOf('albums') > -1) { - newBody['albums'] = body.albums; - } - if (params.types.indexOf('videos') > -1) { - newBody['videos'] = body.videos; - } - if (params.types.indexOf('playlists') > -1) { - newBody['playlists'] = body.playlists; - } - return newBody; - } else { - return body; } - }) - -} - -/** - * Base delete function. - * @param {{method: String, params: Object, type: String}} - */ -TidalAPI.prototype._baseDelete = function(method, params, formdata) { - var self = this; - - if (!loggedIn) { - - return tryLogin(this.authData) - .then(() => { - return self._baseDelete(method, params, formdata, type); - }) - - } - - params.countryCode = params.countryCode ? params.countryCode : _countryCode; - - this.sem1.take( () => { - setTimeout(this.sem1.leave, 1000); - }); - - return request({ - method: 'DELETE', - uri: method, - headers: { - 'Origin': 'https://listen.tidal.com', - 'If-None-Match': '"*"', - 'X-Tidal-SessionId': _sessionID - }, - form: formdata - }) -} - -/** - * Base post function. - * @param {{method: String, params: Object}} - */ -TidalAPI.prototype._basePost = function(method, params, formdata) { - - var self = this; - - if (!loggedIn) { - - return tryLogin(this.authData) - .then(() => { - return self._basePost(method, params, formdata); - }) - - } - - params.countryCode = params.countryCode ? params.countryCode : _countryCode; - - this.sem1.take( () => { - setTimeout(this.sem1.leave, 1000); - }); - - return request({ - method: 'POST', - uri: method, - headers: { - 'Origin': 'https://listen.tidal.com', - 'If-None-Match': '"*"', - 'X-Tidal-SessionId': _sessionID - }, - form: formdata - }) - -} - -module.exports = TidalAPI; + /** + * Get user playlists. + * @param {{id: Number}} + */ + TidalAPI.prototype.getPlaylists = function(user) { + var self = this; + return this.getMyID().then(id => { + return self._baseRequest('/users/' + (id || user) + "/playlists", { + limit: user.limit || 999, + offset: user.offset || 0, + countryCode: _countryCode + }); + } + } + + /** + * Get track stream URL. + * @param {id: String, res: Number} + */ + + TidalAPI.prototype.getArtURL = function(id, width, height) { + width = width || 1280; + height = height || 1280; + return 'https://resources.tidal.com/images/' + id.replace(/-/g, '/') + '/' + width + 'x' + height + '.jpg'; + } + /** + * Generate Metaflac tags. + * @param {{id: Number}} + */ + TidalAPI.prototype.genMetaflacTags = function(track) { + var self = this; + return self.getTrackInfo({ + id: track.id || track + }).then((data) => { + self.getAlbum({ + id: data.album.id + }).then((albumData) => { + var metaflacTag; + metaflacTag = '--remove-all-tags '; + metaflacTag += '--set-tag=\"ARTIST=' + data.artist.name + '\" '; + metaflacTag += '--set-tag=\"TITLE=' + data.title + '\" '; + metaflacTag += '--set-tag=\"ALBUM=' + data.album.title + '\" '; + metaflacTag += '--set-tag=\"TRACKNUMBER=' + data.trackNumber + '\" '; + metaflacTag += '--set-tag=\"COPYRIGHT=' + data.copyright + '\" '; + metaflacTag += '-set-tag="DATE=' + albumData.releaseDate.split("-")[0] + '" '; + if (track.coverPath) { + metaflacTag += '--import-picture-from=' + '\"' + track.coverPath + '\" '; + } + if (track.songPath) { + metaflacTag += '\"' + track.songPath + '\" '; + } + metaflacTag += '--add-replay-gain'; + return metaflacTag; + }) + }); + } + /** + * Base request function. + * @param {{method: String, params: Object, type: String}} + */ + TidalAPI.prototype._baseRequest = function(method, params, type) { + var self = this; + + if (!loggedIn) { + return tryLogin(this.authData).then(() => { + + return self._baseRequest(method, params, type); + }); + } + + this.sem1.take(() => { + setTimeout(this.sem1.leave, 1000); + }); + + params.countryCode = params.countryCode ? params.countryCode : _countryCode; + + return request.get({ + uri: method, + headers: { + 'Origin': 'http://listen.tidal.com', + 'X-Tidal-SessionId': _sessionID, + 'Pragma': 'no-cache' + }, + qs: params + }).then((data) => { + let body = JSON.parse(data); + if (params.types) { + var newBody = {}; + if (params.types.indexOf('tracks') > -1) { + newBody['tracks'] = body.tracks; + } + if (params.types.indexOf('artists') > -1) { + newBody['artists'] = body.artists; + } + if (params.types.indexOf('albums') > -1) { + newBody['albums'] = body.albums; + } + if (params.types.indexOf('videos') > -1) { + newBody['videos'] = body.videos; + } + if (params.types.indexOf('playlists') > -1) { + newBody['playlists'] = body.playlists; + } + return newBody; + } else { + return body; + } + }) + + } + + /** + * Base delete function. + * @param {{method: String, params: Object, type: String}} + */ + TidalAPI.prototype._baseDelete = function(method, params, formdata) { + var self = this; + + if (!loggedIn) { + + return tryLogin(this.authData) + .then(() => { + return self._baseDelete(method, params, formdata, type); + }) + + } + + params.countryCode = params.countryCode ? params.countryCode : _countryCode; + + this.sem1.take(() => { + setTimeout(this.sem1.leave, 1000); + }); + + return request({ + method: 'DELETE', + uri: method, + headers: { + 'Origin': 'https://listen.tidal.com', + 'If-None-Match': '"*"', + 'X-Tidal-SessionId': _sessionID + }, + form: formdata + }) + } + + /** + * Base post function. + * @param {{method: String, params: Object}} + */ + TidalAPI.prototype._basePost = function(method, params, formdata) { + + var self = this; + + if (!loggedIn) { + + return tryLogin(this.authData) + .then(() => { + return self._basePost(method, params, formdata); + }) + + } + + params.countryCode = params.countryCode ? params.countryCode : _countryCode; + + this.sem1.take(() => { + setTimeout(this.sem1.leave, 1000); + }); + + return request({ + method: 'POST', + uri: method, + headers: { + 'Origin': 'https://listen.tidal.com', + 'If-None-Match': '"*"', + 'X-Tidal-SessionId': _sessionID + }, + form: formdata + }) + + } + + module.exports = TidalAPI; From 2ab98d7d55db9ada67aa459dfb8f98eb97a09b3a Mon Sep 17 00:00:00 2001 From: Lucas Augusto Deters Date: Sat, 24 Aug 2019 19:17:49 -0300 Subject: [PATCH 12/22] 0.2.6 --- package-lock.json | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package-lock.json b/package-lock.json index 35b3e3c..293aea0 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "tidalpromise", - "version": "0.2.5", + "version": "0.2.6", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index c5e6d7f..b546763 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "tidalpromise", - "version": "0.2.5", + "version": "0.2.6", "description": "Unofficial Node.js TIDAL Promise API", "main": "./lib/api.js", "scripts": { From 76a594db9d7c7ade97fbc00243f369e5945c9946 Mon Sep 17 00:00:00 2001 From: Lucas Augusto Deters Date: Sat, 24 Aug 2019 19:18:36 -0300 Subject: [PATCH 13/22] upgrade in packages --- package-lock.json | 361 +++++++++++++++++++++------------------------- package.json | 4 +- 2 files changed, 165 insertions(+), 200 deletions(-) diff --git a/package-lock.json b/package-lock.json index 293aea0..1fc747d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -5,20 +5,23 @@ "requires": true, "dependencies": { "ajv": { - "version": "5.5.2", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-5.5.2.tgz", - "integrity": "sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU=", + "version": "6.10.2", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.10.2.tgz", + "integrity": "sha512-TXtUUEYHuaTEbLZWIKUr5pmBuhDLy+8KYtPYdcV8qC+pOZL+NKqYwvWSRrVXHn+ZmRRAu8vJTAznH7Oag6RVRw==", "requires": { - "co": "4.6.0", - "fast-deep-equal": "1.1.0", - "fast-json-stable-stringify": "2.0.0", - "json-schema-traverse": "0.3.1" + "fast-deep-equal": "^2.0.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" } }, "asn1": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.3.tgz", - "integrity": "sha1-2sh4dxPJlmhJ/IGAd36+nB3fO4Y=" + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz", + "integrity": "sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==", + "requires": { + "safer-buffer": "~2.1.0" + } }, "assert-plus": { "version": "1.0.0", @@ -36,25 +39,16 @@ "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=" }, "aws4": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.6.0.tgz", - "integrity": "sha1-g+9cqGCysy5KDe7e6MdxudtXRx4=" + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.8.0.tgz", + "integrity": "sha512-ReZxvNHIOv88FlT7rxcXIIC0fPt4KZqZbOlivyWtXLt8ESx84zd3kMC6iK5jVeS2qt+g7ftS7ye4fi06X5rtRQ==" }, "bcrypt-pbkdf": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.1.tgz", - "integrity": "sha1-Y7xdy2EzG5K8Bf1SiVPDNGKgb40=", - "optional": true, - "requires": { - "tweetnacl": "0.14.5" - } - }, - "boom": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/boom/-/boom-4.3.1.tgz", - "integrity": "sha1-T4owBctKfjiJ90kDD9JbluAdLjE=", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", + "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=", "requires": { - "hoek": "4.2.1" + "tweetnacl": "^0.14.3" } }, "caseless": { @@ -62,17 +56,12 @@ "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=" }, - "co": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", - "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=" - }, "combined-stream": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.6.tgz", - "integrity": "sha1-cj599ugBrFYTETp+RFqbactjKBg=", + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", "requires": { - "delayed-stream": "1.0.0" + "delayed-stream": "~1.0.0" } }, "commander": { @@ -86,30 +75,12 @@ "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" }, - "cryptiles": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/cryptiles/-/cryptiles-3.1.2.tgz", - "integrity": "sha1-qJ+7Ig9c4l7FboxKqKT9e1sNKf4=", - "requires": { - "boom": "5.2.0" - }, - "dependencies": { - "boom": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/boom/-/boom-5.2.0.tgz", - "integrity": "sha512-Z5BTk6ZRe4tXXQlkqftmsAUANpXmuwlsF5Oov8ThoMbQRzdGTA1ngYRW160GexgOgjsFOKJz0LYhoNi+2AMBUw==", - "requires": { - "hoek": "4.2.1" - } - } - } - }, "dashdash": { "version": "1.14.1", "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", "requires": { - "assert-plus": "1.0.0" + "assert-plus": "^1.0.0" } }, "debug": { @@ -133,12 +104,12 @@ "dev": true }, "ecc-jsbn": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.1.tgz", - "integrity": "sha1-D8c6ntXw1Tw4GTOYUj735UN3dQU=", - "optional": true, + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", + "integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=", "requires": { - "jsbn": "0.1.1" + "jsbn": "~0.1.0", + "safer-buffer": "^2.1.0" } }, "escape-string-regexp": { @@ -148,9 +119,9 @@ "dev": true }, "extend": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.1.tgz", - "integrity": "sha1-p1Xqe8Gt/MWjHOfnYtuq3F5jZEQ=" + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==" }, "extsprintf": { "version": "1.3.0", @@ -158,9 +129,9 @@ "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=" }, "fast-deep-equal": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz", - "integrity": "sha1-wFNHeBfIa1HaqFPIHgWbcz0CNhQ=" + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz", + "integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk=" }, "fast-json-stable-stringify": { "version": "2.0.0", @@ -173,13 +144,13 @@ "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=" }, "form-data": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.2.tgz", - "integrity": "sha1-SXBJi+YEwgwAXU9cI67NIda0kJk=", + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", + "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", "requires": { - "asynckit": "0.4.0", - "combined-stream": "1.0.6", - "mime-types": "2.1.18" + "asynckit": "^0.4.0", + "combined-stream": "^1.0.6", + "mime-types": "^2.1.12" } }, "getpass": { @@ -187,7 +158,7 @@ "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", "requires": { - "assert-plus": "1.0.0" + "assert-plus": "^1.0.0" } }, "glob": { @@ -196,8 +167,8 @@ "integrity": "sha1-Spc/Y1uRkPcV0QmH1cAP0oFevj0=", "dev": true, "requires": { - "inherits": "2.0.3", - "minimatch": "0.3.0" + "inherits": "2", + "minimatch": "0.3" } }, "growl": { @@ -212,38 +183,22 @@ "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=" }, "har-validator": { - "version": "5.0.3", - "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.0.3.tgz", - "integrity": "sha1-ukAsJmGU8VlW7xXg/PJCmT9qff0=", - "requires": { - "ajv": "5.5.2", - "har-schema": "2.0.0" - } - }, - "hawk": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/hawk/-/hawk-6.0.2.tgz", - "integrity": "sha512-miowhl2+U7Qle4vdLqDdPt9m09K6yZhkLDTWGoUiUzrQCn+mHHSmfJgAyGaLRZbPmTqfFFjRV1QWCW0VWUJBbQ==", + "version": "5.1.3", + "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.3.tgz", + "integrity": "sha512-sNvOCzEQNr/qrvJgc3UG/kD4QtlHycrzwS+6mfTrrSq97BvaYcPZZI1ZSqGSPR73Cxn4LKTD4PttRwfU7jWq5g==", "requires": { - "boom": "4.3.1", - "cryptiles": "3.1.2", - "hoek": "4.2.1", - "sntp": "2.1.0" + "ajv": "^6.5.5", + "har-schema": "^2.0.0" } }, - "hoek": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/hoek/-/hoek-4.2.1.tgz", - "integrity": "sha512-QLg82fGkfnJ/4iy1xZ81/9SIJiq1NGFUMGs6ParyjBZr6jW2Ufj/snDqTHixNlHdPNwN2RLVD0Pi3igeK9+JfA==" - }, "http-signature": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", "requires": { - "assert-plus": "1.0.0", - "jsprim": "1.4.1", - "sshpk": "1.14.1" + "assert-plus": "^1.0.0", + "jsprim": "^1.2.2", + "sshpk": "^1.7.0" } }, "inherits": { @@ -289,8 +244,7 @@ "jsbn": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", - "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=", - "optional": true + "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=" }, "json-schema": { "version": "0.2.3", @@ -298,9 +252,9 @@ "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=" }, "json-schema-traverse": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz", - "integrity": "sha1-NJptRMU6Ud6JtAgFxdXlm0F9M0A=" + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" }, "json-stringify-safe": { "version": "5.0.1", @@ -319,9 +273,9 @@ } }, "lodash": { - "version": "4.17.5", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.5.tgz", - "integrity": "sha512-svL3uiZf1RwhH+cWrfZn3A4+U58wbP0tGVTLQPbjplZxZ8ROD9VLuNgsRniTlLe7OlSqR79RUehXgpBW/s0IQw==" + "version": "4.17.15", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", + "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==" }, "lru-cache": { "version": "2.7.3", @@ -330,16 +284,16 @@ "dev": true }, "mime-db": { - "version": "1.33.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.33.0.tgz", - "integrity": "sha512-BHJ/EKruNIqJf/QahvxwQZXKygOQ256myeN/Ew+THcAa5q+PjyTTMMeNQC4DZw5AwfvelsUrA6B67NKMqXDbzQ==" + "version": "1.40.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.40.0.tgz", + "integrity": "sha512-jYdeOMPy9vnxEqFRRo6ZvTZ8d9oPb+k18PKoYNYUe2stVEBPPwsln/qWzdbmaIvnhZ9v2P+CuecK+fpUfsV2mA==" }, "mime-types": { - "version": "2.1.18", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.18.tgz", - "integrity": "sha512-lc/aahn+t4/SWV/qcmumYjymLsWfN3ELhpmVuUFjgsORruuZPVSwAQryq+HHGvO/SI2KVX26bx+En+zhM8g8hQ==", + "version": "2.1.24", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.24.tgz", + "integrity": "sha512-WaFHS3MCl5fapm3oLxU4eYDw77IQM2ACcxQ9RIxfaC3ooc6PFuBMGZZsYpvoXS5D5QTWPieo1jjLdAm3TBP3cQ==", "requires": { - "mime-db": "1.33.0" + "mime-db": "1.40.0" } }, "minimatch": { @@ -348,8 +302,8 @@ "integrity": "sha1-J12O2qxPG7MyZHIInnlJyDlGmd0=", "dev": true, "requires": { - "lru-cache": "2.7.3", - "sigmund": "1.0.1" + "lru-cache": "2", + "sigmund": "~1.0.0" } }, "minimist": { @@ -392,76 +346,84 @@ "dev": true }, "oauth-sign": { - "version": "0.8.2", - "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.8.2.tgz", - "integrity": "sha1-Rqarfwrq2N6unsBWV4C31O/rnUM=" + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", + "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==" }, "performance-now": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=" }, + "psl": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/psl/-/psl-1.3.0.tgz", + "integrity": "sha512-avHdspHO+9rQTLbv1RO+MPYeP/SzsCoxofjVnHanETfQhTJrmB0HlDoW+EiN/R+C0BZ+gERab9NY0lPN2TxNag==" + }, "punycode": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", - "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=" + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==" }, "qs": { - "version": "6.5.1", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.1.tgz", - "integrity": "sha512-eRzhrN1WSINYCDCbrz796z37LOe3m5tmW7RQf6oBntukAG1nmovJvhnwHHRMAfeoItc1m2Hk02WER2aQ/iqs+A==" + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", + "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==" }, "request": { - "version": "2.85.0", - "resolved": "https://registry.npmjs.org/request/-/request-2.85.0.tgz", - "integrity": "sha512-8H7Ehijd4js+s6wuVPLjwORxD4zeuyjYugprdOXlPSqaApmL/QOy+EB/beICHVCHkGMKNh5rvihb5ov+IDw4mg==", + "version": "2.88.0", + "resolved": "https://registry.npmjs.org/request/-/request-2.88.0.tgz", + "integrity": "sha512-NAqBSrijGLZdM0WZNsInLJpkJokL72XYjUpnB0iwsRgxh7dB6COrHnTBNwN0E+lHDAJzu7kLAkDeY08z2/A0hg==", "requires": { - "aws-sign2": "0.7.0", - "aws4": "1.6.0", - "caseless": "0.12.0", - "combined-stream": "1.0.6", - "extend": "3.0.1", - "forever-agent": "0.6.1", - "form-data": "2.3.2", - "har-validator": "5.0.3", - "hawk": "6.0.2", - "http-signature": "1.2.0", - "is-typedarray": "1.0.0", - "isstream": "0.1.2", - "json-stringify-safe": "5.0.1", - "mime-types": "2.1.18", - "oauth-sign": "0.8.2", - "performance-now": "2.1.0", - "qs": "6.5.1", - "safe-buffer": "5.1.1", - "stringstream": "0.0.5", - "tough-cookie": "2.3.4", - "tunnel-agent": "0.6.0", - "uuid": "3.2.1" + "aws-sign2": "~0.7.0", + "aws4": "^1.8.0", + "caseless": "~0.12.0", + "combined-stream": "~1.0.6", + "extend": "~3.0.2", + "forever-agent": "~0.6.1", + "form-data": "~2.3.2", + "har-validator": "~5.1.0", + "http-signature": "~1.2.0", + "is-typedarray": "~1.0.0", + "isstream": "~0.1.2", + "json-stringify-safe": "~5.0.1", + "mime-types": "~2.1.19", + "oauth-sign": "~0.9.0", + "performance-now": "^2.1.0", + "qs": "~6.5.2", + "safe-buffer": "^5.1.2", + "tough-cookie": "~2.4.3", + "tunnel-agent": "^0.6.0", + "uuid": "^3.3.2" } }, "request-promise-core": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/request-promise-core/-/request-promise-core-1.1.1.tgz", - "integrity": "sha1-Pu4AssWqgyOc+wTFcA2jb4HNCLY=", + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/request-promise-core/-/request-promise-core-1.1.2.tgz", + "integrity": "sha512-UHYyq1MO8GsefGEt7EprS8UrXsm1TxEvFUX1IMTuSLU2Rh7fTIdFtl8xD7JiEYiWU2dl+NYAjCTksTehQUxPag==", "requires": { - "lodash": "4.17.5" + "lodash": "^4.17.11" } }, "request-promise-native": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/request-promise-native/-/request-promise-native-1.0.5.tgz", - "integrity": "sha1-UoF3D2jgyXGeUWP9P6tIIhX0/aU=", + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/request-promise-native/-/request-promise-native-1.0.7.tgz", + "integrity": "sha512-rIMnbBdgNViL37nZ1b3L/VfPOpSi0TqVDQPAvO6U14lMzOLrt5nilxCQqtDKhZeDiW0/hkCXGoQjhgJd/tCh6w==", "requires": { - "request-promise-core": "1.1.1", - "stealthy-require": "1.1.1", - "tough-cookie": "2.3.4" + "request-promise-core": "1.1.2", + "stealthy-require": "^1.1.1", + "tough-cookie": "^2.3.3" } }, "safe-buffer": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz", - "integrity": "sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg==" + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.0.tgz", + "integrity": "sha512-fZEwUGbVl7kouZs1jCdMLdt95hdIv0ZeHg6L7qPeciMZhZ+/gdesW4wgTARkrFWEpspjEATAzUGPG8N2jJiwbg==" + }, + "safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" }, "semaphore": { "version": "1.1.0", @@ -474,27 +436,20 @@ "integrity": "sha1-P/IfGYytIXX587eBhT/ZTQ0ZtZA=", "dev": true }, - "sntp": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/sntp/-/sntp-2.1.0.tgz", - "integrity": "sha512-FL1b58BDrqS3A11lJ0zEdnJ3UOKqVxawAkF3k7F0CVN7VQ34aZrV+G8BZ1WC9ZL7NyrwsW0oviwsWDgRuVYtJg==", - "requires": { - "hoek": "4.2.1" - } - }, "sshpk": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.14.1.tgz", - "integrity": "sha1-Ew9Zde3a2WPx1W+SuaxsUfqfg+s=", + "version": "1.16.1", + "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.16.1.tgz", + "integrity": "sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg==", "requires": { - "asn1": "0.2.3", - "assert-plus": "1.0.0", - "bcrypt-pbkdf": "1.0.1", - "dashdash": "1.14.1", - "ecc-jsbn": "0.1.1", - "getpass": "0.1.7", - "jsbn": "0.1.1", - "tweetnacl": "0.14.5" + "asn1": "~0.2.3", + "assert-plus": "^1.0.0", + "bcrypt-pbkdf": "^1.0.0", + "dashdash": "^1.12.0", + "ecc-jsbn": "~0.1.1", + "getpass": "^0.1.1", + "jsbn": "~0.1.0", + "safer-buffer": "^2.0.2", + "tweetnacl": "~0.14.0" } }, "stealthy-require": { @@ -502,11 +457,6 @@ "resolved": "https://registry.npmjs.org/stealthy-require/-/stealthy-require-1.1.1.tgz", "integrity": "sha1-NbCYdbT/SfJqd35QmzCQoyJr8ks=" }, - "stringstream": { - "version": "0.0.5", - "resolved": "https://registry.npmjs.org/stringstream/-/stringstream-0.0.5.tgz", - "integrity": "sha1-TkhM1N5aC7vuGORjB3EKioFiGHg=" - }, "supports-color": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-1.2.0.tgz", @@ -520,11 +470,19 @@ "dev": true }, "tough-cookie": { - "version": "2.3.4", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.3.4.tgz", - "integrity": "sha512-TZ6TTfI5NtZnuyy/Kecv+CnoROnyXn2DN97LontgQpCwsX2XyLYCC0ENhYkehSOwAp8rTQKc/NUIF7BkQ5rKLA==", + "version": "2.4.3", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.4.3.tgz", + "integrity": "sha512-Q5srk/4vDM54WJsJio3XNn6K2sCG+CQ8G5Wz6bZhRZoAe/+TxjWB/GlFAnYEbkYVlON9FMk/fE3h2RLpPXo4lQ==", "requires": { - "punycode": "1.4.1" + "psl": "^1.1.24", + "punycode": "^1.4.1" + }, + "dependencies": { + "punycode": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", + "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=" + } } }, "tunnel-agent": { @@ -532,28 +490,35 @@ "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", "requires": { - "safe-buffer": "5.1.1" + "safe-buffer": "^5.0.1" } }, "tweetnacl": { "version": "0.14.5", "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", - "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=", - "optional": true + "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=" + }, + "uri-js": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz", + "integrity": "sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ==", + "requires": { + "punycode": "^2.1.0" + } }, "uuid": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.2.1.tgz", - "integrity": "sha512-jZnMwlb9Iku/O3smGWvZhauCf6cvvpKi4BKRiliS3cxnI+Gz9j5MEpTz2UFuXiKPJocb7gnsLHwiS05ige5BEA==" + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.3.tgz", + "integrity": "sha512-pW0No1RGHgzlpHJO1nsVrHKpOEIxkGg1xB+v0ZmdNH5OAeAwzAVrCnI2/6Mtx+Uys6iaylxa+D3g4j63IKKjSQ==" }, "verror": { "version": "1.10.0", "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", "requires": { - "assert-plus": "1.0.0", + "assert-plus": "^1.0.0", "core-util-is": "1.0.2", - "extsprintf": "1.3.0" + "extsprintf": "^1.2.0" } } } diff --git a/package.json b/package.json index b546763..2e19f53 100644 --- a/package.json +++ b/package.json @@ -24,8 +24,8 @@ }, "homepage": "https://github.com/deters/TidalPromise#readme", "dependencies": { - "request": "^2.69.0", - "request-promise-native": "^1.0.5", + "request": "^2.88.0", + "request-promise-native": "^1.0.7", "semaphore": "^1.1.0" }, "devDependencies": { From d16cf680dee8f5c97aa9a842b678da9d54c6753e Mon Sep 17 00:00:00 2001 From: Lucas Augusto Deters Date: Sat, 24 Aug 2019 19:18:52 -0300 Subject: [PATCH 14/22] 0.2.7 --- package-lock.json | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package-lock.json b/package-lock.json index 1fc747d..141e678 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "tidalpromise", - "version": "0.2.6", + "version": "0.2.7", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index 2e19f53..a79e92e 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "tidalpromise", - "version": "0.2.6", + "version": "0.2.7", "description": "Unofficial Node.js TIDAL Promise API", "main": "./lib/api.js", "scripts": { From 6469967d379c7f0da47cb2d17914ea0822804971 Mon Sep 17 00:00:00 2001 From: Lucas Augusto Deters Date: Sun, 25 Aug 2019 23:02:28 -0300 Subject: [PATCH 15/22] fixed get id --- lib/api.js | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/lib/api.js b/lib/api.js index c9257db..3fc392f 100644 --- a/lib/api.js +++ b/lib/api.js @@ -131,16 +131,20 @@ function tryLogin(authInfo) { * Return userID. */ TidalAPI.prototype.getMyID = function() { + var self = this; - if (!loggedIn) { - return tryLogin(this.authData).then(() => { + return new Promise((resolve, reject) => { - return self.getMyID(); - }); - } + if (!loggedIn) { + tryLogin(this.authData).then(() => { + resolve(_userID); + }); + } else { + resolve(_userID); + } + }); - return _userID; } /** * Global search. From da20d09b721a19538f7e4e456ff754d2ea3b24ff Mon Sep 17 00:00:00 2001 From: Lucas Augusto Deters Date: Sun, 25 Aug 2019 23:02:50 -0300 Subject: [PATCH 16/22] 0.2.8 --- package-lock.json | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package-lock.json b/package-lock.json index 141e678..3cd4af2 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "tidalpromise", - "version": "0.2.7", + "version": "0.2.8", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index a79e92e..52c6027 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "tidalpromise", - "version": "0.2.7", + "version": "0.2.8", "description": "Unofficial Node.js TIDAL Promise API", "main": "./lib/api.js", "scripts": { From 00b414d9859d1c19a2d4136d52afebc9f67f9a02 Mon Sep 17 00:00:00 2001 From: Lucas Augusto Deters Date: Sun, 25 Aug 2019 23:13:49 -0300 Subject: [PATCH 17/22] fixed:w --- lib/api.js | 341 ++++++++++++++++++++++++++--------------------------- 1 file changed, 169 insertions(+), 172 deletions(-) diff --git a/lib/api.js b/lib/api.js index 3fc392f..567190c 100644 --- a/lib/api.js +++ b/lib/api.js @@ -131,20 +131,16 @@ function tryLogin(authInfo) { * Return userID. */ TidalAPI.prototype.getMyID = function() { - var self = this; - return new Promise((resolve, reject) => { + if (!loggedIn) { + return tryLogin(this.authData).then(() => { - if (!loggedIn) { - tryLogin(this.authData).then(() => { - resolve(_userID); - }); - } else { - resolve(_userID); - } - }); + return self.getMyID(); + }); + } + return _userID; } /** * Global search. @@ -400,193 +396,194 @@ TidalAPI.prototype.getVideoStreamURL = function(track) { * @param {{id: Number}} */ TidalAPI.prototype.getUser = function(user) { + var self = this; + return this.getMyID().then(id => { + return self._baseRequest('/users/' + (id || user), { + limit: user.limit || 999, + offset: user.offset || 0 + }, 'user'); + }) +} + +/** + * Get user playlists. + * @param {{id: Number}} + */ +TidalAPI.prototype.getPlaylists = function(user) { var self = this; return this.getMyID().then(id => { - return self._baseRequest('/users/' + (id || user), { + return self._baseRequest('/users/' + (id || user) + "/playlists", { limit: user.limit || 999, - offset: user.offset || 0 - }, 'user'); + offset: user.offset || 0, + countryCode: _countryCode + }); } } + /** - * Get user playlists. + * Get track stream URL. + * @param {id: String, res: Number} + */ + + TidalAPI.prototype.getArtURL = function(id, width, height) { + width = width || 1280; + height = height || 1280; + return 'https://resources.tidal.com/images/' + id.replace(/-/g, '/') + '/' + width + 'x' + height + '.jpg'; + } + /** + * Generate Metaflac tags. * @param {{id: Number}} */ - TidalAPI.prototype.getPlaylists = function(user) { - var self = this; - return this.getMyID().then(id => { - return self._baseRequest('/users/' + (id || user) + "/playlists", { - limit: user.limit || 999, - offset: user.offset || 0, - countryCode: _countryCode - }); + TidalAPI.prototype.genMetaflacTags = function(track) { + var self = this; + return self.getTrackInfo({ + id: track.id || track + }).then((data) => { + self.getAlbum({ + id: data.album.id + }).then((albumData) => { + var metaflacTag; + metaflacTag = '--remove-all-tags '; + metaflacTag += '--set-tag=\"ARTIST=' + data.artist.name + '\" '; + metaflacTag += '--set-tag=\"TITLE=' + data.title + '\" '; + metaflacTag += '--set-tag=\"ALBUM=' + data.album.title + '\" '; + metaflacTag += '--set-tag=\"TRACKNUMBER=' + data.trackNumber + '\" '; + metaflacTag += '--set-tag=\"COPYRIGHT=' + data.copyright + '\" '; + metaflacTag += '-set-tag="DATE=' + albumData.releaseDate.split("-")[0] + '" '; + if (track.coverPath) { + metaflacTag += '--import-picture-from=' + '\"' + track.coverPath + '\" '; } - } + if (track.songPath) { + metaflacTag += '\"' + track.songPath + '\" '; + } + metaflacTag += '--add-replay-gain'; + return metaflacTag; + }) + }); + } + /** + * Base request function. + * @param {{method: String, params: Object, type: String}} + */ + TidalAPI.prototype._baseRequest = function(method, params, type) { + var self = this; - /** - * Get track stream URL. - * @param {id: String, res: Number} - */ + if (!loggedIn) { + return tryLogin(this.authData).then(() => { - TidalAPI.prototype.getArtURL = function(id, width, height) { - width = width || 1280; - height = height || 1280; - return 'https://resources.tidal.com/images/' + id.replace(/-/g, '/') + '/' + width + 'x' + height + '.jpg'; - } - /** - * Generate Metaflac tags. - * @param {{id: Number}} - */ - TidalAPI.prototype.genMetaflacTags = function(track) { - var self = this; - return self.getTrackInfo({ - id: track.id || track - }).then((data) => { - self.getAlbum({ - id: data.album.id - }).then((albumData) => { - var metaflacTag; - metaflacTag = '--remove-all-tags '; - metaflacTag += '--set-tag=\"ARTIST=' + data.artist.name + '\" '; - metaflacTag += '--set-tag=\"TITLE=' + data.title + '\" '; - metaflacTag += '--set-tag=\"ALBUM=' + data.album.title + '\" '; - metaflacTag += '--set-tag=\"TRACKNUMBER=' + data.trackNumber + '\" '; - metaflacTag += '--set-tag=\"COPYRIGHT=' + data.copyright + '\" '; - metaflacTag += '-set-tag="DATE=' + albumData.releaseDate.split("-")[0] + '" '; - if (track.coverPath) { - metaflacTag += '--import-picture-from=' + '\"' + track.coverPath + '\" '; - } - if (track.songPath) { - metaflacTag += '\"' + track.songPath + '\" '; - } - metaflacTag += '--add-replay-gain'; - return metaflacTag; - }) - }); - } - /** - * Base request function. - * @param {{method: String, params: Object, type: String}} - */ - TidalAPI.prototype._baseRequest = function(method, params, type) { - var self = this; - - if (!loggedIn) { - return tryLogin(this.authData).then(() => { - - return self._baseRequest(method, params, type); - }); - } + return self._baseRequest(method, params, type); + }); + } - this.sem1.take(() => { - setTimeout(this.sem1.leave, 1000); - }); - - params.countryCode = params.countryCode ? params.countryCode : _countryCode; - - return request.get({ - uri: method, - headers: { - 'Origin': 'http://listen.tidal.com', - 'X-Tidal-SessionId': _sessionID, - 'Pragma': 'no-cache' - }, - qs: params - }).then((data) => { - let body = JSON.parse(data); - if (params.types) { - var newBody = {}; - if (params.types.indexOf('tracks') > -1) { - newBody['tracks'] = body.tracks; - } - if (params.types.indexOf('artists') > -1) { - newBody['artists'] = body.artists; - } - if (params.types.indexOf('albums') > -1) { - newBody['albums'] = body.albums; - } - if (params.types.indexOf('videos') > -1) { - newBody['videos'] = body.videos; - } - if (params.types.indexOf('playlists') > -1) { - newBody['playlists'] = body.playlists; - } - return newBody; - } else { - return body; - } - }) + this.sem1.take(() => { + setTimeout(this.sem1.leave, 1000); + }); + params.countryCode = params.countryCode ? params.countryCode : _countryCode; + + return request.get({ + uri: method, + headers: { + 'Origin': 'http://listen.tidal.com', + 'X-Tidal-SessionId': _sessionID, + 'Pragma': 'no-cache' + }, + qs: params + }).then((data) => { + let body = JSON.parse(data); + if (params.types) { + var newBody = {}; + if (params.types.indexOf('tracks') > -1) { + newBody['tracks'] = body.tracks; + } + if (params.types.indexOf('artists') > -1) { + newBody['artists'] = body.artists; + } + if (params.types.indexOf('albums') > -1) { + newBody['albums'] = body.albums; + } + if (params.types.indexOf('videos') > -1) { + newBody['videos'] = body.videos; + } + if (params.types.indexOf('playlists') > -1) { + newBody['playlists'] = body.playlists; + } + return newBody; + } else { + return body; } + }) - /** - * Base delete function. - * @param {{method: String, params: Object, type: String}} - */ - TidalAPI.prototype._baseDelete = function(method, params, formdata) { - var self = this; - - if (!loggedIn) { + } - return tryLogin(this.authData) - .then(() => { - return self._baseDelete(method, params, formdata, type); - }) + /** + * Base delete function. + * @param {{method: String, params: Object, type: String}} + */ + TidalAPI.prototype._baseDelete = function(method, params, formdata) { + var self = this; - } + if (!loggedIn) { - params.countryCode = params.countryCode ? params.countryCode : _countryCode; - - this.sem1.take(() => { - setTimeout(this.sem1.leave, 1000); - }); - - return request({ - method: 'DELETE', - uri: method, - headers: { - 'Origin': 'https://listen.tidal.com', - 'If-None-Match': '"*"', - 'X-Tidal-SessionId': _sessionID - }, - form: formdata + return tryLogin(this.authData) + .then(() => { + return self._baseDelete(method, params, formdata, type); }) - } - /** - * Base post function. - * @param {{method: String, params: Object}} - */ - TidalAPI.prototype._basePost = function(method, params, formdata) { + } + + params.countryCode = params.countryCode ? params.countryCode : _countryCode; - var self = this; + this.sem1.take(() => { + setTimeout(this.sem1.leave, 1000); + }); - if (!loggedIn) { + return request({ + method: 'DELETE', + uri: method, + headers: { + 'Origin': 'https://listen.tidal.com', + 'If-None-Match': '"*"', + 'X-Tidal-SessionId': _sessionID + }, + form: formdata + }) + } - return tryLogin(this.authData) - .then(() => { - return self._basePost(method, params, formdata); - }) + /** + * Base post function. + * @param {{method: String, params: Object}} + */ + TidalAPI.prototype._basePost = function(method, params, formdata) { - } + var self = this; + + if (!loggedIn) { - params.countryCode = params.countryCode ? params.countryCode : _countryCode; - - this.sem1.take(() => { - setTimeout(this.sem1.leave, 1000); - }); - - return request({ - method: 'POST', - uri: method, - headers: { - 'Origin': 'https://listen.tidal.com', - 'If-None-Match': '"*"', - 'X-Tidal-SessionId': _sessionID - }, - form: formdata + return tryLogin(this.authData) + .then(() => { + return self._basePost(method, params, formdata); }) - } + } + + params.countryCode = params.countryCode ? params.countryCode : _countryCode; + + this.sem1.take(() => { + setTimeout(this.sem1.leave, 1000); + }); + + return request({ + method: 'POST', + uri: method, + headers: { + 'Origin': 'https://listen.tidal.com', + 'If-None-Match': '"*"', + 'X-Tidal-SessionId': _sessionID + }, + form: formdata + }) + + } - module.exports = TidalAPI; + module.exports = TidalAPI; From ca9719e96fa3391c575babbf8caf85efd4b033c7 Mon Sep 17 00:00:00 2001 From: Lucas Augusto Deters Date: Sun, 25 Aug 2019 23:14:05 -0300 Subject: [PATCH 18/22] 0.2.9 --- package-lock.json | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package-lock.json b/package-lock.json index 3cd4af2..62709dc 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "tidalpromise", - "version": "0.2.8", + "version": "0.2.9", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index 52c6027..4cc2f95 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "tidalpromise", - "version": "0.2.8", + "version": "0.2.9", "description": "Unofficial Node.js TIDAL Promise API", "main": "./lib/api.js", "scripts": { From 3b167311e619271262d2d8ccf50c029d26f81a89 Mon Sep 17 00:00:00 2001 From: Lucas Augusto Deters Date: Sun, 25 Aug 2019 23:17:33 -0300 Subject: [PATCH 19/22] fixed bug --- lib/api.js | 314 ++++++++++++++++++++++++++--------------------------- 1 file changed, 157 insertions(+), 157 deletions(-) diff --git a/lib/api.js b/lib/api.js index 567190c..7df96e3 100644 --- a/lib/api.js +++ b/lib/api.js @@ -410,180 +410,180 @@ TidalAPI.prototype.getUser = function(user) { * @param {{id: Number}} */ TidalAPI.prototype.getPlaylists = function(user) { - var self = this; - return this.getMyID().then(id => { - return self._baseRequest('/users/' + (id || user) + "/playlists", { - limit: user.limit || 999, - offset: user.offset || 0, - countryCode: _countryCode - }); - } - } + var self = this; + return this.getMyID().then(id => { + return self._baseRequest('/users/' + (id || user) + "/playlists", { + limit: user.limit || 999, + offset: user.offset || 0, + countryCode: _countryCode + }); + }) +} - /** - * Get track stream URL. - * @param {id: String, res: Number} - */ +/** + * Get track stream URL. + * @param {id: String, res: Number} + */ - TidalAPI.prototype.getArtURL = function(id, width, height) { - width = width || 1280; - height = height || 1280; - return 'https://resources.tidal.com/images/' + id.replace(/-/g, '/') + '/' + width + 'x' + height + '.jpg'; - } - /** - * Generate Metaflac tags. - * @param {{id: Number}} - */ - TidalAPI.prototype.genMetaflacTags = function(track) { - var self = this; - return self.getTrackInfo({ - id: track.id || track - }).then((data) => { - self.getAlbum({ - id: data.album.id - }).then((albumData) => { - var metaflacTag; - metaflacTag = '--remove-all-tags '; - metaflacTag += '--set-tag=\"ARTIST=' + data.artist.name + '\" '; - metaflacTag += '--set-tag=\"TITLE=' + data.title + '\" '; - metaflacTag += '--set-tag=\"ALBUM=' + data.album.title + '\" '; - metaflacTag += '--set-tag=\"TRACKNUMBER=' + data.trackNumber + '\" '; - metaflacTag += '--set-tag=\"COPYRIGHT=' + data.copyright + '\" '; - metaflacTag += '-set-tag="DATE=' + albumData.releaseDate.split("-")[0] + '" '; - if (track.coverPath) { - metaflacTag += '--import-picture-from=' + '\"' + track.coverPath + '\" '; - } - if (track.songPath) { - metaflacTag += '\"' + track.songPath + '\" '; - } - metaflacTag += '--add-replay-gain'; - return metaflacTag; - }) - }); - } - /** - * Base request function. - * @param {{method: String, params: Object, type: String}} - */ - TidalAPI.prototype._baseRequest = function(method, params, type) { - var self = this; - - if (!loggedIn) { - return tryLogin(this.authData).then(() => { - - return self._baseRequest(method, params, type); - }); +TidalAPI.prototype.getArtURL = function(id, width, height) { + width = width || 1280; + height = height || 1280; + return 'https://resources.tidal.com/images/' + id.replace(/-/g, '/') + '/' + width + 'x' + height + '.jpg'; +} +/** + * Generate Metaflac tags. + * @param {{id: Number}} + */ +TidalAPI.prototype.genMetaflacTags = function(track) { + var self = this; + return self.getTrackInfo({ + id: track.id || track + }).then((data) => { + self.getAlbum({ + id: data.album.id + }).then((albumData) => { + var metaflacTag; + metaflacTag = '--remove-all-tags '; + metaflacTag += '--set-tag=\"ARTIST=' + data.artist.name + '\" '; + metaflacTag += '--set-tag=\"TITLE=' + data.title + '\" '; + metaflacTag += '--set-tag=\"ALBUM=' + data.album.title + '\" '; + metaflacTag += '--set-tag=\"TRACKNUMBER=' + data.trackNumber + '\" '; + metaflacTag += '--set-tag=\"COPYRIGHT=' + data.copyright + '\" '; + metaflacTag += '-set-tag="DATE=' + albumData.releaseDate.split("-")[0] + '" '; + if (track.coverPath) { + metaflacTag += '--import-picture-from=' + '\"' + track.coverPath + '\" '; } + if (track.songPath) { + metaflacTag += '\"' + track.songPath + '\" '; + } + metaflacTag += '--add-replay-gain'; + return metaflacTag; + }) + }); +} +/** + * Base request function. + * @param {{method: String, params: Object, type: String}} + */ +TidalAPI.prototype._baseRequest = function(method, params, type) { + var self = this; - this.sem1.take(() => { - setTimeout(this.sem1.leave, 1000); - }); - - params.countryCode = params.countryCode ? params.countryCode : _countryCode; - - return request.get({ - uri: method, - headers: { - 'Origin': 'http://listen.tidal.com', - 'X-Tidal-SessionId': _sessionID, - 'Pragma': 'no-cache' - }, - qs: params - }).then((data) => { - let body = JSON.parse(data); - if (params.types) { - var newBody = {}; - if (params.types.indexOf('tracks') > -1) { - newBody['tracks'] = body.tracks; - } - if (params.types.indexOf('artists') > -1) { - newBody['artists'] = body.artists; - } - if (params.types.indexOf('albums') > -1) { - newBody['albums'] = body.albums; - } - if (params.types.indexOf('videos') > -1) { - newBody['videos'] = body.videos; - } - if (params.types.indexOf('playlists') > -1) { - newBody['playlists'] = body.playlists; - } - return newBody; - } else { - return body; - } - }) - - } + if (!loggedIn) { + return tryLogin(this.authData).then(() => { - /** - * Base delete function. - * @param {{method: String, params: Object, type: String}} - */ - TidalAPI.prototype._baseDelete = function(method, params, formdata) { - var self = this; + return self._baseRequest(method, params, type); + }); + } - if (!loggedIn) { + this.sem1.take(() => { + setTimeout(this.sem1.leave, 1000); + }); - return tryLogin(this.authData) - .then(() => { - return self._baseDelete(method, params, formdata, type); - }) + params.countryCode = params.countryCode ? params.countryCode : _countryCode; + return request.get({ + uri: method, + headers: { + 'Origin': 'http://listen.tidal.com', + 'X-Tidal-SessionId': _sessionID, + 'Pragma': 'no-cache' + }, + qs: params + }).then((data) => { + let body = JSON.parse(data); + if (params.types) { + var newBody = {}; + if (params.types.indexOf('tracks') > -1) { + newBody['tracks'] = body.tracks; + } + if (params.types.indexOf('artists') > -1) { + newBody['artists'] = body.artists; + } + if (params.types.indexOf('albums') > -1) { + newBody['albums'] = body.albums; + } + if (params.types.indexOf('videos') > -1) { + newBody['videos'] = body.videos; } + if (params.types.indexOf('playlists') > -1) { + newBody['playlists'] = body.playlists; + } + return newBody; + } else { + return body; + } + }) + +} + +/** + * Base delete function. + * @param {{method: String, params: Object, type: String}} + */ +TidalAPI.prototype._baseDelete = function(method, params, formdata) { + var self = this; + + if (!loggedIn) { - params.countryCode = params.countryCode ? params.countryCode : _countryCode; - - this.sem1.take(() => { - setTimeout(this.sem1.leave, 1000); - }); - - return request({ - method: 'DELETE', - uri: method, - headers: { - 'Origin': 'https://listen.tidal.com', - 'If-None-Match': '"*"', - 'X-Tidal-SessionId': _sessionID - }, - form: formdata + return tryLogin(this.authData) + .then(() => { + return self._baseDelete(method, params, formdata, type); }) - } - /** - * Base post function. - * @param {{method: String, params: Object}} - */ - TidalAPI.prototype._basePost = function(method, params, formdata) { + } - var self = this; + params.countryCode = params.countryCode ? params.countryCode : _countryCode; - if (!loggedIn) { + this.sem1.take(() => { + setTimeout(this.sem1.leave, 1000); + }); - return tryLogin(this.authData) - .then(() => { - return self._basePost(method, params, formdata); - }) + return request({ + method: 'DELETE', + uri: method, + headers: { + 'Origin': 'https://listen.tidal.com', + 'If-None-Match': '"*"', + 'X-Tidal-SessionId': _sessionID + }, + form: formdata + }) +} - } +/** + * Base post function. + * @param {{method: String, params: Object}} + */ +TidalAPI.prototype._basePost = function(method, params, formdata) { + + var self = this; + + if (!loggedIn) { - params.countryCode = params.countryCode ? params.countryCode : _countryCode; - - this.sem1.take(() => { - setTimeout(this.sem1.leave, 1000); - }); - - return request({ - method: 'POST', - uri: method, - headers: { - 'Origin': 'https://listen.tidal.com', - 'If-None-Match': '"*"', - 'X-Tidal-SessionId': _sessionID - }, - form: formdata + return tryLogin(this.authData) + .then(() => { + return self._basePost(method, params, formdata); }) - } + } + + params.countryCode = params.countryCode ? params.countryCode : _countryCode; + + this.sem1.take(() => { + setTimeout(this.sem1.leave, 1000); + }); + + return request({ + method: 'POST', + uri: method, + headers: { + 'Origin': 'https://listen.tidal.com', + 'If-None-Match': '"*"', + 'X-Tidal-SessionId': _sessionID + }, + form: formdata + }) + +} - module.exports = TidalAPI; +module.exports = TidalAPI; From b12e59bec8720c838230c0201b851c06d2083e8d Mon Sep 17 00:00:00 2001 From: Lucas Augusto Deters Date: Sun, 25 Aug 2019 23:17:40 -0300 Subject: [PATCH 20/22] 0.2.10 --- package-lock.json | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package-lock.json b/package-lock.json index 62709dc..c3a4fd9 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "tidalpromise", - "version": "0.2.9", + "version": "0.2.10", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index 4cc2f95..49780c3 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "tidalpromise", - "version": "0.2.9", + "version": "0.2.10", "description": "Unofficial Node.js TIDAL Promise API", "main": "./lib/api.js", "scripts": { From bee3660e1eebc613a1f9f2aac619beb7a62b8490 Mon Sep 17 00:00:00 2001 From: Lucas Augusto Deters Date: Mon, 2 Sep 2019 10:04:30 -0300 Subject: [PATCH 21/22] Fixed bug in getMyID --- lib/api.js | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/lib/api.js b/lib/api.js index 7df96e3..dfd454a 100644 --- a/lib/api.js +++ b/lib/api.js @@ -131,16 +131,20 @@ function tryLogin(authInfo) { * Return userID. */ TidalAPI.prototype.getMyID = function() { + var self = this; - if (!loggedIn) { - return tryLogin(this.authData).then(() => { + return new Promise((resolve, reject) => { - return self.getMyID(); - }); - } + if (!loggedIn) { + return tryLogin(this.authData).then(() => { + resolve(_userID); + }).catch(reject); + } else { + resolve(_userID); + } + }); - return _userID; } /** * Global search. From 1218eeaf940606fafeb6d2dcb1c8c4876b16eef8 Mon Sep 17 00:00:00 2001 From: Lucas Augusto Deters Date: Mon, 2 Sep 2019 10:04:43 -0300 Subject: [PATCH 22/22] 0.2.11 --- package-lock.json | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package-lock.json b/package-lock.json index c3a4fd9..8087a7b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "tidalpromise", - "version": "0.2.10", + "version": "0.2.11", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index 49780c3..9955cae 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "tidalpromise", - "version": "0.2.10", + "version": "0.2.11", "description": "Unofficial Node.js TIDAL Promise API", "main": "./lib/api.js", "scripts": {