sandro-rlastfm 0.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/History.txt +5 -0
 - data/README.txt +63 -0
 - data/Rakefile +35 -0
 - data/init.rb +1 -0
 - data/lib/core_extensions.rb +30 -0
 - data/lib/rlastfm.rb +83 -0
 - data/lib/rlastfm/album.rb +42 -0
 - data/lib/rlastfm/artist.rb +67 -0
 - data/lib/rlastfm/helpers/remote_accessor.rb +50 -0
 - data/lib/rlastfm/helpers/scraper.rb +38 -0
 - data/lib/rlastfm/track.rb +10 -0
 - data/lib/rlastfm/venue.rb +23 -0
 - data/rlastfm.gemspec +31 -0
 - data/script/console +10 -0
 - data/spec/rlastfm/album_spec.rb +20 -0
 - data/spec/rlastfm/artist_spec.rb +70 -0
 - data/spec/rlastfm/track_spec.rb +29 -0
 - data/spec/rlastfm/venue_spec.rb +14 -0
 - data/spec/site/charts.artist.html +7809 -0
 - data/spec/site/the_decemberists.getinfo.xml +68 -0
 - data/spec/site/the_decemberists.gettopalbums.xml +715 -0
 - data/spec/site/the_decemberists.the_crane_wife.html +1841 -0
 - data/spec/site/venue.8953935.html +907 -0
 - data/spec/spec_helper.rb +20 -0
 - metadata +78 -0
 
    
        data/History.txt
    ADDED
    
    
    
        data/README.txt
    ADDED
    
    | 
         @@ -0,0 +1,63 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            rlastfm
         
     | 
| 
      
 2 
     | 
    
         
            +
                by Sandro Turriate
         
     | 
| 
      
 3 
     | 
    
         
            +
                http://turriate.com
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
            == DESCRIPTION:
         
     | 
| 
      
 6 
     | 
    
         
            +
             
     | 
| 
      
 7 
     | 
    
         
            +
            Extremely minimal Last.fm wrapper.
         
     | 
| 
      
 8 
     | 
    
         
            +
            This wrapper allows you to lookup an Artist by name, get their albums, and the tracks for each album.
         
     | 
| 
      
 9 
     | 
    
         
            +
             
     | 
| 
      
 10 
     | 
    
         
            +
            == SYNOPSIS:
         
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
      
 12 
     | 
    
         
            +
            >> Rlastfm.api_key = "your lastfm api key"
         
     | 
| 
      
 13 
     | 
    
         
            +
            >> Rlastfm.debug = true # watch the requests you make
         
     | 
| 
      
 14 
     | 
    
         
            +
             
     | 
| 
      
 15 
     | 
    
         
            +
            >> artist = Rlastfm::Artist.new('radiohead')
         
     | 
| 
      
 16 
     | 
    
         
            +
            => #<Rlastfm::Artist:0x115bed0 @initialized_name="radiohead">
         
     | 
| 
      
 17 
     | 
    
         
            +
             
     | 
| 
      
 18 
     | 
    
         
            +
            >> artist.name
         
     | 
| 
      
 19 
     | 
    
         
            +
            => "Radiohead"
         
     | 
| 
      
 20 
     | 
    
         
            +
             
     | 
| 
      
 21 
     | 
    
         
            +
            >> artist.albums
         
     | 
