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.
- data/.travis.yml +6 -0
- data/Gemfile +11 -0
- data/Gemfile.lock +22 -0
- data/History.txt +6 -0
- data/MIT-LICENSE +19 -0
- data/Manifest +72 -0
- data/README.md +135 -0
- data/Rakefile +34 -0
- data/VERSION +1 -0
- data/examples/.gitignore +1 -0
- data/examples/album.rb +16 -0
- data/examples/artist.rb +23 -0
- data/examples/geo.rb +9 -0
- data/examples/lastfm.yml_example +3 -0
- data/examples/scrobble.rb +45 -0
- data/examples/tag.rb +20 -0
- data/examples/track.rb +14 -0
- data/examples/user.rb +18 -0
- data/lib/rockstar.rb +50 -0
- data/lib/rockstar/album.rb +109 -0
- data/lib/rockstar/artist.rb +182 -0
- data/lib/rockstar/auth.rb +21 -0
- data/lib/rockstar/base.rb +48 -0
- data/lib/rockstar/chart.rb +31 -0
- data/lib/rockstar/event.rb +73 -0
- data/lib/rockstar/geo.rb +22 -0
- data/lib/rockstar/metro.rb +26 -0
- data/lib/rockstar/playing.rb +50 -0
- data/lib/rockstar/rest.rb +66 -0
- data/lib/rockstar/scrobble.rb +68 -0
- data/lib/rockstar/session.rb +19 -0
- data/lib/rockstar/simpleauth.rb +62 -0
- data/lib/rockstar/tag.rb +100 -0
- data/lib/rockstar/tokenauth.rb +84 -0
- data/lib/rockstar/track.rb +260 -0
- data/lib/rockstar/user.rb +200 -0
- data/lib/rockstar/venue.rb +59 -0
- data/lib/rockstar/version.rb +3 -0
- data/rockstar.gemspec +174 -0
- data/test/fixtures/xml/album/getinfo_album_Radio_Retalation_artist_Thievery_Corporation.xml +21 -0
- data/test/fixtures/xml/album/getinfo_album_Some_Hearts_artist_Carrie_Underwood.xml +63 -0
- data/test/fixtures/xml/artist/getevents_artist_Metallica.xml +1064 -0
- data/test/fixtures/xml/artist/getimages_artist_Metallica_page_2.xml +1074 -0
- data/test/fixtures/xml/artist/getinfo_artist_Metallica.xml +115 -0
- data/test/fixtures/xml/artist/getsimilar_artist_Metallica.xml +1203 -0
- data/test/fixtures/xml/artist/gettopalbums_artist_Metallica.xml +704 -0
- data/test/fixtures/xml/artist/gettopfans_artist_Metallica.xml +504 -0
- data/test/fixtures/xml/artist/gettoptags_artist_Metallica.xml +403 -0
- data/test/fixtures/xml/artist/gettoptracks_artist_Metallica.xml +800 -0
- data/test/fixtures/xml/geo/getevents_location_london.xml +531 -0
- data/test/fixtures/xml/geo/getmetros_country_germany.xml +44 -0
- data/test/fixtures/xml/tag/gettopalbums_tag_rock.xml +654 -0
- data/test/fixtures/xml/tag/gettopartists_tag_rock.xml +504 -0
- data/test/fixtures/xml/tag/gettoptags.xml +1253 -0
- data/test/fixtures/xml/tag/gettoptracks_tag_rock.xml +704 -0
- data/test/fixtures/xml/track/getinfo_artist_Carrie_Underwood_track_Before_He_Cheats.xml +55 -0
- data/test/fixtures/xml/track/gettopfans_artist_Carrie_Underwood_track_Before_He_Cheats.xml +504 -0
- data/test/fixtures/xml/track/gettoptags_artist_Carrie_Underwood_track_Before_He_Cheats.xml +403 -0
- data/test/fixtures/xml/track/love_artist_Carrie_Underwood_sk_tag_track_Before_He_Cheats.xml +2 -0
- data/test/fixtures/xml/track/updatenowplaying_artist_Carrie_Underwood_sk_tag_track_Before_He_Cheats.xml +10 -0
- data/test/fixtures/xml/user/getevents_sk_token_user_bodot.xml +513 -0
- data/test/fixtures/xml/user/getfriends_user_jnunemaker.xml +173 -0
- data/test/fixtures/xml/user/getinfo_user_jnunemaker.xml +22 -0
- data/test/fixtures/xml/user/getinfo_user_oaknd1.xml +22 -0
- data/test/fixtures/xml/user/getinfo_user_wharle.xml +22 -0
- data/test/fixtures/xml/user/getlovedtracks_user_jnunemaker.xml +775 -0
- data/test/fixtures/xml/user/getneighbours_user_jnunemaker.xml +503 -0
- data/test/fixtures/xml/user/getrecenttracks_user_jnunemaker.xml +133 -0
- data/test/fixtures/xml/user/getrecommendedartists_sk_token_user_jnunemaker.xml +553 -0
- data/test/fixtures/xml/user/gettopalbums_user_jnunemaker.xml +704 -0
- data/test/fixtures/xml/user/gettopartists_period_overall_user_jnunemaker.xml +554 -0
- data/test/fixtures/xml/user/gettoptags_user_jnunemaker.xml +63 -0
- data/test/fixtures/xml/user/gettoptracks_user_jnunemaker.xml +750 -0
- data/test/fixtures/xml/user/getweeklyalbumchart_from_1138536002_to_1139140802_user_jnunemaker.xml +143 -0
- data/test/fixtures/xml/user/getweeklyalbumchart_from__to__user_jnunemaker.xml +31 -0
- data/test/fixtures/xml/user/getweeklyartistchart_from_1138536002_to_1139140802_user_jnunemaker.xml +201 -0
- data/test/fixtures/xml/user/getweeklyartistchart_from__to__user_jnunemaker.xml +21 -0
- data/test/fixtures/xml/user/getweeklychartlist_user_jnunemaker.xml +232 -0
- data/test/fixtures/xml/user/getweeklytrackchart_from_1138536002_to_1139140802_user_jnunemaker.xml +883 -0
- data/test/fixtures/xml/user/getweeklytrackchart_from__to__user_jnunemaker.xml +423 -0
- data/test/fixtures/xml/venue/getevents_venue_8807850.xml +280 -0
- data/test/fixtures/xml/venue/search_country__limit__page__venue_country_DE_venue_cotton.xml +72 -0
- data/test/mocks/rest.rb +67 -0
- data/test/test_helper.rb +18 -0
- data/test/unit/test_album.rb +76 -0
- data/test/unit/test_artist.rb +102 -0
- data/test/unit/test_chart.rb +35 -0
- data/test/unit/test_geo.rb +25 -0
- data/test/unit/test_playing.rb +53 -0
- data/test/unit/test_scrobble.rb +69 -0
- data/test/unit/test_simpleauth.rb +45 -0
- data/test/unit/test_tag.rb +57 -0
- data/test/unit/test_tokenauth.rb +45 -0
- data/test/unit/test_track.rb +82 -0
- data/test/unit/test_user.rb +299 -0
- data/test/unit/test_venue.rb +20 -0
- 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}&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
|