def _follow_unfollow_help(self, other, request_type): """ follow and unfollow are identical, except for the request type. This function implements that functionality to remove duplicate code. """ # Validate input if not isinstance(other, list): other = [other] for elem in other: if type(elem) not in [Artist, User, Playlist]: raise TypeError(elem) # Split up input artists = utils.separate(other, Artist) users = utils.separate(other, User) playlists = utils.separate(other, Playlist) for batch in utils.create_batches(utils.map_ids(artists)): response_json, status_code = utils.request( self._session, request_type=request_type, endpoint=Endpoints.USER_FOLLOW_ARTIST_USER, body=None, uri_params={ 'type': 'artist', 'ids': batch }) if status_code != 204: raise utils.SpotifyError(status_code, response_json) for batch in utils.create_batches(utils.map_ids(users)): response_json, status_code = utils.request( self._session, request_type=request_type, endpoint=Endpoints.USER_FOLLOW_ARTIST_USER, body=None, uri_params={ 'type': 'user', 'ids': batch }) if status_code != 204: raise utils.SpotifyError(status_code, response_json) for playlist in playlists: response_json, status_code = utils.request( self._session, request_type=request_type, endpoint=Endpoints.USER_FOLLOW_PLAYLIST % playlist, body=None, uri_params=None) if status_code != 200: raise utils.SpotifyError(status_code, response_json)
def test_remove(self): user = self.user albums = get_dummy_data(const.ALBUMS, 10, to_obj=True) album_ids = utils.map_ids(albums) tracks = get_dummy_data(const.TRACKS, 10, to_obj=True) playlists = get_dummy_data(const.PLAYLISTS, 10, to_obj=True) # Validate input checking self.assertRaises(TypeError, user.remove, playlists) # Make sure saving albums does what's expected #pylint: disable=unused-argument def request_mock_return(session, request_type, endpoint, body, uri_params): self.assertEqual(request_type, const.REQUEST_DELETE) self.assertIsNotNone(uri_params) self.assertTrue('ids' in uri_params) for elem in uri_params['ids']: self.assertIsInstance(elem, str) self.assertTrue(elem in album_ids) return None, 200 self.request_mock.side_effect = request_mock_return user.remove(albums) # Should not raise exception - expects code 200 for playlists self.request_mock.side_effect = [(None, 200)]*10 user.remove(tracks)
def _save_remove_help(self, other, request_type): """ save and remove are identical, except for the request type and return codes. This function implements that functionality to remove duplicate code. """ # Validate input if not isinstance(other, list): other = [other] for elem in other: if type(elem) not in [Album, Track]: raise TypeError(elem) # Split up input albums = utils.separate(other, Album) tracks = utils.separate(other, Track) for batch in utils.create_batches(utils.map_ids(albums)): response_json, status_code = utils.request( self._session, request_type=request_type, endpoint=Endpoints.USER_SAVE_ALBUMS, body=None, uri_params={'ids': batch}) # All success codes are 200, except saving an album success = 201 if request_type == const.REQUEST_PUT else 200 if status_code != success: raise utils.SpotifyError(status_code, response_json) for batch in utils.create_batches(utils.map_ids(tracks)): response_json, status_code = utils.request( self._session, request_type=request_type, endpoint=Endpoints.USER_SAVE_TRACKS, body=None, uri_params={'ids': batch}) if status_code != 200: raise utils.SpotifyError(status_code, response_json)
def has_saved(self, other): """ Check if the user has one or more things saved to their library. Args: other: check if the current user has 'other' saved to the library. Other must be one of the following: - Track - Album - List: can contain multiple of the above types Returns: List of tuples. Each tuple has an input object and whether the user has that object saved. Required token scopes: - user-library-read Calls endpoints: - GET /v1/me/albums/contains - GET /v1/me/tracks/contains """ # Validate input if not isinstance(other, list): other = [other] for elem in other: if type(elem) not in [Track, Album]: raise TypeError(elem) # Split up input tracks = utils.separate(other, Track) albums = utils.separate(other, Album) # Get boolean values for whether the user has each item saved endpoint = Endpoints.USER_HAS_SAVED track_bools = [] for batch in utils.create_batches(utils.map_ids(tracks)): response_json, status_code = utils.request( self._session, request_type=const.REQUEST_GET, endpoint=endpoint % 'tracks', body=None, uri_params={'ids': batch}) if status_code != 200: raise utils.SpotifyError(status_code, response_json) track_bools.append(response_json) album_bools = [] for batch in utils.create_batches(utils.map_ids(albums)): response_json, status_code = utils.request( self._session, request_type=const.REQUEST_GET, endpoint=endpoint % 'albums', body=None, uri_params={'ids': batch}) if status_code != 200: raise utils.SpotifyError(status_code, response_json) album_bools.append(response_json) # Zip output with input to make tuples zipped_tracks = list(zip(tracks, track_bools)) zipped_albums = list(zip(albums, album_bools)) return zipped_tracks + zipped_albums
def is_following(self, other): """ Check if the current user is following something. Args: other: check if current user is following 'other'. Other must be one of the following: - Artist - User - Playlist - List: can contain multiple of the above types Required token scopes: - user-follow-read - playlist-read-private - playlist-read-collaborative Calls endpoints: - GET /v1/me/following/contains - GET /v1/users/{user_id}/playlists Returns: List of tuples. Each tuple has an input object and whether the user follows the object. """ # Validate input if not isinstance(other, list): other = [other] for elem in other: if type(elem) not in [Artist, User, Playlist]: raise TypeError(elem) # Split up input artists = utils.separate(other, Artist) users = utils.separate(other, User) playlists = utils.separate(other, Playlist) # Get boolean values for whether the user follows each in 'other' endpoint = Endpoints.USER_FOLLOWING_CONTAINS artist_bools = [] for batch in utils.create_batches(utils.map_ids(artists)): response_json, status_code = utils.request( self._session, request_type=const.REQUEST_GET, endpoint=endpoint, body=None, uri_params={ 'type': 'artist', 'ids': batch }) if status_code != 200: raise utils.SpotifyError(status_code, response_json) artist_bools.append(response_json) user_bools = [] for batch in utils.create_batches(utils.map_ids(users)): response_json, status_code = utils.request( self._session, request_type=const.REQUEST_GET, endpoint=endpoint, body=None, uri_params={ 'type': 'user', 'ids': batch }) if status_code != 200: raise utils.SpotifyError(status_code, response_json) user_bools.append(response_json) # For each playlist in other, check if in the User's followed playlists followed_playlists = self.get_following(const.PLAYLISTS) playlist_bools = list(map(lambda p: p in followed_playlists, playlists)) # Zip output with input to make tuples artists = list(zip(artists, artist_bools)) users = list(zip(users, user_bools)) playlists = list(zip(playlists, playlist_bools)) return artists + users + playlists