| 
      
 22 
     | 
    
         
            +
            [#<Rlastfm::Album:0xd598>, #<Rlastfm::Album:0xd599>]
         
     | 
| 
      
 23 
     | 
    
         
            +
             
     | 
| 
      
 24 
     | 
    
         
            +
            >> artist.albums.first.name
         
     | 
| 
      
 25 
     | 
    
         
            +
            => "In Rainbows"
         
     | 
| 
      
 26 
     | 
    
         
            +
             
     | 
| 
      
 27 
     | 
    
         
            +
            >> artist.albums.first.tracks
         
     | 
| 
      
 28 
     | 
    
         
            +
            [#<Rlastfm::Track:0x18f38f0>, #<Rlastfm::Track:0x18f38f1>]
         
     | 
| 
      
 29 
     | 
    
         
            +
             
     | 
| 
      
 30 
     | 
    
         
            +
            == REQUIREMENTS:
         
     | 
| 
      
 31 
     | 
    
         
            +
             
     | 
| 
      
 32 
     | 
    
         
            +
            * hpricot
         
     | 
| 
      
 33 
     | 
    
         
            +
            * httparty
         
     | 
| 
      
 34 
     | 
    
         
            +
            * fakeweb (to run specs)
         
     | 
| 
      
 35 
     | 
    
         
            +
             
     | 
| 
      
 36 
     | 
    
         
            +
            == INSTALL:
         
     | 
| 
      
 37 
     | 
    
         
            +
             
     | 
| 
      
 38 
     | 
    
         
            +
              FIXME
         
     | 
| 
      
 39 
     | 
    
         
            +
             
     | 
| 
      
 40 
     | 
    
         
            +
            == LICENSE:
         
     | 
| 
      
 41 
     | 
    
         
            +
             
     | 
| 
      
 42 
     | 
    
         
            +
            (The MIT License)
         
     | 
| 
      
 43 
     | 
    
         
            +
             
     | 
| 
      
 44 
     | 
    
         
            +
            Copyright (c) 2008
         
     | 
| 
      
 45 
     | 
    
         
            +
             
     | 
| 
      
 46 
     | 
    
         
            +
            Permission is hereby granted, free of charge, to any person obtaining
         
     | 
| 
      
 47 
     | 
    
         
            +
            a copy of this software and associated documentation files (the
         
     | 
| 
      
 48 
     | 
    
         
            +
            'Software'), to deal in the Software without restriction, including
         
     | 
| 
      
 49 
     | 
    
         
            +
            without limitation the rights to use, copy, modify, merge, publish,
         
     | 
| 
      
 50 
     | 
    
         
            +
            distribute, sublicense, and/or sell copies of the Software, and to
         
     | 
| 
      
 51 
     | 
    
         
            +
            permit persons to whom the Software is furnished to do so, subject to
         
     | 
| 
      
 52 
     | 
    
         
            +
            the following conditions:
         
     | 
| 
      
 53 
     | 
    
         
            +
             
     | 
| 
      
 54 
     | 
    
         
            +
            The above copyright notice and this permission notice shall be
         
     | 
| 
      
 55 
     | 
    
         
            +
            included in all copies or substantial portions of the Software.
         
     | 
| 
      
 56 
     | 
    
         
            +
             
     | 
| 
      
 57 
     | 
    
         
            +
            THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
         
     | 
| 
      
 58 
     | 
    
         
            +
            EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
         
     | 
| 
      
 59 
     | 
    
         
            +
            MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
         
     | 
| 
      
 60 
     | 
    
         
            +
            IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
         
     | 
| 
      
 61 
     | 
    
         
            +
            CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
         
     | 
| 
      
 62 
     | 
    
         
            +
            TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
         
     | 
| 
      
 63 
     | 
    
         
            +
            SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
         
     | 
    
        data/Rakefile
    ADDED
    
    | 
         @@ -0,0 +1,35 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # Look in the tasks/setup.rb file for the various options that can be
         
     | 
| 
      
 2 
     | 
    
         
            +
            # configured in this Rakefile. The .rake files in the tasks directory
         
     | 
| 
      
 3 
     | 
    
         
            +
            # are where the options are used.
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
            begin
         
     | 
| 
      
 6 
     | 
    
         
            +
              require 'bones'
         
     | 
| 
      
 7 
     | 
    
         
            +
              Bones.setup
         
     | 
| 
      
 8 
     | 
    
         
            +
            rescue LoadError
         
     | 
| 
      
 9 
     | 
    
         
            +
              begin
         
     | 
| 
      
 10 
     | 
    
         
            +
                load 'tasks/setup.rb'
         
     | 
| 
      
 11 
     | 
    
         
            +
              rescue LoadError
         
     | 
| 
      
 12 
     | 
    
         
            +
                raise RuntimeError, '### please install the "bones" gem ###'
         
     | 
| 
      
 13 
     | 
    
         
            +
              end
         
     | 
| 
      
 14 
     | 
    
         
            +
            end
         
     | 
| 
      
 15 
     | 
    
         
            +
             
     | 
| 
      
 16 
     | 
    
         
            +
            ensure_in_path 'lib'
         
     | 
| 
      
 17 
     | 
    
         
            +
            require 'rlastfm'
         
     | 
| 
      
 18 
     | 
    
         
            +
             
     | 
| 
      
 19 
     | 
    
         
            +
            task :default => 'spec:run'
         
     | 
| 
      
 20 
     | 
    
         
            +
             
     | 
| 
      
 21 
     | 
    
         
            +
            PROJ.name = 'rlastfm'
         
     | 
| 
      
 22 
     | 
    
         
            +
            PROJ.summary = "minimal Last.fm wrapper."
         
     | 
| 
      
 23 
     | 
    
         
            +
            PROJ.description = %Q(#{PROJ.summary}
         
     | 
| 
      
 24 
     | 
    
         
            +
            This wrapper allows you to lookup an Artist by name, get their albums, and the tracks for each album.)
         
     | 
| 
      
 25 
     | 
    
         
            +
            PROJ.authors = 'Sandro Turriate'
         
     | 
| 
      
 26 
     | 
    
         
            +
            PROJ.email = 'sandro.turriate@gmail.com'
         
     | 
| 
      
 27 
     | 
    
         
            +
            PROJ.url = 'http://turriate.com'
         
     | 
| 
      
 28 
     | 
    
         
            +
            PROJ.version = Rlastfm::VERSION
         
     | 
| 
      
 29 
     | 
    
         
            +
            PROJ.rubyforge.name = 'rlastfm'
         
     | 
| 
      
 30 
     | 
    
         
            +
            PROJ.gem.development_dependencies = []
         
     | 
| 
      
 31 
     | 
    
         
            +
             
     | 
| 
      
 32 
     | 
    
         
            +
            PROJ.spec.opts << '--color'
         
     | 
| 
      
 33 
     | 
    
         
            +
            PROJ.ignore_file = '.gitignore'
         
     | 
| 
      
 34 
     | 
    
         
            +
             
     | 
| 
      
 35 
     | 
    
         
            +
            # EOF
         
     | 
    
        data/init.rb
    ADDED
    
    | 
         @@ -0,0 +1 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require File.join(File.dirname(__FILE__), %w(lib rlastfm))
         
     | 
| 
         @@ -0,0 +1,30 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            class Hash
         
     | 
| 
      
 2 
     | 
    
         
            +
              def stringify_keys
         
     | 
| 
      
 3 
     | 
    
         
            +
                inject({}) do |options, (key, value)|
         
     | 
| 
      
 4 
     | 
    
         
            +
                  options[key.to_s] = value
         
     | 
| 
      
 5 
     | 
    
         
            +
                  options
         
     | 
| 
      
 6 
     | 
    
         
            +
                end
         
     | 
| 
      
 7 
     | 
    
         
            +
              end
         
     | 
| 
      
 8 
     | 
    
         
            +
             
     | 
| 
      
 9 
     | 
    
         
            +
              # Destructively convert all keys to strings.
         
     | 
| 
      
 10 
     | 
    
         
            +
              def stringify_keys!
         
     | 
| 
      
 11 
     | 
    
         
            +
                keys.each do |key|
         
     | 
| 
      
 12 
     | 
    
         
            +
                  self[key.to_s] = delete(key)
         
     | 
| 
      
 13 
     | 
    
         
            +
                end
         
     | 
| 
      
 14 
     | 
    
         
            +
                self
         
     | 
| 
      
 15 
     | 
    
         
            +
              end
         
     | 
| 
      
 16 
     | 
    
         
            +
             
     | 
| 
      
 17 
     | 
    
         
            +
              # Return a new hash with all keys converted to symbols.
         
     | 
| 
      
 18 
     | 
    
         
            +
              def symbolize_keys
         
     | 
| 
      
 19 
     | 
    
         
            +
                inject({}) do |options, (key, value)|
         
     | 
| 
      
 20 
     | 
    
         
            +
                  options[(key.to_sym rescue key) || key] = value
         
     | 
| 
      
 21 
     | 
    
         
            +
                  options
         
     | 
| 
      
 22 
     | 
    
         
            +
                end
         
     | 
| 
      
 23 
     | 
    
         
            +
              end
         
     | 
| 
      
 24 
     | 
    
         
            +
             
     | 
| 
      
 25 
     | 
    
         
            +
              # Destructively convert all keys to symbols.
         
     | 
| 
      
 26 
     | 
    
         
            +
              def symbolize_keys!
         
     | 
| 
      
 27 
     | 
    
         
            +
                self.replace(self.symbolize_keys)
         
     | 
| 
      
 28 
     | 
    
         
            +
              end
         
     | 
| 
      
 29 
     | 
    
         
            +
            end
         
     | 
| 
      
 30 
     | 
    
         
            +
             
     | 
    
        data/lib/rlastfm.rb
    ADDED
    
    | 
         @@ -0,0 +1,83 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module Rlastfm
         
     | 
| 
      
 2 
     | 
    
         
            +
              # :stopdoc:
         
     | 
| 
      
 3 
     | 
    
         
            +
              VERSION = '0.0.2'
         
     | 
| 
      
 4 
     | 
    
         
            +
              LIBPATH = ::File.expand_path(::File.dirname(__FILE__)) + ::File::SEPARATOR
         
     | 
| 
      
 5 
     | 
    
         
            +
              PATH = ::File.dirname(LIBPATH) + ::File::SEPARATOR
         
     | 
| 
      
 6 
     | 
    
         
            +
             
     | 
| 
      
 7 
     | 
    
         
            +
              # :startdoc:
         
     | 
| 
      
 8 
     | 
    
         
            +
             
     | 
| 
      
 9 
     | 
    
         
            +
              # Returns the version string for the library.
         
     | 
| 
      
 10 
     | 
    
         
            +
              #
         
     | 
| 
      
 11 
     | 
    
         
            +
              def self.version
         
     | 
| 
      
 12 
     | 
    
         
            +
                VERSION
         
     | 
| 
      
 13 
     | 
    
         
            +
              end
         
     | 
| 
      
 14 
     | 
    
         
            +
             
     | 
| 
      
 15 
     | 
    
         
            +
              # Returns the library path for the module. If any arguments are given,
         
     | 
| 
      
 16 
     | 
    
         
            +
              # they will be joined to the end of the libray path using
         
     | 
| 
      
 17 
     | 
    
         
            +
              # <tt>File.join</tt>.
         
     | 
| 
      
 18 
     | 
    
         
            +
              #
         
     | 
| 
      
 19 
     | 
    
         
            +
              def self.libpath( *args )
         
     | 
| 
      
 20 
     | 
    
         
            +
                args.empty? ? LIBPATH : ::File.join(LIBPATH, args.flatten)
         
     | 
| 
      
 21 
     | 
    
         
            +
              end
         
     | 
| 
      
 22 
     | 
    
         
            +
             
     | 
| 
      
 23 
     | 
    
         
            +
              # Returns the lpath for the module. If any arguments are given,
         
     | 
| 
      
 24 
     | 
    
         
            +
              # they will be joined to the end of the path using
         
     | 
| 
      
 25 
     | 
    
         
            +
              # <tt>File.join</tt>.
         
     | 
| 
      
 26 
     | 
    
         
            +
              #
         
     | 
| 
      
 27 
     | 
    
         
            +
              def self.path( *args )
         
     | 
| 
      
 28 
     | 
    
         
            +
                args.empty? ? PATH : ::File.join(PATH, args.flatten)
         
     | 
| 
      
 29 
     | 
    
         
            +
              end
         
     | 
| 
      
 30 
     | 
    
         
            +
             
     | 
| 
      
 31 
     | 
    
         
            +
              # Utility method used to require all files ending in .rb that lie in the
         
     | 
| 
      
 32 
     | 
    
         
            +
              # directory below this file that has the same name as the filename passed
         
     | 
| 
      
 33 
     | 
    
         
            +
              # in. Optionally, a specific _directory_ name can be passed in such that
         
     | 
| 
      
 34 
     | 
    
         
            +
              # the _filename_ does not have to be equivalent to the directory.
         
     | 
| 
      
 35 
     | 
    
         
            +
              #
         
     | 
| 
      
 36 
     | 
    
         
            +
              def self.require_all_libs_relative_to( fname, dir = nil )
         
     | 
| 
      
 37 
     | 
    
         
            +
                dir ||= ::File.basename(fname, '.*')
         
     | 
| 
      
 38 
     | 
    
         
            +
                search_me = ::File.expand_path(
         
     | 
| 
      
 39 
     | 
    
         
            +
                    ::File.join(::File.dirname(fname), dir, '**', '*.rb'))
         
     | 
| 
      
 40 
     | 
    
         
            +
             
     | 
| 
      
 41 
     | 
    
         
            +
                Dir.glob(search_me).sort.each {|rb| require rb}
         
     | 
| 
      
 42 
     | 
    
         
            +
              end
         
     | 
| 
      
 43 
     | 
    
         
            +
             
     | 
| 
      
 44 
     | 
    
         
            +
              class << self
         
     | 
| 
      
 45 
     | 
    
         
            +
                attr_accessor :api_key, :debug
         
     | 
| 
      
 46 
     | 
    
         
            +
              end
         
     | 
| 
      
 47 
     | 
    
         
            +
             
     | 
| 
      
 48 
     | 
    
         
            +
              self.debug = false
         
     | 
| 
      
 49 
     | 
    
         
            +
            end  # module Rlastfm
         
     | 
| 
      
 50 
     | 
    
         
            +
             
     | 
| 
      
 51 
     | 
    
         
            +
            %w(rubygems hpricot open-uri httparty).each { |l| require l }
         
     | 
| 
      
 52 
     | 
    
         
            +
             
     | 
| 
      
 53 
     | 
    
         
            +
            module HTTParty
         
     | 
| 
      
 54 
     | 
    
         
            +
              class Request
         
     | 
| 
      
 55 
     | 
    
         
            +
                def perform_with_debug
         
     | 
| 
      
 56 
     | 
    
         
            +
                  if Rlastfm.debug
         
     | 
| 
      
 57 
     | 
    
         
            +
                    puts "Performing request to: #{uri.to_s}"
         
     | 
| 
      
 58 
     | 
    
         
            +
                  end
         
     | 
| 
      
 59 
     | 
    
         
            +
                  perform_without_debug
         
     | 
| 
      
 60 
     | 
    
         
            +
                end
         
     | 
| 
      
 61 
     | 
    
         
            +
             
     | 
| 
      
 62 
     | 
    
         
            +
                alias_method :perform_without_debug, :perform
         
     | 
| 
      
 63 
     | 
    
         
            +
                alias_method :perform, :perform_with_debug
         
     | 
| 
      
 64 
     | 
    
         
            +
             
     | 
| 
      
 65 
     | 
    
         
            +
                def query_string_with_sorting(uri)
         
     | 
| 
      
 66 
     | 
    
         
            +
                  unsorted = query_string_without_sorting(uri)
         
     | 
| 
      
 67 
     | 
    
         
            +
                  unsorted.split("&").sort.join("&") if unsorted
         
     | 
| 
      
 68 
     | 
    
         
            +
                end
         
     | 
| 
      
 69 
     | 
    
         
            +
             
     | 
| 
      
 70 
     | 
    
         
            +
                alias_method :query_string_without_sorting, :query_string
         
     | 
| 
      
 71 
     | 
    
         
            +
                alias_method :query_string, :query_string_with_sorting
         
     | 
| 
      
 72 
     | 
    
         
            +
              end
         
     | 
| 
      
 73 
     | 
    
         
            +
            end
         
     | 
| 
      
 74 
     | 
    
         
            +
             
     | 
| 
      
 75 
     | 
    
         
            +
             
     | 
| 
      
 76 
     | 
    
         
            +
            helper_libs = File.join(File.dirname(__FILE__), %w(rlastfm helpers *.rb))
         
     | 
| 
      
 77 
     | 
    
         
            +
            Dir.glob(helper_libs).each { |l| require l }
         
     | 
| 
      
 78 
     | 
    
         
            +
             
     | 
| 
      
 79 
     | 
    
         
            +
            require File.join(File.dirname(__FILE__), 'core_extensions')
         
     | 
| 
      
 80 
     | 
    
         
            +
             
     | 
| 
      
 81 
     | 
    
         
            +
            Rlastfm.require_all_libs_relative_to(__FILE__)
         
     | 
| 
      
 82 
     | 
    
         
            +
             
     | 
| 
      
 83 
     | 
    
         
            +
            # EOF
         
     | 
| 
         @@ -0,0 +1,42 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module Rlastfm
         
     | 
| 
      
 2 
     | 
    
         
            +
              class Album
         
     | 
| 
      
 3 
     | 
    
         
            +
                include Helpers::Scraper
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
                attr_reader :raw
         
     | 
| 
      
 6 
     | 
    
         
            +
                attr_accessor :artist, :images, :name, :play_count, :rank, :url
         
     | 
| 
      
 7 
     | 
    
         
            +
             
     | 
| 
      
 8 
     | 
    
         
            +
                def initialize(hash={})
         
     | 
| 
      
 9 
     | 
    
         
            +
                  @raw = hash.stringify_keys!
         
     | 
| 
      
 10 
     | 
    
         
            +
                  @images = hash['images'] || hash['image']
         
     | 
| 
      
 11 
     | 
    
         
            +
                  @name = hash['name']
         
     | 
| 
      
 12 
     | 
    
         
            +
                  @play_count = hash['play_count'] || hash['playcount']
         
     | 
| 
      
 13 
     | 
    
         
            +
                  @rank = hash['rank']
         
     | 
| 
      
 14 
     | 
    
         
            +
                  @url = hash['url']
         
     | 
| 
      
 15 
     | 
    
         
            +
                  if (a = hash['artist'])
         
     | 
| 
      
 16 
     | 
    
         
            +
                    @artist = a.is_a?(Hash) ? a['name'] : a
         
     | 
| 
      
 17 
     | 
    
         
            +
                  end
         
     | 
| 
      
 18 
     | 
    
         
            +
                end
         
     | 
| 
      
 19 
     | 
    
         
            +
             
     | 
| 
      
 20 
     | 
    
         
            +
                def tracks
         
     | 
| 
      
 21 
     | 
    
         
            +
                  @tracks ||= get_tracks
         
     | 
| 
      
 22 
     | 
    
         
            +
                end
         
     | 
| 
      
 23 
     | 
    
         
            +
             
     | 
| 
      
 24 
     | 
    
         
            +
                private
         
     | 
| 
      
 25 
     | 
    
         
            +
             
     | 
| 
      
 26 
     | 
    
         
            +
                def get_tracks
         
     | 
| 
      
 27 
     | 
    
         
            +
                  doc = doc_for(url)
         
     | 
| 
      
 28 
     | 
    
         
            +
                  artist_container = doc.at(".albumHead h1")
         
     | 
| 
      
 29 
     | 
    
         
            +
                  artist = artist_container.at("a").inner_text
         
     | 
| 
      
 30 
     | 
    
         
            +
                  track_container = doc.at("#albumTracklist")
         
     | 
| 
      
 31 
     | 
    
         
            +
             
     | 
| 
      
 32 
     | 
    
         
            +
                  track_container.search("tbody tr").map do |row|
         
     | 
| 
      
 33 
     | 
    
         
            +
                    Track.new \
         
     | 
| 
      
 34 
     | 
    
         
            +
                      :artist => artist,
         
     | 
| 
      
 35 
     | 
    
         
            +
                      :album => name,
         
     | 
| 
      
 36 
     | 
    
         
            +
                      :number => row.at(".positionCell").to_plain_text,
         
     | 
| 
      
 37 
     | 
    
         
            +
                      :name => row.at(".subjectCell a").inner_text,
         
     | 
| 
      
 38 
     | 
    
         
            +
                      :duration => row.at(".durationCell").to_plain_text
         
     | 
| 
      
 39 
     | 
    
         
            +
                  end
         
     | 
| 
      
 40 
     | 
    
         
            +
                end
         
     | 
| 
      
 41 
     | 
    
         
            +
              end
         
     | 
| 
      
 42 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,67 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module Rlastfm
         
     | 
| 
      
 2 
     | 
    
         
            +
              class Artist
         
     | 
| 
      
 3 
     | 
    
         
            +
                extend Helpers::RemoteAccessor
         
     | 
| 
      
 4 
     | 
    
         
            +
                include Helpers::Scraper
         
     | 
| 
      
 5 
     | 
    
         
            +
                include HTTParty
         
     | 
| 
      
 6 
     | 
    
         
            +
             
     | 
| 
      
 7 
     | 
    
         
            +
                base_uri "http://ws.audioscrobbler.com/2.0/"
         
     | 
| 
      
 8 
     | 
    
         
            +
             
     | 
| 
      
 9 
     | 
    
         
            +
                remote_reader :name, :mbid, :stats, :url, :bio
         
     | 
| 
      
 10 
     | 
    
         
            +
                remote_reader :from => :image, :to => :images
         
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
      
 12 
     | 
    
         
            +
                def self.top_twenty
         
     | 
| 
      
 13 
     | 
    
         
            +
                  doc = doc_for("/charts/artist")
         
     | 
| 
      
 14 
     | 
    
         
            +
                  top_twenty = doc.at('.mediumImageChart')
         
     | 
| 
      
 15 
     | 
    
         
            +
                  top_twenty.search('tr').map do |artist_row|
         
     | 
| 
      
 16 
     | 
    
         
            +
                    name =  artist_row.search('.subject < a').last
         
     | 
| 
      
 17 
     | 
    
         
            +
                    new name
         
     | 
| 
      
 18 
     | 
    
         
            +
                  end
         
     | 
| 
      
 19 
     | 
    
         
            +
                end
         
     | 
| 
      
 20 
     | 
    
         
            +
             
     | 
| 
      
 21 
     | 
    
         
            +
                def initialize(name)
         
     | 
| 
      
 22 
     | 
    
         
            +
                  self.class.default_params :api_key => Rlastfm.api_key
         
     | 
| 
      
 23 
     | 
    
         
            +
                  @initialized_name = name
         
     | 
| 
      
 24 
     | 
    
         
            +
                end
         
     | 
| 
      
 25 
     | 
    
         
            +
             
     | 
| 
      
 26 
     | 
    
         
            +
                def album_by_name(album_name)
         
     | 
| 
      
 27 
     | 
    
         
            +
                  albums.detect {|a| a.name == album_name}
         
     | 
| 
      
 28 
     | 
    
         
            +
                end
         
     | 
| 
      
 29 
     | 
    
         
            +
             
     | 
| 
      
 30 
     | 
    
         
            +
                def albums
         
     | 
| 
      
 31 
     | 
    
         
            +
                  @albums ||= begin
         
     | 
| 
      
 32 
     | 
    
         
            +
                    response = self.class.get('', :query => {:method => "artist.gettopalbums", :artist => name})
         
     | 
| 
      
 33 
     | 
    
         
            +
                    album_collection = response['lfm']['topalbums']['album']
         
     | 
| 
      
 34 
     | 
    
         
            +
                    album_collection.map{|album_attrs| Album.new album_attrs} if album_collection
         
     | 
| 
      
 35 
     | 
    
         
            +
                  end
         
     | 
| 
      
 36 
     | 
    
         
            +
                end
         
     | 
| 
      
 37 
     | 
    
         
            +
             
     | 
| 
      
 38 
     | 
    
         
            +
                def exists?
         
     | 
| 
      
 39 
     | 
    
         
            +
                  ! mbid.nil?
         
     | 
| 
      
 40 
     | 
    
         
            +
                end
         
     | 
| 
      
 41 
     | 
    
         
            +
             
     | 
| 
      
 42 
     | 
    
         
            +
                def raw
         
     | 
| 
      
 43 
     | 
    
         
            +
                  @raw ||= remote_sync!
         
     | 
| 
      
 44 
     | 
    
         
            +
                end
         
     | 
| 
      
 45 
     | 
    
         
            +
             
     | 
| 
      
 46 
     | 
    
         
            +
                def similar_artists
         
     | 
| 
      
 47 
     | 
    
         
            +
                  @similar_artists ||= begin
         
     | 
| 
      
 48 
     | 
    
         
            +
                    raw['similar']['artist'].map do |artist|
         
     | 
| 
      
 49 
     | 
    
         
            +
                      Artist.new artist['name']
         
     | 
| 
      
 50 
     | 
    
         
            +
                    end
         
     | 
| 
      
 51 
     | 
    
         
            +
                  end
         
     | 
| 
      
 52 
     | 
    
         
            +
                end
         
     | 
| 
      
 53 
     | 
    
         
            +
             
     | 
| 
      
 54 
     | 
    
         
            +
                private
         
     | 
| 
      
 55 
     | 
    
         
            +
             
     | 
| 
      
 56 
     | 
    
         
            +
                def remote_sync!
         
     | 
| 
      
 57 
     | 
    
         
            +
                  response = self.class.get('', :query => {:method => 'artist.getinfo', :artist => @initialized_name})
         
     | 
| 
      
 58 
     | 
    
         
            +
                  @synced = true
         
     | 
| 
      
 59 
     | 
    
         
            +
                  @raw = response['lfm']['artist']
         
     | 
| 
      
 60 
     | 
    
         
            +
                end
         
     | 
| 
      
 61 
     | 
    
         
            +
             
     | 
| 
      
 62 
     | 
    
         
            +
                def synced?
         
     | 
| 
      
 63 
     | 
    
         
            +
                  @synced == true
         
     | 
| 
      
 64 
     | 
    
         
            +
                end
         
     | 
| 
      
 65 
     | 
    
         
            +
              end
         
     | 
| 
      
 66 
     | 
    
         
            +
            end
         
     | 
| 
      
 67 
     | 
    
         
            +
             
     | 
| 
         @@ -0,0 +1,50 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module Rlastfm
         
     | 
| 
      
 2 
     | 
    
         
            +
              module Helpers
         
     | 
| 
      
 3 
     | 
    
         
            +
                module RemoteAccessor
         
     | 
| 
      
 4 
     | 
    
         
            +
                  def remote_reader(*accessors)
         
     | 
| 
      
 5 
     | 
    
         
            +
                    accessors.each do |reader|
         
     | 
| 
      
 6 
     | 
    
         
            +
                      case reader
         
     | 
| 
      
 7 
     | 
    
         
            +
                      when Symbol
         
     | 
| 
      
 8 
     | 
    
         
            +
                        add_reader reader
         
     | 
| 
      
 9 
     | 
    
         
            +
                      when Hash
         
     | 
| 
      
 10 
     | 
    
         
            +
                        add_mapped_reader reader
         
     | 
| 
      
 11 
     | 
    
         
            +
                      else
         
     | 
| 
      
 12 
     | 
    
         
            +
                        raise "remote_reader requires a Hash or Symbol"
         
     | 
| 
      
 13 
     | 
    
         
            +
                      end
         
     | 
| 
      
 14 
     | 
    
         
            +
                    end
         
     | 
| 
      
 15 
     | 
    
         
            +
                  end
         
     | 
| 
      
 16 
     | 
    
         
            +
             
     | 
| 
      
 17 
     | 
    
         
            +
                  def add_mapped_reader(mapping)
         
     | 
| 
      
 18 
     | 
    
         
            +
                    remote_reader_name = mapping.delete(:from)
         
     | 
| 
      
 19 
     | 
    
         
            +
                    reader_name        = mapping.delete(:to)
         
     | 
| 
      
 20 
     | 
    
         
            +
                    raise "remote_accessor_mapping requires :from and :to arguments" unless remote_reader_name && reader_name
         
     | 
| 
      
 21 
     | 
    
         
            +
             
     | 
| 
      
 22 
     | 
    
         
            +
                    add_reader reader_name, remote_reader_name
         
     | 
| 
      
 23 
     | 
    
         
            +
                  end
         
     | 
| 
      
 24 
     | 
    
         
            +
             
     | 
| 
      
 25 
     | 
    
         
            +
                  def add_reader(reader_name, remote_reader_name=nil)
         
     | 
| 
      
 26 
     | 
    
         
            +
                    remote_reader_name ||= reader_name
         
     | 
| 
      
 27 
     | 
    
         
            +
                    define_method reader_name do
         
     | 
| 
      
 28 
     | 
    
         
            +
                      raw[remote_reader_name.to_s]
         
     | 
| 
      
 29 
     | 
    
         
            +
                    end
         
     | 
| 
      
 30 
     | 
    
         
            +
             
     | 
| 
      
 31 
     | 
    
         
            +
                    memoize_method reader_name
         
     | 
| 
      
 32 
     | 
    
         
            +
                  end
         
     | 
| 
      
 33 
     | 
    
         
            +
             
     | 
| 
      
 34 
     | 
    
         
            +
                  def memoize_method(method_name)
         
     | 
| 
      
 35 
     | 
    
         
            +
                    i_var_name = :"@#{method_name}"
         
     | 
| 
      
 36 
     | 
    
         
            +
                    method_without = :"#{method_name}_without_memoization"
         
     | 
| 
      
 37 
     | 
    
         
            +
                    method_with = :"#{method_name}_with_memoization"
         
     | 
| 
      
 38 
     | 
    
         
            +
             
     | 
| 
      
 39 
     | 
    
         
            +
                    class_eval do
         
     | 
| 
      
 40 
     | 
    
         
            +
                      define_method method_with do
         
     | 
| 
      
 41 
     | 
    
         
            +
                        instance_variable_get(i_var_name) || instance_variable_set(i_var_name, send(method_without))
         
     | 
| 
      
 42 
     | 
    
         
            +
                      end
         
     | 
| 
      
 43 
     | 
    
         
            +
                      alias_method method_without, method_name
         
     | 
| 
      
 44 
     | 
    
         
            +
                      alias_method method_name, method_with
         
     | 
| 
      
 45 
     | 
    
         
            +
                    end
         
     | 
| 
      
 46 
     | 
    
         
            +
                  end
         
     | 
| 
      
 47 
     | 
    
         
            +
                end
         
     | 
| 
      
 48 
     | 
    
         
            +
              end
         
     | 
| 
      
 49 
     | 
    
         
            +
            end
         
     | 
| 
      
 50 
     | 
    
         
            +
             
     | 
| 
         @@ -0,0 +1,38 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module Rlastfm
         
     | 
| 
      
 2 
     | 
    
         
            +
              module Helpers
         
     | 
| 
      
 3 
     | 
    
         
            +
                module Scraper
         
     | 
| 
      
 4 
     | 
    
         
            +
                  def self.included(base)
         
     | 
| 
      
 5 
     | 
    
         
            +
                    base.class_eval do
         
     | 
| 
      
 6 
     | 
    
         
            +
                      protected
         
     | 
| 
      
 7 
     | 
    
         
            +
             
     | 
| 
      
 8 
     | 
    
         
            +
                      extend ProtectedClassMethods
         
     | 
| 
      
 9 
     | 
    
         
            +
                      include ProtectedInstanceMethods
         
     | 
| 
      
 10 
     | 
    
         
            +
                    end
         
     | 
| 
      
 11 
     | 
    
         
            +
                  end
         
     | 
| 
      
 12 
     | 
    
         
            +
             
     | 
| 
      
 13 
     | 
    
         
            +
                  module ProtectedClassMethods
         
     | 
| 
      
 14 
     | 
    
         
            +
                    def last_fm_uri(path)
         
     | 
| 
      
 15 
     | 
    
         
            +
                      URI::HTTP.build :host => "www.last.fm", :path => path
         
     | 
| 
      
 16 
     | 
    
         
            +
                    end
         
     | 
| 
      
 17 
     | 
    
         
            +
             
     | 
| 
      
 18 
     | 
    
         
            +
                    def doc_for(url_or_path)
         
     | 
| 
      
 19 
     | 
    
         
            +
                      url_or_path = URI.parse(url_or_path)
         
     | 
| 
      
 20 
     | 
    
         
            +
                      url = url_or_path.relative? ? last_fm_uri(url_or_path.to_s).to_s : url_or_path
         
     | 
| 
      
 21 
     | 
    
         
            +
             
     | 
| 
      
 22 
     | 
    
         
            +
                      if Rlastfm.debug
         
     | 
| 
      
 23 
     | 
    
         
            +
                        puts "Releasing scraper on: #{url}"
         
     | 
| 
      
 24 
     | 
    
         
            +
                      end
         
     | 
| 
      
 25 
     | 
    
         
            +
             
     | 
| 
      
 26 
     | 
    
         
            +
                      doc = Hpricot open(url)
         
     | 
| 
      
 27 
     | 
    
         
            +
                    end
         
     | 
| 
      
 28 
     | 
    
         
            +
                  end
         
     | 
| 
      
 29 
     | 
    
         
            +
             
     | 
| 
      
 30 
     | 
    
         
            +
                  module ProtectedInstanceMethods
         
     | 
| 
      
 31 
     | 
    
         
            +
                    def doc_for(url_or_path)
         
     | 
| 
      
 32 
     | 
    
         
            +
                      self.class.doc_for(url_or_path)
         
     | 
| 
      
 33 
     | 
    
         
            +
                    end
         
     | 
| 
      
 34 
     | 
    
         
            +
                  end
         
     | 
| 
      
 35 
     | 
    
         
            +
                end
         
     | 
| 
      
 36 
     | 
    
         
            +
              end
         
     | 
| 
      
 37 
     | 
    
         
            +
            end
         
     | 
| 
      
 38 
     | 
    
         
            +
             
     | 
| 
         @@ -0,0 +1,23 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module Rlastfm
         
     | 
| 
      
 2 
     | 
    
         
            +
              class Venue
         
     | 
| 
      
 3 
     | 
    
         
            +
                include Helpers::Scraper
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
                def initialize(id)
         
     | 
| 
      
 6 
     | 
    
         
            +
                  @venue_id = id
         
     | 
| 
      
 7 
     | 
    
         
            +
                end
         
     | 
| 
      
 8 
     | 
    
         
            +
             
     | 
| 
      
 9 
     | 
    
         
            +
                def id
         
     | 
| 
      
 10 
     | 
    
         
            +
                  @venue_id
         
     | 
| 
      
 11 
     | 
    
         
            +
                end
         
     | 
| 
      
 12 
     | 
    
         
            +
             
     | 
| 
      
 13 
     | 
    
         
            +
                def photo
         
     | 
| 
      
 14 
     | 
    
         
            +
                  @photo ||= begin
         
     | 
| 
      
 15 
     | 
    
         
            +
                    url = "/venue/#{id}"
         
     | 
| 
      
 16 
     | 
    
         
            +
                    doc = doc_for(url)
         
     | 
| 
      
 17 
     | 
    
         
            +
                    image = doc.at('#catalogueImage')
         
     | 
| 
      
 18 
     | 
    
         
            +
                    image.attributes['src']
         
     | 
| 
      
 19 
     | 
    
         
            +
                  end
         
     | 
| 
      
 20 
     | 
    
         
            +
                end
         
     | 
| 
      
 21 
     | 
    
         
            +
              end
         
     | 
| 
      
 22 
     | 
    
         
            +
            end
         
     | 
| 
      
 23 
     | 
    
         
            +
             
     |