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.
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