# Itunes Library Updater # Automatically add new directories to your iTunes library # Created by Nando Vieira # # This script follows my own structure as the following: # # ~/Music/MP3/// # # REQUIREMENT # You'll need Ruby. I'm using Leopard, that ships with Ruby 1.8.6 # You'll also need OSA. To install, just run the command `sudo gem install rubybosa` # # USAGE: # First, run the command `ruby itunes_updater.rb` to create a default configuration # file in your home folder. By default, the script checks only the iTunes music folder. # If you need to add more folders, edit the file `.itunes_updater.yml`. If you need to # skip some folder (a download folder), you can add them to the filter attribute. This # param expects the folder path. # # To update your library you just need to run the command `ruby itunes_updater.rb` # # CONFIGURATION FILE EXAMPLE # updated_at: # libraries: # - ~/Music/MP3 # - ~/Music/MusicBrainz # - ~/Music/iTunes/iTunes Music # filters: # - ~/Music/MP3/Incomplete # - ~/Music/MP3/Downloading # - ~/Music/MP3/Temporary require "rubygems" require "rbosa" require "yaml" class ItunesUpdater attr_accessor :config_file attr_accessor :filters def initialize @itunes = OSA.app('iTunes') @pending = [] @config_file = File.expand_path("~/.itunes_updater.yml") @filters = [] parse_config_file end def pending libraries.each do |lib| lib_folder = File.expand_path(lib) Dir.entries(lib_folder).each do |artist| artist_folder = File.join(lib_folder, artist) next if skip_folder?(artist_folder) Dir.entries(artist_folder).each do |album| album_folder = File.join(artist_folder, album) next if skip_folder?(album_folder) @pending << album_folder end end end @pending.sort end def update! pending.each do |album| @itunes.add(album) end @config["updated_at"] = Time.now.to_s if !save_config_file puts "-- unable to save configuration file on #{@config_file.inspect}" end @pending = [] end def updated_at @config["updated_at"] ? Time.parse(@config["updated_at"].to_s) : (Time.now - (60 * 60 * 24 * 30 * 365)) end def libraries @config["libraries"] || [] end def libraries=(paths) @config["libraries"] = paths end def filters (@config["filters"] || []).map do |filter| filter = File.expand_path(filter) filter.downcase end end def notify(message) title = "iTunes Library Updater" image = "/Applications/iTunes.app/Contents/Resources/iTunes.icns" system("growlnotify -n itunes_library_updater --image #{image} -p 2 -m \"#{message}\" -t \"#{title}\" -wait") end def create_template template = < YML File.open(@config_file, "w+") << template end private def skip_folder?(folder) # check if folder is represented by . or .. return true if folder =~ /\/\.{1,2}/ # check if is directory return true unless File.directory?(folder) # check if folder is in the filter list return true if filters.include?(folder.downcase) # check the modification timestamp return true if File.mtime(folder) < updated_at # the folder is ok to go return false end def parse_config_file @config = YAML.load_file(@config_file) rescue @config = { "updated_at" => nil, "libraries" => [], "filters" => [] } end def save_config_file File.open(@config_file, "w+") do |file| YAML.dump(@config, file) end return true rescue return false end end if $0 == __FILE__ itunes = ItunesUpdater.new if File.exists?(itunes.config_file) pending_items = itunes.pending.size if pending_items > 0 itunes.notify("#{pending_items} pending folder(s)") itunes.update! itunes.notify("Library updated!") else itunes.notify("No pending items found") end else itunes.create_template itunes.notify("The configuration file has been created.\n\nIf you need to customize it, edit the file #{itunes.config_file}") end end