'''Functions that allow Spotify playlist and track manipulation''' from secrets import user_id, spotify_ready_token import json import re import os import logging import argparse import requests # Logging settings logging.basicConfig(format='%(asctime)s %(levelname)s: %(message)s', encoding='utf-8', level=logging.INFO) # Hardcoded URLs SPOTIFY_API_URL = 'https://api.spotify.com/v1/' USERS_API = SPOTIFY_API_URL+'users/' USER_ID_API = USERS_API+user_id PLAYLIST_API = USERS_API+user_id+'/playlists' PLAYLIST_TRACK_API = SPOTIFY_API_URL+'playlists/' TRACK_API = SPOTIFY_API_URL+'tracks/' AUDIO_FEATURES = SPOTIFY_API_URL+'audio-features/' # General Headers headers={ "Content-Type": "application/json", "Authorization" : "Bearer {}".format(spotify_ready_token)} def commandline_menu(): '''Handles commandline arguments''' parser = argparse.ArgumentParser(description='Create custom playlists via Spotify\'s API') parser.add_argument('-p', '--playlist', dest='PLAYLIST_NAME', type=str, required=True, help='name of playlist to be created') parser.add_argument('-l', '--limit', dest='REQUEST_LIMIT', type=str, help='limit of objects to pull with each api call (min 0, max 50)', default=50) parser.add_argument('-v', '--valence', dest='TRACK_VALENCE', type=float, metavar="[0.000-1.000]", help='sets desired valence of the tracks') parser.add_argument('-d', '--danceability', dest='TRACK_DANCE', type=float, metavar="[0.000-1.000]", help='sets desired danceability of the tracks') args = parser.parse_args() return vars(args) def json_to_file(filename, json_data): '''Saves json_data contents to filename file''' with open(filename, 'w') as json_file: json.dump(json_data, json_file) logging.info('File created: %s', filename) logging.debug('%s', json_data) return filename def track_get_metadata(track_id): '''Gets Metadata (album name, artist and etc.) of song''' #logging.info("Getting track metadata...") track_general = requests.get((TRACK_API + track_id), headers=headers).json() track_artist = track_general['artists'][0]['name'] track_name = track_general['name'] track_album_name = track_general['album']['name'] track_metadata = track_artist + ' - ' + track_name + ' / ' + track_album_name logging.debug('Getting metadata for: %s : %s', track_id, track_general) return track_metadata def track_get_features(track_id): '''Gets Audio features of track (valence, danceability and etc)''' url = AUDIO_FEATURES + track_id track_features = requests.get(url, headers=headers).json() logging.debug('Getting track features for: %s : %s', track_id, track_features) return track_features def track_get_ids(filename): '''Gets all track IDs from a file''' track_ids=[] data = {} with open(filename, 'r') as json_file: data = json.load(json_file) for each in range (0, len(data['items'])): track_ids.append(data['items'][each]['track']['id']) logging.debug('Getting track ids from: %s', filename) logging.debug('%s', track_ids) return track_ids def get_liked_songs(spotify_limit, filename): '''Get songs from the user's Liked Songs''' # To prevent spam of Spotify's servers, I save the Library list to a file # before continuing if os.path.exists(filename): logging.info('Songs file - %s found', filename) else: requests.post((USERS_API+user_id), headers=headers) library_list = requests.get((SPOTIFY_API_URL + 'me/tracks?limit='+spotify_limit), headers=headers) json_to_file(filename, library_list.json()) liked_songs = library_list.json() logging.info('Got songs: %s', liked_songs) return liked_songs return filename def get_all_playlists(filename, userid): '''Get all playlists of selected user''' requests.post(('https://api.spotify.com/v1/users/'+userid), headers=headers) offset=0 items=1 playlists = [] while items != 0: response = requests.get( "https://api.spotify.com/v1/users/"+userid+"/playlists?limit=50&offset="+str(offset), headers=headers).json() offset=offset+50 items = len(response['items']) playlists.append([i['name'] for i in response['items']]) logging.info('Got playlists...') logging.debug('Got playlists: %s', playlists) json_to_file(filename, playlists) return playlists def playlist_exists(name, userid): '''Check if a Playlist with this name already exists''' playlists = str(get_all_playlists('playlists.json', userid)) logging.debug('%s', playlists) exists = False if re.search(name, playlists): logging.info('Playlist %s already exists', name) exists = True return exists def playlist_get_tracks(playlist_id): '''Get all tracks from the selected playlist''' offset=0 items=1 playlist_tracks = [] playlist_tracks_names = [] while items != 0: response = requests.get( PLAYLIST_TRACK_API+playlist_id+"/tracks?limit=50&offset="+str(offset), headers=headers).json() logging.debug('Response: %s', response) offset=offset+50 items = len(response['items']) playlist_tracks.append([i['track']['id'] for i in response['items']]) playlist_tracks_names.append([i['track']['name'] for i in response['items']]) logging.info('Got tracks: %s', playlist_tracks_names) logging.debug('Got tracks: %s', playlist_tracks) return playlist_tracks def playlist_create(name, userid): '''Create new Playlist for the current user''' playlist_id = 1 if playlist_exists(name, userid) is False: requests.post((USERS_API+user_id), headers=headers) request_body=json.dumps({ "name": name, "public": True}) response = requests.post(PLAYLIST_API, headers=headers, data=request_body) playlist_id = response.json()['id'] logging.info('Playlist %s created.',name) return playlist_id def add_tracks_to_playlist(track_ids, playlist_id): '''Adds track(s) to the selected Playlist''' logging.info("Adding songs to playlist %s ...", playlist_id) tracks = playlist_get_tracks(playlist_id) new_tracks = [] for each in enumerate(track_ids): if track_ids[each] in tracks: logging.info('Playlist already contains track: %s', track_ids[each]) else: logging.info('Adding track %s to playlist...', track_ids[each]) new_tracks.append(track_ids[each]) new_tracks_uris = ['spotify:track:' + x for x in new_tracks] track_uris = ','.join(new_tracks_uris) response = requests.post(PLAYLIST_TRACK_API+ playlist_id+"/tracks?uris="+track_uris, headers=headers) logging.info('Tracks added: %s to Playlist: %s', track_uris, playlist_id) return response