rockstar-custom 0.6.1

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.
Files changed (97) hide show
  1. data/.travis.yml +6 -0
  2. data/Gemfile +11 -0
  3. data/Gemfile.lock +22 -0
  4. data/History.txt +6 -0
  5. data/MIT-LICENSE +19 -0
  6. data/Manifest +72 -0
  7. data/README.md +135 -0
  8. data/Rakefile +34 -0
  9. data/VERSION +1 -0
  10. data/examples/.gitignore +1 -0
  11. data/examples/album.rb +16 -0
  12. data/examples/artist.rb +23 -0
  13. data/examples/geo.rb +9 -0
  14. data/examples/lastfm.yml_example +3 -0
  15. data/examples/scrobble.rb +45 -0
  16. data/examples/tag.rb +20 -0
  17. data/examples/track.rb +14 -0
  18. data/examples/user.rb +18 -0
  19. data/lib/rockstar.rb +50 -0
  20. data/lib/rockstar/album.rb +109 -0
  21. data/lib/rockstar/artist.rb +182 -0
  22. data/lib/rockstar/auth.rb +21 -0
  23. data/lib/rockstar/base.rb +48 -0
  24. data/lib/rockstar/chart.rb +31 -0
  25. data/lib/rockstar/event.rb +73 -0
  26. data/lib/rockstar/geo.rb +22 -0
  27. data/lib/rockstar/metro.rb +26 -0
  28. data/lib/rockstar/playing.rb +50 -0
  29. data/lib/rockstar/rest.rb +66 -0
  30. data/lib/rockstar/scrobble.rb +68 -0
  31. data/lib/rockstar/session.rb +19 -0
  32. data/lib/rockstar/simpleauth.rb +62 -0
  33. data/lib/rockstar/tag.rb +100 -0
  34. data/lib/rockstar/tokenauth.rb +84 -0
  35. data/lib/rockstar/track.rb +260 -0
  36. data/lib/rockstar/user.rb +200 -0
  37. data/lib/rockstar/venue.rb +59 -0
  38. data/lib/rockstar/version.rb +3 -0
  39. data/rockstar.gemspec +174 -0
  40. data/test/fixtures/xml/album/getinfo_album_Radio_Retalation_artist_Thievery_Corporation.xml +21 -0
  41. data/test/fixtures/xml/album/getinfo_album_Some_Hearts_artist_Carrie_Underwood.xml +63 -0
  42. data/test/fixtures/xml/artist/getevents_artist_Metallica.xml +1064 -0
  43. data/test/fixtures/xml/artist/getimages_artist_Metallica_page_2.xml +1074 -0
  44. data/test/fixtures/xml/artist/getinfo_artist_Metallica.xml +115 -0
  45. data/test/fixtures/xml/artist/getsimilar_artist_Metallica.xml +1203 -0
  46. data/test/fixtures/xml/artist/gettopalbums_artist_Metallica.xml +704 -0
  47. data/test/fixtures/xml/artist/gettopfans_artist_Metallica.xml +504 -0
  48. data/test/fixtures/xml/artist/gettoptags_artist_Metallica.xml +403 -0
  49. data/test/fixtures/xml/artist/gettoptracks_artist_Metallica.xml +800 -0
  50. data/test/fixtures/xml/geo/getevents_location_london.xml +531 -0
  51. data/test/fixtures/xml/geo/getmetros_country_germany.xml +44 -0
  52. data/test/fixtures/xml/tag/gettopalbums_tag_rock.xml +654 -0
  53. data/test/fixtures/xml/tag/gettopartists_tag_rock.xml +504 -0
  54. data/test/fixtures/xml/tag/gettoptags.xml +1253 -0
  55. data/test/fixtures/xml/tag/gettoptracks_tag_rock.xml +704 -0
  56. data/test/fixtures/xml/track/getinfo_artist_Carrie_Underwood_track_Before_He_Cheats.xml +55 -0
  57. data/test/fixtures/xml/track/gettopfans_artist_Carrie_Underwood_track_Before_He_Cheats.xml +504 -0
  58. data/test/fixtures/xml/track/gettoptags_artist_Carrie_Underwood_track_Before_He_Cheats.xml +403 -0
  59. data/test/fixtures/xml/track/love_artist_Carrie_Underwood_sk_tag_track_Before_He_Cheats.xml +2 -0
  60. data/test/fixtures/xml/track/updatenowplaying_artist_Carrie_Underwood_sk_tag_track_Before_He_Cheats.xml +10 -0
  61. data/test/fixtures/xml/user/getevents_sk_token_user_bodot.xml +513 -0
  62. data/test/fixtures/xml/user/getfriends_user_jnunemaker.xml +173 -0
  63. data/test/fixtures/xml/user/getinfo_user_jnunemaker.xml +22 -0
  64. data/test/fixtures/xml/user/getinfo_user_oaknd1.xml +22 -0
  65. data/test/fixtures/xml/user/getinfo_user_wharle.xml +22 -0
  66. data/test/fixtures/xml/user/getlovedtracks_user_jnunemaker.xml +775 -0
  67. data/test/fixtures/xml/user/getneighbours_user_jnunemaker.xml +503 -0
  68. data/test/fixtures/xml/user/getrecenttracks_user_jnunemaker.xml +133 -0
  69. data/test/fixtures/xml/user/getrecommendedartists_sk_token_user_jnunemaker.xml +553 -0
  70. data/test/fixtures/xml/user/gettopalbums_user_jnunemaker.xml +704 -0
  71. data/test/fixtures/xml/user/gettopartists_period_overall_user_jnunemaker.xml +554 -0
  72. data/test/fixtures/xml/user/gettoptags_user_jnunemaker.xml +63 -0
  73. data/test/fixtures/xml/user/gettoptracks_user_jnunemaker.xml +750 -0
  74. data/test/fixtures/xml/user/getweeklyalbumchart_from_1138536002_to_1139140802_user_jnunemaker.xml +143 -0
  75. data/test/fixtures/xml/user/getweeklyalbumchart_from__to__user_jnunemaker.xml +31 -0
  76. data/test/fixtures/xml/user/getweeklyartistchart_from_1138536002_to_1139140802_user_jnunemaker.xml +201 -0
  77. data/test/fixtures/xml/user/getweeklyartistchart_from__to__user_jnunemaker.xml +21 -0
  78. data/test/fixtures/xml/user/getweeklychartlist_user_jnunemaker.xml +232 -0
  79. data/test/fixtures/xml/user/getweeklytrackchart_from_1138536002_to_1139140802_user_jnunemaker.xml +883 -0
  80. data/test/fixtures/xml/user/getweeklytrackchart_from__to__user_jnunemaker.xml +423 -0
  81. data/test/fixtures/xml/venue/getevents_venue_8807850.xml +280 -0
  82. data/test/fixtures/xml/venue/search_country__limit__page__venue_country_DE_venue_cotton.xml +72 -0
  83. data/test/mocks/rest.rb +67 -0
  84. data/test/test_helper.rb +18 -0
  85. data/test/unit/test_album.rb +76 -0
  86. data/test/unit/test_artist.rb +102 -0
  87. data/test/unit/test_chart.rb +35 -0
  88. data/test/unit/test_geo.rb +25 -0
  89. data/test/unit/test_playing.rb +53 -0
  90. data/test/unit/test_scrobble.rb +69 -0
  91. data/test/unit/test_simpleauth.rb +45 -0
  92. data/test/unit/test_tag.rb +57 -0
  93. data/test/unit/test_tokenauth.rb +45 -0
  94. data/test/unit/test_track.rb +82 -0
  95. data/test/unit/test_user.rb +299 -0
  96. data/test/unit/test_venue.rb +20 -0
  97. metadata +269 -0
