echowrap 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (159) hide show
  1. data/.gitignore +22 -0
  2. data/.travis.yml +16 -0
  3. data/Gemfile +13 -0
  4. data/LICENSE.txt +22 -0
  5. data/README.md +111 -0
  6. data/Rakefile +1 -0
  7. data/echowrap.gemspec +24 -0
  8. data/lib/echowrap/analysis.rb +39 -0
  9. data/lib/echowrap/api/artist.rb +387 -0
  10. data/lib/echowrap/api/oauth.rb +25 -0
  11. data/lib/echowrap/api/playlist.rb +248 -0
  12. data/lib/echowrap/api/sandbox.rb +45 -0
  13. data/lib/echowrap/api/song.rb +111 -0
  14. data/lib/echowrap/api/taste_profile.rb +296 -0
  15. data/lib/echowrap/api/track.rb +64 -0
  16. data/lib/echowrap/api/utils.rb +57 -0
  17. data/lib/echowrap/artist.rb +73 -0
  18. data/lib/echowrap/asset.rb +12 -0
  19. data/lib/echowrap/audio_summary.rb +15 -0
  20. data/lib/echowrap/base.rb +88 -0
  21. data/lib/echowrap/biography.rb +13 -0
  22. data/lib/echowrap/blog.rb +8 -0
  23. data/lib/echowrap/call_list.rb +8 -0
  24. data/lib/echowrap/category_map.rb +8 -0
  25. data/lib/echowrap/client.rb +80 -0
  26. data/lib/echowrap/configurable.rb +84 -0
  27. data/lib/echowrap/default.rb +88 -0
  28. data/lib/echowrap/doc_counts.rb +8 -0
  29. data/lib/echowrap/echonest_id.rb +8 -0
  30. data/lib/echowrap/error/bad_gateway.rb +11 -0
  31. data/lib/echowrap/error/bad_request.rb +10 -0
  32. data/lib/echowrap/error/client_error.rb +35 -0
  33. data/lib/echowrap/error/configuration_error.rb +8 -0
  34. data/lib/echowrap/error/forbidden.rb +10 -0
  35. data/lib/echowrap/error/gateway_timeout.rb +11 -0
  36. data/lib/echowrap/error/internal_server_error.rb +11 -0
  37. data/lib/echowrap/error/not_acceptable.rb +10 -0
  38. data/lib/echowrap/error/not_found.rb +10 -0
  39. data/lib/echowrap/error/server_error.rb +28 -0
  40. data/lib/echowrap/error/service_unavailable.rb +11 -0
  41. data/lib/echowrap/error/too_many_requests.rb +12 -0
  42. data/lib/echowrap/error/unauthorized.rb +10 -0
  43. data/lib/echowrap/error/unprocessable_entity.rb +10 -0
  44. data/lib/echowrap/error.rb +32 -0
  45. data/lib/echowrap/familiarity.rb +8 -0
  46. data/lib/echowrap/feed.rb +14 -0
  47. data/lib/echowrap/foreign_id.rb +10 -0
  48. data/lib/echowrap/genre.rb +8 -0
  49. data/lib/echowrap/hotttnesss.rb +8 -0
  50. data/lib/echowrap/image.rb +15 -0
  51. data/lib/echowrap/item.rb +95 -0
  52. data/lib/echowrap/item_request.rb +8 -0
  53. data/lib/echowrap/keyvalues.rb +8 -0
  54. data/lib/echowrap/license.rb +10 -0
  55. data/lib/echowrap/location.rb +8 -0
  56. data/lib/echowrap/meta.rb +9 -0
  57. data/lib/echowrap/news_article.rb +8 -0
  58. data/lib/echowrap/options.rb +10 -0
  59. data/lib/echowrap/playlist.rb +47 -0
  60. data/lib/echowrap/prediction.rb +7 -0
  61. data/lib/echowrap/rate_limit.rb +47 -0
  62. data/lib/echowrap/reference.rb +8 -0
  63. data/lib/echowrap/request/multipart_with_file.rb +36 -0
  64. data/lib/echowrap/response/parse_json.rb +25 -0
  65. data/lib/echowrap/response/raise_error.rb +31 -0
  66. data/lib/echowrap/review.rb +8 -0
  67. data/lib/echowrap/rule.rb +8 -0
  68. data/lib/echowrap/sandbox.rb +11 -0
  69. data/lib/echowrap/seeds.rb +9 -0
  70. data/lib/echowrap/sequenced_data/bar.rb +4 -0
  71. data/lib/echowrap/sequenced_data/beat.rb +4 -0
  72. data/lib/echowrap/sequenced_data/section.rb +6 -0
  73. data/lib/echowrap/sequenced_data/segment.rb +4 -0
  74. data/lib/echowrap/sequenced_data/tatum.rb +4 -0
  75. data/lib/echowrap/sequenced_data.rb +12 -0
  76. data/lib/echowrap/song.rb +24 -0
  77. data/lib/echowrap/status.rb +12 -0
  78. data/lib/echowrap/taste_profile.rb +28 -0
  79. data/lib/echowrap/term.rb +8 -0
  80. data/lib/echowrap/track.rb +21 -0
  81. data/lib/echowrap/update_info.rb +8 -0
  82. data/lib/echowrap/urls.rb +9 -0
  83. data/lib/echowrap/version.rb +18 -0
  84. data/lib/echowrap/video.rb +7 -0
  85. data/lib/echowrap/years_active.rb +8 -0
  86. data/lib/echowrap.rb +78 -0
  87. data/spec/echonest/api/artist_spec.rb +901 -0
  88. data/spec/echonest/api/oauth_spec.rb +29 -0
  89. data/spec/echonest/api/playlist_spec.rb +274 -0
  90. data/spec/echonest/api/sandbox_spec.rb +67 -0
  91. data/spec/echonest/api/song_spec.rb +326 -0
  92. data/spec/echonest/api/taste_profile_spec.rb +403 -0
  93. data/spec/echonest/api/track_spec.rb +167 -0
  94. data/spec/echonest/base_spec.rb +119 -0
  95. data/spec/echonest/client_spec.rb +174 -0
  96. data/spec/echonest/error_spec.rb +20 -0
  97. data/spec/echonest/rate_limit_spec.rb +76 -0
  98. data/spec/echonest_spec.rb +65 -0
  99. data/spec/fixtures/artist/biographies.json +1 -0
  100. data/spec/fixtures/artist/blogs.json +1 -0
  101. data/spec/fixtures/artist/extract.json +1 -0
  102. data/spec/fixtures/artist/familiarity.json +1 -0
  103. data/spec/fixtures/artist/hotttnesss.json +1 -0
  104. data/spec/fixtures/artist/images.json +1 -0
  105. data/spec/fixtures/artist/list_genres.json +1 -0
  106. data/spec/fixtures/artist/list_terms.json +1 -0
  107. data/spec/fixtures/artist/news.json +1 -0
  108. data/spec/fixtures/artist/profile.json +1 -0
  109. data/spec/fixtures/artist/reviews.json +1 -0
  110. data/spec/fixtures/artist/search.json +1 -0
  111. data/spec/fixtures/artist/similar.json +1 -0
  112. data/spec/fixtures/artist/songs.json +1 -0
  113. data/spec/fixtures/artist/suggest.json +1 -0
  114. data/spec/fixtures/artist/terms.json +1 -0
  115. data/spec/fixtures/artist/top_hottt.json +1 -0
  116. data/spec/fixtures/artist/top_terms.json +1 -0
  117. data/spec/fixtures/artist/twitter.json +1 -0
  118. data/spec/fixtures/artist/urls.json +1 -0
  119. data/spec/fixtures/artist/video.json +1 -0
  120. data/spec/fixtures/billie_jean_fingerprint.txt +1 -0
  121. data/spec/fixtures/billie_jean_query.json +16 -0
  122. data/spec/fixtures/oauth/timestamp.json +1 -0
  123. data/spec/fixtures/playlist/basic.json +1 -0
  124. data/spec/fixtures/playlist/dynamic/create.json +1 -0
  125. data/spec/fixtures/playlist/dynamic/delete.json +1 -0
  126. data/spec/fixtures/playlist/dynamic/feedback.json +1 -0
  127. data/spec/fixtures/playlist/dynamic/info.json +1 -0
  128. data/spec/fixtures/playlist/dynamic/next.json +1 -0
  129. data/spec/fixtures/playlist/dynamic/restart.json +1 -0
  130. data/spec/fixtures/playlist/dynamic/steer.json +1 -0
  131. data/spec/fixtures/playlist/static.json +1 -0
  132. data/spec/fixtures/sandbox/access.json +19 -0
  133. data/spec/fixtures/sandbox/list.json +1 -0
  134. data/spec/fixtures/song/identify.json +19 -0
  135. data/spec/fixtures/song/profile.json +1 -0
  136. data/spec/fixtures/song/search.json +1 -0
  137. data/spec/fixtures/taste_profile/ban.json +9 -0
  138. data/spec/fixtures/taste_profile/create.json +1 -0
  139. data/spec/fixtures/taste_profile/delete.json +11 -0
  140. data/spec/fixtures/taste_profile/favorite.json +9 -0
  141. data/spec/fixtures/taste_profile/feed.json +1 -0
  142. data/spec/fixtures/taste_profile/keyvalues.json +4 -0
  143. data/spec/fixtures/taste_profile/list.json +1 -0
  144. data/spec/fixtures/taste_profile/play.json +9 -0
  145. data/spec/fixtures/taste_profile/predict.json +1 -0
  146. data/spec/fixtures/taste_profile/profile.json +1 -0
  147. data/spec/fixtures/taste_profile/rate.json +9 -0
  148. data/spec/fixtures/taste_profile/read.json +1 -0
  149. data/spec/fixtures/taste_profile/similar.json +14 -0
  150. data/spec/fixtures/taste_profile/skip.json +9 -0
  151. data/spec/fixtures/taste_profile/status.json +2 -0
  152. data/spec/fixtures/taste_profile/update.json +10 -0
  153. data/spec/fixtures/taste_profile/update_request_data.json +4 -0
  154. data/spec/fixtures/technolol-music.mp3 +0 -0
  155. data/spec/fixtures/track/analysis.json +3 -0
  156. data/spec/fixtures/track/profile.json +35 -0
  157. data/spec/fixtures/track/upload.json +21 -0
  158. data/spec/helper.rb +50 -0
  159. 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,8 @@
1
+ require 'echowrap/base'
2
+
3
+ module Echowrap
4
+ class DocCounts < Echowrap::Base
5
+ attr_reader :audio, :biographies, :blogs, :images, :news, :reviews, :songs, :video
6
+
7
+ end
8
+ end
@@ -0,0 +1,8 @@
1
+ require 'echowrap/base'
2
+
3
+ module Echowrap
4
+ class EchonestId < Echowrap::Base
5
+ attr_reader :foreign_id, :id
6
+
7
+ end
8
+ 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,10 @@
1
+ require 'echowrap/error/client_error'
2
+
3
+ module Echowrap
4
+ class Error
5
+ # Raised when Echowrap returns the HTTP status code 400
6
+ class BadRequest < Echowrap::Error::ClientError
7
+ HTTP_STATUS_CODE = 400
8
+ end
9
+ end
10
+ 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,8 @@
1
+ require 'echowrap/error'
2
+
3
+ module Echowrap
4
+ class Error
5
+ class ConfigurationError < ::ArgumentError
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,10 @@
1
+ require 'echowrap/error/client_error'
2
+
3
+ module Echowrap
4
+ class Error
5
+ # Raised when Echowrap returns the HTTP status code 403
6
+ class Forbidden < Echowrap::Error::ClientError
7
+ HTTP_STATUS_CODE = 403
8
+ end
9
+ end
10
+ 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,10 @@
1
+ require 'echowrap/error/client_error'
2
+
3
+ module Echowrap
4
+ class Error
5
+ # Raised when Echowrap returns the HTTP status code 406
6
+ class NotAcceptable < Echowrap::Error::ClientError
7
+ HTTP_STATUS_CODE = 406
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,10 @@
1
+ require 'echowrap/error/client_error'
2
+
3
+ module Echowrap
4
+ class Error
5
+ # Raised when Echowrap returns the HTTP status code 404
6
+ class NotFound < Echowrap::Error::ClientError
7
+ HTTP_STATUS_CODE = 404
8
+ end
9
+ end
10
+ 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,10 @@
1
+ require 'echowrap/error/client_error'
2
+
3
+ module Echowrap
4
+ class Error
5
+ # Raised when Echowrap returns the HTTP status code 401
6
+ class Unauthorized < Echowrap::Error::ClientError
7
+ HTTP_STATUS_CODE = 401
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,10 @@
1
+ require 'echowrap/error/client_error'
2
+
3
+ module Echowrap
4
+ class Error
5
+ # Raised when Echowrap returns the HTTP status code 404
6
+ class UnprocessableEntity < Echowrap::Error::ClientError
7
+ HTTP_STATUS_CODE = 422
8
+ end
9
+ end
10
+ 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,8 @@
1
+ require 'echowrap/base'
2
+
3
+ module Echowrap
4
+ class Familiarity < Echowrap::Base
5
+ attr_reader :familiarity, :id, :name
6
+ end
7
+ end
8
+
@@ -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,10 @@
1
+ require 'echowrap/base'
2
+
3
+ module Echowrap
4
+ class ForeignId < Echowrap::Base
5
+ attr_reader :catalog, :foreign_id
6
+
7
+ end
8
+ end
9
+
10
+
@@ -0,0 +1,8 @@
1
+ require 'echowrap/base'
2
+
3
+ module Echowrap
4
+ class Genre < Echowrap::Base
5
+ attr_reader :name
6
+
7
+ end
8
+ end
@@ -0,0 +1,8 @@
1
+ require 'echowrap/base'
2
+
3
+ module Echowrap
4
+ class Hotttnesss < Echowrap::Base
5
+ attr_reader :hotttnesss, :id, :name
6
+ end
7
+ end
8
+
@@ -0,0 +1,15 @@
1
+ require 'echowrap/base'
2
+
3
+ module Echowrap
4
+ class Image < Echowrap::Base
5
+ attr_reader :url
6
+
7
+ # @return [Echowrap::License]
8
+ def license
9
+ @license ||= Echowrap::License.new(@attrs[:license])
10
+ end
11
+
12
+ end
13
+ end
14
+
15
+
@@ -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