mirror of
https://github.com/c0de-archive/spotipy.git
synced 2025-01-04 22:32:40 +00:00
Merge branch 'master' into playlist_description_support
This commit is contained in:
commit
91d89c3256
@ -125,7 +125,10 @@ Authorization Code Flow
|
||||
=======================
|
||||
To support the **Authorization Code Flow** *Spotipy* provides a
|
||||
utility method ``util.prompt_for_user_token`` that will attempt to authorize the
|
||||
user. You can pass your app credentials directly into the method as arguments,
|
||||
user. You can pass your app credentials directly into the method as arguments::
|
||||
|
||||
util.prompt_for_user_token(username,scope,client_id='your-app-redirect-url',client_secret='your-app-redirect-url',redirect_uri='your-app-redirect-url')
|
||||
|
||||
or if you are reluctant to immortalize your app credentials in your source code,
|
||||
you can set environment variables like so::
|
||||
|
||||
|
@ -1,12 +1,11 @@
|
||||
# shows a user's playlists (need to be authenticated via oauth)
|
||||
|
||||
import sys
|
||||
import os
|
||||
import spotipy
|
||||
import spotipy.util as util
|
||||
|
||||
def show_tracks(results):
|
||||
for i, item in enumerate(tracks['items']):
|
||||
for i, item in enumerate(results['items']):
|
||||
track = item['track']
|
||||
print(" %d %32.32s %s" % (i, track['artists'][0]['name'], track['name']))
|
||||
|
||||
@ -22,7 +21,6 @@ if __name__ == '__main__':
|
||||
token = util.prompt_for_user_token(username)
|
||||
|
||||
if token:
|
||||
top = 40
|
||||
sp = spotipy.Spotify(auth=token)
|
||||
playlists = sp.user_playlists(username)
|
||||
for playlist in playlists['items']:
|
||||
|
@ -9,8 +9,8 @@ import time
|
||||
|
||||
import six
|
||||
|
||||
''' A simple and thin Python library for the Spotify Web API
|
||||
'''
|
||||
""" A simple and thin Python library for the Spotify Web API
|
||||
"""
|
||||
|
||||
|
||||
class SpotifyException(Exception):
|
||||
@ -30,7 +30,7 @@ class SpotifyException(Exception):
|
||||
|
||||
|
||||
class Spotify(object):
|
||||
'''
|
||||
"""
|
||||
Example usage::
|
||||
|
||||
import spotipy
|
||||
@ -46,7 +46,7 @@ class Spotify(object):
|
||||
|
||||
user = sp.user('plamere')
|
||||
print(user)
|
||||
'''
|
||||
"""
|
||||
|
||||
trace = False # Enable tracing?
|
||||
trace_out = False
|
||||
@ -54,7 +54,7 @@ class Spotify(object):
|
||||
|
||||
def __init__(self, auth=None, requests_session=True,
|
||||
client_credentials_manager=None, proxies=None, requests_timeout=None):
|
||||
'''
|
||||
"""
|
||||
Create a Spotify API object.
|
||||
|
||||
:param auth: An authorization token (optional)
|
||||
@ -69,7 +69,7 @@ class Spotify(object):
|
||||
Definition of proxies (optional)
|
||||
:param requests_timeout:
|
||||
Tell Requests to stop waiting for a response after a given number of seconds
|
||||
'''
|
||||
"""
|
||||
self.prefix = 'https://api.spotify.com/v1/'
|
||||
self._auth = auth
|
||||
self.client_credentials_manager = client_credentials_manager
|
||||
@ -190,22 +190,22 @@ class Spotify(object):
|
||||
return self._internal_call('PUT', url, payload, kwargs)
|
||||
|
||||
def next(self, result):
|
||||
''' returns the next result given a paged result
|
||||
""" returns the next result given a paged result
|
||||
|
||||
Parameters:
|
||||
- result - a previously returned paged result
|
||||
'''
|
||||
"""
|
||||
if result['next']:
|
||||
return self._get(result['next'])
|
||||
else:
|
||||
return None
|
||||
|
||||
def previous(self, result):
|
||||
''' returns the previous result given a paged result
|
||||
""" returns the previous result given a paged result
|
||||
|
||||
Parameters:
|
||||
- result - a previously returned paged result
|
||||
'''
|
||||
"""
|
||||
if result['previous']:
|
||||
return self._get(result['previous'])
|
||||
else:
|
||||
@ -218,49 +218,49 @@ class Spotify(object):
|
||||
print('warning:' + msg.format(*args), file=sys.stderr)
|
||||
|
||||
def track(self, track_id):
|
||||
''' returns a single track given the track's ID, URI or URL
|
||||
""" returns a single track given the track's ID, URI or URL
|
||||
|
||||
Parameters:
|
||||
- track_id - a spotify URI, URL or ID
|
||||
'''
|
||||
"""
|
||||
|
||||
trid = self._get_id('track', track_id)
|
||||
return self._get('tracks/' + trid)
|
||||
|
||||
def tracks(self, tracks, market = None):
|
||||
''' returns a list of tracks given a list of track IDs, URIs, or URLs
|
||||
""" returns a list of tracks given a list of track IDs, URIs, or URLs
|
||||
|
||||
Parameters:
|
||||
- tracks - a list of spotify URIs, URLs or IDs
|
||||
- market - an ISO 3166-1 alpha-2 country code.
|
||||
'''
|
||||
"""
|
||||
|
||||
tlist = [self._get_id('track', t) for t in tracks]
|
||||
return self._get('tracks/?ids=' + ','.join(tlist), market = market)
|
||||
|
||||
def artist(self, artist_id):
|
||||
''' returns a single artist given the artist's ID, URI or URL
|
||||
""" returns a single artist given the artist's ID, URI or URL
|
||||
|
||||
Parameters:
|
||||
- artist_id - an artist ID, URI or URL
|
||||
'''
|
||||
"""
|
||||
|
||||
trid = self._get_id('artist', artist_id)
|
||||
return self._get('artists/' + trid)
|
||||
|
||||
def artists(self, artists):
|
||||
''' returns a list of artists given the artist IDs, URIs, or URLs
|
||||
""" returns a list of artists given the artist IDs, URIs, or URLs
|
||||
|
||||
Parameters:
|
||||
- artists - a list of artist IDs, URIs or URLs
|
||||
'''
|
||||
"""
|
||||
|
||||
tlist = [self._get_id('artist', a) for a in artists]
|
||||
return self._get('artists/?ids=' + ','.join(tlist))
|
||||
|
||||
def artist_albums(self, artist_id, album_type=None, country=None, limit=20,
|
||||
offset=0):
|
||||
''' Get Spotify catalog information about an artist's albums
|
||||
""" Get Spotify catalog information about an artist's albums
|
||||
|
||||
Parameters:
|
||||
- artist_id - the artist ID, URI or URL
|
||||
@ -268,70 +268,70 @@ class Spotify(object):
|
||||
- country - limit the response to one particular country.
|
||||
- limit - the number of albums to return
|
||||
- offset - the index of the first album to return
|
||||
'''
|
||||
"""
|
||||
|
||||
trid = self._get_id('artist', artist_id)
|
||||
return self._get('artists/' + trid + '/albums', album_type=album_type,
|
||||
country=country, limit=limit, offset=offset)
|
||||
|
||||
def artist_top_tracks(self, artist_id, country='US'):
|
||||
''' Get Spotify catalog information about an artist's top 10 tracks
|
||||
""" Get Spotify catalog information about an artist's top 10 tracks
|
||||
by country.
|
||||
|
||||
Parameters:
|
||||
- artist_id - the artist ID, URI or URL
|
||||
- country - limit the response to one particular country.
|
||||
'''
|
||||
"""
|
||||
|
||||
trid = self._get_id('artist', artist_id)
|
||||
return self._get('artists/' + trid + '/top-tracks', country=country)
|
||||
|
||||
def artist_related_artists(self, artist_id):
|
||||
''' Get Spotify catalog information about artists similar to an
|
||||
""" Get Spotify catalog information about artists similar to an
|
||||
identified artist. Similarity is based on analysis of the
|
||||
Spotify community's listening history.
|
||||
|
||||
Parameters:
|
||||
- artist_id - the artist ID, URI or URL
|
||||
'''
|
||||
"""
|
||||
trid = self._get_id('artist', artist_id)
|
||||
return self._get('artists/' + trid + '/related-artists')
|
||||
|
||||
def album(self, album_id):
|
||||
''' returns a single album given the album's ID, URIs or URL
|
||||
""" returns a single album given the album's ID, URIs or URL
|
||||
|
||||
Parameters:
|
||||
- album_id - the album ID, URI or URL
|
||||
'''
|
||||
"""
|
||||
|
||||
trid = self._get_id('album', album_id)
|
||||
return self._get('albums/' + trid)
|
||||
|
||||
def album_tracks(self, album_id, limit=50, offset=0):
|
||||
''' Get Spotify catalog information about an album's tracks
|
||||
""" Get Spotify catalog information about an album's tracks
|
||||
|
||||
Parameters:
|
||||
- album_id - the album ID, URI or URL
|
||||
- limit - the number of items to return
|
||||
- offset - the index of the first item to return
|
||||
'''
|
||||
"""
|
||||
|
||||
trid = self._get_id('album', album_id)
|
||||
return self._get('albums/' + trid + '/tracks/', limit=limit,
|
||||
offset=offset)
|
||||
|
||||
def albums(self, albums):
|
||||
''' returns a list of albums given the album IDs, URIs, or URLs
|
||||
""" returns a list of albums given the album IDs, URIs, or URLs
|
||||
|
||||
Parameters:
|
||||
- albums - a list of album IDs, URIs or URLs
|
||||
'''
|
||||
"""
|
||||
|
||||
tlist = [self._get_id('album', a) for a in albums]
|
||||
return self._get('albums/?ids=' + ','.join(tlist))
|
||||
|
||||
def search(self, q, limit=10, offset=0, type='track', market=None):
|
||||
''' searches for an item
|
||||
""" searches for an item
|
||||
|
||||
Parameters:
|
||||
- q - the search query
|
||||
@ -340,15 +340,15 @@ class Spotify(object):
|
||||
- type - the type of item to return. One of 'artist', 'album',
|
||||
'track' or 'playlist'
|
||||
- market - An ISO 3166-1 alpha-2 country code or the string from_token.
|
||||
'''
|
||||
"""
|
||||
return self._get('search', q=q, limit=limit, offset=offset, type=type, market=market)
|
||||
|
||||
def user(self, user):
|
||||
''' Gets basic profile information about a Spotify User
|
||||
""" Gets basic profile information about a Spotify User
|
||||
|
||||
Parameters:
|
||||
- user - the id of the usr
|
||||
'''
|
||||
"""
|
||||
return self._get('users/' + user)
|
||||
|
||||
def current_user_playlists(self, limit=50, offset=0):
|
||||
@ -360,23 +360,23 @@ class Spotify(object):
|
||||
return self._get("me/playlists", limit=limit, offset=offset)
|
||||
|
||||
def user_playlists(self, user, limit=50, offset=0):
|
||||
''' Gets playlists of a user
|
||||
""" Gets playlists of a user
|
||||
|
||||
Parameters:
|
||||
- user - the id of the usr
|
||||
- limit - the number of items to return
|
||||
- offset - the index of the first item to return
|
||||
'''
|
||||
"""
|
||||
return self._get("users/%s/playlists" % user, limit=limit,
|
||||
offset=offset)
|
||||
|
||||
def user_playlist(self, user, playlist_id=None, fields=None):
|
||||
''' Gets playlist of a user
|
||||
""" Gets playlist of a user
|
||||
Parameters:
|
||||
- user - the id of the user
|
||||
- playlist_id - the id of the playlist
|
||||
- fields - which fields to return
|
||||
'''
|
||||
"""
|
||||
if playlist_id is None:
|
||||
return self._get("users/%s/starred" % (user), fields=fields)
|
||||
plid = self._get_id('playlist', playlist_id)
|
||||
@ -384,7 +384,7 @@ class Spotify(object):
|
||||
|
||||
def user_playlist_tracks(self, user, playlist_id=None, fields=None,
|
||||
limit=100, offset=0, market=None):
|
||||
''' Get full details of the tracks of a playlist owned by a user.
|
||||
""" Get full details of the tracks of a playlist owned by a user.
|
||||
|
||||
Parameters:
|
||||
- user - the id of the user
|
||||
@ -393,28 +393,31 @@ class Spotify(object):
|
||||
- limit - the maximum number of tracks to return
|
||||
- offset - the index of the first track to return
|
||||
- market - an ISO 3166-1 alpha-2 country code.
|
||||
'''
|
||||
"""
|
||||
plid = self._get_id('playlist', playlist_id)
|
||||
return self._get("users/%s/playlists/%s/tracks" % (user, plid),
|
||||
limit=limit, offset=offset, fields=fields,
|
||||
market=market)
|
||||
|
||||
|
||||
def user_playlist_create(self, user, name, public=True, description=''):
|
||||
''' Creates a playlist for a user
|
||||
""" Creates a playlist for a user
|
||||
|
||||
Parameters:
|
||||
- user - the id of the user
|
||||
- name - the name of the playlist
|
||||
- public - is the created playlist public
|
||||
- description - the description of the playlist
|
||||
'''
|
||||
"""
|
||||
data = {'name': name, 'public': public, 'description': description}
|
||||
|
||||
|
||||
return self._post("users/%s/playlists" % (user,), payload=data)
|
||||
|
||||
def user_playlist_change_details(
|
||||
self, user, playlist_id, name=None, public=None,
|
||||
collaborative=None, description=None):
|
||||
''' Changes a playlist's name and/or public/private state
|
||||
""" Changes a playlist's name and/or public/private state
|
||||
|
||||
Parameters:
|
||||
- user - the id of the user
|
||||
@ -423,7 +426,8 @@ class Spotify(object):
|
||||
- public - optional is the playlist public
|
||||
- collaborative - optional is the playlist collaborative
|
||||
- description - optional description of the playlist
|
||||
'''
|
||||
"""
|
||||
|
||||
data = {}
|
||||
if isinstance(name, six.string_types):
|
||||
data['name'] = name
|
||||
@ -437,37 +441,37 @@ class Spotify(object):
|
||||
payload=data)
|
||||
|
||||
def user_playlist_unfollow(self, user, playlist_id):
|
||||
''' Unfollows (deletes) a playlist for a user
|
||||
""" Unfollows (deletes) a playlist for a user
|
||||
|
||||
Parameters:
|
||||
- user - the id of the user
|
||||
- name - the name of the playlist
|
||||
'''
|
||||
"""
|
||||
return self._delete("users/%s/playlists/%s/followers" % (user, playlist_id))
|
||||
|
||||
def user_playlist_add_tracks(self, user, playlist_id, tracks,
|
||||
position=None):
|
||||
''' Adds tracks to a playlist
|
||||
""" Adds tracks to a playlist
|
||||
|
||||
Parameters:
|
||||
- user - the id of the user
|
||||
- playlist_id - the id of the playlist
|
||||
- tracks - a list of track URIs, URLs or IDs
|
||||
- position - the position to add the tracks
|
||||
'''
|
||||
"""
|
||||
plid = self._get_id('playlist', playlist_id)
|
||||
ftracks = [self._get_uri('track', tid) for tid in tracks]
|
||||
return self._post("users/%s/playlists/%s/tracks" % (user, plid),
|
||||
payload=ftracks, position=position)
|
||||
|
||||
def user_playlist_replace_tracks(self, user, playlist_id, tracks):
|
||||
''' Replace all tracks in a playlist
|
||||
""" Replace all tracks in a playlist
|
||||
|
||||
Parameters:
|
||||
- user - the id of the user
|
||||
- playlist_id - the id of the playlist
|
||||
- tracks - the list of track ids to add to the playlist
|
||||
'''
|
||||
"""
|
||||
plid = self._get_id('playlist', playlist_id)
|
||||
ftracks = [self._get_uri('track', tid) for tid in tracks]
|
||||
payload = {"uris": ftracks}
|
||||
@ -477,7 +481,7 @@ class Spotify(object):
|
||||
def user_playlist_reorder_tracks(
|
||||
self, user, playlist_id, range_start, insert_before,
|
||||
range_length=1, snapshot_id=None):
|
||||
''' Reorder tracks in a playlist
|
||||
""" Reorder tracks in a playlist
|
||||
|
||||
Parameters:
|
||||
- user - the id of the user
|
||||
@ -486,7 +490,7 @@ class Spotify(object):
|
||||
- range_length - optional the number of tracks to be reordered (default: 1)
|
||||
- insert_before - the position where the tracks should be inserted
|
||||
- snapshot_id - optional playlist's snapshot ID
|
||||
'''
|
||||
"""
|
||||
plid = self._get_id('playlist', playlist_id)
|
||||
payload = {"range_start": range_start,
|
||||
"range_length": range_length,
|
||||
@ -498,7 +502,7 @@ class Spotify(object):
|
||||
|
||||
def user_playlist_remove_all_occurrences_of_tracks(
|
||||
self, user, playlist_id, tracks, snapshot_id=None):
|
||||
''' Removes all occurrences of the given tracks from the given playlist
|
||||
""" Removes all occurrences of the given tracks from the given playlist
|
||||
|
||||
Parameters:
|
||||
- user - the id of the user
|
||||
@ -506,7 +510,7 @@ class Spotify(object):
|
||||
- tracks - the list of track ids to add to the playlist
|
||||
- snapshot_id - optional id of the playlist snapshot
|
||||
|
||||
'''
|
||||
"""
|
||||
|
||||
plid = self._get_id('playlist', playlist_id)
|
||||
ftracks = [self._get_uri('track', tid) for tid in tracks]
|
||||
@ -518,7 +522,7 @@ class Spotify(object):
|
||||
|
||||
def user_playlist_remove_specific_occurrences_of_tracks(
|
||||
self, user, playlist_id, tracks, snapshot_id=None):
|
||||
''' Removes all occurrences of the given tracks from the given playlist
|
||||
""" Removes all occurrences of the given tracks from the given playlist
|
||||
|
||||
Parameters:
|
||||
- user - the id of the user
|
||||
@ -527,7 +531,7 @@ class Spotify(object):
|
||||
[ { "uri":"4iV5W9uYEdYUVa79Axb7Rh", "positions":[2] },
|
||||
{ "uri":"1301WleyT98MSxVHPZCA6M", "positions":[7] } ]
|
||||
- snapshot_id - optional id of the playlist snapshot
|
||||
'''
|
||||
"""
|
||||
|
||||
plid = self._get_id('playlist', playlist_id)
|
||||
ftracks = []
|
||||
@ -543,18 +547,18 @@ class Spotify(object):
|
||||
payload=payload)
|
||||
|
||||
def user_playlist_follow_playlist(self, playlist_owner_id, playlist_id):
|
||||
'''
|
||||
"""
|
||||
Add the current authenticated user as a follower of a playlist.
|
||||
|
||||
Parameters:
|
||||
- playlist_owner_id - the user id of the playlist owner
|
||||
- playlist_id - the id of the playlist
|
||||
|
||||
'''
|
||||
"""
|
||||
return self._put("users/{}/playlists/{}/followers".format(playlist_owner_id, playlist_id))
|
||||
|
||||
def user_playlist_is_following(self, playlist_owner_id, playlist_id, user_ids):
|
||||
'''
|
||||
"""
|
||||
Check to see if the given users are following the given playlist
|
||||
|
||||
Parameters:
|
||||
@ -562,85 +566,90 @@ class Spotify(object):
|
||||
- playlist_id - the id of the playlist
|
||||
- user_ids - the ids of the users that you want to check to see if they follow the playlist. Maximum: 5 ids.
|
||||
|
||||
'''
|
||||
"""
|
||||
return self._get("users/{}/playlists/{}/followers/contains?ids={}".format(playlist_owner_id, playlist_id, ','.join(user_ids)))
|
||||
|
||||
def me(self):
|
||||
''' Get detailed profile information about the current user.
|
||||
""" Get detailed profile information about the current user.
|
||||
An alias for the 'current_user' method.
|
||||
'''
|
||||
"""
|
||||
return self._get('me/')
|
||||
|
||||
def current_user(self):
|
||||
''' Get detailed profile information about the current user.
|
||||
""" Get detailed profile information about the current user.
|
||||
An alias for the 'me' method.
|
||||
'''
|
||||
"""
|
||||
return self.me()
|
||||
|
||||
def current_user_playing_track(self):
|
||||
''' Get information about the current users currently playing track.
|
||||
'''
|
||||
return self._get('me/player/currently-playing')
|
||||
|
||||
def current_user_saved_albums(self, limit=20, offset=0):
|
||||
''' Gets a list of the albums saved in the current authorized user's
|
||||
""" Gets a list of the albums saved in the current authorized user's
|
||||
"Your Music" library
|
||||
|
||||
Parameters:
|
||||
- limit - the number of albums to return
|
||||
- offset - the index of the first album to return
|
||||
|
||||
'''
|
||||
"""
|
||||
return self._get('me/albums', limit=limit, offset=offset)
|
||||
|
||||
def current_user_saved_tracks(self, limit=20, offset=0):
|
||||
''' Gets a list of the tracks saved in the current authorized user's
|
||||
""" Gets a list of the tracks saved in the current authorized user's
|
||||
"Your Music" library
|
||||
|
||||
Parameters:
|
||||
- limit - the number of tracks to return
|
||||
- offset - the index of the first track to return
|
||||
|
||||
'''
|
||||
"""
|
||||
return self._get('me/tracks', limit=limit, offset=offset)
|
||||
|
||||
def current_user_followed_artists(self, limit=20, after=None):
|
||||
''' Gets a list of the artists followed by the current authorized user
|
||||
""" Gets a list of the artists followed by the current authorized user
|
||||
|
||||
Parameters:
|
||||
- limit - the number of tracks to return
|
||||
- after - ghe last artist ID retrieved from the previous request
|
||||
|
||||
'''
|
||||
"""
|
||||
return self._get('me/following', type='artist', limit=limit,
|
||||
after=after)
|
||||
|
||||
def current_user_saved_tracks_delete(self, tracks=None):
|
||||
''' Remove one or more tracks from the current user's
|
||||
""" Remove one or more tracks from the current user's
|
||||
"Your Music" library.
|
||||
|
||||
Parameters:
|
||||
- tracks - a list of track URIs, URLs or IDs
|
||||
'''
|
||||
"""
|
||||
tlist = []
|
||||
if tracks is not None:
|
||||
tlist = [self._get_id('track', t) for t in tracks]
|
||||
return self._delete('me/tracks/?ids=' + ','.join(tlist))
|
||||
|
||||
def current_user_saved_tracks_contains(self, tracks=None):
|
||||
''' Check if one or more tracks is already saved in
|
||||
""" Check if one or more tracks is already saved in
|
||||
the current Spotify user’s “Your Music” library.
|
||||
|
||||
Parameters:
|
||||
- tracks - a list of track URIs, URLs or IDs
|
||||
'''
|
||||
"""
|
||||
tlist = []
|
||||
if tracks is not None:
|
||||
tlist = [self._get_id('track', t) for t in tracks]
|
||||
return self._get('me/tracks/contains?ids=' + ','.join(tlist))
|
||||
|
||||
def current_user_saved_tracks_add(self, tracks=None):
|
||||
''' Add one or more tracks to the current user's
|
||||
""" Add one or more tracks to the current user's
|
||||
"Your Music" library.
|
||||
|
||||
Parameters:
|
||||
- tracks - a list of track URIs, URLs or IDs
|
||||
'''
|
||||
"""
|
||||
tlist = []
|
||||
if tracks is not None:
|
||||
tlist = [self._get_id('track', t) for t in tracks]
|
||||
@ -648,43 +657,65 @@ class Spotify(object):
|
||||
|
||||
def current_user_top_artists(self, limit=20, offset=0,
|
||||
time_range='medium_term'):
|
||||
''' Get the current user's top artists
|
||||
""" Get the current user's top artists
|
||||
|
||||
Parameters:
|
||||
- limit - the number of entities to return
|
||||
- offset - the index of the first entity to return
|
||||
- time_range - Over what time frame are the affinities computed
|
||||
Valid-values: short_term, medium_term, long_term
|
||||
'''
|
||||
"""
|
||||
return self._get('me/top/artists', time_range=time_range, limit=limit,
|
||||
offset=offset)
|
||||
|
||||
def current_user_top_tracks(self, limit=20, offset=0,
|
||||
time_range='medium_term'):
|
||||
''' Get the current user's top tracks
|
||||
""" Get the current user's top tracks
|
||||
|
||||
Parameters:
|
||||
- limit - the number of entities to return
|
||||
- offset - the index of the first entity to return
|
||||
- time_range - Over what time frame are the affinities computed
|
||||
Valid-values: short_term, medium_term, long_term
|
||||
'''
|
||||
"""
|
||||
return self._get('me/top/tracks', time_range=time_range, limit=limit,
|
||||
offset=offset)
|
||||
|
||||
def current_user_recently_played(self, limit=50):
|
||||
''' Get the current user's recently played tracks
|
||||
|
||||
Parameters:
|
||||
- limit - the number of entities to return
|
||||
'''
|
||||
return self._get('me/player/recently-played', limit=limit)
|
||||
|
||||
def current_user_saved_albums_add(self, albums=[]):
|
||||
''' Add one or more albums to the current user's
|
||||
""" Add one or more albums to the current user's
|
||||
"Your Music" library.
|
||||
Parameters:
|
||||
- albums - a list of album URIs, URLs or IDs
|
||||
'''
|
||||
"""
|
||||
alist = [self._get_id('album', a) for a in albums]
|
||||
r = self._put('me/albums?ids=' + ','.join(alist))
|
||||
return r
|
||||
|
||||
def user_follow_artists(self, ids=[]):
|
||||
''' Follow one or more artists
|
||||
Parameters:
|
||||
- ids - a list of artist IDs
|
||||
'''
|
||||
return self._put('me/following?type=artist&ids=' + ','.join(ids))
|
||||
|
||||
def user_follow_users(self, ids=[]):
|
||||
''' Follow one or more users
|
||||
Parameters:
|
||||
- ids - a list of user IDs
|
||||
'''
|
||||
return self._put('me/following?type=user&ids=' + ','.join(ids))
|
||||
|
||||
def featured_playlists(self, locale=None, country=None, timestamp=None,
|
||||
limit=20, offset=0):
|
||||
''' Get a list of Spotify featured playlists
|
||||
""" Get a list of Spotify featured playlists
|
||||
|
||||
Parameters:
|
||||
- locale - The desired language, consisting of a lowercase ISO
|
||||
@ -704,13 +735,13 @@ class Spotify(object):
|
||||
- offset - The index of the first item to return. Default: 0
|
||||
(the first object). Use with limit to get the next set of
|
||||
items.
|
||||
'''
|
||||
"""
|
||||
return self._get('browse/featured-playlists', locale=locale,
|
||||
country=country, timestamp=timestamp, limit=limit,
|
||||
offset=offset)
|
||||
|
||||
def new_releases(self, country=None, limit=20, offset=0):
|
||||
''' Get a list of new album releases featured in Spotify
|
||||
""" Get a list of new album releases featured in Spotify
|
||||
|
||||
Parameters:
|
||||
- country - An ISO 3166-1 alpha-2 country code.
|
||||
@ -721,12 +752,12 @@ class Spotify(object):
|
||||
- offset - The index of the first item to return. Default: 0
|
||||
(the first object). Use with limit to get the next set of
|
||||
items.
|
||||
'''
|
||||
"""
|
||||
return self._get('browse/new-releases', country=country, limit=limit,
|
||||
offset=offset)
|
||||
|
||||
def categories(self, country=None, locale=None, limit=20, offset=0):
|
||||
''' Get a list of new album releases featured in Spotify
|
||||
""" Get a list of new album releases featured in Spotify
|
||||
|
||||
Parameters:
|
||||
- country - An ISO 3166-1 alpha-2 country code.
|
||||
@ -740,13 +771,13 @@ class Spotify(object):
|
||||
- offset - The index of the first item to return. Default: 0
|
||||
(the first object). Use with limit to get the next set of
|
||||
items.
|
||||
'''
|
||||
"""
|
||||
return self._get('browse/categories', country=country, locale=locale,
|
||||
limit=limit, offset=offset)
|
||||
|
||||
def category_playlists(self, category_id=None, country=None, limit=20,
|
||||
offset=0):
|
||||
''' Get a list of new album releases featured in Spotify
|
||||
""" Get a list of new album releases featured in Spotify
|
||||
|
||||
Parameters:
|
||||
- category_id - The Spotify category ID for the category.
|
||||
@ -759,13 +790,13 @@ class Spotify(object):
|
||||
- offset - The index of the first item to return. Default: 0
|
||||
(the first object). Use with limit to get the next set of
|
||||
items.
|
||||
'''
|
||||
"""
|
||||
return self._get('browse/categories/' + category_id + '/playlists',
|
||||
country=country, limit=limit, offset=offset)
|
||||
|
||||
def recommendations(self, seed_artists=None, seed_genres=None,
|
||||
seed_tracks=None, limit=20, country=None, **kwargs):
|
||||
''' Get a list of recommended tracks for one to five seeds.
|
||||
""" Get a list of recommended tracks for one to five seeds.
|
||||
|
||||
Parameters:
|
||||
- seed_artists - a list of artist IDs, URIs or URLs
|
||||
@ -784,7 +815,7 @@ class Spotify(object):
|
||||
- min/max/target_<attribute> - For the tuneable track attributes listed
|
||||
in the documentation, these values provide filters and targeting on
|
||||
results.
|
||||
'''
|
||||
"""
|
||||
params = dict(limit=limit)
|
||||
if seed_artists:
|
||||
params['seed_artists'] = ','.join(
|
||||
@ -808,23 +839,23 @@ class Spotify(object):
|
||||
return self._get('recommendations', **params)
|
||||
|
||||
def recommendation_genre_seeds(self):
|
||||
''' Get a list of genres available for the recommendations function.
|
||||
'''
|
||||
""" Get a list of genres available for the recommendations function.
|
||||
"""
|
||||
return self._get('recommendations/available-genre-seeds')
|
||||
|
||||
def audio_analysis(self, track_id):
|
||||
''' Get audio analysis for a track based upon its Spotify ID
|
||||
""" Get audio analysis for a track based upon its Spotify ID
|
||||
Parameters:
|
||||
- track_id - a track URI, URL or ID
|
||||
'''
|
||||
"""
|
||||
trid = self._get_id('track', track_id)
|
||||
return self._get('audio-analysis/' + trid)
|
||||
|
||||
def audio_features(self, tracks=[]):
|
||||
''' Get audio features for one or multiple tracks based upon their Spotify IDs
|
||||
""" Get audio features for one or multiple tracks based upon their Spotify IDs
|
||||
Parameters:
|
||||
- tracks - a list of track URIs, URLs or IDs, maximum: 50 ids
|
||||
'''
|
||||
"""
|
||||
if isinstance(tracks, str):
|
||||
trackid = self._get_id('track', tracks)
|
||||
results = self._get('audio-features/?ids=' + trackid)
|
||||
@ -839,13 +870,172 @@ class Spotify(object):
|
||||
return results
|
||||
|
||||
def audio_analysis(self, id):
|
||||
''' Get audio analysis for a track based upon its Spotify ID
|
||||
""" Get audio analysis for a track based upon its Spotify ID
|
||||
Parameters:
|
||||
- id - a track URIs, URLs or IDs
|
||||
'''
|
||||
"""
|
||||
id = self._get_id('track', id)
|
||||
return self._get('audio-analysis/'+id)
|
||||
|
||||
def devices(self):
|
||||
''' Get a list of user's available devices.
|
||||
'''
|
||||
return self._get("me/player/devices")
|
||||
|
||||
def current_playback(self, market = None):
|
||||
''' Get information about user's current playback.
|
||||
|
||||
Parameters:
|
||||
- market - an ISO 3166-1 alpha-2 country code.
|
||||
'''
|
||||
return self._get("me/player", market = market)
|
||||
|
||||
def currently_playing(self, market = None):
|
||||
''' Get user's currently playing track.
|
||||
|
||||
Parameters:
|
||||
- market - an ISO 3166-1 alpha-2 country code.
|
||||
'''
|
||||
return self._get("me/player/currently-playing", market = market)
|
||||
|
||||
def transfer_playback(self, device_id, force_play = True):
|
||||
''' Transfer playback to another device.
|
||||
Note that the API accepts a list of device ids, but only
|
||||
actually supports one.
|
||||
|
||||
Parameters:
|
||||
- device_id - transfer playback to this device
|
||||
- force_play - true: after transfer, play. false:
|
||||
keep current state.
|
||||
'''
|
||||
data = {
|
||||
'device_ids': [device_id],
|
||||
'play': force_play
|
||||
}
|
||||
return self._put("me/player", payload=data)
|
||||
|
||||
def start_playback(self, device_id = None, context_uri = None, uris = None, offset = None):
|
||||
''' Start or resume user's playback.
|
||||
|
||||
Provide a `context_uri` to start playback or a album,
|
||||
artist, or playlist.
|
||||
|
||||
Provide a `uris` list to start playback of one or more
|
||||
tracks.
|
||||
|
||||
Provide `offset` as {"position": <int>} or {"uri": "<track uri>"}
|
||||
to start playback at a particular offset.
|
||||
|
||||
Parameters:
|
||||
- device_id - device target for playback
|
||||
- context_uri - spotify context uri to play
|
||||
- uris - spotify track uris
|
||||
- offset - offset into context by index or track
|
||||
'''
|
||||
if context_uri is not None and uris is not None:
|
||||
self._warn('specify either context uri or uris, not both')
|
||||
return
|
||||
if uris is not None and not isinstance(uris, list):
|
||||
self._warn('uris must be a list')
|
||||
return
|
||||
data = {}
|
||||
if context_uri is not None:
|
||||
data['context_uri'] = context_uri
|
||||
if uris is not None:
|
||||
data['uris'] = uris
|
||||
if offset is not None:
|
||||
data['offset'] = offset
|
||||
return self._put(self._append_device_id("me/player/play", device_id), payload=data)
|
||||
|
||||
def pause_playback(self, device_id = None):
|
||||
''' Pause user's playback.
|
||||
|
||||
Parameters:
|
||||
- device_id - device target for playback
|
||||
'''
|
||||
return self._put(self._append_device_id("me/player/pause", device_id))
|
||||
|
||||
def next_track(self, device_id = None):
|
||||
''' Skip user's playback to next track.
|
||||
|
||||
Parameters:
|
||||
- device_id - device target for playback
|
||||
'''
|
||||
return self._post(self._append_device_id("me/player/next", device_id))
|
||||
|
||||
def previous_track(self, device_id = None):
|
||||
''' Skip user's playback to previous track.
|
||||
|
||||
Parameters:
|
||||
- device_id - device target for playback
|
||||
'''
|
||||
return self._post(self._append_device_id("me/player/previous", device_id))
|
||||
|
||||
def seek_track(self, position_ms, device_id = None):
|
||||
''' Seek to position in current track.
|
||||
|
||||
Parameters:
|
||||
- position_ms - position in milliseconds to seek to
|
||||
- device_id - device target for playback
|
||||
'''
|
||||
if not isinstance(position_ms, int):
|
||||
self._warn('position_ms must be an integer')
|
||||
return
|
||||
return self._put(self._append_device_id("me/player/seek?position_ms=%s" % position_ms, device_id))
|
||||
|
||||
def repeat(self, state, device_id = None):
|
||||
''' Set repeat mode for playback.
|
||||
|
||||
Parameters:
|
||||
- state - `track`, `context`, or `off`
|
||||
- device_id - device target for playback
|
||||
'''
|
||||
if state not in ['track', 'context', 'off']:
|
||||
self._warn('invalid state')
|
||||
return
|
||||
self._put(self._append_device_id("me/player/repeat?state=%s" % state, device_id))
|
||||
|
||||
def volume(self, volume_percent, device_id = None):
|
||||
''' Set playback volume.
|
||||
|
||||
Parameters:
|
||||
- volume_percent - volume between 0 and 100
|
||||
- device_id - device target for playback
|
||||
'''
|
||||
if not isinstance(volume_percent, int):
|
||||
self._warn('volume must be an integer')
|
||||
return
|
||||
if volume_percent < 0 or volume_percent > 100:
|
||||
self._warn('volume must be between 0 and 100, inclusive')
|
||||
return
|
||||
self._put(self._append_device_id("me/player/volume?volume_percent=%s" % volume_percent, device_id))
|
||||
|
||||
def shuffle(self, state, device_id = None):
|
||||
''' Toggle playback shuffling.
|
||||
|
||||
Parameters:
|
||||
- state - true or false
|
||||
- device_id - device target for playback
|
||||
'''
|
||||
if not isinstance(state, bool):
|
||||
self._warn('state must be a boolean')
|
||||
return
|
||||
state = str(state).lower()
|
||||
self._put(self._append_device_id("me/player/shuffle?state=%s" % state, device_id))
|
||||
|
||||
def _append_device_id(self, path, device_id):
|
||||
''' Append device ID to API path.
|
||||
|
||||
Parameters:
|
||||
- device_id - device id to append
|
||||
'''
|
||||
if device_id:
|
||||
if '?' in path:
|
||||
path += "&device_id=%s" % device_id
|
||||
else:
|
||||
path += "?device_id=%s" % device_id
|
||||
return path
|
||||
|
||||
def _get_id(self, type, id):
|
||||
fields = id.split(':')
|
||||
if len(fields) >= 3:
|
||||
|
@ -73,7 +73,7 @@ class SpotifyClientCredentials(object):
|
||||
|
||||
response = requests.post(self.OAUTH_TOKEN_URL, data=payload,
|
||||
headers=headers, verify=True, proxies=self.proxies)
|
||||
if response.status_code is not 200:
|
||||
if response.status_code != 200:
|
||||
raise SpotifyOauthError(response.reason)
|
||||
token_info = response.json()
|
||||
return token_info
|
||||
@ -153,17 +153,14 @@ class SpotifyOAuth(object):
|
||||
pass
|
||||
|
||||
def _is_scope_subset(self, needle_scope, haystack_scope):
|
||||
if needle_scope:
|
||||
needle_scope = set(needle_scope.split())
|
||||
if haystack_scope:
|
||||
haystack_scope = set(haystack_scope.split())
|
||||
|
||||
needle_scope = set(needle_scope.split()) if needle_scope else set()
|
||||
haystack_scope = set(haystack_scope.split()) if haystack_scope else set()
|
||||
return needle_scope <= haystack_scope
|
||||
|
||||
def is_token_expired(self, token_info):
|
||||
return is_token_expired(token_info)
|
||||
|
||||
def get_authorize_url(self, state=None):
|
||||
def get_authorize_url(self, state=None, show_dialog=False):
|
||||
""" Gets the URL to use to authorize this app
|
||||
"""
|
||||
payload = {'client_id': self.client_id,
|
||||
@ -175,6 +172,8 @@ class SpotifyOAuth(object):
|
||||
state = self.state
|
||||
if state is not None:
|
||||
payload['state'] = state
|
||||
if show_dialog:
|
||||
payload['show_dialog'] = True
|
||||
|
||||
urlparams = urllibparse.urlencode(payload)
|
||||
|
||||
@ -214,7 +213,7 @@ class SpotifyOAuth(object):
|
||||
|
||||
response = requests.post(self.OAUTH_TOKEN_URL, data=payload,
|
||||
headers=headers, verify=True, proxies=self.proxies)
|
||||
if response.status_code is not 200:
|
||||
if response.status_code != 200:
|
||||
raise SpotifyOauthError(response.reason)
|
||||
token_info = response.json()
|
||||
token_info = self._add_custom_values_to_token_info(token_info)
|
||||
|
@ -5,10 +5,9 @@ from __future__ import print_function
|
||||
import os
|
||||
from . import oauth2
|
||||
import spotipy
|
||||
import webbrowser
|
||||
|
||||
def prompt_for_user_token(username, scope=None, client_id = None,
|
||||
client_secret = None, redirect_uri = None):
|
||||
client_secret = None, redirect_uri = None, cache_path = None):
|
||||
''' prompts the user to login if necessary and returns
|
||||
the user token suitable for use with the spotipy.Spotify
|
||||
constructor
|
||||
@ -20,6 +19,7 @@ def prompt_for_user_token(username, scope=None, client_id = None,
|
||||
- client_id - the client id of your app
|
||||
- client_secret - the client secret of your app
|
||||
- redirect_uri - the redirect URI of your app
|
||||
- cache_path - path to location to save tokens
|
||||
|
||||
'''
|
||||
|
||||
@ -46,8 +46,9 @@ def prompt_for_user_token(username, scope=None, client_id = None,
|
||||
''')
|
||||
raise spotipy.SpotifyException(550, -1, 'no credentials set')
|
||||
|
||||
cache_path = cache_path or ".cache-" + username
|
||||
sp_oauth = oauth2.SpotifyOAuth(client_id, client_secret, redirect_uri,
|
||||
scope=scope, cache_path=".cache-" + username )
|
||||
scope=scope, cache_path=cache_path)
|
||||
|
||||
# try to get a valid token for this user, from the cache,
|
||||
# if not in the cache, the create a new (this will send
|
||||
@ -67,6 +68,7 @@ def prompt_for_user_token(username, scope=None, client_id = None,
|
||||
''')
|
||||
auth_url = sp_oauth.get_authorize_url()
|
||||
try:
|
||||
import webbrowser
|
||||
webbrowser.open(auth_url)
|
||||
print("Opened %s in your browser" % auth_url)
|
||||
except:
|
||||
|
@ -146,6 +146,24 @@ class TestSpotifyOAuth(unittest.TestCase):
|
||||
parsed_qs = urllibparse.parse_qs(parsed_url.query)
|
||||
self.assertEqual(parsed_qs['state'][0], state)
|
||||
|
||||
def test_get_authorize_url_does_not_show_dialog_by_default(self):
|
||||
oauth = SpotifyOAuth("CLID", "CLISEC", "REDIR")
|
||||
|
||||
url = oauth.get_authorize_url()
|
||||
|
||||
parsed_url = urllibparse.urlparse(url)
|
||||
parsed_qs = urllibparse.parse_qs(parsed_url.query)
|
||||
self.assertNotIn('show_dialog', parsed_qs)
|
||||
|
||||
def test_get_authorize_url_shows_dialog_when_requested(self):
|
||||
oauth = SpotifyOAuth("CLID", "CLISEC", "REDIR")
|
||||
|
||||
url = oauth.get_authorize_url(show_dialog=True)
|
||||
|
||||
parsed_url = urllibparse.urlparse(url)
|
||||
parsed_qs = urllibparse.parse_qs(parsed_url.query)
|
||||
self.assertTrue(parsed_qs['show_dialog'])
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
|
Loading…
Reference in New Issue
Block a user