@@ -0,0 +1,31 @@
1
+ module Rockstar
2
+ class Chart < Base
3
+ class << self
4
+ def new_from_xml(xml, doc)
5
+ Chart.new(xml['from'], xml['to'])
6
+ end
7
+ end
8
+ def initialize(from, to)
9
+ raise ArgumentError, "From is required" if from.blank?
10
+ raise ArgumentError, "To is required" if to.blank?
11
+ @from = from
12
+ @to = to
13
+ end
14
+
15
+ def from=(value)
16
+ @from = value.to_i
17
+ end
18
+
19
+ def to=(value)
20
+ @to = value.to_i
21
+ end
22
+
23
+ def from
24
+ @from.to_i
25
+ end
26
+
27
+ def to
28
+ @to.to_i
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,73 @@
1
+ module Rockstar
2
+ class Event < Base
3
+
4
+ attr_accessor :eid, :title, :artists, :headliners, :start_date, :end_date,
5
+ :description, :attendance, :reviews, :tag, :url, :website, :tickets,
6
+ :cancelled, :tags, :images, :venue
7
+
8
+ class << self
9
+ def new_from_xml(xml, doc)
10
+ e = Event.new(
11
+ (xml).at(:id).inner_html,
12
+ (xml).at(:title).inner_html
13
+ )
14
+
15
+ e.artists = []
16
+ xml.search("/artists/artist").each {|a|
17
+ e.artists << a.inner_html
18
+ }
19
+
20
+ e.headliners = []
21
+ xml.search("/artists/headliner").each{|h|
22
+ e.headliners << h.inner_html
23
+ }
24
+
25
+ e.start_date = Base.parse_time(xml.search("/startDate").inner_html.strip)
26
+ e.end_date = Base.parse_time(xml.search("/endDate").inner_html.strip)
27
+ e.description = xml.search("/description").inner_html.strip
28
+ e.attendance = xml.search("/attendance").inner_html.strip.to_i
29
+ e.reviews = xml.search("/reviews").inner_html.strip.to_i
30
+ e.tag = xml.search("/tag").inner_html.strip
31
+ e.url = xml.search("/url").inner_html.strip
32
+ e.website = xml.search("/website").inner_html.strip
33
+ e.cancelled = xml.search("/cancelled").inner_html.strip == 1
34
+
35
+ e.tickets = []
36
+ xml.search("/tickets/ticket").each{|t|
37
+ e.tickets << t.inner_html
38
+ }
39
+
40
+ e.tags = []
41
+ xml.search("/tags/tag").each{|t|
42
+ e.tags << t.inner_html
43
+ }
44
+
45
+ e.images = {}
46
+ xml.search('/image').each {|image|
47
+ e.images[image['size']] = image.inner_html if e.images[image['size']].nil?
48
+ }
49
+
50
+ e.venue = Venue.new_from_xml(xml.search('/venue'), doc) if xml.search('/venue')
51
+
52
+ e
53
+ end
54
+ end
55
+
56
+ def initialize(id, title)
57
+ raise ArgumentError, "ID is required" if id.blank?
58
+ raise ArgumentError, "Title is required" if title.blank?
59
+ @eid = id
60
+ @title = title
61
+ end
62
+
63
+ def image(which=:medium)
64
+ which = which.to_s
65
+ raise ArgumentError unless ['small', 'medium', 'large', 'extralarge', 'mega'].include?(which)
66
+ if (self.images.nil?)
67
+ load_info
68
+ end
69
+ self.images[which]
70
+ end
71
+ end
72
+ end
73
+
@@ -0,0 +1,22 @@
1
+ module Rockstar
2
+ class Geo < Base
3
+
4
+
5
+ # Get events in a specific location. Opts can be
6
+ #
7
+ # * :location => 'madrid' # A city name from geo.metros
8
+ # * :lat => 50.0, :long => 14.0 # A geo point
9
+ #
10
+ # Additionally you can set the distance from that point with
11
+ # :distance => 50 # 50 km from the given location
12
+ #
13
+ def events(opts = {}, force = false)
14
+ get_instance("geo.getEvents", :events, :event, opts, force)
15
+ end
16
+
17
+ def metros(country, force = false)
18
+ get_instance("geo.getMetros", :metros, :metro, {:country => country}, force)
19
+ end
20
+
21
+ end
22
+ end
@@ -0,0 +1,26 @@
1
+ module Rockstar
2
+ class Metro < Base
3
+
4
+ attr_accessor :name, :country
5
+
6
+ class << self
7
+ def new_from_xml(xml, doc)
8
+ Metro.new(
9
+ (xml).at(:name).inner_html,
10
+ (xml).at(:country).inner_html
11
+ )
12
+ end
13
+ end
14
+
15
+ def initialize(name, country)
16
+ raise ArgumentError, "Name is required" if name.blank?
17
+ raise ArgumentError, "Country is required" if country.blank?
18
+ @name = name
19
+ @country = country
20
+ end
21
+
22
+ end
23
+ end
24
+
25
+
26
+
@@ -0,0 +1,50 @@
1
+ module Rockstar
2
+ class Playing
3
+ # you should read last.fm/api/submissions#np first!
4
+
5
+ attr_accessor :session_id, :now_playing_url, :artist, :track,
6
+ :album, :length, :track_number, :mb_track_id
7
+ attr_reader :status
8
+
9
+ def initialize(args = {})
10
+ @session_id = args[:session_id] # from Rockstar::SimpleAuth
11
+ @now_playing_url = args[:now_playing_url] # from Rockstar::SimpleAuth (can change)
12
+ @artist = args[:artist] # track artist
13
+ @track = args[:track] # track name
14
+ @album = args[:album] || '' # track album (optional)
15
+ @length = args[:length] || '' # track length in seconds (optional)
16
+ @track_number = args[:track_number] || '' # track number (optional)
17
+ @mb_track_id = args[:mb_track_id] || '' # MusicBrainz track ID (optional)
18
+
19
+ if [@session_id, @now_playing_url, @artist, @track].any?(&:blank?)
20
+ raise ArgumentError, 'Missing required argument'
21
+ elsif !@length.to_s.empty? && @length.to_i <= 30 # see last.fm/api
22
+ raise ArgumentError, 'Length must be greater than 30 seconds'
23
+ end
24
+
25
+ @connection = REST::Connection.new(@now_playing_url)
26
+ end
27
+
28
+ def submit!
29
+ warn "[DEPRECATION] the `playing` class is deprecated. Please use track.updateNowPlaying"
30
+ query = { :s => @session_id,
31
+ :a => @artist,
32
+ :t => @track,
33
+ :b => @album,
34
+ :l => @length,
35
+ :n => @track_number,
36
+ :m => @mb_track_id }
37
+
38
+ @status = @connection.post('', false, query)
39
+
40
+ case @status
41
+ when /OK/
42
+
43
+ when /BADSESSION/
44
+ raise BadSessionError # rerun Rockstar::SimpleAuth#handshake!
45
+ else
46
+ raise RequestFailedError
47
+ end
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,66 @@
1
+ require 'net/https'
2
+ require 'digest/md5'
3
+
4
+ module Rockstar
5
+ module REST
6
+ class Connection
7
+ def initialize(base_url, args = {})
8
+ @base_url = base_url
9
+ @username = args[:username]
10
+ @password = args[:password]
11
+ end
12
+
13
+ def get(resource, sign_request, args = {})
14
+ request(resource, "get", args, sign_request)
15
+ end
16
+
17
+ def post(resource, sign_request, args = nil)
18
+ request(resource, "post", args, sign_request)
19
+ end
20
+
21
+ def request(resource, method = "get", args = {}, sign_request=false)
22
+ url = URI.parse(@base_url)
23
+
24
+ if (!resource.blank?)
25
+ args[:method] = resource
26
+ args[:api_key]= Rockstar.lastfm_api_key
27
+ end
28
+
29
+ if args
30
+ sorted_keys = args.keys.sort_by{|k|k.to_s}
31
+ query = sorted_keys.collect { |k| "%s=%s" % [escape(k.to_s), escape(args[k].to_s)] }.join("&")
32
+
33
+ if !args[:sk].nil? ||sign_request # Session Key available => sign the request or sign_request = true?
34
+ signed = sorted_keys.collect {|k| "%s%s" % [k.to_s, args[k].to_s]}.join()
35
+
36
+ auth = Digest::MD5.hexdigest("#{signed}#{Rockstar.lastfm_api_secret}")
37
+ query += "&api_sig=#{auth}"
38
+ end
39
+ url.query = query
40
+ end
41
+
42
+ case method
43
+ when "get"
44
+ req = Net::HTTP::Get.new(url.request_uri)
45
+ when "post"
46
+ req = Net::HTTP::Post.new(url.request_uri)
47
+ end
48
+
49
+ if @username and @password
50
+ req.basic_auth(@username, @password)
51
+ end
52
+
53
+ http = Net::HTTP.new(url.host, url.port)
54
+ http.use_ssl = (url.port == 443)
55
+
56
+ res = http.start() { |conn| conn.request(req) }
57
+ res.body
58
+ end
59
+
60
+ private
61
+ def escape(str)
62
+ URI.escape(str, Regexp.new("[^#{URI::PATTERN::UNRESERVED}]"))
63
+ end
64
+ end
65
+ end
66
+ end
@@ -0,0 +1,68 @@
1
+ # exception definitions
2
+ class BadSessionError < StandardError; end
3
+ class RequestFailedError < StandardError; end
4
+
5
+ module Rockstar
6
+ class Scrobble
7
+ # you need to read last.fm/api/submissions#subs first!
8
+
9
+ attr_accessor :session_id, :submission_url, :artist, :track, :time,
10
+ :source, :length, :album, :track_number, :mb_track_id, :rating
11
+ attr_reader :status
12
+
13
+ def initialize(args = {})
14
+ @session_id = args[:session_id] # from Rockstar::TokenAuth
15
+ @submission_url = args[:submission_url] # from Rockstar::TokenAuth (can change)
16
+ @artist = args[:artist] # track artist
17
+ @track = args[:track] # track name
18
+ @time = args[:time] # a Time object set to the time the track started playing
19
+ @source = args[:source] || 'P' # track source, see last.fm/api/submissions#subs
20
+ @length = args[:length].to_s || '' # track length in seconds
21
+ @album = args[:album] || '' # track album name (optional)
22
+ @track_number = args[:track_number] || '' # track number (optional)
23
+ @mb_track_id = args[:mb_track_id] || '' # MusicBrainz track ID (optional)
24
+ @rating = args[:rating] || '' # Rating for clip (optional L=Love, B=Ban (if source=L), S=Skip (if source=L))
25
+
26
+ if [@session_id, @submission_url, @artist, @track].any?(&:blank?)
27
+ raise ArgumentError, 'Missing required argument'
28
+ elsif @time.class.to_s != 'Time'
29
+ raise ArgumentError, ":time must be a Time object"
30
+ elsif !['P','R','E','U'].include?(@source) # see last.fm/api/submissions#subs
31
+ raise ArgumentError, "Invalid source"
32
+ elsif @source == 'P' && @length.blank? # length is not optional if source is P
33
+ raise ArgumentError, 'Length must be set'
34
+ elsif !@length.blank? && @length.to_i <= 30 # see last.fm/api/submissions#subs
35
+ raise ArgumentError, 'Length must be greater than 30 seconds'
36
+ end
37
+
38
+ @connection = REST::Connection.new(@submission_url)
39
+ end
40
+
41
+ def submit!
42
+ warn "[DEPRECATION] the `scrobble` class is deprecated. Please use track.scrobble"
43
+ query = { :s => @session_id,
44
+ 'a[0]' => @artist,
45
+ 't[0]' => @track,
46
+ 'i[0]' => @time.utc.to_i,
47
+ 'o[0]' => @source,
48
+ 'r[0]' => @rating,
49
+ 'l[0]' => @length,
50
+ 'b[0]' => @album,
51
+ 'n[0]' => @track_number,
52
+ 'm[0]' => @mb_track_id }
53
+
54
+ @status = @connection.post('', false, query)
55
+
56
+ case @status
57
+ when /OK/
58
+
59
+ when /BADSESSION/
60
+ raise BadSessionError # rerun Rockstar::SimpleAuth#handshake!
61
+ when /FAILED/
62
+ raise RequestFailedError, @status
63
+ else
64
+ raise RequestFailedError
65
+ end
66
+ end
67
+ end
68
+ end
@@ -0,0 +1,19 @@
1
+ module Rockstar
2
+ class Session < Base
3
+ attr_accessor :username, :key, :subscriber
4
+
5
+ class << self
6
+ def new_from_xml(xml, doc=nil)
7
+ t = Session.new()
8
+ t.username = (xml).at(:name).inner_html
9
+ t.key = (xml).at(:key).inner_html
10
+ t.subscriber = (xml).at(:subscriber).inner_html
11
+ t
12
+ end
13
+ end
14
+ end
15
+ end
16
+
17
+
18
+
19
+
@@ -0,0 +1,62 @@
1
+ require 'digest/md5'
2
+
3
+ # exception definitions
4
+ class BadAuthError < StandardError; end
5
+ class BannedError < StandardError; end
6
+ class BadTimeError < StandardError; end
7
+ module Rockstar
8
+ AUTH_URL = 'http://post.audioscrobbler.com'
9
+ AUTH_VER = '1.2.1'
10
+
11
+ # This class is deprecated. Please use TokenAuth instead.
12
+ class SimpleAuth
13
+ # you should read last.fm/api/submissions#handshake
14
+
15
+ attr_accessor :user, :password, :client_id, :client_ver
16
+ attr_reader :status, :session_id, :now_playing_url, :submission_url
17
+
18
+ def initialize(args = {})
19
+ warn "[DEPRECATION] This class is deprecated. Please use TokenAuth instead!"
20
+
21
+ @user = args[:user] # last.fm username
22
+ @password = args[:password] # last.fm password
23
+ @client_id = 'rck' # Client ID assigned by last.fm; Don't change this!
24
+ @client_ver = Rockstar::Version
25
+
26
+ raise ArgumentError, 'Missing required argument' if @user.blank? || @password.blank?
27
+
28
+ @connection = REST::Connection.new(AUTH_URL)
29
+ end
30
+
31
+ def handshake!
32
+ password_hash = Digest::MD5.hexdigest(@password)
33
+ timestamp = Time.now.to_i.to_s
34
+ token = Digest::MD5.hexdigest(password_hash + timestamp)
35
+
36
+ query = { :hs => 'true',
37
+ :p => AUTH_VER,
38
+ :c => @client_id,
39
+ :v => @client_ver,
40
+ :u => @user,
41
+ :t => timestamp,
42
+ :a => token }
43
+ result = @connection.get('/', false, query)
44
+
45
+ @status = result.split(/\n/)[0]
46
+ case @status
47
+ when /OK/
48
+ @session_id, @now_playing_url, @submission_url = result.split(/\n/)[1,3]
49
+ when /BANNED/
50
+ raise BannedError # something is wrong with the gem, check for an update
51
+ when /BADAUTH/
52
+ raise BadAuthError # invalid user/password
53
+ when /FAILED/
54
+ raise RequestFailedError, @status
55
+ when /BADTIME/
56
+ raise BadTimeError # system time is way off
57
+ else
58
+ raise RequestFailedError
59
+ end
60
+ end
61
+ end
62
+ end
@@ -0,0 +1,100 @@
1
+ # Below is code samples for how to find the top albums and tracks for a tag.
2
+ #
3
+ # tag = Rockstar::Tag.new('country')
4
+ #
5
+ # puts 'Top Albums'
6
+ # tag.top_albums.each { |a| puts "(#{a.count}) #{a.name} by #{a.artist}" }
7
+ #
8
+ # puts
9
+ #
10
+ # puts 'Top Tracks'
11
+ # tag.top_tracks.each { |t| puts "(#{t.count}) #{t.name} by #{t.artist}" }
12
+ #
13
+ # Which would output something similar to:
14
+ #
15
+ # Top Albums
16
+ # (29) American IV: The Man Comes Around by Johnny Cash
17
+ # (14) Folks Pop In at the Waterhouse by Various Artists
18
+ # (13) Hapless by Flowers From The Man Who Shot Your Cousin
19
+ # (9) Taking The Long Way by Dixie Chicks
20
+ # (8) Unchained by Johnny Cash
21
+ # (8) American III: Solitary Man by Johnny Cash
22
+ # (8) Wide Open Spaces by Dixie Chicks
23
+ # (7) It's Now or Later by Tangled Star
24
+ # (7) Greatest Hits by Hank Williams
25
+ # (7) American Recordings by Johnny Cash
26
+ # (6) Forgotten Landscape by theNoLifeKing
27
+ # (6) At Folsom Prison by Johnny Cash
28
+ # (6) Fox Confessor Brings the Flood by Neko Case
29
+ # (6) Murder by Johnny Cash
30
+ # (5) Gloom by theNoLifeKing
31
+ # (5) Set This Circus Down by Tim McGraw
32
+ # (5) Blacklisted by Neko Case
33
+ # (5) Breathe by Faith Hill
34
+ # (5) Unearthed (disc 4: My Mother's Hymn Book) by Johnny Cash
35
+ # (4) Home by Dixie Chicks
36
+ #
37
+ # Top Tracks
38
+ # (221) Hurt by Johnny Cash
39
+ # (152) I Walk the Line by Johnny Cash
40
+ # (147) Ring of Fire by Johnny Cash
41
+ # (125) Folsom Prison Blues by Johnny Cash
42
+ # (77) The Man Comes Around by Johnny Cash
43
+ # (67) Personal Jesus by Johnny Cash
44
+ # (65) Not Ready To Make Nice by Dixie Chicks
45
+ # (63) Before He Cheats by Carrie Underwood
46
+ # (62) Give My Love to Rose by Johnny Cash
47
+ # (49) Jackson by Johnny Cash
48
+ # (49) What Hurts The Most by Rascal Flatts
49
+ # (48) Big River by Johnny Cash
50
+ # (46) Man in Black by Johnny Cash
51
+ # (46) Jolene by Dolly Parton
52
+ # (46) Friends in Low Places by Garth Brooks
53
+ # (46) One by Johnny Cash
54
+ # (44) Cocaine Blues by Johnny Cash
55
+ # (41) Get Rhythm by Johnny Cash
56
+ # (41) I Still Miss Someone by Johnny Cash
57
+ # (40) The Devil Went Down to Georgia by Charlie Daniels Band
58
+ module Rockstar
59
+ class Tag < Base
60
+ attr_accessor :name, :count, :url
61
+
62
+ class << self
63
+ def new_from_xml(xml, doc=nil)
64
+ name = (xml).at(:name).inner_html
65
+ t = Tag.new(name)
66
+ t.count = (xml).at(:count).inner_html
67
+ t.url = Base.fix_url((xml).at(:url).inner_html)
68
+ t
69
+ end
70
+
71
+ def top_tags
72
+ doc = fetch_and_parse("tag.getTopTags")
73
+ @top_tags = (doc/"toptags/tag").collect do |tag|
74
+ t = Tag.new((tag/'name').inner_html)
75
+ t.count = (tag/'count').inner_html
76
+ t.url = Base.fix_url((tag/'url').inner_html)
77
+ t
78
+ end
79
+ end
80
+ end
81
+
82
+ def initialize(name)
83
+ raise ArgumentError, "Name is required" if name.blank?
84
+ @name = name
85
+ end
86
+
87
+
88
+ def top_artists(force=false)
89
+ get_instance("tag.getTopArtists", :top_artists, :artist, {:tag => @name}, force)
90
+ end
91
+
92
+ def top_albums(force=false)
93
+ get_instance("tag.getTopAlbums", :top_albums, :album, {:tag => @name}, force)
94
+ end
95
+
96
+ def top_tracks(force=false)
97
+ get_instance("tag.getTopTracks", :top_tracks, :track, {:tag => @name}, force)
98
+ end
99
+ end
100
+ end