├── README.md ├── add_last_songs_to_top_of_playlist.py └── delete_dups_from_playlists.py /README.md: -------------------------------------------------------------------------------- 1 | Google Music Playlist Scripts 2 | ============================= 3 | 4 | Some quick scripts for editing Google Music playlists. 5 | 6 | Uses the unofficial Google Music Api by [simon weber](https://github.com/simon-weber). 7 | 8 | ## Usage 9 | 10 | ### Install [Unofficial Google Music Api](https://github.com/simon-weber/Unofficial-Google-Music-API) 11 | * Pip installation: `sudo pip install --upgrade gmusicapi` 12 | 13 | ### OAuth Login 14 | * Both scripts use OAuth to login with gmusicapi. Simply run either script once to generate the credentials. 15 | * The credentials will be saved to `~/.local/share/gmusicapi.cred` 16 | 17 | ### delete_dups_from_playlists 18 | * This script deletes the duplicate songs from within each individual playlist. The tracks must be identical (ie. the same track id and song file) to be deleted. 19 | 20 | ### add_last_songs_to_top_of_playlist 21 | * This script provides a way to move the last N songs of a playlist to be the first N songs. Run it without arguments to see the usage. 22 | 23 | ### Warning 24 | * Neither script prompts you before making changes to your playlists. 25 | -------------------------------------------------------------------------------- /add_last_songs_to_top_of_playlist.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | from gmusicapi import Mobileclient 3 | import sys 4 | 5 | ### Functions 6 | 7 | def get_playlist_tracks(name, playlists): 8 | for playlist in playlists: 9 | if playlist['name'].lower() == name.lower(): 10 | tracks = playlist['tracks'] 11 | return tracks 12 | print "ERROR: No playlist '" + name + "'found" 13 | exit(1) 14 | 15 | 16 | def move_songs_to_top(api, tracks, num_tracks_to_move): 17 | num_tracks = len(tracks) 18 | preceding_entry = tracks[0] 19 | for x in range(0, num_tracks_to_move): 20 | entry_to_move = tracks[num_tracks - 1 - x] 21 | track_id = api.reorder_playlist_entry(entry_to_move, None, preceding_entry) 22 | if track_id[0] == entry_to_move['id']: 23 | print "Successfully moved track " + entry_to_move['id'] 24 | else: 25 | print "Failed to move track " + entry_to_move['id'] 26 | 27 | ### Main 28 | 29 | if len(sys.argv) != 3: 30 | print "USAGE:" 31 | print "./add_last_songs_to_top_of_playlist.py 'PLAYLIST NAME' NUMBER_SONGS" 32 | print 33 | print "example: ./add_last_songs_to_top_of_playlist.py 'Ultimate Everything' 5" 34 | print " will move the last 5 songs in 'Ultimate Everything' to the top of the playlist." 35 | exit(0) 36 | else: 37 | playlist_name = sys.argv[1] 38 | num_songs = sys.argv[2] 39 | 40 | # Setup the gmusicapi 41 | api = Mobileclient() 42 | api.__init__() 43 | 44 | 45 | # Check to see if OAuth credentials available, ask user to setup if not 46 | try: 47 | api.oauth_login(Mobileclient.FROM_MAC_ADDRESS) 48 | except: 49 | print "No OAuth credentials found! Please setup in the following screen!" 50 | api.perform_oauth() 51 | api.oauth_login(Mobileclient.FROM_MAC_ADDRESS) # If it fails here, it wasn't meant to be 52 | 53 | # Then, move on to doing all the work 54 | if api.is_authenticated(): 55 | print "Successfully logged in. Moving " + num_songs + " tracks to top of playlist" 56 | playlists = api.get_all_user_playlist_contents() 57 | tracks = get_playlist_tracks(playlist_name, playlists) 58 | move_songs_to_top(api, tracks, int(num_songs)) 59 | 60 | print "Script completed successfully!" -------------------------------------------------------------------------------- /delete_dups_from_playlists.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | from gmusicapi import Mobileclient 3 | import sys 4 | import time 5 | 6 | ### Functions 7 | 8 | def find_and_remove_dups(api, tracks): 9 | track_set = set() 10 | for track in tracks: 11 | tries = 0 12 | trackId = track['trackId'] 13 | entryId = track['id'] 14 | if trackId in track_set: 15 | print " found duplicate with trackId: " + trackId 16 | while tries < 3: 17 | try: 18 | sys.stdout.write(" attempting to delete... ") # Makes it so no newline appears, cleaner output 19 | api.remove_entries_from_playlist(entryId) 20 | #break 21 | except: 22 | tries += 1 23 | sys.stdout.write(str(tries) + "... ") 24 | if tries == 3: 25 | print "Failed too many times, exiting!" 26 | api.logout() 27 | exit(1) 28 | time.sleep(1) 29 | print "Success!" 30 | break 31 | time.sleep(1) # Helps prevent Google from creating backend errors 32 | else: 33 | track_set.add(trackId) 34 | 35 | ### Main 36 | 37 | # Display help and exit if arguments present 38 | if len(sys.argv) != 1: 39 | print "USAGE:" 40 | print "./delete_dups_from_playlists.py" 41 | print 42 | print " Will delete all duplicate songs within each playlist" 43 | exit(0) 44 | 45 | # Setup the gmusicapi 46 | api = Mobileclient() 47 | api.__init__() 48 | 49 | 50 | # Check to see if OAuth credentials available, ask user to setup if not 51 | try: 52 | api.oauth_login(Mobileclient.FROM_MAC_ADDRESS) 53 | except: 54 | print "No OAuth credentials found! Please setup in the following screen!" 55 | api.perform_oauth() 56 | api.oauth_login(Mobileclient.FROM_MAC_ADDRESS) # If it fails here, it wasn't meant to be 57 | 58 | # Then, move on to doing all the work 59 | if api.is_authenticated(): 60 | print "Successfully logged in. Finding duplicates in playlists" 61 | playlists = api.get_all_user_playlist_contents() 62 | 63 | for playlist in playlists: 64 | print "Deleting duplicates from " + playlist['name'] + "..." 65 | tracks = playlist['tracks'] 66 | find_and_remove_dups(api, tracks) 67 | api.logout() 68 | else: 69 | print "Not logged in! Exiting..." 70 | exit(1) 71 | 72 | print "Script has finished successfully!" --------------------------------------------------------------------------------