rscrobbler 0.2.2 → 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.
- checksums.yaml +15 -0
- data/lib/lastfm/album.rb +197 -55
- data/lib/lastfm/artist.rb +291 -48
- data/lib/lastfm/auth.rb +33 -0
- data/lib/lastfm/buylink.rb +34 -34
- data/lib/lastfm/chart.rb +61 -0
- data/lib/lastfm/event.rb +128 -62
- data/lib/lastfm/geo.rb +123 -0
- data/lib/lastfm/group.rb +67 -0
- data/lib/lastfm/library.rb +115 -0
- data/lib/lastfm/playlist.rb +38 -0
- data/lib/lastfm/radio.rb +39 -0
- data/lib/lastfm/shout.rb +20 -20
- data/lib/lastfm/struct.rb +59 -40
- data/lib/lastfm/tag.rb +144 -29
- data/lib/lastfm/tasteometer.rb +35 -0
- data/lib/lastfm/track.rb +324 -57
- data/lib/lastfm/user.rb +264 -0
- data/lib/lastfm/venue.rb +60 -25
- data/lib/lastfm/wiki.rb +20 -20
- data/lib/rscrobbler.rb +207 -214
- data/test/test_album.rb +35 -35
- metadata +20 -25
- data/lib/lastfm/api/album.rb +0 -140
- data/lib/lastfm/api/artist.rb +0 -243
- data/lib/lastfm/api/auth.rb +0 -35
- data/lib/lastfm/api/chart.rb +0 -63
- data/lib/lastfm/api/event.rb +0 -71
- data/lib/lastfm/api/geo.rb +0 -125
- data/lib/lastfm/api/group.rb +0 -69
- data/lib/lastfm/api/library.rb +0 -117
- data/lib/lastfm/api/playlist.rb +0 -40
- data/lib/lastfm/api/radio.rb +0 -41
- data/lib/lastfm/api/tag.rb +0 -120
- data/lib/lastfm/api/tasteometer.rb +0 -37
- data/lib/lastfm/api/track.rb +0 -272
- data/lib/lastfm/api/user.rb +0 -266
- data/lib/lastfm/api/venue.rb +0 -40
data/lib/lastfm/venue.rb
CHANGED
@@ -1,25 +1,60 @@
|
|
1
|
-
module LastFM
|
2
|
-
class Venue < Struct.new(:id, :name, :location, :url, :website, :phone_number, :images)
|
3
|
-
|
4
|
-
def update_from_node(node)
|
5
|
-
case node.name.to_sym
|
6
|
-
when :id
|
7
|
-
self.id = node.content.to_i
|
8
|
-
when :name
|
9
|
-
self.name = node.content
|
10
|
-
when :location
|
11
|
-
# ??? city, country, street, postalcode, geo:lat, geo:long
|
12
|
-
when :url
|
13
|
-
self.url = node.content
|
14
|
-
when :website
|
15
|
-
self.website = node.content
|
16
|
-
when :phoneNumber
|
17
|
-
self.phone_number = node.content
|
18
|
-
when :image
|
19
|
-
self.images ||= {}
|
20
|
-
self.images.merge!({node['size'].to_sym => node.content})
|
21
|
-
end
|
22
|
-
end
|
23
|
-
|
24
|
-
|
25
|
-
|
1
|
+
module LastFM
|
2
|
+
class Venue < Struct.new(:id, :name, :location, :url, :website, :phone_number, :images)
|
3
|
+
|
4
|
+
def update_from_node(node)
|
5
|
+
case node.name.to_sym
|
6
|
+
when :id
|
7
|
+
self.id = node.content.to_i
|
8
|
+
when :name
|
9
|
+
self.name = node.content
|
10
|
+
when :location
|
11
|
+
# ??? city, country, street, postalcode, geo:lat, geo:long
|
12
|
+
when :url
|
13
|
+
self.url = node.content
|
14
|
+
when :website
|
15
|
+
self.website = node.content
|
16
|
+
when :phoneNumber
|
17
|
+
self.phone_number = node.content
|
18
|
+
when :image
|
19
|
+
self.images ||= {}
|
20
|
+
self.images.merge!({node['size'].to_sym => node.content})
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
# API Methods
|
25
|
+
class << self
|
26
|
+
|
27
|
+
# Get a list of upcoming events for a venue.
|
28
|
+
#
|
29
|
+
# @option params [Fixnum, required] :venue the id for the venue to fetch event listings for
|
30
|
+
# @option params [Boolean, optional] :festivalsonly whether only festivals should be returned, or all events
|
31
|
+
# @see http://www.last.fm/api/show?service=394
|
32
|
+
def get_events( params )
|
33
|
+
LastFM.get( "venue.getEvents", params )
|
34
|
+
end
|
35
|
+
|
36
|
+
# Get a paginated list of all the events held at this venue in the past.
|
37
|
+
#
|
38
|
+
# @option params [Fixnum, required] :venue the id for the venue to fetch event listings for
|
39
|
+
# @option params [Boolean, optional] :festivalsonly whether only festivals should be returned, or all events
|
40
|
+
# @option params [Fixnum, optional] :page the page number to fetch. defaults to first page
|
41
|
+
# @option params [Fixnum, optional] :limit the number of results to fetch per page. defaults to 50
|
42
|
+
# @see http://www.last.fm/api/show?service=395
|
43
|
+
def get_past_events( params )
|
44
|
+
LastFM.get( "venue.getPastEvents", params )
|
45
|
+
end
|
46
|
+
|
47
|
+
# Search for a venue by venue name.
|
48
|
+
#
|
49
|
+
# @option params [String, required] :venue the venue name to search for
|
50
|
+
# @option params [String, optional] :country a country name used to limit results, as defined by ISO 3166-1
|
51
|
+
# @option params [Fixnum, optional] :page the page number to fetch. defaults to first page
|
52
|
+
# @option params [Fixnum, optional] :limit the number of results to fetch per page. defaults to 50
|
53
|
+
# @see http://www.last.fm/api/show?service=396
|
54
|
+
def search( params )
|
55
|
+
LastFM.get( "venue.search", params )
|
56
|
+
end
|
57
|
+
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
data/lib/lastfm/wiki.rb
CHANGED
@@ -1,20 +1,20 @@
|
|
1
|
-
module LastFM
|
2
|
-
|
3
|
-
# @attr [Time] published Date the information in this entry was published
|
4
|
-
# @attr [String] summary Short summary of the information in this entry
|
5
|
-
# @attr [String] content Full content of this entry
|
6
|
-
class Wiki < Struct.new(:published, :summary, :content)
|
7
|
-
|
8
|
-
def update_from_node(node)
|
9
|
-
case node.name.to_sym
|
10
|
-
when :published
|
11
|
-
self.published = Time.parse(node.content) rescue nil
|
12
|
-
when :summary #TODO: Remove CDATA wrapper
|
13
|
-
self.summary = node.content
|
14
|
-
when :content #TODO: Remove CDATA wrapper
|
15
|
-
self.content = node.content
|
16
|
-
end
|
17
|
-
end
|
18
|
-
|
19
|
-
end
|
20
|
-
end
|
1
|
+
module LastFM
|
2
|
+
|
3
|
+
# @attr [Time] published Date the information in this entry was published
|
4
|
+
# @attr [String] summary Short summary of the information in this entry
|
5
|
+
# @attr [String] content Full content of this entry
|
6
|
+
class Wiki < Struct.new(:published, :summary, :content)
|
7
|
+
|
8
|
+
def update_from_node(node)
|
9
|
+
case node.name.to_sym
|
10
|
+
when :published
|
11
|
+
self.published = Time.parse(node.content) rescue nil
|
12
|
+
when :summary #TODO: Remove CDATA wrapper
|
13
|
+
self.summary = node.content
|
14
|
+
when :content #TODO: Remove CDATA wrapper
|
15
|
+
self.content = node.content
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|
20
|
+
end
|
data/lib/rscrobbler.rb
CHANGED
@@ -1,214 +1,207 @@
|
|
1
|
-
require '
|
2
|
-
require '
|
3
|
-
require '
|
4
|
-
require '
|
5
|
-
require '
|
6
|
-
require '
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
require
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
#
|
51
|
-
#
|
52
|
-
#
|
53
|
-
#
|
54
|
-
#
|
55
|
-
#
|
56
|
-
#
|
57
|
-
#
|
58
|
-
#
|
59
|
-
#
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
#
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
#
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
#
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
#
|
105
|
-
#
|
106
|
-
# @
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
#
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
#
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
#
|
147
|
-
#
|
148
|
-
#
|
149
|
-
#
|
150
|
-
#
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
#
|
184
|
-
#
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
str << key << params[key]
|
209
|
-
end
|
210
|
-
Digest::MD5.hexdigest( str << api_secret )
|
211
|
-
end
|
212
|
-
|
213
|
-
end
|
214
|
-
end
|
1
|
+
require 'cgi'
|
2
|
+
require 'digest/md5'
|
3
|
+
require 'json'
|
4
|
+
require 'libxml'
|
5
|
+
require 'net/http'
|
6
|
+
require 'time'
|
7
|
+
require 'uri'
|
8
|
+
|
9
|
+
$:.unshift(File.dirname(__FILE__))
|
10
|
+
|
11
|
+
[
|
12
|
+
:struct,
|
13
|
+
:album,
|
14
|
+
:artist,
|
15
|
+
:auth,
|
16
|
+
:buylink,
|
17
|
+
:chart,
|
18
|
+
:event,
|
19
|
+
:geo,
|
20
|
+
:group,
|
21
|
+
:library,
|
22
|
+
:playlist,
|
23
|
+
:radio,
|
24
|
+
:shout,
|
25
|
+
:tag,
|
26
|
+
:tasteometer,
|
27
|
+
:track,
|
28
|
+
:user,
|
29
|
+
:venue,
|
30
|
+
:wiki
|
31
|
+
].each{|model| require "lastfm/#{model}"}
|
32
|
+
|
33
|
+
module LastFM
|
34
|
+
VERSION = '0.3.0'
|
35
|
+
|
36
|
+
HOST = 'ws.audioscrobbler.com'
|
37
|
+
API_VERSION = '2.0'
|
38
|
+
|
39
|
+
class LastFMError < StandardError; end
|
40
|
+
class AuthenticationError < StandardError; end
|
41
|
+
|
42
|
+
class << self
|
43
|
+
attr_accessor :api_key, :api_secret, :username, :auth_token, :session_key, :logger
|
44
|
+
|
45
|
+
# Configure the module and begin a session. Once established (and successfully
|
46
|
+
# executed), the module is ready to send api calls to Last.fm.
|
47
|
+
#
|
48
|
+
# @example
|
49
|
+
# LastFM.establish_session do |session|
|
50
|
+
# session.username = ...
|
51
|
+
# session.auth_token = ...
|
52
|
+
# session.api_key = ...
|
53
|
+
# session.api_secret = ...
|
54
|
+
# end
|
55
|
+
#
|
56
|
+
# @param [Block] &block block used to configure the module's attributes
|
57
|
+
# @return [String] session key if successfully connected
|
58
|
+
# @raise [AuthenticationError] if any authentication attributes are missing
|
59
|
+
# @raise [LastFMError] if the HTTP request to Last.fm returns an error
|
60
|
+
def establish_session(&block)
|
61
|
+
yield self
|
62
|
+
self.authenticate!
|
63
|
+
end
|
64
|
+
|
65
|
+
# Authenticate the service with provided login credentials. Use mobile
|
66
|
+
# authentication to avoid redirecting to the website to log in.
|
67
|
+
#
|
68
|
+
# @see http://www.last.fm/api/authspec last.fm auth spec
|
69
|
+
# @return [String] session key provided from authentication
|
70
|
+
def authenticate!
|
71
|
+
[:api_key, :api_secret, :username, :auth_token].each do |cred|
|
72
|
+
raise AuthenticationError, "Missing credential: #{cred}" unless LastFM.send(cred)
|
73
|
+
end
|
74
|
+
self.session_key = Auth.get_mobile_session( username: username, auth_token: auth_token ).find_first('session/key').content
|
75
|
+
end
|
76
|
+
|
77
|
+
# Has the service been authenticated?
|
78
|
+
#
|
79
|
+
# @return [Boolean] whether the service has been authenticated
|
80
|
+
def authenticated?
|
81
|
+
!!session_key
|
82
|
+
end
|
83
|
+
|
84
|
+
# Ensure the service has been authenticated; raise an error if it hasn't.
|
85
|
+
#
|
86
|
+
# @raise [AuthenticationError] if the service hasn't been authenticated.
|
87
|
+
def requires_authentication
|
88
|
+
raise AuthenticationError, 'LastFM Authentication Required' unless authenticated?
|
89
|
+
end
|
90
|
+
|
91
|
+
# Generate auth token from username and given password.
|
92
|
+
#
|
93
|
+
# @param [String] password password to use
|
94
|
+
# @return [String] md5 digest of the username and password
|
95
|
+
def generate_auth_token( password )
|
96
|
+
self.auth_token = Digest::MD5.hexdigest( username + Digest::MD5.hexdigest(password) )
|
97
|
+
end
|
98
|
+
|
99
|
+
# Construct an HTTP GET call from params, and load the response into a LibXML Document.
|
100
|
+
#
|
101
|
+
# @param [String] method last.fm api method to call
|
102
|
+
# @param [Boolean] secure whether to sign the request with a method signature and session key
|
103
|
+
# (one exception being auth methods, which require a method signature but no session key)
|
104
|
+
# @param [Hash] params parameters to send, excluding method, api_key, api_sig, and sk
|
105
|
+
# @return [LibXML::XML::Document] xml document of the data contained in the response
|
106
|
+
# @raise [LastFMError] if the request fails
|
107
|
+
def get( method, params = {}, secure = false )
|
108
|
+
path = generate_path(method, secure, params)
|
109
|
+
logger.debug( "Last.fm HTTP GET: #{HOST}#{path}" ) if logger
|
110
|
+
response = Net::HTTP.get_response( HOST, path )
|
111
|
+
validate( LibXML::XML::Parser.string( response.body ).parse )
|
112
|
+
end
|
113
|
+
|
114
|
+
# Construct an HTTP POST call from params, and check the response status.
|
115
|
+
#
|
116
|
+
# @param [String] method last.fm api method to call
|
117
|
+
# @param [Hash] params parameters to send, excluding method, api_key, api_sig, and sk
|
118
|
+
# @return [LibXML::XML::Document] xml document of the data contained in the response
|
119
|
+
# @raise [LastFMError] if the request fails
|
120
|
+
def post( method, params )
|
121
|
+
post_uri = URI.parse("http://#{HOST}/#{API_VERSION}/")
|
122
|
+
params = construct_params( method, :secure, params )
|
123
|
+
logger.debug( "Last.fm HTTP POST: #{post_uri}, #{params.to_s}" ) if logger
|
124
|
+
response = Net::HTTP.post_form( post_uri, params )
|
125
|
+
validate( LibXML::XML::Parser.string( response.body ).parse )
|
126
|
+
end
|
127
|
+
|
128
|
+
private
|
129
|
+
|
130
|
+
# Check an XML document for status = failed, and throw a descriptive error if it's found.
|
131
|
+
#
|
132
|
+
# @param [LibXML::XML::Document] xml xml document to check for errors
|
133
|
+
# @return [LibXML::XML::Document] the xml document if no errors were found
|
134
|
+
# @raise [LastFMError] if an error is found
|
135
|
+
# @private
|
136
|
+
def validate( xml )
|
137
|
+
raise LastFMError, xml.find_first('error').content if xml.root.attributes['status'] == 'failed'
|
138
|
+
xml
|
139
|
+
end
|
140
|
+
|
141
|
+
# Normalize the parameter list by converting boolean values to 0 or 1, array values to
|
142
|
+
# comma-separated strings, and all other values to a string. Remove any nil values, and
|
143
|
+
# camel-case the parameter keys. Add method, api key, session key, and api signature
|
144
|
+
# parameters where necessary.
|
145
|
+
#
|
146
|
+
# @param [String] method last.fm api method
|
147
|
+
# @param [Boolean] secure whether to include session key and api signature in the parameters
|
148
|
+
# @param [Hash] params parameters to normalize and add to
|
149
|
+
# @return [Hash] complete, normalized parameters
|
150
|
+
# @private
|
151
|
+
def construct_params( method, secure, params )
|
152
|
+
params = params.each_with_object({}) do |(k,v), h|
|
153
|
+
v = v ? 1 : 0 if !!v == v # convert booleans into 0 or 1
|
154
|
+
v = v.compact.join(',') if v.is_a?(Array) # convert arrays into comma-separated strings
|
155
|
+
v = v.to_i if v.is_a?(Time) # convert times into integer unix timestamps
|
156
|
+
h[camel_case(k)] = v.to_s unless v.nil?
|
157
|
+
end
|
158
|
+
params['method'] = method
|
159
|
+
params['api_key'] = api_key
|
160
|
+
params['sk'] = session_key if authenticated? && secure
|
161
|
+
params['api_sig'] = generate_method_signature( params ) if secure
|
162
|
+
params
|
163
|
+
end
|
164
|
+
|
165
|
+
# Return a the camelCased version of the given string or symbol, with underscores removed,
|
166
|
+
# word capitalized, and the first letter lower case.
|
167
|
+
#
|
168
|
+
# @param [String] str the string (or symbol) to camel case
|
169
|
+
# @return [String] the camelcased version of the given string
|
170
|
+
def camel_case(key)
|
171
|
+
exceptions = { playlist_id: 'playlistID', playlist_url: 'playlistURL',
|
172
|
+
speed_multiplier: 'speed_multiplier', fingerprint_id: 'fingerprintid' }
|
173
|
+
return exceptions[key] if exceptions.include?(key)
|
174
|
+
camel = key.to_s.split('_').map{|s| s.capitalize}.join
|
175
|
+
camel[0].downcase + camel[1..-1]
|
176
|
+
end
|
177
|
+
|
178
|
+
# Generate the path for a particular method call given params.
|
179
|
+
#
|
180
|
+
# @param [String] method last.fm method to call
|
181
|
+
# @param [Boolean] secure whether to include session key and api signature in the call
|
182
|
+
# @param [optional, Hash] params parameters to include in the api call
|
183
|
+
# @return [String] path for the api call
|
184
|
+
# @private
|
185
|
+
def generate_path( method, secure, params={} )
|
186
|
+
params = construct_params( method, secure, params )
|
187
|
+
url = "/#{API_VERSION}/?method=#{params.delete('method')}"
|
188
|
+
params.inject(url) do |url, (key, value)|
|
189
|
+
url << "&#{key}=#{CGI.escape value}"
|
190
|
+
end
|
191
|
+
end
|
192
|
+
|
193
|
+
# Generate a method signature based on given parameters.
|
194
|
+
#
|
195
|
+
# @param [Hash] parameters to combine into a method signature
|
196
|
+
# @return [String] method signature based on all the parameters
|
197
|
+
# @see http://www.last.fm/api/authspec#8
|
198
|
+
# @private
|
199
|
+
def generate_method_signature( params )
|
200
|
+
str = params.keys.sort.inject('') do |str, key|
|
201
|
+
str << key << params[key]
|
202
|
+
end
|
203
|
+
Digest::MD5.hexdigest( str << api_secret )
|
204
|
+
end
|
205
|
+
|
206
|
+
end
|
207
|
+
end
|
data/test/test_album.rb
CHANGED
@@ -1,36 +1,36 @@
|
|
1
|
-
require 'test/unit'
|
2
|
-
load 'lib/rscrobbler.rb'
|
3
|
-
|
4
|
-
def check_attributes(model, attrs)
|
5
|
-
attrs.each do |attr|
|
6
|
-
assert_not_nil model.send(attr), "#{attr} expected to be set."
|
7
|
-
end
|
8
|
-
end
|
9
|
-
|
10
|
-
class LastFM::AlbumTest < Test::Unit::TestCase
|
11
|
-
|
12
|
-
def setup
|
13
|
-
LastFM.api_key = 'b25b959554ed76058ac220b7b2e0a026'
|
14
|
-
@artist = 'Cher'
|
15
|
-
@album = 'Believe'
|
16
|
-
end
|
17
|
-
|
18
|
-
def test_search
|
19
|
-
albums = LastFM::Album.search :album => @album, :limit => 1
|
20
|
-
assert_equal 1, albums.size
|
21
|
-
assert albums.first.is_a? LastFM::Album
|
22
|
-
check_attributes albums.first, [:name, :artist, :id, :url, :images, :streamable, :mbid]
|
23
|
-
end
|
24
|
-
|
25
|
-
def test_get_info
|
26
|
-
assert_raise LastFM::LastFMError do
|
27
|
-
LastFM::Album.get_info :album => @album
|
28
|
-
end
|
29
|
-
album = LastFM::Album.get_info :artist => @artist, :album => @album
|
30
|
-
assert_equal @artist, album.artist
|
31
|
-
assert_equal @album, album.name
|
32
|
-
assert album.wiki.is_a? LastFM::Wiki
|
33
|
-
check_attributes album, [:artist, :id, :images, :listeners, :mbid, :name, :playcount, :release_date, :tags, :tracks, :url, :wiki]
|
34
|
-
end
|
35
|
-
|
1
|
+
require 'test/unit'
|
2
|
+
load 'lib/rscrobbler.rb'
|
3
|
+
|
4
|
+
def check_attributes(model, attrs)
|
5
|
+
attrs.each do |attr|
|
6
|
+
assert_not_nil model.send(attr), "#{attr} expected to be set."
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
class LastFM::AlbumTest < Test::Unit::TestCase
|
11
|
+
|
12
|
+
def setup
|
13
|
+
LastFM.api_key = 'b25b959554ed76058ac220b7b2e0a026'
|
14
|
+
@artist = 'Cher'
|
15
|
+
@album = 'Believe'
|
16
|
+
end
|
17
|
+
|
18
|
+
def test_search
|
19
|
+
albums = LastFM::Album.search :album => @album, :limit => 1
|
20
|
+
assert_equal 1, albums.size
|
21
|
+
assert albums.first.is_a? LastFM::Album
|
22
|
+
check_attributes albums.first, [:name, :artist, :id, :url, :images, :streamable, :mbid]
|
23
|
+
end
|
24
|
+
|
25
|
+
def test_get_info
|
26
|
+
assert_raise LastFM::LastFMError do
|
27
|
+
LastFM::Album.get_info :album => @album
|
28
|
+
end
|
29
|
+
album = LastFM::Album.get_info :artist => @artist, :album => @album
|
30
|
+
assert_equal @artist, album.artist
|
31
|
+
assert_equal @album, album.name
|
32
|
+
assert album.wiki.is_a? LastFM::Wiki
|
33
|
+
check_attributes album, [:artist, :id, :images, :listeners, :mbid, :name, :playcount, :release_date, :tags, :tracks, :url, :wiki]
|
34
|
+
end
|
35
|
+
|
36
36
|
end
|