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,84 @@
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
+
9
+ # = Token Authentification
10
+ #
11
+ # There are 2 ways to get an auth token :
12
+ #
13
+ # = Desktop-App
14
+ # 1. Get a new token to request authorisation:
15
+ # token = Rockstar::Auth.new.token
16
+ # 2. Open a webbrowser with http://www.last.fm/api/auth/?api_key=xxxxxxxxxxx&token=xxxxxxxx
17
+ # 3. Wait for the User to confirm that he accepted your request.
18
+ # 4. Continue with "Get the session token"
19
+ #
20
+ # = Web-App
21
+ # 1. Redirect the user to http://www.last.fm/api/auth/?api_key={YOUR_API_KEY}&amp;cb={YOUR_RETURN_URL}
22
+ # 2. If the user accepts, lastfm will redirect to YOUR_RETURN_URL?token=TOKEN
23
+ # token = params[:token]
24
+ # 3. Continue with "Get the session token"
25
+ #
26
+ # = Get the session token
27
+ # 1. Use the previous token and call
28
+ # session = Rockstar::Auth.new.session(token)
29
+ # 2. Store the session.key and session.username returned. The session.key will not
30
+ # expire. It is save to store it into your database.
31
+ # 3. Use this session.key as token to authentificate with this class :
32
+ # auth = Rockstar::TokenAuth.new({:username => 'chunky', :token => 'bacon'})
33
+ # auth.handshake!
34
+ #
35
+ class TokenAuth
36
+ # you should read last.fm/api/submissions#handshake
37
+
38
+ attr_accessor :user, :token, :client_id, :client_ver
39
+ attr_reader :status, :session_id, :now_playing_url, :submission_url
40
+
41
+ def initialize(args = {})
42
+ @user = args[:username] # last.fm user
43
+ @token = args[:token] # last.fm token
44
+ @client_id = 'rck' # Client ID assigned by last.fm; Don't change this!
45
+ @client_ver = Rockstar::Version
46
+
47
+ raise ArgumentError, 'Missing required argument' if @user.blank? || @token.blank?
48
+
49
+ @connection = REST::Connection.new(Rockstar::AUTH_URL)
50
+ end
51
+
52
+ def handshake!
53
+ timestamp = Time.now.to_i.to_s
54
+ auth = Digest::MD5.hexdigest("#{Rockstar.lastfm_api_secret}#{timestamp}")
55
+
56
+ query = { :hs => 'true',
57
+ :p => AUTH_VER,
58
+ :c => @client_id,
59
+ :v => @client_ver,
60
+ :u => @user,
61
+ :t => timestamp,
62
+ :a => auth,
63
+ :api_key=>Rockstar.lastfm_api_key,
64
+ :sk => @token }
65
+ result = @connection.get('/', true, query)
66
+
67
+ @status = result.split(/\n/)[0]
68
+ case @status
69
+ when /OK/
70
+ @session_id, @now_playing_url, @submission_url = result.split(/\n/)[1,3]
71
+ when /BANNED/
72
+ raise BannedError # something is wrong with the gem, check for an update
73
+ when /BADAUTH/
74
+ raise BadAuthError # invalid user/password
75
+ when /FAILED/
76
+ raise RequestFailedError, @status
77
+ when /BADTIME/
78
+ raise BadTimeError # system time is way off
79
+ else
80
+ raise RequestFailedError
81
+ end
82
+ end
83
+ end
84
+ end
@@ -0,0 +1,260 @@
1
+ # Below is an example of how to get the top fans for a track.
2
+ #
3
+ # track = Rockstar::Track.new('Carrie Underwood', 'Before He Cheats')
4
+ # puts 'Fans'
5
+ # puts "=" * 4
6
+ # track.fans.each { |u| puts u.username }
7
+ #
8
+ # Which would output something like:
9
+ #
10
+ # track = Rockstar::Track.new('Carrie Underwood', 'Before He Cheats')
11
+ # puts 'Fans'
12
+ # puts "=" * 4
13
+ # track.fans.each { |u| puts "(#{u.weight}) #{u.username}" }
14
+ #
15
+ # Fans
16
+ # ====
17
+ # (69163) PimpinRose
18
+ # (7225) selene204
19
+ # (7000) CelestiaLegends
20
+ # (6817) muehllr
21
+ # (5387) Mudley
22
+ # (5368) ilovejohnny1984
23
+ # (5232) MeganIAD
24
+ # (5132) Veric
25
+ # (5097) aeVnar
26
+ # (3390) kristaaan
27
+ # (3239) kelseaowns
28
+ # (2780) syndication
29
+ # (2735) mkumm
30
+ # (2706) Kimmybeebee
31
+ # (2648) skorpcroze
32
+ # (2549) mistergreg
33
+ # (2449) mlmjcace
34
+ # (2302) tiNEey
35
+ # (2169) ajsbabiegirl
36
+
37
+ class BadSessionError < StandardError; end
38
+ class UnavailableError < StandardError; end
39
+ class RequestFailedError < StandardError; end
40
+
41
+
42
+ module Rockstar
43
+ class Track < Base
44
+ attr_accessor :artist, :artist_mbid, :name, :mbid, :playcount, :rank, :url
45
+ attr_accessor :summary, :content, :streamable, :album, :album_mbid, :date, :date_uts, :duration
46
+
47
+ # only seems to be used on top tracks for tag
48
+ attr_accessor :count, :thumbnail, :image, :images
49
+
50
+ # for weekly top tracks
51
+ attr_accessor :chartposition
52
+
53
+ class << self
54
+ def new_from_xml(xml, doc=nil)
55
+ artist = (xml).at(:artist)['name'] if (xml).at(:artist) && !(xml).at(:artist)['name'].nil?
56
+ artist = (xml).at(:artist).at(:name).inner_html if artist.nil? && (xml).at(:artist) && (xml).at(:artist).at(:name)
57
+ artist = (xml).at(:artist).inner_html if artist.nil? && (xml).at(:artist)
58
+ artist = doc.root['artist'] if artist.nil? && doc.root['artist']
59
+ name = (xml).at(:name).inner_html if (xml).at(:name)
60
+ name = xml['name'] if name.nil? && xml['name']
61
+
62
+ track = Track.new(artist, name)
63
+ track.load_info(xml)
64
+ track
65
+ end
66
+
67
+ def love(artist, track, session_key)
68
+ doc = Hpricot::XML(Track.connection.post("track.love", true, {:track => track, :artist => artist, :sk => session_key}))
69
+ doc.at("lfm")["status"]
70
+ end
71
+
72
+ # Scrobble a song
73
+ #
74
+ # Possible parameters:
75
+ # session_key (required) : the session key you got during authentification
76
+ # track (required) : name of the track
77
+ # artist (required) : name of the artist of the track
78
+ # time (required) : a time object set to the time the track started playing
79
+ # album : Name of the album
80
+ # albumArtist : Name of the album artist if artist differs
81
+ # trackNumber : Number of the track
82
+ # mbid : MusicBrainz ID of the track
83
+ # duration : track length
84
+ def scrobble(params = {})
85
+ if params[:session_key].blank? || params[:track].blank? || params[:time].nil? || params[:artist].blank?
86
+ raise ArgumentError, "Missing required argument"
87
+ end
88
+
89
+ query = {
90
+ :sk => params[:session_key],
91
+ "track[0]" => params[:track],
92
+ "timestamp[0]"=> params[:time].utc.to_i,
93
+ "artist[0]" => params[:artist]
94
+ }
95
+
96
+ query["album[0]"] = params[:album] if !params[:album].blank?
97
+ query["albumArtist[0]"] = params[:albumArtist] if !params[:albumArtist].blank?
98
+ query["trackNumber[0]"] = params[:trackNumber] if !params[:trackNumber].blank?
99
+ query["mbid[0]"] = params[:mbid] if !params[:mbid].blank?
100
+ query["duration[0]"] = params[:duration] if !params[:duration].blank?
101
+
102
+ doc = Hpricot::XML(Track.connection.post("track.scrobble", true, query))
103
+
104
+ if doc.at("lfm")["status"] == "failed"
105
+ case doc.at("lfm").at("error")["code"].to_i
106
+ when 9
107
+ raise BadSessionError, doc.at("lfm").at("error").inner_html
108
+ when 11, 16
109
+ raise UnavailableError, doc.at("lfm").at("error").inner_html
110
+ else
111
+ raise RequestFailedError, doc.at("lfm").at("error").inner_html
112
+ end
113
+ end
114
+
115
+ doc.at("lfm")["status"]
116
+ end
117
+
118
+ # Update the current playing song
119
+ #
120
+ # Possible parameters:
121
+ # session_key (required) : the session key you got during authentification
122
+ # track (required) : name of the track
123
+ # artist (required) : name of the artist of the track
124
+ # album : Name of the album
125
+ # albumArtist : Name of the album artist if artist differs
126
+ # trackNumber : Number of the track
127
+ # mbid : MusicBrainz ID of the track
128
+ # duration : track length
129
+ def updateNowPlaying(params = {})
130
+ if params[:session_key].blank? || params[:track].blank? || params[:artist].blank?
131
+ raise ArgumentError, "Missing required argument"
132
+ end
133
+
134
+ query = {
135
+ :sk => params[:session_key],
136
+ "track" => params[:track],
137
+ "artist" => params[:artist]
138
+ }
139
+
140
+ query["album"] = params[:album] if !params[:album].blank?
141
+ query["albumArtist"] = params[:albumArtist] if !params[:albumArtist].blank?
142
+ query["trackNumber"] = params[:trackNumber] if !params[:trackNumber].blank?
143
+ query["mbid"] = params[:mbid] if !params[:mbid].blank?
144
+ query["duration"] = params[:duration] if !params[:duration].blank?
145
+
146
+ doc = Hpricot::XML(Track.connection.post("track.updateNowPlaying", true, query))
147
+
148
+ if doc.at("lfm")["status"] == "failed"
149
+ case doc.at("lfm").at("error")["code"].to_i
150
+ when 9
151
+ raise BadSessionError, doc.at("lfm").at("error").inner_html
152
+ when 11, 16
153
+ raise UnavailableError, doc.at("lfm").at("error").inner_html
154
+ else
155
+ raise RequestFailedError, doc.at("lfm").at("error").inner_html
156
+ end
157
+ end
158
+
159
+ doc.at("lfm")["status"]
160
+ end
161
+
162
+ end
163
+
164
+ def initialize(artist, name, o={})
165
+ raise ArgumentError, "Artist is required" if artist.blank?
166
+ raise ArgumentError, "Name is required" if name.blank?
167
+ @artist = artist
168
+ @name = name
169
+
170
+ options = {:include_info => false}.merge(o)
171
+ load_info if options[:include_info]
172
+ end
173
+
174
+ def load_info(xml=nil)
175
+ unless xml
176
+ doc = self.class.fetch_and_parse("track.getInfo", {:artist => @artist, :track => @name})
177
+ xml = (doc / :track).first
178
+ end
179
+
180
+ return self if xml.nil?
181
+
182
+ self.artist_mbid = (xml).at(:artist)['mbid'] if (xml).at(:artist) && (xml).at(:artist)['mbid']
183
+ self.artist_mbid = (xml).at(:artist).at(:mbid).inner_html if artist_mbid.nil? && (xml).at(:artist) && (xml).at(:artist).at(:mbid)
184
+ self.mbid = (xml).at(:mbid).inner_html if (xml).at(:mbid)
185
+ self.playcount = (xml).at(:playcount).inner_html if (xml).at(:playcount)
186
+ self.chartposition = self.rank = xml['rank'] if xml['rank']
187
+ self.url = Base.fix_url((xml).at(:url).inner_html) if (xml).at(:url)
188
+ self.streamable = (xml).at(:track)['streamable'] if (xml).at(:track) && (xml).at(:track)['streamable']
189
+ self.streamable = (xml).at(:streamable).inner_html == '1' ? 'yes' : 'no' if streamable.nil? && (xml).at(:streamable)
190
+ self.duration = (xml).at(:duration).inner_html.to_i if (xml).at(:duration)
191
+
192
+ self.count = xml['count'] if xml['count']
193
+ self.album = (xml).at(:album).inner_html if (xml).at(:album)
194
+ self.album_mbid = (xml).at(:album)['mbid'] if (xml).at(:album) && (xml).at(:album)['mbid']
195
+ self.date = Base.parse_time((xml).at(:date).inner_html) if (xml).at(:date)
196
+ self.date_uts = (xml).at(:date)['uts'] if (xml).at(:date) && (xml).at(:date)['uts']
197
+
198
+ if wiki_xml = xml.at(:wiki)
199
+ self.summary = wiki_xml.at(:summary).to_plain_text if wiki_xml.at(:summary)
200
+ self.content = wiki_xml.at(:content).to_plain_text if wiki_xml.at(:content)
201
+ end
202
+
203
+ self.images = {}
204
+ (xml/'image').each {|image|
205
+ self.images[image['size']] = image.inner_html if self.images[image['size']].nil?
206
+ }
207
+
208
+ self.thumbnail = images['small']
209
+ self.image = images['medium']
210
+
211
+ self
212
+ end
213
+
214
+ def albums(force=false)
215
+ get_instance("track.getInfo", :albums, :album, {:track => @name, :artist => @artist}, force)
216
+ end
217
+
218
+ def fans(force=false)
219
+ get_instance("track.getTopFans", :fans, :user, {:track => @name, :artist => @artist}, force)
220
+ end
221
+
222
+ def tags(force=false)
223
+ get_instance("track.getTopTags", :tags, :tag, {:track => @name, :artist => @artist}, force)
224
+ end
225
+
226
+ # The session_key is returned by auth.session.key
227
+ def love(session_key)
228
+ Track.love(@artist, @name, session_key)
229
+ end
230
+
231
+ # scrobble this track
232
+ # time : a time object set to the time the track started playing
233
+ # session_key: the session key you got during authentification
234
+ def scrobble(time, session_key)
235
+ Track.scrobble({
236
+ :session_key => session_key,
237
+ :time => time,
238
+ :track => @name,
239
+ :artist => @artist,
240
+ :album => @album,
241
+ :mbid => @mbid
242
+ })
243
+ end
244
+
245
+ # inform last.fm that this track is currently playing
246
+ # time : a time object set to the time the track started playing
247
+ # session_key: the session key you got during authentification
248
+ def updateNowPlaying(time, session_key)
249
+ Track.updateNowPlaying({
250
+ :session_key => session_key,
251
+ :time => time,
252
+ :track => @name,
253
+ :artist => @artist,
254
+ :album => @album,
255
+ :mbid => @mbid
256
+ })
257
+ end
258
+
259
+ end
260
+ end
@@ -0,0 +1,200 @@
1
+ # Probably the most common use of this lib would be to get your most recent tracks or your top tracks. Below are some code samples.
2
+ # user = Rockstar::User.new('jnunemaker')
3
+ #
4
+ # puts "#{user.username}'s Recent Tracks"
5
+ # puts "=" * (user.username.length + 16)
6
+ # user.recent_tracks.each { |t| puts t.name }
7
+ #
8
+ # puts
9
+ # puts
10
+ #
11
+ # puts "#{user.username}'s Top Tracks"
12
+ # puts "=" * (user.username.length + 13)
13
+ # user.top_tracks.each { |t| puts "(#{t.playcount}) #{t.name}" }
14
+ #
15
+ # Which would output something like:
16
+ #
17
+ # jnunemaker's Recent Tracks
18
+ # ==========================
19
+ # Everything You Want
20
+ # You're a God
21
+ # Bitter Sweet Symphony [Original Version]
22
+ # Lord I Guess I'll Never Know
23
+ # Country Song
24
+ # Bitter Sweet Symphony (Radio Edit)
25
+ #
26
+ #
27
+ # jnunemaker's Top Tracks
28
+ # =======================
29
+ # (62) Probably Wouldn't Be This Way
30
+ # (55) Not Ready To Make Nice
31
+ # (45) Easy Silence
32
+ # (43) Song 2
33
+ # (40) Everybody Knows
34
+ # (39) Before He Cheats
35
+ # (39) Something's Gotta Give
36
+ # (38) Hips Don't Lie (featuring Wyclef Jean)
37
+ # (37) Unwritten
38
+ # (37) Move Along
39
+ # (37) Dance, Dance
40
+ # (36) We Belong Together
41
+ # (36) Jesus, Take the Wheel
42
+ # (36) Black Horse and the Cherry Tree (radio version)
43
+ # (35) Photograph
44
+ # (35) You're Beautiful
45
+ # (35) Walk Away
46
+ # (34) Stickwitu
47
+ module Rockstar
48
+ class User < Base
49
+ # attributes needed to initialize
50
+ attr_reader :username, :period
51
+
52
+ # profile attributes
53
+ attr_accessor :id, :cluster, :url, :realname, :mbox_sha1sum, :registered
54
+ attr_accessor :registered_unixtime, :age, :gender, :country, :playcount, :avatar, :realname, :images
55
+
56
+ # neighbor attributes
57
+ attr_accessor :match
58
+
59
+ # track fans attributes
60
+ attr_accessor :weight
61
+
62
+ class << self
63
+ def new_from_xml(xml, doc=nil)
64
+ u = User.new((xml).at(:name).inner_html)
65
+ u.url = Base.fix_url((xml).at(:url).inner_html) if (xml).at(:url)
66
+
67
+ u.images = {}
68
+ (xml/'image').each {|image|
69
+ u.images[image['size']] = image.inner_html if u.images[image['size']].nil?
70
+ }
71
+
72
+ u.avatar = u.images['small']
73
+
74
+ u.weight = (xml).at(:weight).inner_html if (xml).at(:weight)
75
+ u.match = (xml).at(:match).inner_html if (xml).at(:match)
76
+ u.realname= (xml).at(:realname).inner_html if (xml).at(:realname)
77
+ u
78
+ end
79
+
80
+ def find(*args)
81
+ options = {:include_profile => false}
82
+ options.merge!(args.pop) if args.last.is_a?(Hash)
83
+ users = args.flatten.inject([]) { |users, u| users << User.new(u, options); users }
84
+ users.length == 1 ? users.pop : users
85
+ end
86
+ end
87
+
88
+ def initialize(username, o={})
89
+ options = {:include_profile => false, :period => 'overall'}.merge(o)
90
+ raise ArgumentError if username.blank?
91
+ @username = username
92
+ @period = options[:period]
93
+ load_profile() if options[:include_profile]
94
+ end
95
+
96
+ def current_events(format=:ics)
97
+ warn "[DEPRECATION] `current_events` is deprecated. The current api doesn't offer ics/ical formatted data."
98
+ end
99
+
100
+ def friends_events(format=:ics)
101
+ warn "[DEPRECATION] `friends_events` is deprecated. The current api doesn't offer ics/ical formatted data."
102
+ end
103
+
104
+ def recommended_events(format=:ics)
105
+ warn "[DEPRECATION] `recommended_events` is deprecated. The current api doesn't offer ics/ical formatted data."
106
+ end
107
+
108
+ def load_profile
109
+ doc = self.class.fetch_and_parse("user.getInfo", {:user => @username})
110
+ @id = (doc).at(:id).inner_html
111
+ @url = Base.fix_url((doc).at(:url).inner_html)
112
+ @realname = (doc).at(:realname).inner_html
113
+ @registered = (doc).at(:registered).inner_html
114
+ @registered_unixtime = (doc).at(:registered)['unixtime']
115
+ @age = (doc).at(:age).inner_html
116
+ @gender = (doc).at(:gender).inner_html
117
+ @country = (doc).at(:country).inner_html
118
+ @playcount = (doc).at(:playcount).inner_html
119
+
120
+ @images = {}
121
+ (doc/'image').each {|image|
122
+ @images[image['size']] = image.inner_html
123
+ }
124
+
125
+ @avatar = @images["small"]
126
+ end
127
+
128
+ def top_artists(force=false)
129
+ get_instance("user.getTopArtists", :top_artists, :artist, {:user => @username, :period => @period}, force)
130
+ end
131
+
132
+ def top_albums(force=false)
133
+ get_instance("user.getTopAlbums", :top_albums, :album, {:user => @username}, force)
134
+ end
135
+
136
+ def top_tracks(force=false)
137
+ get_instance("user.getTopTracks", :top_tracks, :track, {:user => @username}, force)
138
+ end
139
+
140
+ def top_tags(force=false)
141
+ get_instance("user.getTopTags", :top_tags, :tag, {:user => @username}, force)
142
+ end
143
+
144
+ def friends(force=false)
145
+ get_instance("user.getFriends", :friends, :user, {:user => @username}, force)
146
+ end
147
+
148
+ def neighbours(force=false)
149
+ get_instance("user.getNeighbours", :neighbours, :user, {:user => @username}, force)
150
+ end
151
+
152
+ def recent_tracks(force=false)
153
+ get_instance("user.getRecentTracks", :recent_tracks, :track, {:user => @username}, force)
154
+ end
155
+
156
+ def recent_banned_tracks(force=false)
157
+ warn "[DEPRECATION] `recent_banned_tracks` is deprecated. The current api doesn't offer this function"
158
+ []
159
+ end
160
+
161
+ def recent_loved_tracks(force=false)
162
+ get_instance("user.getLovedTracks", :recent_loved_tracks, :track, {:user => @username}, force)
163
+ end
164
+
165
+ def recommendations(force=false)
166
+ warn "[DEPRECATION] `recommendations` is deprecated. Please use recommended_artists"
167
+ []
168
+ end
169
+
170
+ # The session_key is returned by auth.session.key
171
+ def recommended_artists(session_key, force=false)
172
+ get_instance("user.getRecommendedArtists", :recommendations, :artist, {:user => @username, :sk => session_key}, force)
173
+ end
174
+
175
+ def charts(force=false)
176
+ get_instance("user.getWeeklyChartList", :charts, :chart, {:user => @username}, force)
177
+ end
178
+
179
+ def weekly_artist_chart(from=nil, to=nil)
180
+ doc = self.class.fetch_and_parse("user.getWeeklyArtistChart", {:user => @username, :from => from, :to => to})
181
+ (doc/:artist).inject([]) { |elements, el| elements << Artist.new_from_xml(el); elements }
182
+ end
183
+
184
+ def weekly_album_chart(from=nil, to=nil)
185
+ doc = self.class.fetch_and_parse("user.getWeeklyAlbumChart", {:user => @username, :from => from, :to => to})
186
+ (doc/:album).inject([]) { |elements, el| elements << Album.new_from_xml(el); elements }
187
+ end
188
+
189
+ def weekly_track_chart(from=nil, to=nil)
190
+ doc = self.class.fetch_and_parse("user.getWeeklyTrackChart", {:user => @username, :from => from, :to => to})
191
+ (doc/:track).inject([]) { |elements, el| elements << Track.new_from_xml(el); elements }
192
+ end
193
+
194
+ # Get the recommendated events for the user, auth.session.key needed.
195
+ def events(session_key, force = false)
196
+ get_instance("user.getEvents", :events, :event, {:user => @username, :sk => session_key}, force)
197
+ end
198
+
199
+ end
200
+ end