Created
December 5, 2008 18:28
-
-
Save wesrog/32444 to your computer and use it in GitHub Desktop.
Last.fm Tagger CLI
This file contains hidden or 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
# Last.fm Tagger v0.7 | |
# | |
# Author: | |
# [email protected] | |
# | |
# Abstract: | |
# For each selected track in iTunes, retrieve the genre from Last.fm and accordingly tag the track. | |
# Use -q to subdue confirmations | |
# | |
# Todo: | |
# Option to tag artist if no tag exists in last.fm records | |
# Retrieve all tags above <count>50</count>, prompt for tag choice | |
begin require 'rubygems'; rescue LoadError; end | |
%W{rbosa cgi rexml/document}.map { |i| require i } | |
OSA.utf8_strings = true | |
class Artist | |
attr_reader :name, :genre | |
def initialize(name='', genre='') | |
@name, @genre = name, genre | |
query unless name == '' | |
end | |
def query | |
puts %{Querying last.fm for: "#{@name}"...} | |
begin | |
doc = REXML::Document.new(Net::HTTP.get(URI("http://ws.audioscrobbler.com/1.0/artist/#{URI.escape(CGI.escape(@name))}/toptags.xml"))) | |
rescue EOFError => e | |
puts "#{Color.error} Request timed out! Trying again..." | |
query | |
end | |
genre = REXML::XPath.first(doc, "//toptags/tag/name") | |
genre.nil? ? @genre = "" : @genre = genre.text.strip | |
@name = name.strip | |
end | |
end | |
class LastfmTagger | |
@@tagged, @@skipped = 0, 0 | |
def initialize | |
itunes = OSA.app('iTunes') | |
@selection = itunes.selection.get | |
if @selection.empty? | |
$stderr.puts "#{Color.error} Please select some tracks in iTunes" | |
else | |
# construct pseudo Artist to satify @selection loop | |
@artist = Artist.new | |
end | |
end | |
def process | |
@selection.each do |track| | |
# check if artist differs; if so, reinstantiate @artist | |
if @artist.name.downcase != track.artist.strip.downcase | |
@artist = Artist.new(track.artist) | |
# no need to write tag if it is identical, therefore skip until it differs | |
if track.genre.strip.downcase == @artist.genre.downcase | |
puts "#{Color.pass} Identical genres. Skipping..." | |
@@skipped += 1 | |
@input = 'n' | |
elsif @artist.genre == "" | |
puts %{#{Color.pass} No tags found for "#{@artist.name}".} | |
@@skipped += 1 | |
@input = 'n' | |
else | |
@input = confirm | |
end | |
end | |
track.genre = @artist.genre if @input == 'y' | |
end | |
puts "Done. Tagged #{@@tagged} artists. Skipped #{@@skipped}." | |
end | |
def confirm | |
print %{#{Color.success} Tagging "#{@artist.name}" as "#{@artist.genre}". } | |
@@tagged += 1 | |
# add some space when in quiet mode | |
if quiet? | |
puts | |
return 'y' | |
end | |
print %{Continue? (Y/N) } | |
gets.chomp.downcase | |
end | |
# handles -q argument | |
def quiet? | |
return true if ARGV[0] == '-q' | |
end | |
end | |
class Color | |
def self.pass | |
"[ \e[33mPASS\e[0m ]" | |
end | |
def self.success | |
"[ \e[32mSUCCESS\e[0m ]" | |
end | |
def self.error | |
"[ \e[31mERROR\e[0m ]" | |
end | |
end | |
LastfmTagger.new.process |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment