import argparse
import json
import sys
import spotipy
import spotipy.util as util

# You must modify these values to use this tool
CLIENT_ID = 'YOUR CLIENT ID HERE'
CLIENT_SECRET = 'YOUR CLIENT SECRET HERE'
REDIRECT_URI = 'YOUR REDIRECT URI HERE'

DEFAULT_SCOPE = 'playlist-read-private user-library-read'
DEFAULT_TRACKS_LIMIT = 20


# Requires a session 'sp' and username
def generate_music_library_tracks(sp, username):
    saved_tracks_result = sp.current_user_saved_tracks(DEFAULT_TRACKS_LIMIT)

    while saved_tracks_result['items']:
        saved_tracks = saved_tracks_result['items']
        for track in saved_tracks:
            yield track

        saved_tracks_result = sp.next(saved_tracks_result)
        if not saved_tracks_result:
            break


def generate_playlist_tracks(sp, username, playlist_id):
    playlist_tracks_result = sp.user_playlist_tracks(
        username, playlist_id, limit=DEFAULT_TRACKS_LIMIT)

    while playlist_tracks_result['items']:
        playlist_tracks = playlist_tracks_result['items']
        for track in playlist_tracks:
            yield track

        playlist_tracks_result = sp.next(playlist_tracks_result)
        if not playlist_tracks_result:
            break


def get_user_token(username):
    return spotipy.util.prompt_for_user_token(
        username, DEFAULT_SCOPE, CLIENT_ID, CLIENT_SECRET, REDIRECT_URI)


def get_playlist_id(sp, username, playlist_name):
    playlists = sp.user_playlists(username)
    for playlist in playlists['items']:
        if playlist['owner']['id'] != username:
            continue
        if playlist['name'] != playlist_name:
            continue

        return playlist['id']
    return None


def init_session(username):
    token = get_user_token(username)

    if not token:
        print "Can't get token for", username
        return None

    return spotipy.Spotify(auth=token)


def make_track_summary(track_result):
    track = track_result['track']
    summary = {
        'album': track['album']['name'],
        'album_type': track['album']['type'],
        'name': track['name'],
        'artists': [artist['name'] for artist in track['artists']]
    }

    # Maybe these ID's will be useful someday
    if 'isrc' in track['external_ids']:
        summary['isrc'] = track['external_ids']['isrc']

    return summary


def serialize_track(track):
    return json.dumps(track)

# Run as main
if __name__ == '__main__':
    parser = argparse.ArgumentParser()
    parser.add_argument('username')
    parser.add_argument('output_file')
    parser.add_argument('--use_music_library', action='store_true')
    parser.add_argument('--playlist')

    args = parser.parse_args()

    sp = init_session(args.username)

    # Bad session
    if not sp:
        print 'Did not log in successfully'
        sys.exit()

    if args.use_music_library:
        tracks_source = generate_music_library_tracks(sp, args.username)
    elif args.playlist:
        playlist_id = get_playlist_id(sp, args.username, args.playlist)
        if not playlist_id:
            print 'Cannot find playlist: %s' % args.playlist
            sys.exit()

        tracks_source = generate_playlist_tracks(
            sp, args.username, playlist_id)
    else:
        print 'Must specify playlist or --use_music_library'
        sys.exit()

    output_file = open(args.output_file, 'w')
    for track in tracks_source:
        track_summary = make_track_summary(track)
        output_file.write(serialize_track(track_summary) + '\n')

@@ -123,17 +123,157 @@
 his tool
+.%0A# These values must match thoes in your Spotify app settings exactly, e.g.%0A# case-sensitive and exact path for URI (trailing slash, etc.).
 %0A
-
 CLIENT_I
@@ -471,47 +471,8 @@
 0%0A%0A%0A
-# Requires a session 'sp' and username%0A
 def 
@@ -512,24 +512,72 @@
  username):%0A
+    %22%22%22Requires a session 'sp' and username.%22%22%22%0A
     saved_tr
@@ -966,16 +966,86 @@
 st_id):%0A
+    %22%22%22Requires a session 'sp', username, and Spotify playlist id.%22%22%22%0A
     play
@@ -1464,24 +1464,94 @@
 (username):%0A
+    %22%22%22Prompt for and return a session token for a given username.%22%22%22%0A
     return s
@@ -1706,24 +1706,88 @@
 list_name):%0A
+    %22%22%22Requires a session 'sp', username, and playlist name.%22%22%22%0A
     playlist
@@ -2067,24 +2067,88 @@
 (username):%0A
+    %22%22%22Initialize and return a Spotify session for username.%22%22%22%0A
     token = 
@@ -2337,16 +2337,64 @@
 esult):%0A
+    %22%22%22Generate a summary of a track result.%22%22%22%0A
     trac
@@ -2819,16 +2819,71 @@
 track):%0A
+    %22%22%22Serialize a track summary object for output.%22%22%22%0A
     retu
@@ -2917,16 +2917,17 @@
  as main
+.
 %0Aif __na
@@ -3233,24 +3233,24 @@
 .username)%0A%0A
-
     # Bad se
@@ -3254,16 +3254,74 @@
  session
+.%0A    # It looks like right now this never gets triggered.
 %0A    if 

Improve documentation and formatting.