summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--README.md0
-rw-r--r--getspot.py171
2 files changed, 171 insertions, 0 deletions
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/README.md
diff --git a/getspot.py b/getspot.py
new file mode 100644
index 0000000..1978ffa
--- /dev/null
+++ b/getspot.py
@@ -0,0 +1,171 @@
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
+"""
+Created on Sat Apr 3 22:42:36 2021
+
+@author: fish
+
+Try to get and parse spotify playlists
+
+spotify:playlist:7hGGMcWOPgXj2qFw5DQyXP - likes_2021
+spotify:playlist:2etpNxusBBUoXoxb3BOsF3 - likes_2020
+
+
+
+Todo:
+----
+ - extract the wanted info (track name, artist(s), picture url,
+ track URI, etc) more elegantly
+ - handle multiple artists
+ - access token timeout? check if check is needed
+ - find alternative to the kludge to prevent skipping first list
+
+Done:
+----
+ 2021-04-04: handle longer playlists
+
+Outline:
+-------
+ - get playlist
+ - extract playlist metadata
+ - create playlist dictionary
+ (---)
+ - extract tracks & store
+ - check if done, else iterate over next set of tracks
+ (---)
+ - store completed list, clean up.
+
+
+Playlist format:
+---------------
+ Playlist = {'name': '',
+ 'image': '',
+ 'uri': '',
+ 'tracks': [
+ {'artist': '',
+ 'name': ''
+ },
+ {'artist': ''
+ 'name': ''
+ }
+ ]
+ }
+
+"""
+
+import json
+import requests
+
+# GLOBALS
+
+# kludge to avoid storing secrets in git repo
+with open('spotifyids') as f:
+ CLIENT_ID, CLIENT_SECRET = f.readline().rstrip().split(',')
+AUTH_URL = 'https://accounts.spotify.com/api/token'
+BASE_URL = 'https://api.spotify.com/v1/'
+# base URL of all Spotify API endpoints
+
+PLAYLIST_ID = '37i9dQZF1EMdXVibVNv347' # temp
+
+
+def get_access_token():
+ """
+ Get the temporary access token from the Spotify servers
+ (POST request)
+ """
+
+ auth_response = requests.post(AUTH_URL, {
+ 'grant_type': 'client_credentials',
+ 'client_id': CLIENT_ID,
+ 'client_secret': CLIENT_SECRET,
+ })
+
+ # convert the response to JSON
+ auth_response_data = auth_response.json()
+
+ # save the access token
+ access_token = auth_response_data['access_token']
+ return access_token
+
+
+def get_playlist(access_token):
+ """
+ Get playlist from the servers with this request:
+ GET https://api.spotify.com/v1/playlists/{playlist_id}
+ """
+ headers = {'Authorization': 'Bearer {token}'.format(token=access_token)}
+ # actual GET request with proper header
+ playlist = requests.get(BASE_URL + 'playlists/'
+ + PLAYLIST_ID, headers=headers)
+ playlist = playlist.json()
+ return playlist
+
+
+# playlist ID from the URI
+# playlist_id = '7hGGMcWOPgXj2qFw5DQyXP' # 2021 - shorter than 100 (for now)
+# playlist_id = '2etpNxusBBUoXoxb3BOsF3' # 2020 - longer than 100
+
+
+# %% create playlist dict
+
+
+playlist = get_playlist(get_access_token())
+my_playlist = {'name': playlist['name'],
+ 'uri': playlist['uri'],
+ 'image': playlist['images'][0]['url'],
+ 'tracks': []
+ }
+
+
+# %% strip down to the tracks
+
+work_playlist = playlist['tracks']
+work_playlist['next'] = BASE_URL + 'playlists/' + PLAYLIST_ID + '/tracks'
+# kludge
+
+
+def do_work(access_token):
+ """ extract info from playlist """
+ headers = {'Authorization': 'Bearer {token}'.format(token=access_token)}
+ while True:
+ work_playlist = requests.get(work_playlist['next'], headers=headers)
+ work_playlist = work_playlist.json()
+ print('url is: ', work_playlist['next'])
+
+ # Extract and store playlist items
+ playlist_tracks = []
+
+ for track in work_playlist['items']:
+ playlist_tracks.append({
+ 'artist': track['track']['artists'][0]['name'],
+ 'name': track['track']['name']})
+
+ playlist['tracks'] = playlist['tracks'] + playlist_tracks
+
+ # break loop if no next url
+ if not work_playlist['next']:
+ break
+ return
+
+# %% store list & clean up
+def cleanup():
+ """ store list to file and cleanup etc """
+ playlist_name = playlist['name'] + '-' + playlist_id + '.json'
+
+ with open(playlist_name, 'w') as outfile:
+ json.dump(playlist, outfile, indent=4)
+ return
+
+
+def setup():
+ pass
+
+def main():
+
+ setup()
+ do_work(access_token)
+ cleanup()
+ return
+
+
+main()