public
Created

  • Download Gist
update_ratings.py
Python
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82
from collections import defaultdict
import plistlib
 
# I copied files locally.
# NEW is what gets written.
# CURRENT is the current "iTunes Library.xml" file (or rather, my copy).
# OLD is an old backup with lots of good ratings.
OLD = 'itunes.xml'
CURRENT = 'itunes_2012.xml'
NEW = 'updated.xml'
 
# I match based on filenames. IDs are different, sigh.
# But I needed to compensate for a new iTunes folder structure.
OLD_PREFIX = 'file://localhost/Users/reinout/Music/iTunes/iTunes%20Music/'
CURRENT_PREFIX = 'file://localhost/Users/reinout/Music/iTunes/iTunes%20Media/Music/'
 
 
def main():
# Read in the old tracks and grab the ratings.
old = plistlib.readPlist(OLD)
old_tracks = old['Tracks']
print "Found {} old tracks".format(len(old_tracks))
old_ratings = {}
for track in old_tracks.values():
filename = track['Location'].replace(OLD_PREFIX, '')
rating = track.get('Rating')
if rating is None:
continue
old_ratings[filename] = rating
print "Found {} old ratings".format(len(old_ratings))
 
# Same with the current ratings. If we've rated something, we want to
# keep that rating.
current = plistlib.readPlist(CURRENT)
current_tracks = current['Tracks']
print "Found {} current tracks".format(len(current_tracks))
current_ratings = {}
for track in current_tracks.values():
filename = track['Location'].replace(CURRENT_PREFIX, '')
rating = track.get('Rating')
if rating is None:
continue
current_ratings[filename] = rating
print "Found {} current ratings".format(len(current_ratings))
 
# Figure out which old ratings we want to move over.
new_ratings = {}
for filename in old_ratings:
if filename not in current_ratings:
new_ratings[filename]= old_ratings[filename]
print "This means {} new ratings".format(len(new_ratings))
 
# Create a dict {rating: tracks} for the new ratings I want to set.
new_playlists = defaultdict(list)
for track in current_tracks.values():
filename = track['Location'].replace(CURRENT_PREFIX, '')
new_rating = new_ratings.get(filename)
if new_rating is None:
continue
track_id = track['Track ID']
new_playlists[new_rating].append(track_id)
 
# Create a playlist per rating. You can set the playlist's items to
# the correct rating in iTunes just fine.
playlists = []
for rating, track_ids in new_playlists.items():
print rating, len(track_ids)
new_playlist = {}
new_playlist['Name'] = str(rating) + ' points'
new_playlist['Visible'] = True
new_playlist['Playlist ID'] = 8000 + rating
new_playlist['All Items'] = True
new_playlist['Playlist Items'] = [{'Track ID': track_id}
for track_id in track_ids]
playlists.append(new_playlist)
# Zap the existing ones, otherwise you end up with double items.
current['Playlists'] = playlists
plistlib.writePlist(current, NEW)
 
 
if __name__ == '__main__':
main()

Please sign in to comment on this gist.

Something went wrong with that request. Please try again.