From 6cee02535ea02b2b3a93f45ac346c90dbce6540a Mon Sep 17 00:00:00 2001 From: Ed Moore Date: Thu, 19 Mar 2015 10:38:13 +0800 Subject: [PATCH] Added method to check if user follows a playlist #16 --- README.md | 17 +++++++++++++++ dist/angular-spotify.min.js | 2 +- src/angular-spotify.js | 8 +++++++ test/spec/angular-spotify.spec.js | 36 +++++++++++++++++++++++++++++++ 4 files changed, 62 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 992ced3..826c7b5 100644 --- a/README.md +++ b/README.md @@ -334,6 +334,8 @@ Spotify.reorderPlaylistTracks('1176458919', '2TkWjGCu8jurholsfdWtG4', { range_start: 8, range_length: 5, insert_before: 0 +}).then(function (data) { + console.log(data); }); ``` @@ -477,6 +479,21 @@ Spotify.unfollowPlaylist('jmperezperez', '2v3iNvBX8Ay1Gt2uXtUKUT').then(function }); ``` +####Check if Users Follow a Playlist +Check to see if one or more Spotify users are following a specified playlist.Following a playlist can be done publicly or privately. Checking if a user publicly follows a playlist doesn't require any scopes; if the user is publicly following the playlist, this endpoint returns true. + +Checking if the user is privately following a playlist is only possible for the current user when that user has granted access to the ```playlist-read-private``` scope. +```javascript +Spotify.playlistFollowingContains('owner_id', 'playlist_id', 'comma separated string or array of user ids'); +``` +Example: +```javascript +Spotify.playlistFollowingContains('jmperezperez', '2v3iNvBX8Ay1Gt2uXtUKUT', 'possan,elogain').then(function (data) { + console.log(data); +}); +``` + + ###User Profiles User needs to be logged in to gain access to user profiles diff --git a/dist/angular-spotify.min.js b/dist/angular-spotify.min.js index e4c6fc4..83e63b8 100644 --- a/dist/angular-spotify.min.js +++ b/dist/angular-spotify.min.js @@ -1,2 +1,2 @@ /*! angular-spotify 2015-03-19 */ -!function(a,b){"use strict";b.module("spotify",[]).provider("Spotify",function(){var c={};c.clientId=null,c.redirectUri=null,c.scope=null,c.accessToken=null,this.setClientId=function(a){return c.clientId=a,c.clientId},this.getClientId=function(){return c.clientId},this.setAuthToken=function(a){return c.accessToken=a,c.accessToken},this.setRedirectUri=function(a){return c.redirectUri=a,c.redirectUri},this.getRedirectUri=function(){return c.redirectUri},this.setScope=function(a){return c.scope=a,c.scope};var d={};d.toQueryString=function(a){var c=[];return b.forEach(a,function(a,b){this.push(encodeURIComponent(b)+"="+encodeURIComponent(a))},c),c.join("&")},c.apiBase="https://api.spotify.com/v1",this.$get=["$q","$http","$window",function(e,f,g){function h(){this.clientId=c.clientId,this.redirectUri=c.redirectUri,this.apiBase=c.apiBase,this.scope=c.scope,this.accessToken=null,this.toQueryString=d.toQueryString}return h.prototype.api=function(a,b,c,d,g){var h=e.defer();return f({url:this.apiBase+a,method:b?b:"GET",params:c,data:d,headers:g}).success(function(a){h.resolve(a)}).error(function(a){h.reject(a)}),h.promise},h.prototype.search=function(a,b,c){return c=c||{},c.q=a,c.type=b,this.api("/search","GET",c)},h.prototype.getAlbum=function(a){return a=-1===a.indexOf("spotify:")?a:a.split(":")[2],this.api("/albums/"+a)},h.prototype.getAlbums=function(a){return a=b.isString(a)?a.split(","):a,b.forEach(a,function(b,c){a[c]=b.indexOf("spotify:")>-1?b.split(":")[2]:b}),this.api("/albums","GET",{ids:a?a.toString():""})},h.prototype.getAlbumTracks=function(a,b){return a=-1===a.indexOf("spotify:")?a:a.split(":")[2],this.api("/albums/"+a+"/tracks","GET",b)},h.prototype.getArtist=function(a){return a=-1===a.indexOf("spotify:")?a:a.split(":")[2],this.api("/artists/"+a)},h.prototype.getArtists=function(a){return a=b.isString(a)?a.split(","):a,b.forEach(a,function(b,c){a[c]=b.indexOf("spotify:")>-1?b.split(":")[2]:b}),this.api("/artists/","GET",{ids:a?a.toString():""})},h.prototype.getArtistAlbums=function(a,b){return a=-1===a.indexOf("spotify:")?a:a.split(":")[2],this.api("/artists/"+a+"/albums","GET",b)},h.prototype.getArtistTopTracks=function(a,b){return a=-1===a.indexOf("spotify:")?a:a.split(":")[2],this.api("/artists/"+a+"/top-tracks","GET",{country:b})},h.prototype.getRelatedArtists=function(a){return a=-1===a.indexOf("spotify:")?a:a.split(":")[2],this.api("/artists/"+a+"/related-artists")},h.prototype.getTrack=function(a){return a=-1===a.indexOf("spotify:")?a:a.split(":")[2],this.api("/tracks/"+a)},h.prototype.getTracks=function(a){return a=b.isString(a)?a.split(","):a,b.forEach(a,function(b,c){a[c]=b.indexOf("spotify:")>-1?b.split(":")[2]:b}),this.api("/tracks/","GET",{ids:a?a.toString():""})},h.prototype.getUserPlaylists=function(a,b){return this.api("/users/"+a+"/playlists","GET",b,null,{Authorization:"Bearer "+this.authToken})},h.prototype.getPlaylist=function(a,b,c){return this.api("/users/"+a+"/playlists/"+b,"GET",c,null,{Authorization:"Bearer "+this.authToken})},h.prototype.getPlaylistTracks=function(a,b,c){return this.api("/users/"+a+"/playlists/"+b+"/tracks","GET",c,null,{Authorization:"Bearer "+this.authToken})},h.prototype.createPlaylist=function(a,b){return this.api("/users/"+a+"/playlists","POST",null,b,{Authorization:"Bearer "+this.authToken,"Content-Type":"application/json"})},h.prototype.addPlaylistTracks=function(a,c,d,e){return d=b.isArray(d)?d:d.split(","),b.forEach(d,function(a,b){d[b]=-1===a.indexOf("spotify:")?"spotify:track:"+a:a}),this.api("/users/"+a+"/playlists/"+c+"/tracks","POST",{uris:d.toString(),position:e?e.position:null},null,{Authorization:"Bearer "+this.authToken,"Content-Type":"application/json"})},h.prototype.removePlaylistTracks=function(a,c,d){d=b.isArray(d)?d:d.split(",");var e;return b.forEach(d,function(a,b){e=d[b],d[b]={uri:-1===e.indexOf("spotify:")?"spotify:track:"+e:e}}),this.api("/users/"+a+"/playlists/"+c+"/tracks","DELETE",null,{tracks:d},{Authorization:"Bearer "+this.authToken,"Content-Type":"application/json"})},h.prototype.reorderPlaylistTracks=function(a,b,c){return this.api("/users/"+a+"/playlists/"+b+"/tracks","PUT",null,c,{Authorization:"Bearer "+this.authToken,"Content-Type":"application/json"})},h.prototype.replacePlaylistTracks=function(a,c,d){d=b.isArray(d)?d:d.split(",");var e;return b.forEach(d,function(a,b){e=d[b],d[b]=-1===e.indexOf("spotify:")?"spotify:track:"+e:e}),this.api("/users/"+a+"/playlists/"+c+"/tracks","PUT",{uris:d.toString()},null,{Authorization:"Bearer "+this.authToken,"Content-Type":"application/json"})},h.prototype.updatePlaylistDetails=function(a,b,c){return this.api("/users/"+a+"/playlists/"+b,"PUT",null,c,{Authorization:"Bearer "+this.authToken,"Content-Type":"application/json"})},h.prototype.getUser=function(a){return this.api("/users/"+a)},h.prototype.getCurrentUser=function(){return this.api("/me","GET",null,null,{Authorization:"Bearer "+this.authToken})},h.prototype.getSavedUserTracks=function(a){return this.api("/me/tracks","GET",a,null,{Authorization:"Bearer "+this.authToken})},h.prototype.userTracksContains=function(a){return a=b.isString(a)?a.split(","):a,b.forEach(a,function(b,c){a[c]=b.indexOf("spotify:")>-1?b.split(":")[2]:b}),this.api("/me/tracks/contains","GET",{ids:a.toString()},null,{Authorization:"Bearer "+this.authToken})},h.prototype.saveUserTracks=function(a){return a=b.isString(a)?a.split(","):a,b.forEach(a,function(b,c){a[c]=b.indexOf("spotify:")>-1?b.split(":")[2]:b}),this.api("/me/tracks","PUT",{ids:a.toString()},null,{Authorization:"Bearer "+this.authToken})},h.prototype.removeUserTracks=function(a){return a=b.isString(a)?a.split(","):a,b.forEach(a,function(b,c){a[c]=b.indexOf("spotify:")>-1?b.split(":")[2]:b}),this.api("/me/tracks","DELETE",{ids:a.toString()},null,{Authorization:"Bearer "+this.authToken,"Content-Type":"application/json"})},h.prototype.getFeaturedPlaylists=function(a){return this.api("/browse/featured-playlists","GET",a,null,{Authorization:"Bearer "+this.authToken})},h.prototype.getNewReleases=function(a){return this.api("/browse/new-releases","GET",a,null,{Authorization:"Bearer "+this.authToken})},h.prototype.follow=function(a,b){return this.api("/me/following","PUT",{type:a,ids:b},null,{Authorization:"Bearer "+this.authToken})},h.prototype.unfollow=function(a,b){return this.api("/me/following","DELETE",{type:a,ids:b},null,{Authorization:"Bearer "+this.authToken})},h.prototype.userFollowingContains=function(a,b){return this.api("/me/following/contains","GET",{type:a,ids:b},null,{Authorization:"Bearer "+this.authToken})},h.prototype.followPlaylist=function(a,b,c){return this.api("/users/"+a+"/playlists/"+b+"/followers","PUT",null,{"public":c||null},{Authorization:"Bearer "+this.authToken,"Content-Type":"application/json"})},h.prototype.unfollowPlaylist=function(a,b){return this.api("/users/"+a+"/playlists/"+b+"/followers","DELETE",null,null,{Authorization:"Bearer "+this.authToken})},h.prototype.setAuthToken=function(a){return this.authToken=a,this.authToken},h.prototype.login=function(){function b(a){"spotify-token"===a.key&&(l&&l.close(),d.setAuthToken(a.newValue),g.removeEventListener("storage",b,!1),c.resolve(a.newValue))}var c=e.defer(),d=this,f=400,h=500,i=screen.width/2-f/2,j=screen.height/2-h/2,k={client_id:this.clientId,redirect_uri:this.redirectUri,scope:this.scope||"",response_type:"token"},l=a.open("https://accounts.spotify.com/authorize?"+this.toQueryString(k),"Spotify","menubar=no,location=no,resizable=yes,scrollbars=yes,status=no,width="+f+",height="+h+",top="+j+",left="+i);return g.addEventListener("storage",b,!1),c.promise},new h}]})}(window,angular); \ No newline at end of file +!function(a,b){"use strict";b.module("spotify",[]).provider("Spotify",function(){var c={};c.clientId=null,c.redirectUri=null,c.scope=null,c.accessToken=null,this.setClientId=function(a){return c.clientId=a,c.clientId},this.getClientId=function(){return c.clientId},this.setAuthToken=function(a){return c.accessToken=a,c.accessToken},this.setRedirectUri=function(a){return c.redirectUri=a,c.redirectUri},this.getRedirectUri=function(){return c.redirectUri},this.setScope=function(a){return c.scope=a,c.scope};var d={};d.toQueryString=function(a){var c=[];return b.forEach(a,function(a,b){this.push(encodeURIComponent(b)+"="+encodeURIComponent(a))},c),c.join("&")},c.apiBase="https://api.spotify.com/v1",this.$get=["$q","$http","$window",function(e,f,g){function h(){this.clientId=c.clientId,this.redirectUri=c.redirectUri,this.apiBase=c.apiBase,this.scope=c.scope,this.accessToken=null,this.toQueryString=d.toQueryString}return h.prototype.api=function(a,b,c,d,g){var h=e.defer();return f({url:this.apiBase+a,method:b?b:"GET",params:c,data:d,headers:g}).success(function(a){h.resolve(a)}).error(function(a){h.reject(a)}),h.promise},h.prototype.search=function(a,b,c){return c=c||{},c.q=a,c.type=b,this.api("/search","GET",c)},h.prototype.getAlbum=function(a){return a=-1===a.indexOf("spotify:")?a:a.split(":")[2],this.api("/albums/"+a)},h.prototype.getAlbums=function(a){return a=b.isString(a)?a.split(","):a,b.forEach(a,function(b,c){a[c]=b.indexOf("spotify:")>-1?b.split(":")[2]:b}),this.api("/albums","GET",{ids:a?a.toString():""})},h.prototype.getAlbumTracks=function(a,b){return a=-1===a.indexOf("spotify:")?a:a.split(":")[2],this.api("/albums/"+a+"/tracks","GET",b)},h.prototype.getArtist=function(a){return a=-1===a.indexOf("spotify:")?a:a.split(":")[2],this.api("/artists/"+a)},h.prototype.getArtists=function(a){return a=b.isString(a)?a.split(","):a,b.forEach(a,function(b,c){a[c]=b.indexOf("spotify:")>-1?b.split(":")[2]:b}),this.api("/artists/","GET",{ids:a?a.toString():""})},h.prototype.getArtistAlbums=function(a,b){return a=-1===a.indexOf("spotify:")?a:a.split(":")[2],this.api("/artists/"+a+"/albums","GET",b)},h.prototype.getArtistTopTracks=function(a,b){return a=-1===a.indexOf("spotify:")?a:a.split(":")[2],this.api("/artists/"+a+"/top-tracks","GET",{country:b})},h.prototype.getRelatedArtists=function(a){return a=-1===a.indexOf("spotify:")?a:a.split(":")[2],this.api("/artists/"+a+"/related-artists")},h.prototype.getTrack=function(a){return a=-1===a.indexOf("spotify:")?a:a.split(":")[2],this.api("/tracks/"+a)},h.prototype.getTracks=function(a){return a=b.isString(a)?a.split(","):a,b.forEach(a,function(b,c){a[c]=b.indexOf("spotify:")>-1?b.split(":")[2]:b}),this.api("/tracks/","GET",{ids:a?a.toString():""})},h.prototype.getUserPlaylists=function(a,b){return this.api("/users/"+a+"/playlists","GET",b,null,{Authorization:"Bearer "+this.authToken})},h.prototype.getPlaylist=function(a,b,c){return this.api("/users/"+a+"/playlists/"+b,"GET",c,null,{Authorization:"Bearer "+this.authToken})},h.prototype.getPlaylistTracks=function(a,b,c){return this.api("/users/"+a+"/playlists/"+b+"/tracks","GET",c,null,{Authorization:"Bearer "+this.authToken})},h.prototype.createPlaylist=function(a,b){return this.api("/users/"+a+"/playlists","POST",null,b,{Authorization:"Bearer "+this.authToken,"Content-Type":"application/json"})},h.prototype.addPlaylistTracks=function(a,c,d,e){return d=b.isArray(d)?d:d.split(","),b.forEach(d,function(a,b){d[b]=-1===a.indexOf("spotify:")?"spotify:track:"+a:a}),this.api("/users/"+a+"/playlists/"+c+"/tracks","POST",{uris:d.toString(),position:e?e.position:null},null,{Authorization:"Bearer "+this.authToken,"Content-Type":"application/json"})},h.prototype.removePlaylistTracks=function(a,c,d){d=b.isArray(d)?d:d.split(",");var e;return b.forEach(d,function(a,b){e=d[b],d[b]={uri:-1===e.indexOf("spotify:")?"spotify:track:"+e:e}}),this.api("/users/"+a+"/playlists/"+c+"/tracks","DELETE",null,{tracks:d},{Authorization:"Bearer "+this.authToken,"Content-Type":"application/json"})},h.prototype.reorderPlaylistTracks=function(a,b,c){return this.api("/users/"+a+"/playlists/"+b+"/tracks","PUT",null,c,{Authorization:"Bearer "+this.authToken,"Content-Type":"application/json"})},h.prototype.replacePlaylistTracks=function(a,c,d){d=b.isArray(d)?d:d.split(",");var e;return b.forEach(d,function(a,b){e=d[b],d[b]=-1===e.indexOf("spotify:")?"spotify:track:"+e:e}),this.api("/users/"+a+"/playlists/"+c+"/tracks","PUT",{uris:d.toString()},null,{Authorization:"Bearer "+this.authToken,"Content-Type":"application/json"})},h.prototype.updatePlaylistDetails=function(a,b,c){return this.api("/users/"+a+"/playlists/"+b,"PUT",null,c,{Authorization:"Bearer "+this.authToken,"Content-Type":"application/json"})},h.prototype.getUser=function(a){return this.api("/users/"+a)},h.prototype.getCurrentUser=function(){return this.api("/me","GET",null,null,{Authorization:"Bearer "+this.authToken})},h.prototype.getSavedUserTracks=function(a){return this.api("/me/tracks","GET",a,null,{Authorization:"Bearer "+this.authToken})},h.prototype.userTracksContains=function(a){return a=b.isString(a)?a.split(","):a,b.forEach(a,function(b,c){a[c]=b.indexOf("spotify:")>-1?b.split(":")[2]:b}),this.api("/me/tracks/contains","GET",{ids:a.toString()},null,{Authorization:"Bearer "+this.authToken})},h.prototype.saveUserTracks=function(a){return a=b.isString(a)?a.split(","):a,b.forEach(a,function(b,c){a[c]=b.indexOf("spotify:")>-1?b.split(":")[2]:b}),this.api("/me/tracks","PUT",{ids:a.toString()},null,{Authorization:"Bearer "+this.authToken})},h.prototype.removeUserTracks=function(a){return a=b.isString(a)?a.split(","):a,b.forEach(a,function(b,c){a[c]=b.indexOf("spotify:")>-1?b.split(":")[2]:b}),this.api("/me/tracks","DELETE",{ids:a.toString()},null,{Authorization:"Bearer "+this.authToken,"Content-Type":"application/json"})},h.prototype.getFeaturedPlaylists=function(a){return this.api("/browse/featured-playlists","GET",a,null,{Authorization:"Bearer "+this.authToken})},h.prototype.getNewReleases=function(a){return this.api("/browse/new-releases","GET",a,null,{Authorization:"Bearer "+this.authToken})},h.prototype.follow=function(a,b){return this.api("/me/following","PUT",{type:a,ids:b},null,{Authorization:"Bearer "+this.authToken})},h.prototype.unfollow=function(a,b){return this.api("/me/following","DELETE",{type:a,ids:b},null,{Authorization:"Bearer "+this.authToken})},h.prototype.userFollowingContains=function(a,b){return this.api("/me/following/contains","GET",{type:a,ids:b},null,{Authorization:"Bearer "+this.authToken})},h.prototype.followPlaylist=function(a,b,c){return this.api("/users/"+a+"/playlists/"+b+"/followers","PUT",null,{"public":c||null},{Authorization:"Bearer "+this.authToken,"Content-Type":"application/json"})},h.prototype.unfollowPlaylist=function(a,b){return this.api("/users/"+a+"/playlists/"+b+"/followers","DELETE",null,null,{Authorization:"Bearer "+this.authToken})},h.prototype.playlistFollowingContains=function(a,b,c){return this.api("/users/"+a+"/playlists/"+b+"/followers/contains","GET",{ids:c.toString()},null,{Authorization:"Bearer "+this.authToken})},h.prototype.setAuthToken=function(a){return this.authToken=a,this.authToken},h.prototype.login=function(){function b(a){"spotify-token"===a.key&&(l&&l.close(),d.setAuthToken(a.newValue),g.removeEventListener("storage",b,!1),c.resolve(a.newValue))}var c=e.defer(),d=this,f=400,h=500,i=screen.width/2-f/2,j=screen.height/2-h/2,k={client_id:this.clientId,redirect_uri:this.redirectUri,scope:this.scope||"",response_type:"token"},l=a.open("https://accounts.spotify.com/authorize?"+this.toQueryString(k),"Spotify","menubar=no,location=no,resizable=yes,scrollbars=yes,status=no,width="+f+",height="+h+",top="+j+",left="+i);return g.addEventListener("storage",b,!1),c.promise},new h}]})}(window,angular); \ No newline at end of file diff --git a/src/angular-spotify.js b/src/angular-spotify.js index 8360857..01ccf0d 100644 --- a/src/angular-spotify.js +++ b/src/angular-spotify.js @@ -406,6 +406,14 @@ }); }; + NgSpotify.prototype.playlistFollowingContains = function(userId, playlistId, ids) { + return this.api('/users/' + userId + '/playlists/' + playlistId + '/followers/contains', 'GET', { + ids: ids.toString() + }, null, { + 'Authorization': 'Bearer ' + this.authToken + }); + }; + /** ====================== Login ===================== */ diff --git a/test/spec/angular-spotify.spec.js b/test/spec/angular-spotify.spec.js index b51fab5..4653805 100644 --- a/test/spec/angular-spotify.spec.js +++ b/test/spec/angular-spotify.spec.js @@ -251,6 +251,10 @@ describe('angular-spotify', function () { expect(Spotify.unfollowPlaylist).toBeDefined(); }); + it('should have a method playlistFollowingContains()', function () { + expect(Spotify.playlistFollowingContains).toBeDefined(); + }); + describe('Spotify.api', function () { var $httpBackend; @@ -1655,6 +1659,38 @@ describe('angular-spotify', function () { }); }); }); + + describe('Spotify.playlistFollowingContains', function () { + it('should call the correct URL', function () { + spyOn(Spotify, 'api'); + + Spotify.setAuthToken('TESTING'); + + Spotify.playlistFollowingContains('jmperezperez', '2v3iNvBX8Ay1Gt2uXtUKUT', 'possan,elogain'); + + expect(Spotify.api).toHaveBeenCalled(); + expect(Spotify.api).toHaveBeenCalledWith('/users/jmperezperez/playlists/2v3iNvBX8Ay1Gt2uXtUKUT/followers/contains', 'GET', { + ids: 'possan,elogain' + }, null, { + 'Authorization': 'Bearer TESTING' + }); + }); + + it('should be able to be called with an array of users', function () { + spyOn(Spotify, 'api'); + + Spotify.setAuthToken('TESTING'); + + Spotify.playlistFollowingContains('jmperezperez', '2v3iNvBX8Ay1Gt2uXtUKUT', ['possan','elogain']); + + expect(Spotify.api).toHaveBeenCalled(); + expect(Spotify.api).toHaveBeenCalledWith('/users/jmperezperez/playlists/2v3iNvBX8Ay1Gt2uXtUKUT/followers/contains', 'GET', { + ids: 'possan,elogain' + }, null, { + 'Authorization': 'Bearer TESTING' + }); + }); + }); }); });