Skip to content

Instantly share code, notes, and snippets.

@atog
Created September 17, 2008 11:04
Show Gist options
  • Save atog/11226 to your computer and use it in GitHub Desktop.
Save atog/11226 to your computer and use it in GitHub Desktop.
Backup your iTunes library to Amazon S3
itunes-s3.yml
#
# This little script backs up your iTunes Library to Amazon S3.
#
# You a need file 'itunes-s3.yml' with config settings
# containing the following info:
#
# s3_backup_bucket: your-itunes-backup
# s3_access_key_id: your_S3_id
# s3_secret_access_key: your_S3_access_key
# max_nr_per_run: 10
# purchased_first: true
#
# Run by providing your iTunes Library xml file
#
# Changes 25/09: use filename as key in memory file instead of iTunes track_id. Too many problems.
# Changes 25/09: drop the whole memory thing. Too many problems.
#
#
require "rubygems"
require "libxml"
require "yaml"
require "aws/s3"
require "uri"
class Song
attr_accessor :filename, :purchased, :name, :artist, :key
def self.create(node)
song = Song.new
song.purchased = false
node.find('key').each do |k|
case k.content
when "Location":
song.filename = URI.decode(k.next.content.gsub('file://localhost', ''))
song.key = File.basename(song.filename)
when "Name":
song.name = k.next.content
when "Purchased":
song.purchased = true
when "Artist":
song.artist = k.next.content
end
end
song
end
def to_s
rvalue = "#{artist} - #{name} (#{key}, #{purchased.nil? ? false : true})"
end
end
class BackupManager
attr_reader :nr, :purchased_first, :counter, :bucket, :songs, :songs_done
def initialize
@settings = YAML.load_file('itunes-s3.yml')
@nr = @settings['max_nr_per_run'] || 10;
@purchased_first = @settings['purchased_first'] || true;
@bucket = @settings['s3_backup_bucket']
@counter = 0; @songs = []
AWS::S3::Base.establish_connection!(
:access_key_id => @settings['s3_access_key_id'],
:secret_access_key => @settings['s3_secret_access_key']
)
fetch_stored
end
def backup(lib_xml)
load_lib(lib_xml)
for song in @songs
break if max?
save(song)
end
end
private
def load_lib(lib_xml)
doc = LibXML::XML::Document.file(lib_xml)
root = doc.root
doc.find('//plist/dict/dict/dict').each do |node|
@songs << Song.create(node)
end
if @purchased_first
@songs.sort!{|x,y| y.purchased.to_s <=> x.purchased.to_s}
end
end
def max?
@counter == @nr
end
# save the song to S3
def save(song)
unless @songs_done.include?(song.key)
puts "Save #{song}"
AWS::S3::S3Object.store(song.key, open(song.filename), bucket)
@counter += 1
@songs_done << song.key
end
end
def fetch_stored
puts "Fetching stored from S3"
@songs_done = AWS::S3::Bucket.find(bucket).objects.collect { |o| o.key }
puts "Done! (#{songs_done.size} songs)"
end
end
BackupManager.new.backup(ARGV[0])
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment