rockstar 0.3.0

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 (77) hide show
  1. data/.gitignore +3 -0
  2. data/History.txt +6 -0
  3. data/MIT-LICENSE +19 -0
  4. data/Manifest +72 -0
  5. data/README.rdoc +140 -0
  6. data/Rakefile +21 -0
  7. data/VERSION +1 -0
  8. data/examples/.gitignore +1 -0
  9. data/examples/album.rb +16 -0
  10. data/examples/artist.rb +17 -0
  11. data/examples/lastfm.yml_example +3 -0
  12. data/examples/scrobble.rb +55 -0
  13. data/examples/tag.rb +20 -0
  14. data/examples/track.rb +14 -0
  15. data/examples/user.rb +18 -0
  16. data/lib/rockstar.rb +39 -0
  17. data/lib/rockstar/album.rb +108 -0
  18. data/lib/rockstar/artist.rb +135 -0
  19. data/lib/rockstar/auth.rb +21 -0
  20. data/lib/rockstar/base.rb +37 -0
  21. data/lib/rockstar/chart.rb +31 -0
  22. data/lib/rockstar/playing.rb +49 -0
  23. data/lib/rockstar/rest.rb +66 -0
  24. data/lib/rockstar/scrobble.rb +67 -0
  25. data/lib/rockstar/session.rb +19 -0
  26. data/lib/rockstar/simpleauth.rb +62 -0
  27. data/lib/rockstar/tag.rb +100 -0
  28. data/lib/rockstar/tokenauth.rb +84 -0
  29. data/lib/rockstar/track.rb +103 -0
  30. data/lib/rockstar/user.rb +194 -0
  31. data/lib/rockstar/version.rb +3 -0
  32. data/rockstar.gemspec +138 -0
  33. data/test/fixtures/xml/album/getinfo_album_Some_Hearts_artist_Carrie_Underwood.xml +63 -0
  34. data/test/fixtures/xml/artist/getsimilar_artist_Metallica.xml +1203 -0
  35. data/test/fixtures/xml/artist/gettopalbums_artist_Metallica.xml +704 -0
  36. data/test/fixtures/xml/artist/gettopfans_artist_Metallica.xml +504 -0
  37. data/test/fixtures/xml/artist/gettoptags_artist_Metallica.xml +403 -0
  38. data/test/fixtures/xml/artist/gettoptracks_artist_Metallica.xml +800 -0
  39. data/test/fixtures/xml/tag/gettopalbums_tag_rock.xml +654 -0
  40. data/test/fixtures/xml/tag/gettopartists_tag_rock.xml +504 -0
  41. data/test/fixtures/xml/tag/gettoptags.xml +1253 -0
  42. data/test/fixtures/xml/tag/gettoptracks_tag_rock.xml +704 -0
  43. data/test/fixtures/xml/track/gettopfans_artist_Carrie_Underwood_track_Before_He_Cheats.xml +504 -0
  44. data/test/fixtures/xml/track/gettoptags_artist_Carrie_Underwood_track_Before_He_Cheats.xml +403 -0
  45. data/test/fixtures/xml/track/love_artist_Carrie_Underwood_sk_tag_track_Before_He_Cheats.xml +2 -0
  46. data/test/fixtures/xml/user/getfriends_user_jnunemaker.xml +173 -0
  47. data/test/fixtures/xml/user/getinfo_user_jnunemaker.xml +22 -0
  48. data/test/fixtures/xml/user/getinfo_user_oaknd1.xml +22 -0
  49. data/test/fixtures/xml/user/getinfo_user_wharle.xml +22 -0
  50. data/test/fixtures/xml/user/getlovedtracks_user_jnunemaker.xml +775 -0
  51. data/test/fixtures/xml/user/getneighbours_user_jnunemaker.xml +503 -0
  52. data/test/fixtures/xml/user/getrecenttracks_user_jnunemaker.xml +133 -0
  53. data/test/fixtures/xml/user/getrecommendedartists_sk_token_user_jnunemaker.xml +553 -0
  54. data/test/fixtures/xml/user/gettopalbums_user_jnunemaker.xml +704 -0
  55. data/test/fixtures/xml/user/gettopartists_user_jnunemaker.xml +554 -0
  56. data/test/fixtures/xml/user/gettoptags_user_jnunemaker.xml +63 -0
  57. data/test/fixtures/xml/user/gettoptracks_user_jnunemaker.xml +750 -0
  58. data/test/fixtures/xml/user/getweeklyalbumchart_from_1138536002_to_1139140802_user_jnunemaker.xml +143 -0
  59. data/test/fixtures/xml/user/getweeklyalbumchart_from__to__user_jnunemaker.xml +31 -0
  60. data/test/fixtures/xml/user/getweeklyartistchart_from_1138536002_to_1139140802_user_jnunemaker.xml +201 -0
  61. data/test/fixtures/xml/user/getweeklyartistchart_from__to__user_jnunemaker.xml +21 -0
  62. data/test/fixtures/xml/user/getweeklychartlist_user_jnunemaker.xml +232 -0
  63. data/test/fixtures/xml/user/getweeklytrackchart_from_1138536002_to_1139140802_user_jnunemaker.xml +883 -0
  64. data/test/fixtures/xml/user/getweeklytrackchart_from__to__user_jnunemaker.xml +423 -0
  65. data/test/mocks/rest.rb +61 -0
  66. data/test/test_helper.rb +17 -0
  67. data/test/unit/test_album.rb +67 -0
  68. data/test/unit/test_artist.rb +69 -0
  69. data/test/unit/test_chart.rb +35 -0
  70. data/test/unit/test_playing.rb +53 -0
  71. data/test/unit/test_scrobble.rb +69 -0
  72. data/test/unit/test_simpleauth.rb +45 -0
  73. data/test/unit/test_tag.rb +57 -0
  74. data/test/unit/test_tokenauth.rb +45 -0
  75. data/test/unit/test_track.rb +44 -0
  76. data/test/unit/test_user.rb +252 -0
  77. metadata +190 -0
@@ -0,0 +1,67 @@
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
+ query = { :s => @session_id,
43
+ 'a[0]' => @artist,
44
+ 't[0]' => @track,
45
+ 'i[0]' => @time.utc.to_i,
46
+ 'o[0]' => @source,
47
+ 'r[0]' => @rating,
48
+ 'l[0]' => @length,
49
+ 'b[0]' => @album,
50
+ 'n[0]' => @track_number,
51
+ 'm[0]' => @mb_track_id }
52
+
53
+ @status = @connection.post('', false, query)
54
+
55
+ case @status
56
+ when /OK/
57
+
58
+ when /BADSESSION/
59
+ raise BadSessionError # rerun Rockstar::SimpleAuth#handshake!
60
+ when /FAILED/
61
+ raise RequestFailedError, @status
62
+ else
63
+ raise RequestFailedError
64
+ end
65
+ end
66
+ end
67
+ 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 = 'rbs' # 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
@@ -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
+ # new 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 = 'rbs' # 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,103 @@
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
+ module Rockstar
37
+ class Track < Base
38
+ attr_accessor :artist, :artist_mbid, :name, :mbid, :playcount, :rank, :url
39
+ attr_accessor :streamable, :album, :album_mbid, :date, :date_uts
40
+
41
+ # only seems to be used on top tracks for tag
42
+ attr_accessor :count, :thumbnail, :image, :images
43
+
44
+ # for weekly top tracks
45
+ attr_accessor :chartposition
46
+
47
+ class << self
48
+ def new_from_xml(xml, doc=nil)
49
+ artist = (xml).at(:artist)['name'] if (xml).at(:artist) && !(xml).at(:artist)['name'].nil?
50
+ artist = (xml).at(:artist).at(:name).inner_html if artist.nil? && (xml).at(:artist) && (xml).at(:artist).at(:name)
51
+ artist = (xml).at(:artist).inner_html if artist.nil? && (xml).at(:artist)
52
+ artist = doc.root['artist'] if artist.nil? && doc.root['artist']
53
+ name = (xml).at(:name).inner_html if (xml).at(:name)
54
+ name = xml['name'] if name.nil? && xml['name']
55
+ t = Track.new(artist, name)
56
+ t.artist_mbid = (xml).at(:artist)['mbid'] if (xml).at(:artist) && (xml).at(:artist)['mbid']
57
+ t.artist_mbid = (xml).at(:artist).at(:mbid).inner_html if t.artist_mbid.nil? && (xml).at(:artist) && (xml).at(:artist).at(:mbid)
58
+ t.mbid = (xml).at(:mbid).inner_html if (xml).at(:mbid)
59
+ t.playcount = (xml).at(:playcount).inner_html if (xml).at(:playcount)
60
+ t.chartposition = t.rank = xml['rank'] if xml['rank']
61
+ t.url = Base.fix_url((xml).at(:url).inner_html) if (xml).at(:url)
62
+ t.streamable = (xml).at(:track)['streamable'] if (xml).at(:track) && (xml).at(:track)['streamable']
63
+ t.streamable = (xml).at(:streamable).inner_html == '1' ? 'yes' : 'no' if t.streamable.nil? && (xml).at(:streamable)
64
+
65
+ t.count = xml['count'] if xml['count']
66
+ t.album = (xml).at(:album).inner_html if (xml).at(:album)
67
+ t.album_mbid = (xml).at(:album)['mbid'] if (xml).at(:album) && (xml).at(:album)['mbid']
68
+ t.date = Time.parse((xml).at(:date).inner_html) if (xml).at(:date)
69
+ t.date_uts = (xml).at(:date)['uts'] if (xml).at(:date) && (xml).at(:date)['uts']
70
+
71
+ t.images = {}
72
+ (xml/'image').each {|image|
73
+ t.images[image['size']] = image.inner_html
74
+ }
75
+
76
+ t.thumbnail = t.images['small']
77
+ t.image = t.images['medium']
78
+ t
79
+ end
80
+ end
81
+
82
+ def initialize(artist, name)
83
+ raise ArgumentError, "Artist is required" if artist.blank?
84
+ raise ArgumentError, "Name is required" if name.blank?
85
+ @artist = artist
86
+ @name = name
87
+ end
88
+
89
+ def fans(force=false)
90
+ get_instance("track.getTopFans", :fans, :user, {:track => @name, :artist => @artist}, force)
91
+ end
92
+
93
+ def tags(force=false)
94
+ get_instance("track.getTopTags", :tags, :tag, {:track => @name, :artist => @artist}, force)
95
+ end
96
+
97
+ # The session_key is returned by auth.session.key
98
+ def love(session_key)
99
+ doc = Hpricot::XML(self.class.connection.post("track.love", true, {:track => @name, :artist => @artist, :sk => session_key}))
100
+ doc.at("lfm")["status"]
101
+ end
102
+ end
103
+ end
@@ -0,0 +1,194 @@
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
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
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}.merge(o)
90
+ raise ArgumentError if username.blank?
91
+ @username = username
92
+ load_profile() if options[:include_profile]
93
+ end
94
+
95
+ def current_events(format=:ics)
96
+ warn "[DEPRECATION] `current_events` is deprecated. The current api doesn't offer ics/ical formatted data."
97
+ end
98
+
99
+ def friends_events(format=:ics)
100
+ warn "[DEPRECATION] `friends_events` is deprecated. The current api doesn't offer ics/ical formatted data."
101
+ end
102
+
103
+ def recommended_events(format=:ics)
104
+ warn "[DEPRECATION] `recommended_events` is deprecated. The current api doesn't offer ics/ical formatted data."
105
+ end
106
+
107
+ def load_profile
108
+ doc = self.class.fetch_and_parse("user.getInfo", {:user => @username})
109
+ @id = (doc).at(:id).inner_html
110
+ @url = Base.fix_url((doc).at(:url).inner_html)
111
+ @realname = (doc).at(:realname).inner_html
112
+ @registered = (doc).at(:registered).inner_html
113
+ @registered_unixtime = (doc).at(:registered)['unixtime']
114
+ @age = (doc).at(:age).inner_html
115
+ @gender = (doc).at(:gender).inner_html
116
+ @country = (doc).at(:country).inner_html
117
+ @playcount = (doc).at(:playcount).inner_html
118
+
119
+ @images = {}
120
+ (doc/'image').each {|image|
121
+ @images[image['size']] = image.inner_html
122
+ }
123
+
124
+ @avatar = @images["small"]
125
+ end
126
+
127
+ def top_artists(force=false)
128
+ get_instance("user.getTopArtists", :top_artists, :artist, {:user => @username}, force)
129
+ end
130
+
131
+ def top_albums(force=false)
132
+ get_instance("user.getTopAlbums", :top_albums, :album, {:user => @username}, force)
133
+ end
134
+
135
+ def top_tracks(force=false)
136
+ get_instance("user.getTopTracks", :top_tracks, :track, {:user => @username}, force)
137
+ end
138
+
139
+ def top_tags(force=false)
140
+ get_instance("user.getTopTags", :top_tags, :tag, {:user => @username}, force)
141
+ end
142
+
143
+ def friends(force=false)
144
+ get_instance("user.getFriends", :friends, :user, {:user => @username}, force)
145
+ end
146
+
147
+ def neighbours(force=false)
148
+ get_instance("user.getNeighbours", :neighbours, :user, {:user => @username}, force)
149
+ end
150
+
151
+ def recent_tracks(force=false)
152
+ get_instance("user.getRecentTracks", :recent_tracks, :track, {:user => @username}, force)
153
+ end
154
+
155
+ def recent_banned_tracks(force=false)
156
+ warn "[DEPRECATION] `recent_banned_tracks` is deprecated. The current api doesn't offer this function"
157
+ []
158
+ end
159
+
160
+ def recent_loved_tracks(force=false)
161
+ get_instance("user.getLovedTracks", :recent_loved_tracks, :track, {:user => @username}, force)
162
+ end
163
+
164
+ def recommendations(force=false)
165
+ warn "[DEPRECATION] `recommendations` is deprecated. Please use recommended_artists"
166
+ []
167
+ end
168
+
169
+ # The session_key is returned by auth.session.key
170
+ def recommended_artists(session_key, force=false)
171
+ get_instance("user.getRecommendedArtists", :recommendations, :artist, {:user => @username, :sk => session_key}, force)
172
+ end
173
+
174
+ def charts(force=false)
175
+ get_instance("user.getWeeklyChartList", :charts, :chart, {:user => @username}, force)
176
+ end
177
+
178
+ def weekly_artist_chart(from=nil, to=nil)
179
+ doc = self.class.fetch_and_parse("user.getWeeklyArtistChart", {:user => @username, :from => from, :to => to})
180
+ (doc/:artist).inject([]) { |elements, el| elements << Artist.new_from_xml(el); elements }
181
+ end
182
+
183
+ def weekly_album_chart(from=nil, to=nil)
184
+ doc = self.class.fetch_and_parse("user.getWeeklyAlbumChart", {:user => @username, :from => from, :to => to})
185
+ (doc/:album).inject([]) { |elements, el| elements << Album.new_from_xml(el); elements }
186
+ end
187
+
188
+ def weekly_track_chart(from=nil, to=nil)
189
+ doc = self.class.fetch_and_parse("user.getWeeklyTrackChart", {:user => @username, :from => from, :to => to})
190
+ (doc/:track).inject([]) { |elements, el| elements << Track.new_from_xml(el); elements }
191
+ end
192
+
193
+ end
194
+ end