diff --git a/CHANGELOG.md b/CHANGELOG.md index b96d3781..6ff8a956 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -26,6 +26,10 @@ Rebasing master onto v3 doesn't require a changelog update. - Replaced the `set_auth` and `auth_manager` properties with standard attributes. - Replaced string concatenations and `str.format()` with f-strings +### Fixed + +- Fixed playlist_add_items() to accept only URIs and URLs and not IDs, since 'track' and 'episode' cannot be inferred from ID only + ### Removed - Removed the following deprecated methods from `Spotify`: @@ -52,7 +56,7 @@ Rebasing master onto v3 doesn't require a changelog update. ### Added - Added examples for audiobooks, shows and episodes methods to examples directory -- Use newer string formatters (https://pyformat.info) +- Use newer string formatters ([https://pyformat.info](https://pyformat.info)) ### Fixed diff --git a/spotipy/client.py b/spotipy/client.py index c3d0201d..da61db87 100644 --- a/spotipy/client.py +++ b/spotipy/client.py @@ -787,10 +787,15 @@ def playlist_add_items( - items - a list of track/episode URIs or URLs - position - the position to add the tracks """ + for item in items: + if not self._is_uri(item) and not self._is_url(item): + raise RuntimeError("playlist_add_items() only accepts URIs and URLs.") plid = self._get_id("playlist", playlist_id) - ftracks = [self._get_uri("track", tid) for tid in items] + items = [self._url_to_uri(item) if self._is_url(item) else item for item in items] return self._post( - f"playlists/{plid}/tracks", payload=ftracks, position=position + f"playlists/{plid}/tracks", + payload=items, + position=position, ) def playlist_replace_items(self, playlist_id, items): @@ -1717,6 +1722,13 @@ def _get_uri(self, type, id): def _is_uri(self, uri): return re.search(Spotify._regex_spotify_uri, uri) is not None + def _is_url(self, url): + return url.startswith("http") + + def _url_to_uri(self, url): + splitted = url.split("/") + return "spotify:" + splitted[-2] + ":" + splitted[-1] + def _search_multiple_markets(self, q, limit, offset, type, markets, total): if total and limit > total: limit = total diff --git a/tests/integration/user_endpoints/test.py b/tests/integration/user_endpoints/test.py index ab7cba1f..568fac6f 100644 --- a/tests/integration/user_endpoints/test.py +++ b/tests/integration/user_endpoints/test.py @@ -47,6 +47,14 @@ def setUpClass(cls): "spotify:episode:7cRcsGYYRUFo1OF3RgRzdx", ] + cls.tracks_and_episodes = [ + "spotify:track:3F5CgOj3wFlRv51JsHbxhe", + "http://open.spotify.com/track/5mCPDVBb16L4XQwDdbRUpz", + + "spotify:episode:7AY0yaj2k0W3obOSCfm6m4", + "https://open.spotify.com/episode/5AJB2BTp7RExSGpbQlIsXI" + ] + scope = ( 'playlist-modify-public ' 'user-library-read ' @@ -112,7 +120,7 @@ def test_current_user_follow_playlist(self): def test_playlist_replace_items(self): # add tracks to playlist self.spotify.playlist_add_items( - self.new_playlist['id'], self.four_tracks) + self.new_playlist['id'], self.tracks_and_episodes) playlist = self.spotify.playlist(self.new_playlist['id']) self.assertEqual(playlist['tracks']['total'], 4) self.assertEqual(len(playlist['tracks']['items']), 4)