hornairs-scrobbler 0.2.3

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 (161) hide show
  1. data/.gitignore +13 -0
  2. data/.loadpath +5 -0
  3. data/History.txt +5 -0
  4. data/MIT-LICENSE +19 -0
  5. data/Manifest +75 -0
  6. data/README.rdoc +104 -0
  7. data/Rakefile +10 -0
  8. data/VERSION.yml +5 -0
  9. data/examples/album.rb +20 -0
  10. data/examples/artist.rb +13 -0
  11. data/examples/playlist.rb +7 -0
  12. data/examples/scrobble.rb +31 -0
  13. data/examples/tag.rb +11 -0
  14. data/examples/track.rb +12 -0
  15. data/examples/user.rb +15 -0
  16. data/lib/scrobbler.rb +33 -0
  17. data/lib/scrobbler/album.rb +181 -0
  18. data/lib/scrobbler/artist.rb +165 -0
  19. data/lib/scrobbler/auth.rb +47 -0
  20. data/lib/scrobbler/base.rb +105 -0
  21. data/lib/scrobbler/event.rb +105 -0
  22. data/lib/scrobbler/geo.rb +27 -0
  23. data/lib/scrobbler/helper/image.rb +52 -0
  24. data/lib/scrobbler/helper/streamable.rb +40 -0
  25. data/lib/scrobbler/library.rb +112 -0
  26. data/lib/scrobbler/playing.rb +49 -0
  27. data/lib/scrobbler/playlist.rb +87 -0
  28. data/lib/scrobbler/radio.rb +12 -0
  29. data/lib/scrobbler/rest.rb +47 -0
  30. data/lib/scrobbler/scrobble.rb +116 -0
  31. data/lib/scrobbler/session.rb +9 -0
  32. data/lib/scrobbler/shout.rb +21 -0
  33. data/lib/scrobbler/simpleauth.rb +60 -0
  34. data/lib/scrobbler/tag.rb +113 -0
  35. data/lib/scrobbler/track.rb +152 -0
  36. data/lib/scrobbler/user.rb +222 -0
  37. data/lib/scrobbler/venue.rb +67 -0
  38. data/setup.rb +1585 -0
  39. data/tasks/jeweler.rake +15 -0
  40. data/tasks/rdoc.rake +7 -0
  41. data/tasks/tests.rake +13 -0
  42. data/tasks/yardoc.rake +8 -0
  43. data/test/fixtures/xml/album/info.xml +43 -0
  44. data/test/fixtures/xml/artist/fans.xml +52 -0
  45. data/test/fixtures/xml/artist/info.xml +58 -0
  46. data/test/fixtures/xml/artist/similar.xml +1004 -0
  47. data/test/fixtures/xml/artist/topalbums.xml +61 -0
  48. data/test/fixtures/xml/artist/toptags.xml +19 -0
  49. data/test/fixtures/xml/artist/toptracks.xml +62 -0
  50. data/test/fixtures/xml/auth/session.xml +7 -0
  51. data/test/fixtures/xml/auth/token.xml +3 -0
  52. data/test/fixtures/xml/event/attend.xml +3 -0
  53. data/test/fixtures/xml/event/attendees.xml +53 -0
  54. data/test/fixtures/xml/event/event.xml +35 -0
  55. data/test/fixtures/xml/event/shouts.xml +35 -0
  56. data/test/fixtures/xml/geo/events-distance-p1.xml +151 -0
  57. data/test/fixtures/xml/geo/events-lat-long.xml +167 -0
  58. data/test/fixtures/xml/geo/events-p1.xml +152 -0
  59. data/test/fixtures/xml/geo/events-p2.xml +380 -0
  60. data/test/fixtures/xml/geo/events-p3.xml +427 -0
  61. data/test/fixtures/xml/geo/top_artists-p1.xml +76 -0
  62. data/test/fixtures/xml/geo/top_tracks-p1.xml +77 -0
  63. data/test/fixtures/xml/library/albums-f30.xml +454 -0
  64. data/test/fixtures/xml/library/albums-p1.xml +754 -0
  65. data/test/fixtures/xml/library/albums-p2.xml +754 -0
  66. data/test/fixtures/xml/library/albums-p3.xml +754 -0
  67. data/test/fixtures/xml/library/albums-p4.xml +739 -0
  68. data/test/fixtures/xml/library/albums-p5.xml +754 -0
  69. data/test/fixtures/xml/library/albums-p6.xml +754 -0
  70. data/test/fixtures/xml/library/albums-p7.xml +739 -0
  71. data/test/fixtures/xml/library/albums-p8.xml +724 -0
  72. data/test/fixtures/xml/library/artists-f30.xml +334 -0
  73. data/test/fixtures/xml/library/artists-p1.xml +554 -0
  74. data/test/fixtures/xml/library/artists-p2.xml +554 -0
  75. data/test/fixtures/xml/library/artists-p3.xml +554 -0
  76. data/test/fixtures/xml/library/artists-p4.xml +554 -0
  77. data/test/fixtures/xml/library/artists-p5.xml +554 -0
  78. data/test/fixtures/xml/library/artists-p6.xml +554 -0
  79. data/test/fixtures/xml/library/artists-p7.xml +444 -0
  80. data/test/fixtures/xml/library/tracks-f30.xml +472 -0
  81. data/test/fixtures/xml/library/tracks-p1.xml +789 -0
  82. data/test/fixtures/xml/library/tracks-p10.xml +771 -0
  83. data/test/fixtures/xml/library/tracks-p11.xml +792 -0
  84. data/test/fixtures/xml/library/tracks-p12.xml +777 -0
  85. data/test/fixtures/xml/library/tracks-p13.xml +762 -0
  86. data/test/fixtures/xml/library/tracks-p14.xml +759 -0
  87. data/test/fixtures/xml/library/tracks-p15.xml +762 -0
  88. data/test/fixtures/xml/library/tracks-p16.xml +756 -0
  89. data/test/fixtures/xml/library/tracks-p17.xml +780 -0
  90. data/test/fixtures/xml/library/tracks-p18.xml +756 -0
  91. data/test/fixtures/xml/library/tracks-p19.xml +774 -0
  92. data/test/fixtures/xml/library/tracks-p2.xml +765 -0
  93. data/test/fixtures/xml/library/tracks-p20.xml +777 -0
  94. data/test/fixtures/xml/library/tracks-p21.xml +777 -0
  95. data/test/fixtures/xml/library/tracks-p22.xml +771 -0
  96. data/test/fixtures/xml/library/tracks-p23.xml +765 -0
  97. data/test/fixtures/xml/library/tracks-p24.xml +783 -0
  98. data/test/fixtures/xml/library/tracks-p25.xml +777 -0
  99. data/test/fixtures/xml/library/tracks-p26.xml +777 -0
  100. data/test/fixtures/xml/library/tracks-p27.xml +756 -0
  101. data/test/fixtures/xml/library/tracks-p28.xml +771 -0
  102. data/test/fixtures/xml/library/tracks-p29.xml +753 -0
  103. data/test/fixtures/xml/library/tracks-p3.xml +771 -0
  104. data/test/fixtures/xml/library/tracks-p30.xml +780 -0
  105. data/test/fixtures/xml/library/tracks-p31.xml +753 -0
  106. data/test/fixtures/xml/library/tracks-p32.xml +771 -0
  107. data/test/fixtures/xml/library/tracks-p33.xml +762 -0
  108. data/test/fixtures/xml/library/tracks-p34.xml +538 -0
  109. data/test/fixtures/xml/library/tracks-p4.xml +792 -0
  110. data/test/fixtures/xml/library/tracks-p5.xml +780 -0
  111. data/test/fixtures/xml/library/tracks-p6.xml +789 -0
  112. data/test/fixtures/xml/library/tracks-p7.xml +789 -0
  113. data/test/fixtures/xml/library/tracks-p8.xml +780 -0
  114. data/test/fixtures/xml/library/tracks-p9.xml +774 -0
  115. data/test/fixtures/xml/tag/similar.xml +254 -0
  116. data/test/fixtures/xml/tag/topalbums.xml +805 -0
  117. data/test/fixtures/xml/tag/topartists.xml +605 -0
  118. data/test/fixtures/xml/tag/toptags.xml +1254 -0
  119. data/test/fixtures/xml/tag/toptracks.xml +852 -0
  120. data/test/fixtures/xml/track/fans.xml +34 -0
  121. data/test/fixtures/xml/track/info.xml +53 -0
  122. data/test/fixtures/xml/track/toptags.xml +504 -0
  123. data/test/fixtures/xml/user/events.xml +401 -0
  124. data/test/fixtures/xml/user/friends.xml +30 -0
  125. data/test/fixtures/xml/user/lovedtracks.xml +678 -0
  126. data/test/fixtures/xml/user/neighbours.xml +23 -0
  127. data/test/fixtures/xml/user/playlists.xml +61 -0
  128. data/test/fixtures/xml/user/profile.xml +12 -0
  129. data/test/fixtures/xml/user/recentbannedtracks.xml +24 -0
  130. data/test/fixtures/xml/user/recentlovedtracks.xml +24 -0
  131. data/test/fixtures/xml/user/recenttracks.xml +124 -0
  132. data/test/fixtures/xml/user/systemrecs.xml +18 -0
  133. data/test/fixtures/xml/user/topalbums.xml +61 -0
  134. data/test/fixtures/xml/user/topartists.xml +41 -0
  135. data/test/fixtures/xml/user/toptags.xml +44 -0
  136. data/test/fixtures/xml/user/toptracks.xml +65 -0
  137. data/test/fixtures/xml/user/weeklyalbumchart.xml +256 -0
  138. data/test/fixtures/xml/user/weeklyartistchart.xml +220 -0
  139. data/test/fixtures/xml/user/weeklytrackchart.xml +746 -0
  140. data/test/fixtures/xml/venue/events.xml +151 -0
  141. data/test/fixtures/xml/venue/venue.xml +16 -0
  142. data/test/mocks/rest.rb +212 -0
  143. data/test/spec_helper.rb +7 -0
  144. data/test/test_helper.rb +20 -0
  145. data/test/unit/album_spec.rb +52 -0
  146. data/test/unit/artist_spec.rb +130 -0
  147. data/test/unit/auth_spec.rb +36 -0
  148. data/test/unit/event_spec.rb +109 -0
  149. data/test/unit/geo_spec.rb +148 -0
  150. data/test/unit/library_spec.rb +133 -0
  151. data/test/unit/playing_test.rb +53 -0
  152. data/test/unit/playlist_spec.rb +25 -0
  153. data/test/unit/radio_spec.rb +22 -0
  154. data/test/unit/scrobble_spec.rb +55 -0
  155. data/test/unit/scrobble_test.rb +69 -0
  156. data/test/unit/simpleauth_test.rb +45 -0
  157. data/test/unit/tag_spec.rb +101 -0
  158. data/test/unit/track_spec.rb +95 -0
  159. data/test/unit/user_spec.rb +264 -0
  160. data/test/unit/venue_spec.rb +104 -0
  161. metadata +265 -0
