diff --git a/scripts/gpm_retrieve/gpm_retrieve.py b/scripts/gpm_retrieve/gpm_retrieve.py index c20a02d..87fc9f3 100755 --- a/scripts/gpm_retrieve/gpm_retrieve.py +++ b/scripts/gpm_retrieve/gpm_retrieve.py @@ -1,36 +1,49 @@ #!/usr/bin/env python3 -from gmusicapi import Mobileclient +import Mobileclient from gmusicapi import argparse import sys import requests import json +import urllib.parse + +creds_path = sys.path[0] + '/mobileclient.cred' -creds_path=sys.path[0] + '/mobileclient.cred' def authenticate(api): creds = api.perform_oauth(storage_filepath=creds_path, open_browser=False) -def uploadLibrary(mudbase_api, songs): +def uploadLibrary(mudbase_api, mudbase_user, mudbase_password, songs): + # First, attempt to login and start a session. + s = requests.Session() + response = s.post(mudbase_api + '/login?username=' + + urllib.parse.quote(mudbase_user) + + '&password=' + + urllib.parse.quote(mudbase_password)) + + if response.status_code != 200: + print("Unable to log in to MuDBase API.") + # Helpers def getArtistStoreIds(song): if 'artistId' in song: - return [ song['artistId'][0] ] - return []; + return [song['artistId'][0]] + return [] + def getSongStoreIds(song): if 'storeId' in song: - return [ song['storeId'] ] + return [song['storeId']] return [] # Create GPM import tag - gpmTagIdResponse = requests.post(mudbase_api + '/tag', data = { + gpmTagIdResponse = s.post(mudbase_api + '/tag', data={ 'name': 'GPM Import' }).json() gpmTagId = gpmTagIdResponse['id'] print(f"Created tag \"GPM Import\", response: {gpmTagIdResponse}") # Create the root genre tag - genreRootResponse = requests.post(mudbase_api + '/tag', data = { + genreRootResponse = s.post(mudbase_api + '/tag', data={ 'name': 'Genre' }).json() genreRootTagId = genreRootResponse['id'] @@ -47,75 +60,80 @@ def uploadLibrary(mudbase_api, songs): # Determine artist properties. artist = { 'name': song['artist'], - 'storeLinks': [ 'https://play.google.com/music/m' + id for id in getArtistStoreIds(song) ], - 'tagIds': [ gpmTagId ] + 'storeLinks': ['https://play.google.com/music/m' + id for id in getArtistStoreIds(song)], + 'tagIds': [gpmTagId] } if 'artist' in song else None # Determine album properties. album = { 'name': song['album'], - 'tagIds': [ gpmTagId ] + 'tagIds': [gpmTagId] } if 'album' in song else None # Determine genre properties. genre = { 'name': song['genre'], - 'parentId': genreRootTagId + 'parentId': genreRootTagId } if 'genre' in song else None # Upload artist if not already done artistId = None if artist: - for key,value in storedArtists.items(): + for key, value in storedArtists.items(): if value == artist: artistId = key break if not artistId: - response = requests.post(mudbase_api + '/artist', json = artist).json() + response = s.post(mudbase_api + '/artist', json=artist).json() artistId = response['id'] - print(f"Created artist \"{artist['name']}\", response: {response}") + print( + f"Created artist \"{artist['name']}\", response: {response}") storedArtists[artistId] = artist # Upload album if not already done albumId = None if album: - for key,value in storedAlbums.items(): + for key, value in storedAlbums.items(): if value == album: albumId = key break if not albumId: - response = requests.post(mudbase_api + '/album', json = album).json() + response = s.post(mudbase_api + '/album', json=album).json() albumId = response['id'] - print(f"Created album \"{album['name']}\", response: {response}") + print( + f"Created album \"{album['name']}\", response: {response}") storedAlbums[albumId] = album # Upload genre if not already done genreTagId = None if genre: - for key,value in storedGenreTags.items(): + for key, value in storedGenreTags.items(): if value == genre: genreTagId = key break if not genreTagId: - response = requests.post(mudbase_api + '/tag', json = genre).json() + response = s.post(mudbase_api + '/tag', json=genre).json() genreTagId = response['id'] - print(f"Created genre tag \"Genre / {genre['name']}\", response: {response}") + print( + f"Created genre tag \"Genre / {genre['name']}\", response: {response}") storedGenreTags[genreTagId] = genre # Upload the song itself - tagIds = [ gpmTagId ] + tagIds = [gpmTagId] if genreTagId: tagIds.append(genreTagId) _song = { 'title': song['title'], - 'artistIds': [ artistId ] if artistId != None else [], - 'albumIds': [ albumId ] if albumId != None else [], + 'artistIds': [artistId] if artistId != None else [], + 'albumIds': [albumId] if albumId != None else [], 'tagIds': tagIds, - 'storeLinks': [ 'https://play.google.com/music/m/' + id for id in getSongStoreIds(song) ], + 'storeLinks': ['https://play.google.com/music/m/' + id for id in getSongStoreIds(song)], } - response = requests.post(mudbase_api + '/song', json = _song).json() - print(f"Created song \"{song['title']}\" with artist ID {artistId}, album ID {albumId}, response: {response}") - + response = s.post(mudbase_api + '/song', json=_song).json() + print( + f"Created song \"{song['title']}\" with artist ID {artistId}, album ID {albumId}, response: {response}") + + def getData(api): return { "songs": api.get_all_songs(), @@ -125,7 +143,7 @@ def getData(api): def getSongs(data): # Get songs from library - songs = [] #data['songs'] + songs = [] # data['songs'] # Append songs from playlists for playlist in data['playlists']: @@ -135,16 +153,27 @@ def getSongs(data): # Uniquify by using a dict. After all, same song may appear in # multiple playlists. - sI = lambda song: song['artist'] + '-' + song['title'] if 'artist' in song and 'title' in song else 'z' + def sI(song): return song['artist'] + '-' + \ + song['title'] if 'artist' in song and 'title' in song else 'z' return list(dict((sI(song), song) for song in songs).values()) + api = Mobileclient() -parser = argparse.ArgumentParser(description="Import Google Music library into MudBase.") -parser.add_argument('--authenticate', help="Generate credentials for authentication", action="store_true") -parser.add_argument('--store-to', help="Store GPM library to JSON for later upload", action='store', dest='store_to') -parser.add_argument('--load-from', help="Load GPM library from JSON for upload", action='store', dest='load_from') -parser.add_argument('--mudbase_api', help="Address for the Mudbase back-end API to upload to", action='store', dest='mudbase_api') +parser = argparse.ArgumentParser( + description="Import Google Music library into MudBase.") +parser.add_argument( + '--authenticate', help="Generate credentials for authentication", action="store_true") +parser.add_argument('--store-to', help="Store GPM library to JSON for later upload", + action='store', dest='store_to') +parser.add_argument('--load-from', help="Load GPM library from JSON for upload", + action='store', dest='load_from') +parser.add_argument('--mudbase_api', help="Address for the Mudbase back-end API to upload to", + action='store', dest='mudbase_api') +parser.add_argument('--mudbase_user', help="Username for the Mudbase API", + action='store', dest="mudbase_user") +parser.add_argument('--mudbase_password', help="Password for the Mudbase API", + action='store', dest="mudbase_password") args = parser.parse_args() @@ -155,7 +184,8 @@ data = None # Determine whether we need to log in to GPM and get songs if args.store_to or (not args.load_from and args.mudbase_api): - api.oauth_login(Mobileclient.FROM_MAC_ADDRESS, oauth_credentials=creds_path) + api.oauth_login(Mobileclient.FROM_MAC_ADDRESS, + oauth_credentials=creds_path) data = getData(api) # Determine whether to save to a file @@ -172,5 +202,7 @@ songs = getSongs(data) print(f"Found {len(songs)} songs.") if args.mudbase_api: - api.oauth_login(Mobileclient.FROM_MAC_ADDRESS, oauth_credentials=creds_path) - uploadLibrary(args.mudbase_api, songs) + api.oauth_login(Mobileclient.FROM_MAC_ADDRESS, + oauth_credentials=creds_path) + uploadLibrary(args.mudbase_api, args.mudbase_user, + args.mudbase_password, songs)