diff --git a/CHANGELOG.md b/CHANGELOG.md index 1cb4f5d..043a626 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added - Support for `playlist_tracks` + - Support for `playlist_upload_cover_image` ### Changed @@ -147,4 +148,4 @@ Updates to match released API Repackaged for saner imports ## [1.0.0] - 2017-04-05 -Initial release +Initial release \ No newline at end of file diff --git a/spotipy/client.py b/spotipy/client.py index 1befef9..893fcb5 100644 --- a/spotipy/client.py +++ b/spotipy/client.py @@ -107,10 +107,16 @@ class Spotify(object): if not url.startswith('http'): url = self.prefix + url headers = self._auth_headers() - headers['Content-Type'] = 'application/json' - if payload: - args["data"] = json.dumps(payload) + if 'content_type' in args['params']: + headers['Content-Type'] = args['params']['content_type'] + del args['params']['content_type'] + if payload: + args["data"] = payload + else: + headers['Content-Type'] = 'application/json' + if payload: + args["data"] = json.dumps(payload) if self.trace_out: print(url) @@ -400,6 +406,22 @@ class Spotify(object): limit=limit, offset=offset, fields=fields, market=market) + def playlist_upload_cover_image(self, + playlist_id, + image_b64): + """ + Replace the image used to represent a specific playlist + + Parameters: + - playlist_id - the id of the playlist + - image_b64 - image data as a Base64 encoded JPEG image string + (maximum payload size is 256 KB) + """ + plid = self._get_id('playlist', playlist_id) + return self._put("playlists/{}/images".format(plid), + payload=image_b64, + content_type="image/jpeg") + def user_playlist(self, user, playlist_id=None, fields=None, market=None): warnings.warn( diff --git a/tests/test_auth.py b/tests/test_auth.py index 0f6ef16..438e88f 100644 --- a/tests/test_auth.py +++ b/tests/test_auth.py @@ -24,6 +24,7 @@ import os import sys import unittest import warnings +import requests sys.path.insert(0, os.path.abspath(os.pardir)) @@ -86,13 +87,30 @@ class AuthTestSpotipy(unittest.TestCase): 'user-library-modify ' 'user-read-private ' 'user-top-read ' - 'user-follow-modify' + 'user-follow-modify ' + 'ugc-image-upload' ) self.token = prompt_for_user_token(self.username, scope=self.scope) self.spotify = Spotify(auth=self.token) + # Helper + def get_or_create_spotify_playlist(self, playlist_name): + playlists = self.spotify.user_playlists(self.username) + while playlists: + for item in playlists['items']: + if item['name'] == playlist_name: + return item + playlists = self.spotify.next(playlists) + return self.spotify.user_playlist_create( + self.username, playlist_name) + + # Helper + def get_as_base64(self, url): + import base64 + return base64.b64encode(requests.get(url).content).decode("utf-8") + def test_track_bad_id(self): try: self.spotify.track(self.bad_id) @@ -223,23 +241,12 @@ class AuthTestSpotipy(unittest.TestCase): items = response['items'] self.assertTrue(len(items) > 0) - def get_or_create_spotify_playlist(self, playlist_name): - playlists = self.spotify.user_playlists(self.username) - while playlists: - for item in playlists['items']: - if item['name'] == playlist_name: - return item['id'] - playlists = self.spotify.next(playlists) - playlist = self.spotify.user_playlist_create( - self.username, playlist_name) - playlist_id = playlist['uri'] - return playlist_id - def test_user_playlist_ops(self): sp = self.spotify # create empty playlist - playlist_id = self.get_or_create_spotify_playlist( + playlist = self.get_or_create_spotify_playlist( 'spotipy-testing-playlist-1') + playlist_id = playlist['id'] # remove all tracks from it sp.user_playlist_replace_tracks( @@ -292,6 +299,21 @@ class AuthTestSpotipy(unittest.TestCase): self.assertTrue(len(pl["items"]) == 2) self.assertTrue(pl["total"] > 0) + def test_playlist_upload_cover_image(self): + pl1 = self.get_or_create_spotify_playlist('spotipy-testing-playlist-1') + plid = pl1['uri'] + old_b64 = pl1['images'][0]['url'] + + # Upload random dog image + r = requests.get('https://dog.ceo/api/breeds/image/random') + dog_base64 = self.get_as_base64(r.json()['message']) + self.spotify.playlist_upload_cover_image(plid, dog_base64) + + # Image must be different + pl1 = self.spotify.playlist(plid) + new_b64 = self.get_as_base64(pl1['images'][0]['url']) + self.assertTrue(old_b64 != new_b64) + def test_user_follows_and_unfollows_artist(self): # Initially follows 1 artist res = self.spotify.current_user_followed_artists()