mirror of
https://github.com/spotipy-dev/spotipy.git
synced 2026-06-19 09:13:53 +00:00
parent
ccfda079c8
commit
b01adba826
@ -20,6 +20,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||||||
- backoff_factor
|
- backoff_factor
|
||||||
- Spin up a local webserver to auto-fill authentication URL
|
- Spin up a local webserver to auto-fill authentication URL
|
||||||
- Use session in SpotifyAuthBase
|
- Use session in SpotifyAuthBase
|
||||||
|
- Logging used instead of print statements
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|
||||||
|
|||||||
@ -8,7 +8,7 @@ If you would like to contribute to spotipy follow these steps:
|
|||||||
export SPOTIPY_CLIENT_ID=client_id_here
|
export SPOTIPY_CLIENT_ID=client_id_here
|
||||||
export SPOTIPY_CLIENT_SECRET=client_secret_here
|
export SPOTIPY_CLIENT_SECRET=client_secret_here
|
||||||
export SPOTIPY_CLIENT_USERNAME=client_username_here # This is actually an id not spotify display name
|
export SPOTIPY_CLIENT_USERNAME=client_username_here # This is actually an id not spotify display name
|
||||||
export SPOTIPY_REDIRECT_URI=http://localhost/ # Make url is set in app you created to get your ID and SECRET
|
export SPOTIPY_REDIRECT_URI=http://localhost:8080 # Make url is set in app you created to get your ID and SECRET
|
||||||
```
|
```
|
||||||
|
|
||||||
### Create virtual environment, install dependencies, run tests:
|
### Create virtual environment, install dependencies, run tests:
|
||||||
|
|||||||
@ -1,27 +1,36 @@
|
|||||||
|
import argparse
|
||||||
# Add tracks to 'Your Collection' of saved tracks
|
import logging
|
||||||
|
import os
|
||||||
import pprint
|
|
||||||
import sys
|
|
||||||
|
|
||||||
import spotipy
|
import spotipy
|
||||||
import spotipy.util as util
|
import spotipy.util as util
|
||||||
|
|
||||||
|
logger = logging.getLogger('examples.add_a_saved_album')
|
||||||
|
logging.basicConfig(level='DEBUG')
|
||||||
|
|
||||||
scope = 'user-library-modify'
|
scope = 'user-library-modify'
|
||||||
|
|
||||||
if len(sys.argv) > 2:
|
|
||||||
username = sys.argv[1]
|
|
||||||
aids = sys.argv[2:]
|
|
||||||
else:
|
|
||||||
print("Usage: %s username album-id ..." % (sys.argv[0],))
|
|
||||||
sys.exit()
|
|
||||||
|
|
||||||
token = util.prompt_for_user_token(username, scope)
|
def get_args():
|
||||||
|
parser = argparse.ArgumentParser(description='Creates a playlist for user')
|
||||||
|
parser.add_argument('-u', '--username', required=False,
|
||||||
|
default=os.environ.get('SPOTIPY_CLIENT_USERNAME'),
|
||||||
|
help='Username id. Defaults to environment var')
|
||||||
|
parser.add_argument('-a', '--aids', action='append',
|
||||||
|
required=True, help='Album ids')
|
||||||
|
return parser.parse_args()
|
||||||
|
|
||||||
if token:
|
|
||||||
sp = spotipy.Spotify(auth=token)
|
def main():
|
||||||
sp.trace = False
|
args = get_args()
|
||||||
results = sp.current_user_saved_albums_add(albums=aids)
|
token = util.prompt_for_user_token(args.username, scope)
|
||||||
pprint.pprint(results)
|
|
||||||
else:
|
if token:
|
||||||
print("Can't get token for", username)
|
sp = spotipy.Spotify(auth=token)
|
||||||
|
sp.current_user_saved_albums_add(albums=args.aids)
|
||||||
|
else:
|
||||||
|
logger.error("Can't get token for %s", args.username)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
main()
|
||||||
|
|||||||
@ -1,27 +1,37 @@
|
|||||||
|
import argparse
|
||||||
# Add tracks to 'Your Collection' of saved tracks
|
import logging
|
||||||
|
import os
|
||||||
import pprint
|
|
||||||
import sys
|
|
||||||
|
|
||||||
import spotipy
|
import spotipy
|
||||||
import spotipy.util as util
|
import spotipy.util as util
|
||||||
|
|
||||||
scope = 'user-library-modify'
|
scope = 'user-library-modify'
|
||||||
|
|
||||||
if len(sys.argv) > 2:
|
logger = logging.getLogger('examples.add_a_saved_track')
|
||||||
username = sys.argv[1]
|
logging.basicConfig(level='DEBUG')
|
||||||
tids = sys.argv[2:]
|
|
||||||
else:
|
|
||||||
print("Usage: %s username track-id ..." % (sys.argv[0],))
|
|
||||||
sys.exit()
|
|
||||||
|
|
||||||
token = util.prompt_for_user_token(username, scope)
|
|
||||||
|
|
||||||
if token:
|
def get_args():
|
||||||
sp = spotipy.Spotify(auth=token)
|
parser = argparse.ArgumentParser(description='Add tracks to Your '
|
||||||
sp.trace = False
|
'Collection of saved tracks')
|
||||||
results = sp.current_user_saved_tracks_add(tracks=tids)
|
parser.add_argument('-u', '--username', required=False,
|
||||||
pprint.pprint(results)
|
default=os.environ.get('SPOTIPY_CLIENT_USERNAME'),
|
||||||
else:
|
help='Username id. Defaults to environment var')
|
||||||
print("Can't get token for", username)
|
parser.add_argument('-t', '--tids', action='append',
|
||||||
|
required=True, help='Track ids')
|
||||||
|
return parser.parse_args()
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
args = get_args()
|
||||||
|
token = util.prompt_for_user_token(args.username, scope)
|
||||||
|
|
||||||
|
if token:
|
||||||
|
sp = spotipy.Spotify(auth=token)
|
||||||
|
sp.current_user_saved_tracks_add(tracks=args.tids)
|
||||||
|
else:
|
||||||
|
logger.error("Can't get token for %s", args.username)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
main()
|
||||||
|
|||||||
@ -1,26 +1,37 @@
|
|||||||
|
import argparse
|
||||||
# Adds tracks to a playlist
|
import logging
|
||||||
|
import os
|
||||||
import sys
|
|
||||||
|
|
||||||
import spotipy
|
import spotipy
|
||||||
import spotipy.util as util
|
import spotipy.util as util
|
||||||
|
|
||||||
if len(sys.argv) > 3:
|
logger = logging.getLogger('examples.add_tracks_to_playlist')
|
||||||
username = sys.argv[1]
|
logging.basicConfig(level='DEBUG')
|
||||||
playlist_id = sys.argv[2]
|
|
||||||
track_ids = sys.argv[3:]
|
|
||||||
else:
|
|
||||||
print("Usage: %s username playlist_id track_id ..." % (sys.argv[0],))
|
|
||||||
sys.exit()
|
|
||||||
|
|
||||||
scope = 'playlist-modify-public'
|
scope = 'playlist-modify-public'
|
||||||
token = util.prompt_for_user_token(username, scope)
|
|
||||||
|
|
||||||
if token:
|
|
||||||
sp = spotipy.Spotify(auth=token)
|
def get_args():
|
||||||
sp.trace = False
|
parser = argparse.ArgumentParser(description='Adds track to user playlist')
|
||||||
results = sp.user_playlist_add_tracks(username, playlist_id, track_ids)
|
parser.add_argument('-u', '--username', required=False,
|
||||||
print(results)
|
default=os.environ.get('SPOTIPY_CLIENT_USERNAME'),
|
||||||
else:
|
help='Username id. Defaults to environment var')
|
||||||
print("Can't get token for", username)
|
parser.add_argument('-t', '--tids', action='append',
|
||||||
|
required=True, help='Track ids')
|
||||||
|
parser.add_argument('-p', '--playlist', required=True,
|
||||||
|
help='Playlist to add track to')
|
||||||
|
return parser.parse_args()
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
args = get_args()
|
||||||
|
token = util.prompt_for_user_token(args.username, scope)
|
||||||
|
|
||||||
|
if token:
|
||||||
|
sp = spotipy.Spotify(auth=token)
|
||||||
|
sp.user_playlist_add_tracks(args.username, args.playlist, args.tids)
|
||||||
|
else:
|
||||||
|
logger.error("Can't get token for %s", args.username)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
main()
|
||||||
|
|||||||
@ -1,9 +1,20 @@
|
|||||||
|
import argparse
|
||||||
|
import logging
|
||||||
|
|
||||||
from spotipy.oauth2 import SpotifyClientCredentials
|
from spotipy.oauth2 import SpotifyClientCredentials
|
||||||
import sys
|
|
||||||
import spotipy
|
import spotipy
|
||||||
|
|
||||||
''' shows the albums and tracks for a given artist.
|
logger = logging.getLogger('examples.artist_albums')
|
||||||
'''
|
logging.basicConfig(level='INFO')
|
||||||
|
|
||||||
|
sp = spotipy.Spotify(client_credentials_manager=SpotifyClientCredentials())
|
||||||
|
|
||||||
|
|
||||||
|
def get_args():
|
||||||
|
parser = argparse.ArgumentParser(description='Gets albums from artist')
|
||||||
|
parser.add_argument('-a', '--artist', required=True,
|
||||||
|
help='Name of Artist')
|
||||||
|
return parser.parse_args()
|
||||||
|
|
||||||
|
|
||||||
def get_artist(name):
|
def get_artist(name):
|
||||||
@ -27,19 +38,18 @@ def show_artist_albums(artist):
|
|||||||
for album in albums:
|
for album in albums:
|
||||||
name = album['name']
|
name = album['name']
|
||||||
if name not in seen:
|
if name not in seen:
|
||||||
print((' ' + name))
|
logger.info('ALBUM: %s', name)
|
||||||
seen.add(name)
|
seen.add(name)
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
def main():
|
||||||
sp = spotipy.Spotify(client_credentials_manager=SpotifyClientCredentials())
|
args = get_args()
|
||||||
|
artist = get_artist(args.artist)
|
||||||
if len(sys.argv) < 2:
|
if artist:
|
||||||
print(('Usage: {0} artist name'.format(sys.argv[0])))
|
show_artist_albums(artist)
|
||||||
else:
|
else:
|
||||||
name = ' '.join(sys.argv[1:])
|
logger.error("Can't find artist: %s", artist)
|
||||||
artist = get_artist(name)
|
|
||||||
if artist:
|
|
||||||
show_artist_albums(artist)
|
if __name__ == '__main__':
|
||||||
else:
|
main()
|
||||||
print("Can't find that artist")
|
|
||||||
|
|||||||
@ -1,9 +1,19 @@
|
|||||||
|
import argparse
|
||||||
|
import logging
|
||||||
|
|
||||||
from spotipy.oauth2 import SpotifyClientCredentials
|
from spotipy.oauth2 import SpotifyClientCredentials
|
||||||
import sys
|
|
||||||
import spotipy
|
import spotipy
|
||||||
|
|
||||||
''' shows the albums and tracks for a given artist.
|
logger = logging.getLogger('examples.artist_discography')
|
||||||
'''
|
logging.basicConfig(level='INFO')
|
||||||
|
|
||||||
|
|
||||||
|
def get_args():
|
||||||
|
parser = argparse.ArgumentParser(description='Shows albums and tracks for '
|
||||||
|
'given artist')
|
||||||
|
parser.add_argument('-a', '--artist', required=True,
|
||||||
|
help='Name of Artist')
|
||||||
|
return parser.parse_args()
|
||||||
|
|
||||||
|
|
||||||
def get_artist(name):
|
def get_artist(name):
|
||||||
@ -22,45 +32,41 @@ def show_album_tracks(album):
|
|||||||
while results['next']:
|
while results['next']:
|
||||||
results = sp.next(results)
|
results = sp.next(results)
|
||||||
tracks.extend(results['items'])
|
tracks.extend(results['items'])
|
||||||
for track in tracks:
|
for i, track in enumerate(tracks):
|
||||||
print(' ', track['name'])
|
logger.info('%s. %s', i+1, track['name'])
|
||||||
print()
|
|
||||||
print(track)
|
|
||||||
|
|
||||||
|
|
||||||
def show_artist_albums(id):
|
def show_artist_albums(artist):
|
||||||
albums = []
|
albums = []
|
||||||
results = sp.artist_albums(artist['id'], album_type='album')
|
results = sp.artist_albums(artist['id'], album_type='album')
|
||||||
albums.extend(results['items'])
|
albums.extend(results['items'])
|
||||||
while results['next']:
|
while results['next']:
|
||||||
results = sp.next(results)
|
results = sp.next(results)
|
||||||
albums.extend(results['items'])
|
albums.extend(results['items'])
|
||||||
print('Total albums:', len(albums))
|
logger.info('Total albums: %s', len(albums))
|
||||||
unique = set() # skip duplicate albums
|
unique = set() # skip duplicate albums
|
||||||
for album in albums:
|
for album in albums:
|
||||||
name = album['name'].lower()
|
name = album['name'].lower()
|
||||||
if name not in unique:
|
if name not in unique:
|
||||||
print(name)
|
logger.info('ALBUM: %s', name)
|
||||||
unique.add(name)
|
unique.add(name)
|
||||||
show_album_tracks(album)
|
show_album_tracks(album)
|
||||||
|
|
||||||
|
|
||||||
def show_artist(artist):
|
def show_artist(artist):
|
||||||
print('====', artist['name'], '====')
|
logger.info('====%s====', artist['name'])
|
||||||
print('Popularity: ', artist['popularity'])
|
logger.info('Popularity: %s', artist['popularity'])
|
||||||
if len(artist['genres']) > 0:
|
if len(artist['genres']) > 0:
|
||||||
print('Genres: ', ','.join(artist['genres']))
|
logger.info('Genres: %s', ','.join(artist['genres']))
|
||||||
|
|
||||||
|
def main():
|
||||||
|
args = get_args()
|
||||||
|
artist = get_artist(args.artist)
|
||||||
|
show_artist(artist)
|
||||||
|
show_artist_albums(artist)
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
client_credentials_manager = SpotifyClientCredentials()
|
client_credentials_manager = SpotifyClientCredentials()
|
||||||
sp = spotipy.Spotify(client_credentials_manager=client_credentials_manager)
|
sp = spotipy.Spotify(client_credentials_manager=client_credentials_manager)
|
||||||
sp.trace = False
|
main()
|
||||||
|
|
||||||
if len(sys.argv) < 2:
|
|
||||||
print(('Usage: {0} artist name'.format(sys.argv[0])))
|
|
||||||
else:
|
|
||||||
name = ' '.join(sys.argv[1:])
|
|
||||||
artist = get_artist(name)
|
|
||||||
show_artist(artist)
|
|
||||||
show_artist_albums(artist)
|
|
||||||
|
|||||||
@ -1,13 +1,22 @@
|
|||||||
import sys
|
import argparse
|
||||||
|
import logging
|
||||||
|
|
||||||
import spotipy
|
import spotipy
|
||||||
|
|
||||||
''' shows recommendations for the given artist
|
|
||||||
'''
|
|
||||||
|
|
||||||
from spotipy.oauth2 import SpotifyClientCredentials
|
from spotipy.oauth2 import SpotifyClientCredentials
|
||||||
|
|
||||||
|
|
||||||
|
logger = logging.getLogger('examples.artist_recommendations')
|
||||||
|
logging.basicConfig(level='INFO')
|
||||||
|
|
||||||
client_credentials_manager = SpotifyClientCredentials()
|
client_credentials_manager = SpotifyClientCredentials()
|
||||||
sp = spotipy.Spotify(client_credentials_manager=client_credentials_manager)
|
sp = spotipy.Spotify(client_credentials_manager=client_credentials_manager)
|
||||||
sp.trace = False
|
|
||||||
|
|
||||||
|
def get_args():
|
||||||
|
parser = argparse.ArgumentParser(description='Recommendations for the '
|
||||||
|
'given artist')
|
||||||
|
parser.add_argument('-a', '--artist', required=True, help='Name of Artist')
|
||||||
|
return parser.parse_args()
|
||||||
|
|
||||||
|
|
||||||
def get_artist(name):
|
def get_artist(name):
|
||||||
@ -22,16 +31,18 @@ def get_artist(name):
|
|||||||
def show_recommendations_for_artist(artist):
|
def show_recommendations_for_artist(artist):
|
||||||
results = sp.recommendations(seed_artists=[artist['id']])
|
results = sp.recommendations(seed_artists=[artist['id']])
|
||||||
for track in results['tracks']:
|
for track in results['tracks']:
|
||||||
print(track['name'], '-', track['artists'][0]['name'])
|
logger.info('Recommendation: %s - %s', track['name'],
|
||||||
|
track['artists'][0]['name'])
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
args = get_args()
|
||||||
|
artist = get_artist(args.artist)
|
||||||
|
if artist:
|
||||||
|
show_recommendations_for_artist(artist)
|
||||||
|
else:
|
||||||
|
logger.error("Can't find that artist", args.artist)
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
if len(sys.argv) < 2:
|
main()
|
||||||
print(('Usage: {0} artist name'.format(sys.argv[0])))
|
|
||||||
else:
|
|
||||||
name = ' '.join(sys.argv[1:])
|
|
||||||
artist = get_artist(name)
|
|
||||||
if artist:
|
|
||||||
show_recommendations_for_artist(artist)
|
|
||||||
else:
|
|
||||||
print("Can't find that artist", name)
|
|
||||||
|
|||||||
@ -1,42 +1,54 @@
|
|||||||
|
import argparse
|
||||||
# Modify the details of a playlist (name, public, collaborative)
|
import logging
|
||||||
|
import os
|
||||||
import sys
|
|
||||||
|
|
||||||
import spotipy
|
import spotipy
|
||||||
import spotipy.util as util
|
import spotipy.util as util
|
||||||
|
|
||||||
if len(sys.argv) > 3:
|
logger = logging.getLogger('examples.change_playlist_details')
|
||||||
username = sys.argv[1]
|
logging.basicConfig(level='DEBUG')
|
||||||
playlist_id = sys.argv[2]
|
|
||||||
name = sys.argv[3]
|
|
||||||
|
|
||||||
public = None
|
|
||||||
if len(sys.argv) > 4:
|
|
||||||
public = sys.argv[4].lower() == 'true'
|
|
||||||
|
|
||||||
collaborative = None
|
|
||||||
if len(sys.argv) > 5:
|
|
||||||
collaborative = sys.argv[5].lower() == 'true'
|
|
||||||
|
|
||||||
description = None
|
|
||||||
if len(sys.argv) > 6:
|
|
||||||
description = sys.argv[6]
|
|
||||||
|
|
||||||
else:
|
|
||||||
print("Usage: %s username playlist_id name [public collaborative "
|
|
||||||
"description]" % (sys.argv[0]))
|
|
||||||
sys.exit()
|
|
||||||
|
|
||||||
scope = 'playlist-modify-public playlist-modify-private'
|
scope = 'playlist-modify-public playlist-modify-private'
|
||||||
token = util.prompt_for_user_token(username, scope)
|
|
||||||
|
|
||||||
if token:
|
|
||||||
sp = spotipy.Spotify(auth=token)
|
def get_args():
|
||||||
sp.trace = False
|
parser = argparse.ArgumentParser(description='Modify details of playlist')
|
||||||
results = sp.user_playlist_change_details(
|
parser.add_argument('-u', '--username', required=False,
|
||||||
username, playlist_id, name=name, public=public,
|
default=os.environ.get('SPOTIPY_CLIENT_USERNAME'),
|
||||||
collaborative=collaborative, description=description)
|
help='Username id. Defaults to environment var')
|
||||||
print(results)
|
parser.add_argument('-p', '--playlist', required=True,
|
||||||
else:
|
help='Playlist id to alter details')
|
||||||
print("Can't get token for"), username
|
parser.add_argument('-n', '--name', required=False,
|
||||||
|
help='Name of playlist')
|
||||||
|
parser.add_argument('--public', action='store_true', required=False,
|
||||||
|
help='Include param if playlist is public')
|
||||||
|
parser.add_argument('--private', action='store_false', required=False,
|
||||||
|
default=None,
|
||||||
|
help='Include param to make playlist is private')
|
||||||
|
parser.add_argument('-c', '--collaborative', action='store_true',
|
||||||
|
required=False, default=None,
|
||||||
|
help='Include param if playlist is collaborative')
|
||||||
|
parser.add_argument('-i', '--independent', action='store_false',
|
||||||
|
required=False, default=None,
|
||||||
|
help='Include param to make playlist non collaborative')
|
||||||
|
parser.add_argument('-d', '--description', default=None, required=False,
|
||||||
|
help='Description of playlist')
|
||||||
|
return parser.parse_args()
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
args = get_args()
|
||||||
|
token = util.prompt_for_user_token(args.username, scope)
|
||||||
|
if token:
|
||||||
|
sp = spotipy.Spotify(auth=token)
|
||||||
|
sp.user_playlist_change_details(
|
||||||
|
args.username, args.playlist, name=args.name,
|
||||||
|
public=args.public or args.private,
|
||||||
|
collaborative=args.collaborative or args.independent,
|
||||||
|
description=args.description)
|
||||||
|
else:
|
||||||
|
logger.error("Can't get token for %s", args.username)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
main()
|
||||||
|
|||||||
@ -1,30 +1,39 @@
|
|||||||
# Creates a playlist for a user
|
# Creates a playlist for a user
|
||||||
|
import argparse
|
||||||
import pprint
|
import logging
|
||||||
import sys
|
import os
|
||||||
|
|
||||||
import spotipy
|
import spotipy
|
||||||
import spotipy.util as util
|
import spotipy.util as util
|
||||||
|
|
||||||
|
logger = logging.getLogger('examples.create_playlist')
|
||||||
|
logging.basicConfig(level='DEBUG')
|
||||||
|
|
||||||
if len(sys.argv) > 2:
|
|
||||||
username = sys.argv[1]
|
|
||||||
playlist_name = sys.argv[2]
|
|
||||||
playlist_description = sys.argv[3]
|
|
||||||
else:
|
|
||||||
print(
|
|
||||||
"Usage: %s username playlist-name playlist-description" %
|
|
||||||
(sys.argv[0],))
|
|
||||||
sys.exit()
|
|
||||||
|
|
||||||
scope = "playlist-modify-public"
|
def get_args():
|
||||||
token = util.prompt_for_user_token(username, scope)
|
parser = argparse.ArgumentParser(description='Creates a playlist for user')
|
||||||
|
parser.add_argument('-u', '--username', required=False,
|
||||||
|
default=os.environ.get('SPOTIPY_CLIENT_USERNAME'),
|
||||||
|
help='Username id. Defaults to environment var')
|
||||||
|
parser.add_argument('-p', '--playlist', required=True,
|
||||||
|
help='Name of Playlist')
|
||||||
|
parser.add_argument('-d', '--description', required=False, default='',
|
||||||
|
help='Description of Playlist')
|
||||||
|
return parser.parse_args()
|
||||||
|
|
||||||
if token:
|
|
||||||
sp = spotipy.Spotify(auth=token)
|
def main():
|
||||||
sp.trace = False
|
args = get_args()
|
||||||
playlists = sp.user_playlist_create(username, playlist_name,
|
scope = "playlist-modify-public"
|
||||||
description=playlist_description)
|
token = util.prompt_for_user_token(args.username, scope)
|
||||||
pprint.pprint(playlists)
|
|
||||||
else:
|
if token:
|
||||||
print("Can't get token for", username)
|
logger.info('USERNAME: %s, PLAYLIST: %s', args.username, args.playlist)
|
||||||
|
sp = spotipy.Spotify(auth=token)
|
||||||
|
sp.user_playlist_create(args.username, args.playlist)
|
||||||
|
else:
|
||||||
|
logger.error("Can't get token for: %s", args.username)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
main()
|
||||||
|
|||||||
@ -1,19 +0,0 @@
|
|||||||
# shows acoustic features for tracks for the given artist
|
|
||||||
|
|
||||||
from __future__ import print_function # (at top of module)
|
|
||||||
from spotipy.oauth2 import SpotifyClientCredentials
|
|
||||||
import spotipy
|
|
||||||
|
|
||||||
|
|
||||||
client_credentials_manager = SpotifyClientCredentials()
|
|
||||||
sp = spotipy.Spotify(client_credentials_manager=client_credentials_manager)
|
|
||||||
sp.trace = True
|
|
||||||
try:
|
|
||||||
print('bad call 0')
|
|
||||||
bad_artist_call = sp.artist('spotify:artist:12341234')
|
|
||||||
except spotipy.client.SpotifyException:
|
|
||||||
print('bad call 0 exception')
|
|
||||||
|
|
||||||
print('bad call 1')
|
|
||||||
bad_artist_call = sp.artist('spotify:artist:12341234')
|
|
||||||
print('bad artist', bad_artist_call)
|
|
||||||
@ -1,14 +0,0 @@
|
|||||||
# shows artist info for a URN or URL
|
|
||||||
|
|
||||||
import spotipy
|
|
||||||
import sys
|
|
||||||
import pprint
|
|
||||||
|
|
||||||
if len(sys.argv) > 1:
|
|
||||||
search_str = sys.argv[1]
|
|
||||||
else:
|
|
||||||
search_str = 'Radiohead'
|
|
||||||
|
|
||||||
sp = spotipy.Spotify(requests_timeout=.1)
|
|
||||||
result = sp.search(search_str)
|
|
||||||
pprint.pprint(result)
|
|
||||||
@ -2,10 +2,10 @@
|
|||||||
|
|
||||||
""" A simple and thin Python library for the Spotify Web API """
|
""" A simple and thin Python library for the Spotify Web API """
|
||||||
|
|
||||||
from __future__ import print_function
|
__all__ = ["Spotify", "SpotifyException"]
|
||||||
|
|
||||||
import json
|
import json
|
||||||
import sys
|
import logging
|
||||||
import warnings
|
import warnings
|
||||||
|
|
||||||
import requests
|
import requests
|
||||||
@ -14,6 +14,8 @@ import six
|
|||||||
|
|
||||||
from spotipy.exceptions import SpotifyException
|
from spotipy.exceptions import SpotifyException
|
||||||
|
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
class Spotify(object):
|
class Spotify(object):
|
||||||
"""
|
"""
|
||||||
@ -24,18 +26,12 @@ class Spotify(object):
|
|||||||
urn = 'spotify:artist:3jOstUTkEu2JkjvRdBA5Gu'
|
urn = 'spotify:artist:3jOstUTkEu2JkjvRdBA5Gu'
|
||||||
sp = spotipy.Spotify()
|
sp = spotipy.Spotify()
|
||||||
|
|
||||||
sp.trace = True # turn on tracing
|
|
||||||
sp.trace_out = True # turn on trace out
|
|
||||||
|
|
||||||
artist = sp.artist(urn)
|
artist = sp.artist(urn)
|
||||||
print(artist)
|
print(artist)
|
||||||
|
|
||||||
user = sp.user('plamere')
|
user = sp.user('plamere')
|
||||||
print(user)
|
print(user)
|
||||||
"""
|
"""
|
||||||
|
|
||||||
trace = False # Enable tracing?
|
|
||||||
trace_out = False
|
|
||||||
max_retries = 3
|
max_retries = 3
|
||||||
default_retry_codes = (429, 500, 502, 503, 504)
|
default_retry_codes = (429, 500, 502, 503, 504)
|
||||||
|
|
||||||
@ -161,8 +157,8 @@ class Spotify(object):
|
|||||||
if payload:
|
if payload:
|
||||||
args["data"] = json.dumps(payload)
|
args["data"] = json.dumps(payload)
|
||||||
|
|
||||||
if self.trace_out:
|
logger.debug('Sending %s to %s with Headers: %s and Body: %r ',
|
||||||
print(url)
|
method, url, headers, args.get('data'))
|
||||||
|
|
||||||
try:
|
try:
|
||||||
response = self._session.request(
|
response = self._session.request(
|
||||||
@ -170,15 +166,6 @@ class Spotify(object):
|
|||||||
timeout=self.requests_timeout, **args
|
timeout=self.requests_timeout, **args
|
||||||
)
|
)
|
||||||
|
|
||||||
if self.trace: # pragma: no cover
|
|
||||||
print()
|
|
||||||
print("Request headers:", headers)
|
|
||||||
print("Response headers:", response.headers)
|
|
||||||
print("HTTP status", response.status_code)
|
|
||||||
print(method, response.url)
|
|
||||||
if payload:
|
|
||||||
print("Data", json.dumps(payload))
|
|
||||||
|
|
||||||
response.raise_for_status()
|
response.raise_for_status()
|
||||||
results = response.json()
|
results = response.json()
|
||||||
except requests.exceptions.HTTPError:
|
except requests.exceptions.HTTPError:
|
||||||
@ -187,6 +174,9 @@ class Spotify(object):
|
|||||||
except (ValueError, KeyError):
|
except (ValueError, KeyError):
|
||||||
msg = "error"
|
msg = "error"
|
||||||
|
|
||||||
|
logger.error('HTTP Error for %s to %s returned %s due to %s',
|
||||||
|
method, url, response.status_code, msg)
|
||||||
|
|
||||||
raise SpotifyException(
|
raise SpotifyException(
|
||||||
response.status_code,
|
response.status_code,
|
||||||
-1,
|
-1,
|
||||||
@ -194,6 +184,7 @@ class Spotify(object):
|
|||||||
headers=response.headers,
|
headers=response.headers,
|
||||||
)
|
)
|
||||||
except requests.exceptions.RetryError:
|
except requests.exceptions.RetryError:
|
||||||
|
logger.error('Max Retries reached')
|
||||||
raise SpotifyException(
|
raise SpotifyException(
|
||||||
599,
|
599,
|
||||||
-1,
|
-1,
|
||||||
@ -203,9 +194,7 @@ class Spotify(object):
|
|||||||
except ValueError:
|
except ValueError:
|
||||||
results = None
|
results = None
|
||||||
|
|
||||||
if self.trace: # pragma: no cover
|
logger.debug('RESULTS: %s', results)
|
||||||
print("Response:", results)
|
|
||||||
print()
|
|
||||||
return results
|
return results
|
||||||
|
|
||||||
def _get(self, url, args=None, payload=None, **kwargs):
|
def _get(self, url, args=None, payload=None, **kwargs):
|
||||||
@ -251,12 +240,6 @@ class Spotify(object):
|
|||||||
else:
|
else:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def _warn_old(self, msg):
|
|
||||||
print("warning:" + msg, file=sys.stderr)
|
|
||||||
|
|
||||||
def _warn(self, msg, *args):
|
|
||||||
print("warning:" + msg.format(*args), file=sys.stderr)
|
|
||||||
|
|
||||||
def track(self, track_id):
|
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
|
||||||
|
|
||||||
@ -1322,10 +1305,10 @@ class Spotify(object):
|
|||||||
start playing the next song.
|
start playing the next song.
|
||||||
"""
|
"""
|
||||||
if context_uri is not None and uris is not None:
|
if context_uri is not None and uris is not None:
|
||||||
self._warn("specify either context uri or uris, not both")
|
logger.warning("Specify either context uri or uris, not both")
|
||||||
return
|
return
|
||||||
if uris is not None and not isinstance(uris, list):
|
if uris is not None and not isinstance(uris, list):
|
||||||
self._warn("uris must be a list")
|
logger.warning("URIs must be a list")
|
||||||
return
|
return
|
||||||
data = {}
|
data = {}
|
||||||
if context_uri is not None:
|
if context_uri is not None:
|
||||||
@ -1374,7 +1357,7 @@ class Spotify(object):
|
|||||||
- device_id - device target for playback
|
- device_id - device target for playback
|
||||||
"""
|
"""
|
||||||
if not isinstance(position_ms, int):
|
if not isinstance(position_ms, int):
|
||||||
self._warn("position_ms must be an integer")
|
logger.warning("Position_ms must be an integer")
|
||||||
return
|
return
|
||||||
return self._put(
|
return self._put(
|
||||||
self._append_device_id(
|
self._append_device_id(
|
||||||
@ -1390,7 +1373,7 @@ class Spotify(object):
|
|||||||
- device_id - device target for playback
|
- device_id - device target for playback
|
||||||
"""
|
"""
|
||||||
if state not in ["track", "context", "off"]:
|
if state not in ["track", "context", "off"]:
|
||||||
self._warn("invalid state")
|
logger.warning("Invalid state")
|
||||||
return
|
return
|
||||||
self._put(
|
self._put(
|
||||||
self._append_device_id(
|
self._append_device_id(
|
||||||
@ -1406,10 +1389,10 @@ class Spotify(object):
|
|||||||
- device_id - device target for playback
|
- device_id - device target for playback
|
||||||
"""
|
"""
|
||||||
if not isinstance(volume_percent, int):
|
if not isinstance(volume_percent, int):
|
||||||
self._warn("volume must be an integer")
|
logger.warning("Volume must be an integer")
|
||||||
return
|
return
|
||||||
if volume_percent < 0 or volume_percent > 100:
|
if volume_percent < 0 or volume_percent > 100:
|
||||||
self._warn("volume must be between 0 and 100, inclusive")
|
logger.warning("Volume must be between 0 and 100, inclusive")
|
||||||
return
|
return
|
||||||
self._put(
|
self._put(
|
||||||
self._append_device_id(
|
self._append_device_id(
|
||||||
@ -1426,7 +1409,7 @@ class Spotify(object):
|
|||||||
- device_id - device target for playback
|
- device_id - device target for playback
|
||||||
"""
|
"""
|
||||||
if not isinstance(state, bool):
|
if not isinstance(state, bool):
|
||||||
self._warn("state must be a boolean")
|
logger.warning("state must be a boolean")
|
||||||
return
|
return
|
||||||
state = str(state).lower()
|
state = str(state).lower()
|
||||||
self._put(
|
self._put(
|
||||||
@ -1476,19 +1459,15 @@ class Spotify(object):
|
|||||||
fields = id.split(":")
|
fields = id.split(":")
|
||||||
if len(fields) >= 3:
|
if len(fields) >= 3:
|
||||||
if type != fields[-2]:
|
if type != fields[-2]:
|
||||||
self._warn(
|
logger.warning('Expected id of type %s but found type %s %s',
|
||||||
"expected id of type %s but found type %s %s"
|
type, fields[-2], id)
|
||||||
% (type, fields[-2], id)
|
|
||||||
)
|
|
||||||
return fields[-1]
|
return fields[-1]
|
||||||
fields = id.split("/")
|
fields = id.split("/")
|
||||||
if len(fields) >= 3:
|
if len(fields) >= 3:
|
||||||
itype = fields[-2]
|
itype = fields[-2]
|
||||||
if type != itype:
|
if type != itype:
|
||||||
self._warn(
|
logger.warning('Expected id of type %s but found type %s %s',
|
||||||
"expected id of type %s but found type %s %s"
|
type, itype, id)
|
||||||
% (type, itype, id)
|
|
||||||
)
|
|
||||||
return fields[-1].split("?")[0]
|
return fields[-1].split("?")[0]
|
||||||
return id
|
return id
|
||||||
|
|
||||||
|
|||||||
@ -1,7 +1,5 @@
|
|||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
from __future__ import print_function
|
|
||||||
|
|
||||||
__all__ = [
|
__all__ = [
|
||||||
"is_token_expired",
|
"is_token_expired",
|
||||||
"SpotifyClientCredentials",
|
"SpotifyClientCredentials",
|
||||||
@ -11,10 +9,11 @@ __all__ = [
|
|||||||
|
|
||||||
import base64
|
import base64
|
||||||
import json
|
import json
|
||||||
|
import logging
|
||||||
import os
|
import os
|
||||||
import sys
|
|
||||||
import time
|
import time
|
||||||
import warnings
|
import warnings
|
||||||
|
import webbrowser
|
||||||
|
|
||||||
import requests
|
import requests
|
||||||
from spotipy.util import CLIENT_CREDS_ENV_VARS, get_host_port
|
from spotipy.util import CLIENT_CREDS_ENV_VARS, get_host_port
|
||||||
@ -26,6 +25,8 @@ import six.moves.urllib.parse as urllibparse
|
|||||||
from six.moves.BaseHTTPServer import HTTPServer, BaseHTTPRequestHandler
|
from six.moves.BaseHTTPServer import HTTPServer, BaseHTTPRequestHandler
|
||||||
from six.moves.urllib_parse import urlparse, parse_qsl
|
from six.moves.urllib_parse import urlparse, parse_qsl
|
||||||
|
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
class SpotifyOauthError(Exception):
|
class SpotifyOauthError(Exception):
|
||||||
pass
|
pass
|
||||||
@ -273,7 +274,8 @@ class SpotifyOAuth(SpotifyAuthBase):
|
|||||||
f.write(json.dumps(token_info))
|
f.write(json.dumps(token_info))
|
||||||
f.close()
|
f.close()
|
||||||
except IOError:
|
except IOError:
|
||||||
self._warn("couldn't write token cache to " + self.cache_path)
|
logger.warning('Couldn\'t write token to cache at: %s',
|
||||||
|
self.cache_path)
|
||||||
|
|
||||||
def _is_scope_subset(self, needle_scope, haystack_scope):
|
def _is_scope_subset(self, needle_scope, haystack_scope):
|
||||||
needle_scope = set(needle_scope.split()) if needle_scope else set()
|
needle_scope = set(needle_scope.split()) if needle_scope else set()
|
||||||
@ -323,25 +325,19 @@ class SpotifyOAuth(SpotifyAuthBase):
|
|||||||
|
|
||||||
def _open_auth_url(self):
|
def _open_auth_url(self):
|
||||||
auth_url = self.get_authorize_url()
|
auth_url = self.get_authorize_url()
|
||||||
|
|
||||||
try:
|
try:
|
||||||
import webbrowser
|
|
||||||
webbrowser.open(auth_url)
|
webbrowser.open(auth_url)
|
||||||
print("Opened %s in your browser" % auth_url)
|
logger.info("Opened %s in your browser", auth_url)
|
||||||
except webbrowser.Error:
|
except webbrowser.Error:
|
||||||
print("Please navigate here: %s" % auth_url)
|
logger.error("Please navigate here: %s", auth_url)
|
||||||
|
|
||||||
def _get_auth_response_interactive(self):
|
def _get_auth_response_interactive(self):
|
||||||
self._open_auth_url()
|
self._open_auth_url()
|
||||||
print("")
|
|
||||||
print("")
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
response = raw_input("Enter the URL you were redirected to: ")
|
response = raw_input("Enter the URL you were redirected to: ")
|
||||||
except NameError:
|
except NameError:
|
||||||
response = input("Enter the URL you were redirected to: ")
|
response = input("Enter the URL you were redirected to: ")
|
||||||
print("")
|
|
||||||
print("")
|
|
||||||
return self.parse_response_code(response)
|
return self.parse_response_code(response)
|
||||||
|
|
||||||
def _get_auth_response_local_server(self, redirect_port):
|
def _get_auth_response_local_server(self, redirect_port):
|
||||||
@ -357,16 +353,11 @@ class SpotifyOAuth(SpotifyAuthBase):
|
|||||||
raise SpotifyOauthError("Server listening on localhost has not been accessed")
|
raise SpotifyOauthError("Server listening on localhost has not been accessed")
|
||||||
|
|
||||||
def get_auth_response(self):
|
def get_auth_response(self):
|
||||||
print(
|
logger.info('User authentication requires interaction with your '
|
||||||
"""
|
'web browser. Once you enter your credentials and '
|
||||||
|
'give authorization, you will be redirected to '
|
||||||
User authentication requires interaction with your
|
'a url. Paste that url you were directed to to '
|
||||||
web browser. Once you enter your credentials and
|
'complete the authorization.')
|
||||||
give authorization, you will be redirected to
|
|
||||||
a url.
|
|
||||||
|
|
||||||
"""
|
|
||||||
)
|
|
||||||
|
|
||||||
redirect_info = urlparse(self.redirect_uri)
|
redirect_info = urlparse(self.redirect_uri)
|
||||||
redirect_host, redirect_port = get_host_port(redirect_info.netloc)
|
redirect_host, redirect_port = get_host_port(redirect_info.netloc)
|
||||||
@ -374,10 +365,8 @@ class SpotifyOAuth(SpotifyAuthBase):
|
|||||||
if redirect_host in ("127.0.0.1", "localhost") and redirect_info.scheme == "http":
|
if redirect_host in ("127.0.0.1", "localhost") and redirect_info.scheme == "http":
|
||||||
return self._get_auth_response_local_server(redirect_port)
|
return self._get_auth_response_local_server(redirect_port)
|
||||||
else:
|
else:
|
||||||
print("""
|
logger.info('Paste that url you were directed to in order to '
|
||||||
Paste that url you were directed to to
|
'complete the authorization')
|
||||||
complete the authorization.
|
|
||||||
""")
|
|
||||||
return self._get_auth_response_interactive()
|
return self._get_auth_response_interactive()
|
||||||
|
|
||||||
def get_authorization_code(self, response=None):
|
def get_authorization_code(self, response=None):
|
||||||
@ -393,7 +382,6 @@ class SpotifyOAuth(SpotifyAuthBase):
|
|||||||
as a string.
|
as a string.
|
||||||
"""
|
"""
|
||||||
if as_dict:
|
if as_dict:
|
||||||
print("")
|
|
||||||
warnings.warn(
|
warnings.warn(
|
||||||
"You're using 'as_dict = True'."
|
"You're using 'as_dict = True'."
|
||||||
"get_access_token will return the token string directly in future "
|
"get_access_token will return the token string directly in future "
|
||||||
@ -402,7 +390,6 @@ class SpotifyOAuth(SpotifyAuthBase):
|
|||||||
DeprecationWarning,
|
DeprecationWarning,
|
||||||
stacklevel=2,
|
stacklevel=2,
|
||||||
)
|
)
|
||||||
print("")
|
|
||||||
if check_cache:
|
if check_cache:
|
||||||
token_info = self.get_cached_token()
|
token_info = self.get_cached_token()
|
||||||
if token_info is not None:
|
if token_info is not None:
|
||||||
@ -461,9 +448,13 @@ class SpotifyOAuth(SpotifyAuthBase):
|
|||||||
proxies=self.proxies,
|
proxies=self.proxies,
|
||||||
timeout=self.requests_timeout,
|
timeout=self.requests_timeout,
|
||||||
)
|
)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
response.raise_for_status()
|
response.raise_for_status()
|
||||||
except BaseException:
|
except BaseException:
|
||||||
|
logger.error('Couldn\'t refresh token. Response Status Code: %s '
|
||||||
|
'Reason: %s', response.status_code, response.reason)
|
||||||
|
|
||||||
message = "Couldn't refresh token: code:%d reason:%s" % (
|
message = "Couldn't refresh token: code:%d reason:%s" % (
|
||||||
response.status_code,
|
response.status_code,
|
||||||
response.reason,
|
response.reason,
|
||||||
@ -472,6 +463,7 @@ class SpotifyOAuth(SpotifyAuthBase):
|
|||||||
-1,
|
-1,
|
||||||
message,
|
message,
|
||||||
headers)
|
headers)
|
||||||
|
|
||||||
token_info = response.json()
|
token_info = response.json()
|
||||||
token_info = self._add_custom_values_to_token_info(token_info)
|
token_info = self._add_custom_values_to_token_info(token_info)
|
||||||
if "refresh_token" not in token_info:
|
if "refresh_token" not in token_info:
|
||||||
@ -488,9 +480,6 @@ class SpotifyOAuth(SpotifyAuthBase):
|
|||||||
token_info["scope"] = self.scope
|
token_info["scope"] = self.scope
|
||||||
return token_info
|
return token_info
|
||||||
|
|
||||||
def _warn(self, msg):
|
|
||||||
print("warning:" + msg, file=sys.stderr)
|
|
||||||
|
|
||||||
|
|
||||||
class RequestHandler(BaseHTTPRequestHandler):
|
class RequestHandler(BaseHTTPRequestHandler):
|
||||||
def do_GET(self):
|
def do_GET(self):
|
||||||
|
|||||||
@ -2,14 +2,15 @@
|
|||||||
|
|
||||||
""" Shows a user's playlists (need to be authenticated via oauth) """
|
""" Shows a user's playlists (need to be authenticated via oauth) """
|
||||||
|
|
||||||
from __future__ import print_function
|
|
||||||
|
|
||||||
__all__ = ["CLIENT_CREDS_ENV_VARS", "prompt_for_user_token"]
|
__all__ = ["CLIENT_CREDS_ENV_VARS", "prompt_for_user_token"]
|
||||||
|
|
||||||
|
import logging
|
||||||
import os
|
import os
|
||||||
|
|
||||||
import spotipy
|
import spotipy
|
||||||
|
|
||||||
|
LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
CLIENT_CREDS_ENV_VARS = {
|
CLIENT_CREDS_ENV_VARS = {
|
||||||
"client_id": "SPOTIPY_CLIENT_ID",
|
"client_id": "SPOTIPY_CLIENT_ID",
|
||||||
"client_secret": "SPOTIPY_CLIENT_SECRET",
|
"client_secret": "SPOTIPY_CLIENT_SECRET",
|
||||||
@ -54,7 +55,7 @@ def prompt_for_user_token(
|
|||||||
redirect_uri = os.getenv("SPOTIPY_REDIRECT_URI")
|
redirect_uri = os.getenv("SPOTIPY_REDIRECT_URI")
|
||||||
|
|
||||||
if not client_id:
|
if not client_id:
|
||||||
print(
|
LOGGER.warning(
|
||||||
"""
|
"""
|
||||||
You need to set your Spotify API credentials.
|
You need to set your Spotify API credentials.
|
||||||
You can do this by setting environment variables like so:
|
You can do this by setting environment variables like so:
|
||||||
@ -99,7 +100,7 @@ def prompt_for_user_token(
|
|||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
def get_host_port(netloc, default_port=80):
|
def get_host_port(netloc, default_port=8080):
|
||||||
if ":" in netloc:
|
if ":" in netloc:
|
||||||
host, port = netloc.split(":", 1)
|
host, port = netloc.split(":", 1)
|
||||||
port = int(port)
|
port = int(port)
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user