Last active
July 13, 2017 07:38
-
-
Save hube/9055dc2b88f7107751aa5c99a40117e6 to your computer and use it in GitHub Desktop.
Apple Music Metadata Matching Script (originally taken from https://cl.ly/C3kK)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env ruby | |
# by @tapbot_paul | |
# Don't blame me if this nukes your metadata, formats your drive, kills your kids | |
# This script goes through any iCloud Matched songs in your iTunes library and tries to update the | |
# metadata from the iTunes Store | |
# Will run against entire library | |
# Known to work with Ruby 1.9.3-p551, macOS 10.12.5, iTunes 12.6.1.25 | |
# install the required gems with the following commands | |
# sudo gem install json | |
# sudo gem install rb-appscript | |
# then run the script with "ruby meta.rb" | |
require 'appscript' | |
require 'json' | |
require 'open-uri' | |
class Track | |
attr_reader :itunes_track | |
def initialize(itunes_track) | |
@itunes_track = itunes_track | |
end | |
def itunes_id | |
return @itunes_id if !@itunes_id.nil? | |
path = @itunes_track.location.get.path | |
file_string = File.open(path, 'r').read(1024) # data always seems to be around 600-700 bytes in | |
index = file_string.index('song') | |
if index | |
@itunes_id = file_string[index+4, 4].unpack('N')[0] | |
else | |
puts "Couldn't find @itunes_track id #{track.name.get}" | |
end | |
end | |
def has_itunes_id? | |
!itunes_id.nil? | |
end | |
def name | |
@itunes_track.name.get | |
end | |
def artist | |
@itunes_track.artist.get | |
end | |
def update(result) | |
@itunes_track.artist.set(result['artistName']) | |
@itunes_track.album.set(result['collectionName']) | |
@itunes_track.name.set(result['trackName']) | |
@itunes_track.year.set(Date.parse(result['releaseDate']).year) | |
@itunes_track.disc_count.set(result['discCount']) | |
@itunes_track.disc_number.set(result['discNumber']) | |
@itunes_track.track_count.set(result['trackCount']) | |
@itunes_track.track_number.set(result['trackNumber']) | |
@itunes_track.genre.set(result['primaryGenreName']) | |
# @itunes_track.album_artist.set(result['artistName']) | |
@itunes_track.comment.set('') | |
@itunes_track.composer.set('') | |
@itunes_track.grouping.set('') | |
@itunes_track.bpm.set('') | |
@itunes_track.lyrics.set('') | |
end | |
end | |
all_tracks = Appscript.app.by_name("iTunes").library_playlists[1].tracks.get | |
matched_tracks = Hash.new { |hash, key| hash[key] = [] } | |
all_tracks.each do |track| | |
if track.kind.get == 'Matched AAC audio file' | |
matched_track = Track.new(track) | |
if matched_track.has_itunes_id? | |
matched_tracks[matched_track.itunes_id] << matched_track | |
else | |
raise "Track #{matched_track.name.inspect} by #{matched_track.artist.inspect} has no iTunes ID" | |
end | |
end | |
end | |
puts "Found #{matched_tracks.size} unique tracks out of #{all_tracks.size} total tracks" | |
WORK_SIZE = 100 | |
counter = 0 | |
matched_tracks.keys.each_slice(WORK_SIZE).with_index do |track_ids, index| | |
puts WORK_SIZE * (index + 1) | |
updated_tracks = [] | |
# Country defaults to US, lang defaults to en | |
track_data = JSON.parse(open("http://itunes.apple.com/lookup?id=#{track_ids.join(',')}").read) | |
# For retrieving Chinese track data | |
# track_data = JSON.parse(open("http://itunes.apple.com/lookup?id=#{track_ids.join(',')}&country=HK&lang=zh_HK").read) | |
track_data['results'].each do |result| | |
result_id = result['trackId'] | |
matched_tracks[result_id].each do |track| | |
track.update(result) | |
end | |
counter += 1 | |
updated_tracks << result_id | |
end | |
missing_tracks = track_ids - updated_tracks | |
if missing_tracks.size > 0 | |
puts "Missed tracks:" | |
puts missing_tracks.inspect | |
end | |
end | |
puts "Matched #{counter} tracks out of #{matched_tracks.size}" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment