module Kagu class Track include AttributesInitializer include Comparable MANDATORY_ATTRIBUTES = %w(added_at id length path) IS_MAC_OS = RUBY_PLATFORM =~ /darwin/ attr_reader :added_at, :album, :artist, :genre, :id, :length, :path, :title, :year def initialize(attributes = {}) super raise Error.new("No such file: #{path.inspect}") if File.exists?(path) && !exists? end def <=>(other) return nil unless other.is_a?(self.class) added_at <=> other.added_at end def ==(other) other.is_a?(self.class) && artist == other.artist && title == other.title && (length.to_i - other.length.to_i).abs < 3 end def eql?(other) super || self == other end def exists? File.file?(path) end def relative_path(directory) directory.present? && directory.starts_with?(directory) ? path.gsub(/\A#{Regexp.escape(directory)}\//, '') : path end def to_s "#{artist} - #{title}" end private def added_at=(value) @added_at = value.is_a?(Time) ? value.utc : nil end def album=(value) @album = value.to_s.squish.presence end def artist=(value) @artist = value.to_s.squish.presence end def genre=(value) @genre = value.to_s.squish.presence end def html_entities_decode(value) @@html_entities ||= HTMLEntities.new @@html_entities.decode(value.to_s) end def id=(value) @id = value.to_s =~ /\A[0-9]+\z/ ? value.to_i : nil end def itunes_album=(value) self.album = html_entities_decode(value) end def itunes_artist=(value) self.artist = html_entities_decode(value) end def itunes_date_added=(value) self.added_at = value.present? ? Time.parse(value.to_s) : nil end def itunes_genre=(value) self.genre = html_entities_decode(value) end def itunes_location=(value) self.path = CGI.unescape(html_entities_decode(value).gsub('+', '%2B')).gsub(/\Afile:\/\/(localhost)?/, '') self.path = path.encode('UTF-8', 'UTF-8-MAC') if IS_MAC_OS end def itunes_name=(value) self.title = html_entities_decode(value) end def itunes_total_time=(value) self.length = value.to_s =~ /\A[0-9]+\z/ ? (value.to_i / 1000.0).round : nil end def itunes_track_id=(value) self.id = value end def itunes_year=(value) self.year = value end def length=(value) @length = value.to_s =~ /\A[0-9]+\z/ ? value.to_i : nil end def path=(value) @path = value.to_s.presence end def title=(value) @title = value.to_s.squish.presence end def year=(value) @year = value.to_s =~ /\A\d{,4}\z/ ? value.to_i : nil end end end