echowrap 0.0.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/.gitignore +22 -0
- data/.travis.yml +16 -0
- data/Gemfile +13 -0
- data/LICENSE.txt +22 -0
- data/README.md +111 -0
- data/Rakefile +1 -0
- data/echowrap.gemspec +24 -0
- data/lib/echowrap/analysis.rb +39 -0
- data/lib/echowrap/api/artist.rb +387 -0
- data/lib/echowrap/api/oauth.rb +25 -0
- data/lib/echowrap/api/playlist.rb +248 -0
- data/lib/echowrap/api/sandbox.rb +45 -0
- data/lib/echowrap/api/song.rb +111 -0
- data/lib/echowrap/api/taste_profile.rb +296 -0
- data/lib/echowrap/api/track.rb +64 -0
- data/lib/echowrap/api/utils.rb +57 -0
- data/lib/echowrap/artist.rb +73 -0
- data/lib/echowrap/asset.rb +12 -0
- data/lib/echowrap/audio_summary.rb +15 -0
- data/lib/echowrap/base.rb +88 -0
- data/lib/echowrap/biography.rb +13 -0
- data/lib/echowrap/blog.rb +8 -0
- data/lib/echowrap/call_list.rb +8 -0
- data/lib/echowrap/category_map.rb +8 -0
- data/lib/echowrap/client.rb +80 -0
- data/lib/echowrap/configurable.rb +84 -0
- data/lib/echowrap/default.rb +88 -0
- data/lib/echowrap/doc_counts.rb +8 -0
- data/lib/echowrap/echonest_id.rb +8 -0
- data/lib/echowrap/error/bad_gateway.rb +11 -0
- data/lib/echowrap/error/bad_request.rb +10 -0
- data/lib/echowrap/error/client_error.rb +35 -0
- data/lib/echowrap/error/configuration_error.rb +8 -0
- data/lib/echowrap/error/forbidden.rb +10 -0
- data/lib/echowrap/error/gateway_timeout.rb +11 -0
- data/lib/echowrap/error/internal_server_error.rb +11 -0
- data/lib/echowrap/error/not_acceptable.rb +10 -0
- data/lib/echowrap/error/not_found.rb +10 -0
- data/lib/echowrap/error/server_error.rb +28 -0
- data/lib/echowrap/error/service_unavailable.rb +11 -0
- data/lib/echowrap/error/too_many_requests.rb +12 -0
- data/lib/echowrap/error/unauthorized.rb +10 -0
- data/lib/echowrap/error/unprocessable_entity.rb +10 -0
- data/lib/echowrap/error.rb +32 -0
- data/lib/echowrap/familiarity.rb +8 -0
- data/lib/echowrap/feed.rb +14 -0
- data/lib/echowrap/foreign_id.rb +10 -0
- data/lib/echowrap/genre.rb +8 -0
- data/lib/echowrap/hotttnesss.rb +8 -0
- data/lib/echowrap/image.rb +15 -0
- data/lib/echowrap/item.rb +95 -0
- data/lib/echowrap/item_request.rb +8 -0
- data/lib/echowrap/keyvalues.rb +8 -0
- data/lib/echowrap/license.rb +10 -0
- data/lib/echowrap/location.rb +8 -0
- data/lib/echowrap/meta.rb +9 -0
- data/lib/echowrap/news_article.rb +8 -0
- data/lib/echowrap/options.rb +10 -0
- data/lib/echowrap/playlist.rb +47 -0
- data/lib/echowrap/prediction.rb +7 -0
- data/lib/echowrap/rate_limit.rb +47 -0
- data/lib/echowrap/reference.rb +8 -0
- data/lib/echowrap/request/multipart_with_file.rb +36 -0
- data/lib/echowrap/response/parse_json.rb +25 -0
- data/lib/echowrap/response/raise_error.rb +31 -0
- data/lib/echowrap/review.rb +8 -0
- data/lib/echowrap/rule.rb +8 -0
- data/lib/echowrap/sandbox.rb +11 -0
- data/lib/echowrap/seeds.rb +9 -0
- data/lib/echowrap/sequenced_data/bar.rb +4 -0
- data/lib/echowrap/sequenced_data/beat.rb +4 -0
- data/lib/echowrap/sequenced_data/section.rb +6 -0
- data/lib/echowrap/sequenced_data/segment.rb +4 -0
- data/lib/echowrap/sequenced_data/tatum.rb +4 -0
- data/lib/echowrap/sequenced_data.rb +12 -0
- data/lib/echowrap/song.rb +24 -0
- data/lib/echowrap/status.rb +12 -0
- data/lib/echowrap/taste_profile.rb +28 -0
- data/lib/echowrap/term.rb +8 -0
- data/lib/echowrap/track.rb +21 -0
- data/lib/echowrap/update_info.rb +8 -0
- data/lib/echowrap/urls.rb +9 -0
- data/lib/echowrap/version.rb +18 -0
- data/lib/echowrap/video.rb +7 -0
- data/lib/echowrap/years_active.rb +8 -0
- data/lib/echowrap.rb +78 -0
- data/spec/echonest/api/artist_spec.rb +901 -0
- data/spec/echonest/api/oauth_spec.rb +29 -0
- data/spec/echonest/api/playlist_spec.rb +274 -0
- data/spec/echonest/api/sandbox_spec.rb +67 -0
- data/spec/echonest/api/song_spec.rb +326 -0
- data/spec/echonest/api/taste_profile_spec.rb +403 -0
- data/spec/echonest/api/track_spec.rb +167 -0
- data/spec/echonest/base_spec.rb +119 -0
- data/spec/echonest/client_spec.rb +174 -0
- data/spec/echonest/error_spec.rb +20 -0
- data/spec/echonest/rate_limit_spec.rb +76 -0
- data/spec/echonest_spec.rb +65 -0
- data/spec/fixtures/artist/biographies.json +1 -0
- data/spec/fixtures/artist/blogs.json +1 -0
- data/spec/fixtures/artist/extract.json +1 -0
- data/spec/fixtures/artist/familiarity.json +1 -0
- data/spec/fixtures/artist/hotttnesss.json +1 -0
- data/spec/fixtures/artist/images.json +1 -0
- data/spec/fixtures/artist/list_genres.json +1 -0
- data/spec/fixtures/artist/list_terms.json +1 -0
- data/spec/fixtures/artist/news.json +1 -0
- data/spec/fixtures/artist/profile.json +1 -0
- data/spec/fixtures/artist/reviews.json +1 -0
- data/spec/fixtures/artist/search.json +1 -0
- data/spec/fixtures/artist/similar.json +1 -0
- data/spec/fixtures/artist/songs.json +1 -0
- data/spec/fixtures/artist/suggest.json +1 -0
- data/spec/fixtures/artist/terms.json +1 -0
- data/spec/fixtures/artist/top_hottt.json +1 -0
- data/spec/fixtures/artist/top_terms.json +1 -0
- data/spec/fixtures/artist/twitter.json +1 -0
- data/spec/fixtures/artist/urls.json +1 -0
- data/spec/fixtures/artist/video.json +1 -0
- data/spec/fixtures/billie_jean_fingerprint.txt +1 -0
- data/spec/fixtures/billie_jean_query.json +16 -0
- data/spec/fixtures/oauth/timestamp.json +1 -0
- data/spec/fixtures/playlist/basic.json +1 -0
- data/spec/fixtures/playlist/dynamic/create.json +1 -0
- data/spec/fixtures/playlist/dynamic/delete.json +1 -0
- data/spec/fixtures/playlist/dynamic/feedback.json +1 -0
- data/spec/fixtures/playlist/dynamic/info.json +1 -0
- data/spec/fixtures/playlist/dynamic/next.json +1 -0
- data/spec/fixtures/playlist/dynamic/restart.json +1 -0
- data/spec/fixtures/playlist/dynamic/steer.json +1 -0
- data/spec/fixtures/playlist/static.json +1 -0
- data/spec/fixtures/sandbox/access.json +19 -0
- data/spec/fixtures/sandbox/list.json +1 -0
- data/spec/fixtures/song/identify.json +19 -0
- data/spec/fixtures/song/profile.json +1 -0
- data/spec/fixtures/song/search.json +1 -0
- data/spec/fixtures/taste_profile/ban.json +9 -0
- data/spec/fixtures/taste_profile/create.json +1 -0
- data/spec/fixtures/taste_profile/delete.json +11 -0
- data/spec/fixtures/taste_profile/favorite.json +9 -0
- data/spec/fixtures/taste_profile/feed.json +1 -0
- data/spec/fixtures/taste_profile/keyvalues.json +4 -0
- data/spec/fixtures/taste_profile/list.json +1 -0
- data/spec/fixtures/taste_profile/play.json +9 -0
- data/spec/fixtures/taste_profile/predict.json +1 -0
- data/spec/fixtures/taste_profile/profile.json +1 -0
- data/spec/fixtures/taste_profile/rate.json +9 -0
- data/spec/fixtures/taste_profile/read.json +1 -0
- data/spec/fixtures/taste_profile/similar.json +14 -0
- data/spec/fixtures/taste_profile/skip.json +9 -0
- data/spec/fixtures/taste_profile/status.json +2 -0
- data/spec/fixtures/taste_profile/update.json +10 -0
- data/spec/fixtures/taste_profile/update_request_data.json +4 -0
- data/spec/fixtures/technolol-music.mp3 +0 -0
- data/spec/fixtures/track/analysis.json +3 -0
- data/spec/fixtures/track/profile.json +35 -0
- data/spec/fixtures/track/upload.json +21 -0
- data/spec/helper.rb +50 -0
- metadata +323 -0
@@ -0,0 +1,80 @@
|
|
1
|
+
require 'faraday'
|
2
|
+
require 'multi_json'
|
3
|
+
require 'echowrap/configurable'
|
4
|
+
require 'echowrap/api/artist'
|
5
|
+
require 'echowrap/api/playlist'
|
6
|
+
require 'echowrap/api/sandbox'
|
7
|
+
require 'echowrap/api/song'
|
8
|
+
require 'echowrap/api/oauth'
|
9
|
+
require 'echowrap/api/taste_profile'
|
10
|
+
require 'echowrap/api/track'
|
11
|
+
require 'simple_oauth'
|
12
|
+
|
13
|
+
|
14
|
+
module Echowrap
|
15
|
+
class Client
|
16
|
+
include Echowrap::API::Artist
|
17
|
+
include Echowrap::API::Playlist
|
18
|
+
include Echowrap::API::Sandbox
|
19
|
+
include Echowrap::API::Song
|
20
|
+
include Echowrap::API::Oauth
|
21
|
+
include Echowrap::API::TasteProfile
|
22
|
+
include Echowrap::API::Track
|
23
|
+
include Echowrap::Configurable
|
24
|
+
|
25
|
+
# Initializes a new Client object
|
26
|
+
#
|
27
|
+
# @param options [Hash]
|
28
|
+
# @return [Echowrap::Client]
|
29
|
+
def initialize(options={})
|
30
|
+
Echowrap::Configurable.keys.each do |key|
|
31
|
+
instance_variable_set(:"@#{key}", options[key] || Echowrap.instance_variable_get(:"@#{key}"))
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
# Perform an HTTP GET request
|
36
|
+
def get(path, params={})
|
37
|
+
request(:get, path, params)
|
38
|
+
end
|
39
|
+
|
40
|
+
# Perform an HTTP POST request
|
41
|
+
def post(path, params={})
|
42
|
+
signature_params = params.values.any?{|value| value.respond_to?(:to_io)} ? {} : params
|
43
|
+
request(:post, path, params, signature_params)
|
44
|
+
end
|
45
|
+
|
46
|
+
private
|
47
|
+
|
48
|
+
def setup_authentication_parameters(method, path, params)
|
49
|
+
params = params.merge(:api_key => @api_key)
|
50
|
+
params = params.merge(oauth_parameters(method, path, params)) if params.delete(:oauth_request)
|
51
|
+
params
|
52
|
+
end
|
53
|
+
|
54
|
+
def request(method, path, params={}, signature_params=params)
|
55
|
+
params = setup_authentication_parameters(method, path, params)
|
56
|
+
connection.send(method.to_sym, path, params).env
|
57
|
+
rescue Faraday::Error::ClientError
|
58
|
+
raise Echowrap::Error::ClientError
|
59
|
+
rescue MultiJson::DecodeError
|
60
|
+
raise Echowrap::Error::DecodeError
|
61
|
+
end
|
62
|
+
|
63
|
+
# Returns a Faraday::Connection object
|
64
|
+
#
|
65
|
+
# @return [Faraday::Connection]
|
66
|
+
def connection
|
67
|
+
@connection ||= begin
|
68
|
+
connection_options = {:builder => @middleware}
|
69
|
+
connection_options[:ssl] = {:verify => true} if @endpoint[0..4] == 'https'
|
70
|
+
Faraday.new(@endpoint, @connection_options.merge(connection_options))
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
def oauth_parameters(method, path, params={})
|
75
|
+
uri = URI(@endpoint + path)
|
76
|
+
SimpleOAuth::Header.new(method, uri, params, credentials).signed_attributes
|
77
|
+
end
|
78
|
+
|
79
|
+
end
|
80
|
+
end
|
@@ -0,0 +1,84 @@
|
|
1
|
+
require 'echowrap/default'
|
2
|
+
require 'echowrap/error/configuration_error'
|
3
|
+
require 'forwardable'
|
4
|
+
|
5
|
+
module Echowrap
|
6
|
+
module Configurable
|
7
|
+
extend Forwardable
|
8
|
+
attr_writer :api_key, :consumer_key, :shared_secret
|
9
|
+
attr_accessor :endpoint, :connection_options, :middleware
|
10
|
+
def_delegator :options, :hash
|
11
|
+
|
12
|
+
class << self
|
13
|
+
def keys
|
14
|
+
@keys ||= [
|
15
|
+
:api_key,
|
16
|
+
:consumer_key,
|
17
|
+
:shared_secret,
|
18
|
+
:endpoint,
|
19
|
+
:connection_options,
|
20
|
+
:middleware,
|
21
|
+
]
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
# Convenience method to allow configuration options to be set in a block
|
26
|
+
#
|
27
|
+
# @raise [Echowrap::Error::ConfigurationError] Error is raised when supplied
|
28
|
+
# echonest credentials are not a String or Symbol.
|
29
|
+
def configure
|
30
|
+
yield self
|
31
|
+
validate_credential_type!
|
32
|
+
self
|
33
|
+
end
|
34
|
+
|
35
|
+
# @return [Boolean]
|
36
|
+
def credentials?
|
37
|
+
credentials.values.all?
|
38
|
+
end
|
39
|
+
|
40
|
+
def reset!
|
41
|
+
Echowrap::Configurable.keys.each do |key|
|
42
|
+
instance_variable_set(:"@#{key}", Echowrap::Default.options[key])
|
43
|
+
end
|
44
|
+
self
|
45
|
+
end
|
46
|
+
|
47
|
+
alias setup reset!
|
48
|
+
|
49
|
+
private
|
50
|
+
def application_only_auth?
|
51
|
+
true
|
52
|
+
end
|
53
|
+
|
54
|
+
# @return [Hash]
|
55
|
+
def credentials
|
56
|
+
{
|
57
|
+
:api_key => @api_key,
|
58
|
+
:consumer_key => @consumer_key,
|
59
|
+
:consumer_secret => @shared_secret,
|
60
|
+
}
|
61
|
+
end
|
62
|
+
|
63
|
+
# @return [Hash]
|
64
|
+
def options
|
65
|
+
Hash[Echowrap::Configurable.keys.map{|key| [key, instance_variable_get(:"@#{key}")]}]
|
66
|
+
end
|
67
|
+
|
68
|
+
# Ensures that all credentials set during configuration are of a
|
69
|
+
# valid type. Valid types are String and Symbol.
|
70
|
+
#
|
71
|
+
# @raise [Echowrap::Error::ConfigurationError] Error is raised when
|
72
|
+
# supplied echonest credentials are not a String or Symbol.
|
73
|
+
def validate_credential_type!
|
74
|
+
credentials.each do |credential, value|
|
75
|
+
next if value.nil?
|
76
|
+
|
77
|
+
unless value.is_a?(String) || value.is_a?(Symbol)
|
78
|
+
raise(Error::ConfigurationError, "Invalid #{credential} specified: #{value} must be a string or symbol.")
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
end
|
84
|
+
end
|
@@ -0,0 +1,88 @@
|
|
1
|
+
require 'faraday'
|
2
|
+
require 'faraday/request/multipart'
|
3
|
+
require 'echowrap/configurable'
|
4
|
+
require 'echowrap/error/client_error'
|
5
|
+
require 'echowrap/error/server_error'
|
6
|
+
require 'echowrap/request/multipart_with_file'
|
7
|
+
require 'echowrap/response/parse_json'
|
8
|
+
require 'echowrap/response/raise_error'
|
9
|
+
require 'echowrap/version'
|
10
|
+
|
11
|
+
module Echowrap
|
12
|
+
module Default
|
13
|
+
ENDPOINT = 'http://developer.echonest.com' unless defined? Echowrap::Default::ENDPOINT
|
14
|
+
CONNECTION_OPTIONS = {
|
15
|
+
:headers => {
|
16
|
+
:accept => 'application/json',
|
17
|
+
:user_agent => "Echowrap Ruby Gem #{Echowrap::Version}",
|
18
|
+
},
|
19
|
+
:request => {
|
20
|
+
:open_timeout => 5,
|
21
|
+
:timeout => 10,
|
22
|
+
:params_encoder => Faraday::FlatParamsEncoder
|
23
|
+
},
|
24
|
+
:ssl => {
|
25
|
+
:verify => false
|
26
|
+
},
|
27
|
+
} unless defined? Echnoest::Default::CONNECTION_OPTIONS
|
28
|
+
IDENTITY_MAP = false unless defined? Echowrap::Default::IDENTITY_MAP
|
29
|
+
MIDDLEWARE = Faraday::RackBuilder.new do |builder|
|
30
|
+
# Convert file uploads to Faraday::UploadIO objects
|
31
|
+
builder.use Echowrap::Request::MultipartWithFile
|
32
|
+
# Checks for files in the payload
|
33
|
+
builder.use Faraday::Request::Multipart
|
34
|
+
# Convert request params to "www-form-urlencoded"
|
35
|
+
builder.use Faraday::Request::UrlEncoded
|
36
|
+
# Handle 4xx server responses
|
37
|
+
builder.use Echowrap::Response::RaiseError, Echowrap::Error::ClientError
|
38
|
+
# Parse JSON response bodies using MultiJson
|
39
|
+
builder.use Echowrap::Response::ParseJson
|
40
|
+
# Handle 5xx server responses
|
41
|
+
builder.use Echowrap::Response::RaiseError, Echowrap::Error::ServerError
|
42
|
+
# Set Faraday's HTTP adapter
|
43
|
+
builder.adapter Faraday.default_adapter
|
44
|
+
end unless defined? Echowrap::Default::MIDDLEWARE
|
45
|
+
|
46
|
+
class << self
|
47
|
+
|
48
|
+
# @return [Hash]
|
49
|
+
def options
|
50
|
+
Hash[Echowrap::Configurable.keys.map{|key| [key, send(key)]}]
|
51
|
+
end
|
52
|
+
|
53
|
+
# @return [String]
|
54
|
+
def api_key
|
55
|
+
ENV['ECHONEST_API_KEY']
|
56
|
+
end
|
57
|
+
|
58
|
+
# @return [String]
|
59
|
+
def consumer_key
|
60
|
+
ENV['ECHONEST_CONSUMER_KEY']
|
61
|
+
end
|
62
|
+
|
63
|
+
# @return [String]
|
64
|
+
def shared_secret
|
65
|
+
ENV['ECHONEST_SHARED_SECRET']
|
66
|
+
end
|
67
|
+
|
68
|
+
# @note This is configurable in case you want to use a Echowrap-compatible endpoint.
|
69
|
+
# @return [String]
|
70
|
+
def endpoint
|
71
|
+
ENDPOINT
|
72
|
+
end
|
73
|
+
|
74
|
+
def connection_options
|
75
|
+
CONNECTION_OPTIONS
|
76
|
+
end
|
77
|
+
|
78
|
+
# @note Faraday's middleware stack implementation is comparable to that of Rack middleware. The order of middleware is important: the first middleware on the list wraps all others, while the last middleware is the innermost one.
|
79
|
+
# @see https://github.com/technoweenie/faraday#advanced-middleware-usage
|
80
|
+
# @see http://mislav.uniqpath.com/2011/07/faraday-advanced-http/
|
81
|
+
# @return [Faraday::RackBuilder]
|
82
|
+
def middleware
|
83
|
+
MIDDLEWARE
|
84
|
+
end
|
85
|
+
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
require 'echowrap/error/server_error'
|
2
|
+
|
3
|
+
module Echowrap
|
4
|
+
class Error
|
5
|
+
# Raised when Echowrap returns the HTTP status code 502
|
6
|
+
class BadGateway < Echowrap::Error::ServerError
|
7
|
+
HTTP_STATUS_CODE = 502
|
8
|
+
MESSAGE = "Echowrap is down or being upgraded."
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
require 'echowrap/error'
|
2
|
+
|
3
|
+
module Echowrap
|
4
|
+
class Error
|
5
|
+
# Raised when Echowrap returns a 4xx HTTP status code or there's an error in Faraday
|
6
|
+
class ClientError < Echowrap::Error
|
7
|
+
|
8
|
+
# Create a new error from an HTTP environment
|
9
|
+
#
|
10
|
+
# @param response [Hash]
|
11
|
+
# @return [Echowrap::Error]
|
12
|
+
def self.from_response(response={})
|
13
|
+
new(parse_error(response[:body]), response[:response_headers])
|
14
|
+
end
|
15
|
+
|
16
|
+
private
|
17
|
+
|
18
|
+
def self.parse_error(body)
|
19
|
+
if body.nil?
|
20
|
+
''
|
21
|
+
elsif body[:error]
|
22
|
+
body[:error]
|
23
|
+
elsif body[:errors]
|
24
|
+
first = Array(body[:errors]).first
|
25
|
+
if first.is_a?(Hash)
|
26
|
+
first[:message].chomp
|
27
|
+
else
|
28
|
+
first.chomp
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
require 'echowrap/error/server_error'
|
2
|
+
|
3
|
+
module Echowrap
|
4
|
+
class Error
|
5
|
+
# Raised when Echowrap returns the HTTP status code 504
|
6
|
+
class GatewayTimeout < Echowrap::Error::ServerError
|
7
|
+
HTTP_STATUS_CODE = 504
|
8
|
+
MESSAGE = "The Echowrap servers are up, but the request couldn't be serviced due to some failure within our stack. Try again later."
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
require 'echowrap/error/server_error'
|
2
|
+
|
3
|
+
module Echowrap
|
4
|
+
class Error
|
5
|
+
# Raised when Echowrap returns the HTTP status code 500
|
6
|
+
class InternalServerError < Echowrap::Error::ServerError
|
7
|
+
HTTP_STATUS_CODE = 500
|
8
|
+
MESSAGE = "Something is technically wrong."
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
require 'echowrap/error'
|
2
|
+
|
3
|
+
module Echowrap
|
4
|
+
class Error
|
5
|
+
# Raised when Echowrap returns a 5xx HTTP status code
|
6
|
+
class ServerError < Echowrap::Error
|
7
|
+
MESSAGE = "Server Error"
|
8
|
+
|
9
|
+
# Create a new error from an HTTP environment
|
10
|
+
#
|
11
|
+
# @param response [Hash]
|
12
|
+
# @return [Echowrap::Error]
|
13
|
+
def self.from_response(response={})
|
14
|
+
new(nil, response[:response_headers])
|
15
|
+
end
|
16
|
+
|
17
|
+
# Initializes a new ServerError object
|
18
|
+
#
|
19
|
+
# @param message [String]
|
20
|
+
# @param response_headers [Hash]
|
21
|
+
# @return [Echowrap::Error::ServerError]
|
22
|
+
def initialize(message=nil, response_headers={})
|
23
|
+
super((message || self.class.const_get(:MESSAGE)), response_headers)
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
require 'echowrap/error/server_error'
|
2
|
+
|
3
|
+
module Echowrap
|
4
|
+
class Error
|
5
|
+
# Raised when Echowrap returns the HTTP status code 503
|
6
|
+
class ServiceUnavailable < Echowrap::Error::ServerError
|
7
|
+
HTTP_STATUS_CODE = 503
|
8
|
+
MESSAGE = "(__-){ Echowrap is over capacity."
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
require 'echowrap/error/client_error'
|
2
|
+
|
3
|
+
module Echowrap
|
4
|
+
class Error
|
5
|
+
# Raised when Echowrap returns the HTTP status code 429
|
6
|
+
class TooManyRequests < Echowrap::Error::ClientError
|
7
|
+
HTTP_STATUS_CODE = 429
|
8
|
+
end
|
9
|
+
EnhanceYourCalm = TooManyRequests
|
10
|
+
RateLimited = TooManyRequests
|
11
|
+
end
|
12
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
module Echowrap
|
2
|
+
# Custom error class for rescuing from all Echowrap errors
|
3
|
+
class Error < StandardError
|
4
|
+
attr_reader :rate_limit, :wrapped_exception
|
5
|
+
|
6
|
+
# @return [Hash]
|
7
|
+
def self.errors
|
8
|
+
@errors ||= Hash[descendants.map{|klass| [klass.const_get(:HTTP_STATUS_CODE), klass]}]
|
9
|
+
end
|
10
|
+
|
11
|
+
# @return [Array]
|
12
|
+
def self.descendants
|
13
|
+
ObjectSpace.each_object(::Class).select{|klass| klass < self}
|
14
|
+
end
|
15
|
+
|
16
|
+
# Initializes a new Error object
|
17
|
+
#
|
18
|
+
# @param exception [Exception, String]
|
19
|
+
# @param response_headers [Hash]
|
20
|
+
# @return [Echowrap::Error]
|
21
|
+
def initialize(exception=$!, response_headers={})
|
22
|
+
@rate_limit = Echowrap::RateLimit.new(response_headers)
|
23
|
+
@wrapped_exception = exception
|
24
|
+
exception.respond_to?(:backtrace) ? super(exception.message) : super(exception.to_s)
|
25
|
+
end
|
26
|
+
|
27
|
+
def backtrace
|
28
|
+
@wrapped_exception.respond_to?(:backtrace) ? @wrapped_exception.backtrace : super
|
29
|
+
end
|
30
|
+
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
require 'echowrap/base'
|
2
|
+
|
3
|
+
module Echowrap
|
4
|
+
class Feed < Echowrap::Base
|
5
|
+
attr_reader :name, :url, :date_posted, :date_found, :id, :summary, :type
|
6
|
+
|
7
|
+
# @return [Array]
|
8
|
+
def references
|
9
|
+
@references ||= map_collection(Echowrap::Reference, :references)
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
|
@@ -0,0 +1,95 @@
|
|
1
|
+
require 'echowrap/base'
|
2
|
+
|
3
|
+
module Echowrap
|
4
|
+
class Item < Echowrap::Base
|
5
|
+
attr_reader :artist_familiarity, :artist_hotttnesss, :artist_id, :artist_name,
|
6
|
+
:date_added, :foreign_id, :last_modified, :play_count, :song_hotttnesss,
|
7
|
+
:song_id, :song_name, :song_type
|
8
|
+
|
9
|
+
# @return [Echowrap::ArtistLocation]
|
10
|
+
def artist_location
|
11
|
+
@artist_location ||= Echowrap::Location.new(@attrs[:artist_location])
|
12
|
+
end
|
13
|
+
|
14
|
+
# @return [Echowrap::AudioSummary]
|
15
|
+
def audio_summary
|
16
|
+
@audio_summary ||= Echowrap::AudioSummary.new(@attrs[:audio_summary])
|
17
|
+
end
|
18
|
+
|
19
|
+
# @return [Array]
|
20
|
+
def biographies
|
21
|
+
@biographies ||= map_collection(Echowrap::Biography, :biographies)
|
22
|
+
end
|
23
|
+
|
24
|
+
# @return [Array]
|
25
|
+
def blogs
|
26
|
+
@blogs ||= map_collection(Echowrap::Blog, :blogs)
|
27
|
+
end
|
28
|
+
|
29
|
+
# @return [Echowrap::DocCounts]
|
30
|
+
def doc_counts
|
31
|
+
@doc_counts ||= Echowrap::DocCounts.new(@attrs[:doc_counts])
|
32
|
+
end
|
33
|
+
|
34
|
+
# @return [Array]
|
35
|
+
def foreign_ids
|
36
|
+
@foreign_ids ||= map_collection(Echowrap::ForeignId, :foreign_ids)
|
37
|
+
end
|
38
|
+
|
39
|
+
# @return [Array]
|
40
|
+
def images
|
41
|
+
@images ||= map_collection(Echowrap::Image, :images)
|
42
|
+
end
|
43
|
+
|
44
|
+
# @return [Echowrap::Location]
|
45
|
+
def location
|
46
|
+
@location ||= Echowrap::Location.new(@attrs[:artist_location])
|
47
|
+
end
|
48
|
+
|
49
|
+
# @return [Array]
|
50
|
+
def news
|
51
|
+
@news ||= map_collection(Echowrap::NewsArticle, :news)
|
52
|
+
end
|
53
|
+
|
54
|
+
# @return [Echowrap::ItemRequest]
|
55
|
+
def request
|
56
|
+
@request ||= Echowrap::ItemRequest.new(@attrs[:request])
|
57
|
+
end
|
58
|
+
|
59
|
+
# @return [Array]
|
60
|
+
def reviews
|
61
|
+
@reviews ||= map_collection(Echowrap::Review, :reviews)
|
62
|
+
end
|
63
|
+
|
64
|
+
# @return [Array]
|
65
|
+
def songs
|
66
|
+
@songs ||= map_collection(Echowrap::Song, :songs)
|
67
|
+
end
|
68
|
+
|
69
|
+
# @return [Array]
|
70
|
+
def terms
|
71
|
+
@terms ||= map_collection(Echowrap::Term, :terms)
|
72
|
+
end
|
73
|
+
|
74
|
+
# @return [Array]
|
75
|
+
def tracks
|
76
|
+
@tracks ||= map_collection(Echowrap::Track, :tracks)
|
77
|
+
end
|
78
|
+
|
79
|
+
# @return [Echowrap::Urls]
|
80
|
+
def urls
|
81
|
+
@urls ||= Echowrap::Urls.new(@attrs[:urls])
|
82
|
+
end
|
83
|
+
|
84
|
+
# @return [Array]
|
85
|
+
def video
|
86
|
+
@video ||= map_collection(Echowrap::Video, :video)
|
87
|
+
end
|
88
|
+
|
89
|
+
# @return [Array]
|
90
|
+
def years_active
|
91
|
+
@years_active ||= map_collection(Echowrap::YearsActive, :years_active)
|
92
|
+
end
|
93
|
+
|
94
|
+
end
|
95
|
+
end
|