@@ -0,0 +1,165 @@
1
+ # Below are examples of how to find an artists top tracks and similar artists.
2
+ #
3
+ # artist = Scrobbler::Artist.new('Carrie Underwood')
4
+ #
5
+ # puts 'Top Tracks'
6
+ # puts "=" * 10
7
+ # artist.top_tracks.each { |t| puts "(#{t.reach}) #{t.name}" }
8
+ #
9
+ # puts
10
+ #
11
+ # puts 'Similar Artists'
12
+ # puts "=" * 15
13
+ # artist.similar.each { |a| puts "(#{a.match}%) #{a.name}" }
14
+ #
15
+ # Would output something similar to:
16
+ #
17
+ # Top Tracks
18
+ # ==========
19
+ # (8797) Before He Cheats
20
+ # (3574) Don't Forget to Remember Me
21
+ # (3569) Wasted
22
+ # (3246) Some Hearts
23
+ # (3142) Jesus, Take the Wheel
24
+ # (2600) Starts With Goodbye
25
+ # (2511) Jesus Take The Wheel
26
+ # (2423) Inside Your Heaven
27
+ # (2328) Lessons Learned
28
+ # (2040) I Just Can't Live a Lie
29
+ # (1899) Whenever You Remember
30
+ # (1882) We're Young and Beautiful
31
+ # (1854) That's Where It Is
32
+ # (1786) I Ain't in Checotah Anymore
33
+ # (1596) The Night Before (Life Goes On)
34
+ #
35
+ # Similar Artists
36
+ # ===============
37
+ # (100%) Rascal Flatts
38
+ # (84.985%) Keith Urban
39
+ # (84.007%) Kellie Pickler
40
+ # (82.694%) Katharine McPhee
41
+ # (81.213%) Martina McBride
42
+ # (79.397%) Faith Hill
43
+ # (77.121%) Tim McGraw
44
+ # (75.191%) Jessica Simpson
45
+ # (75.182%) Sara Evans
46
+ # (75.144%) The Wreckers
47
+ # (73.034%) Kenny Chesney
48
+ # (71.765%) Dixie Chicks
49
+ # (71.084%) Kelly Clarkson
50
+ # (69.535%) Miranda Lambert
51
+ # (66.952%) LeAnn Rimes
52
+ # (66.398%) Mandy Moore
53
+ # (65.817%) Bo Bice
54
+ # (65.279%) Diana DeGarmo
55
+ # (65.115%) Gretchen Wilson
56
+ # (62.982%) Clay Aiken
57
+ # (62.436%) Ashlee Simpson
58
+ # (62.160%) Christina Aguilera
59
+ module Scrobbler
60
+ # @todo Add missing functions that require authentication
61
+ # @todo Integrate search functionality into this class which is already implemented in Scrobbler::Search
62
+ class Artist < Base
63
+ mixins :image, :streamable
64
+
65
+ attr_accessor :name, :mbid, :playcount, :rank, :url, :count
66
+ attr_accessor :chartposition
67
+ attr_accessor :match, :tagcount, :listeners
68
+
69
+ class << self
70
+ def new_from_xml(xml, o={})
71
+ data = data_from_xml(xml, o)
72
+ return nil if data[:name].nil?
73
+ Artist.new(data[:name], data)
74
+ end
75
+
76
+ def data_from_xml(xml, o={})
77
+ data = {}
78
+
79
+ # Get all information from the root's children nodes
80
+ xml.children.each do |child|
81
+ data[:playcount] = child.content.to_i if child.name == 'playcount'
82
+ data[:mbid] = child.content if child.name == 'mbid'
83
+ data[:url] = child.content if child.name == 'url'
84
+ data[:match] = child.content.to_i if child.name == 'match'
85
+ data[:tagcount] = child.content.to_i if child.name == 'tagcount'
86
+ data[:chartposition] = child.content if child.name == 'chartposition'
87
+ data[:name] = child.content if child.name == 'name'
88
+ maybe_streamable_node(data, child)
89
+ maybe_image_node(data, child)
90
+ end
91
+
92
+ # If we have not found anything in the content of this node yet then
93
+ # this must be a simple artist node which has the name of the artist
94
+ # as its content
95
+ data[:name] = xml.content if data == {}
96
+
97
+ # Get all information from the root's attributes
98
+ data[:name] = xml['name'] if xml['name']
99
+ data[:rank] = xml['rank'].to_i if xml['rank']
100
+ maybe_streamable_attribute data, xml
101
+ data[:mbid] = xml['mbid'] if xml['mbid']
102
+ data
103
+ end
104
+ end
105
+
106
+ def initialize(name, data = {})
107
+ super()
108
+ raise ArgumentError, "Name is required" if name.blank?
109
+ @name = name
110
+ populate_data(data)
111
+ end
112
+
113
+ @info_loaded = false
114
+ # Get the metadata
115
+ def load_info
116
+ doc = Base.request('artist.getinfo', {'artist' => @name})
117
+ doc.root.children.each do |child|
118
+ next unless child.name == 'artist'
119
+ data = self.class.data_from_xml(child)
120
+ populate_data(data)
121
+ @info_loaded = true
122
+ break
123
+ end
124
+ end # load_info
125
+
126
+
127
+ # Get the URL to the ical or rss representation of the current events that
128
+ # a artist will play
129
+ #
130
+ # @todo Use the API function and parse that into a common ruby structure
131
+ def current_events(format=:ics)
132
+ format = :ics if format.to_s == 'ical'
133
+ raise ArgumentError unless ['ics', 'rss'].include?(format.to_s)
134
+ "#{API_URL.chop}/2.0/artist/#{CGI::escape(@name)}/events.#{format}"
135
+ end
136
+
137
+ def similar(force=false)
138
+ get_response('artist.getsimilar', :similar, 'similarartists', 'artist', {'artist' => @name}, force)
139
+ end
140
+
141
+ def top_fans(force=false)
142
+ get_response('artist.gettopfans', :top_fans, 'topfans', 'user', {'artist' => @name}, force)
143
+ end
144
+
145
+ def top_tracks(force=false)
146
+ get_response('artist.gettoptracks', :top_tracks, 'toptracks', 'track', {'artist'=>@name}, force)
147
+ end
148
+
149
+ def top_albums(force=false)
150
+ get_response('artist.gettopalbums', :top_albums, 'topalbums', 'album', {'artist'=>@name}, force)
151
+ end
152
+
153
+ def top_tags(force=false)
154
+ get_response('artist.gettoptags', :top_tags, 'toptags', 'tag', {'artist' => @name}, force)
155
+ end
156
+
157
+ def ==(otherArtist)
158
+ if otherArtist.is_a?(Scrobbler::Artist)
159
+ return (@name == otherArtist.name)
160
+ end
161
+ false
162
+ end
163
+
164
+ end
165
+ end
@@ -0,0 +1,47 @@
1
+ module Scrobbler
2
+ # @todo everything
3
+ class Auth < Base
4
+
5
+ def initialize(username)
6
+ super()
7
+ @username = username
8
+ end
9
+
10
+ def session(token)
11
+ doc = Base.request('auth.getsession', :signed => true, :token => token)
12
+ asession = {}
13
+ doc.root.children.each do |child1|
14
+ next unless child1.name == 'session'
15
+ child1.children.each do |child2|
16
+ if child2.name == 'name'
17
+ asession[:name] = child2.content
18
+ elsif child2.name == 'key'
19
+ asession[:key] = child2.content
20
+ elsif child2.name == 'subscriber'
21
+ asession[:subscriber] = true if child2.content == '1'
22
+ asession[:subscriber] = false unless child2.content == '1'
23
+ end
24
+ end
25
+ end
26
+ Scrobbler::Session.new(asession)
27
+ end
28
+
29
+ def token
30
+ doc = Base.request('auth.gettoken', :signed => true)
31
+ stoken = ''
32
+ doc.root.children.each do |child|
33
+ next unless child.name == 'token'
34
+ stoken = child.content
35
+ end
36
+ stoken
37
+ end
38
+
39
+ def url(options={})
40
+ options[:token] = token if options[:token].nil?
41
+ options[:api_key] = @@api_key
42
+ "http://www.last.fm/api/auth/?api_key=#{options[:api_key]}&token=#{options[:token]}"
43
+ end
44
+
45
+ end
46
+ end
47
+
@@ -0,0 +1,105 @@
1
+ require 'digest/md5'
2
+
3
+ $KCODE = 'u'
4
+
5
+ include LibXML
6
+
7
+ module Scrobbler
8
+
9
+ API_URL = 'http://ws.audioscrobbler.com/'
10
+
11
+ class Base
12
+ def Base.api_key=(api_key)
13
+ @@api_key = api_key
14
+ end
15
+
16
+ def Base.secret=(secret)
17
+ @@secret = secret
18
+ end
19
+
20
+ def Base.connection
21
+ @connection ||= REST::Connection.new(API_URL)
22
+ end
23
+
24
+ def Base.sanitize(param)
25
+ URI.escape(param.to_s, Regexp.new("[^#{URI::PATTERN::UNRESERVED}]"))
26
+ end
27
+
28
+ def Base.get(api_method, parent, element, parameters = {})
29
+ scrobbler_class = "scrobbler/#{element.to_s}".camelize.constantize
30
+ doc = request(api_method, parameters)
31
+ elements = []
32
+ doc.root.children.each do |child|
33
+ next unless child.name == parent.to_s
34
+ child.children.each do |child2|
35
+ next unless child2.name == element.to_s
36
+ elements << scrobbler_class.new_from_xml(child2)
37
+ end
38
+ end
39
+ elements
40
+ end
41
+
42
+ def Base.post_request(api_method, parameters = {}, request_method = 'get')
43
+ Base.request(api_method, parameters, 'post')
44
+ end
45
+
46
+ def Base.request(api_method, parameters = {}, request_method = 'get')
47
+ parameters = {:signed => false}.merge(parameters)
48
+ parameters['api_key'] = @@api_key
49
+ parameters['method'] = api_method.to_s
50
+ paramlist = []
51
+ # Check if we want a signed call and pop :signed
52
+ if parameters.delete :signed
53
+ #1: Sort alphabetically
54
+ params = parameters.sort{|a,b| a[0].to_s<=>b[0].to_s}
55
+ #2: concat them into one string
56
+ str = params.join('')
57
+ #3: Append secret
58
+ str = str + @@secret
59
+ #4: Make a md5 hash
60
+ md5 = Digest::MD5.hexdigest(str)
61
+ params << [:api_sig, md5]
62
+ params.each do |a|
63
+ paramlist << "#{sanitize(a[0])}=#{sanitize(a[1])}"
64
+ end
65
+ else
66
+ parameters.each do |key, value|
67
+ paramlist << "#{sanitize(key)}=#{sanitize(value)}"
68
+ end
69
+ end
70
+ url = '/2.0/?' + paramlist.join('&')
71
+ XML::Document.string(self.connection.send(request_method,url))
72
+ end
73
+
74
+
75
+ private
76
+
77
+ def Base.mixins(*args)
78
+ args.each do |arg|
79
+ if arg == :image
80
+ extend Scrobbler::ImageClassFuncs
81
+ include Scrobbler::ImageObjectFuncs
82
+ elsif arg == :streamable
83
+ attr_reader :streamable
84
+ extend StreamableClassFuncs
85
+ include StreamableObjectFuncs
86
+ else
87
+ raise ArgumentError, "#{arg} is not a known mixin"
88
+ end
89
+ end
90
+ end
91
+
92
+ def populate_data(data = {})
93
+ data.each do |key, value|
94
+ instance_variable_set("@#{key.to_s}", value)
95
+ end
96
+ end
97
+
98
+ def get_response(api_method, instance_name, parent, element, params, force=false)
99
+ if instance_variable_get("@#{instance_name}").nil? || force
100
+ instance_variable_set("@#{instance_name}", Base.get(api_method, parent, element, params))
101
+ end
102
+ instance_variable_get("@#{instance_name}")
103
+ end
104
+ end # class Base
105
+ end # module Scrobbler
@@ -0,0 +1,105 @@
1
+ module Scrobbler
2
+ class Event < Base
3
+ # Load Helper modules
4
+ include ImageObjectFuncs
5
+ extend ImageClassFuncs
6
+
7
+ attr_accessor :id, :title, :start_date, :start_time, :description
8
+ attr_accessor :reviews, :tag, :url, :artists, :headliner, :image_small
9
+ attr_accessor :image_medium, :image_large, :attendance, :venue
10
+
11
+ class << self
12
+
13
+ def update_or_create_from_xml(xml, event=nil)
14
+ data = {}
15
+ artists = []
16
+ headliner = nil
17
+ venue = nil
18
+
19
+ xml.children.each do |child|
20
+ data[:id] = child.content.to_i if child.name == 'id'
21
+ data[:title] = child.content if child.name == 'title'
22
+
23
+ if child.name == 'artists'
24
+ child.children.each do |artist_element|
25
+ artists << Artist.new(artist_element.content) if artist_element.name == 'artist'
26
+ headliner = Artist.new(artist_element.content) if artist_element.name == 'headliner'
27
+ end
28
+ artists << headliner unless headliner.nil? || headliner_alrady_listed_in_artist_list?(artists,headliner)
29
+ end
30
+
31
+ maybe_image_node(data, child)
32
+ data[:url] = child.content if child.name == 'url'
33
+ data[:description] = child.content if child.name == 'description'
34
+ data[:attendance] = child.content.to_i if child.name == 'attendance'
35
+ data[:reviews] = child.content.to_i if child.name == 'reviews'
36
+ data[:tag] = child.content if child.name == 'tag'
37
+ data[:start_date] = Time.parse(child.content) if child.name == 'startDate'
38
+ data[:start_time] = child.content if child.name == 'startTime'
39
+ venue = Venue.new_from_xml(child) if child.name == 'venue'
40
+ end
41
+
42
+ if event.nil?
43
+ event = Event.new(data[:id],data)
44
+ else
45
+ event.send :populate_data, data
46
+ end
47
+
48
+ event.artists = artists.uniq
49
+ event.headliner = headliner
50
+ event.venue = venue
51
+ event
52
+ end
53
+
54
+ def headliner_alrady_listed_in_artist_list?(artists,headliner)
55
+ artists.each do |artist|
56
+ return true if artist.name == headliner.name
57
+ end
58
+ false
59
+ end
60
+
61
+ def new_from_libxml(xml)
62
+ update_or_create_from_xml(xml)
63
+ end
64
+ end
65
+
66
+ def initialize(id,input={})
67
+ raise ArgumentError if id.blank?
68
+ @id = id
69
+ populate_data(input)
70
+ load_info() if input[:include_info]
71
+ end
72
+
73
+ def shouts(force = false)
74
+ get_response('event.getshouts', :shouts, 'shouts', 'shout', {'event'=>@id}, force)
75
+ end
76
+
77
+ def attendees(force = false)
78
+ get_response('event.getattendees', :attendees, 'attendees', 'user', {'event'=>@id}, force)
79
+ end
80
+
81
+ def shout
82
+ # This function require authentication, but SimpleAuth is not yet 2.0
83
+ raise NotImplementedError
84
+ end
85
+
86
+ def attend(session, attendance_status)
87
+ doc = Base.post_request('event.attend',{:event => @id, :signed => true, :status => attendance_status, :sk => session.key})
88
+ end
89
+
90
+ def share
91
+ # This function require authentication, but SimpleAuth is not yet 2.0
92
+ raise NotImplementedError
93
+ end
94
+
95
+ # Load additional informatalbumion about this event
96
+ #
97
+ # Calls "event.getinfo" REST method
98
+ def load_info
99
+ doc = Base.request('event.getinfo', {'event' => @id})
100
+ doc.root.children.each do |child|
101
+ Event.update_or_create_from_xml(child, self) if child.name == 'event'
102
+ end
103
+ end
104
+ end
105
+ end
@@ -0,0 +1,27 @@
1
+ module Scrobbler
2
+ class Geo < Base
3
+
4
+ # Gets a list of events based on the location that
5
+ # the Geo object is set to
6
+ def events(options={})
7
+ options = set_default_options(options)
8
+ get_response('geo.getevents', :events, 'events', 'event', options, options[:force])
9
+ end
10
+
11
+ def top_artists(options={})
12
+ options = set_default_options(options)
13
+ get_response('geo.gettopartists', :artists, 'topartists', 'artist', options, options[:force])
14
+ end
15
+
16
+ def top_tracks(options={})
17
+ options = set_default_options(options)
18
+ get_response('geo.gettoptracks', :tracks, 'toptracks', 'track', options, options[:force])
19
+ end
20
+
21
+ private
22
+
23
+ def set_default_options(options={})
24
+ {:force => false, :page => 1}.merge options
25
+ end
26
+ end
27
+ end