esi-sdk 1.1.2 → 2.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (49) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/cicd.yml +17 -2
  3. data/.gitignore +2 -0
  4. data/CHANGELOG.md +38 -0
  5. data/Gemfile +1 -0
  6. data/Gemfile.lock +21 -40
  7. data/README.md +2 -0
  8. data/Rakefile +75 -37
  9. data/bin/console +1 -1
  10. data/esi-sdk.gemspec +2 -3
  11. data/lib/esi/client/alliance.rb +103 -10
  12. data/lib/esi/client/assets.rb +193 -18
  13. data/lib/esi/client/bookmarks.rb +130 -12
  14. data/lib/esi/client/calendar.rb +144 -16
  15. data/lib/esi/client/character.rb +414 -42
  16. data/lib/esi/client/clones.rb +65 -6
  17. data/lib/esi/client/contacts.rb +294 -30
  18. data/lib/esi/client/contracts.rb +294 -31
  19. data/lib/esi/client/corporation.rb +755 -152
  20. data/lib/esi/client/dogma.rb +118 -12
  21. data/lib/esi/client/faction_warfare.rb +198 -14
  22. data/lib/esi/client/fittings.rb +94 -10
  23. data/lib/esi/client/fleets.rb +469 -49
  24. data/lib/esi/client/incursions.rb +23 -1
  25. data/lib/esi/client/industry.rb +250 -23
  26. data/lib/esi/client/insurance.rb +23 -1
  27. data/lib/esi/client/killmails.rb +95 -10
  28. data/lib/esi/client/location.rb +98 -9
  29. data/lib/esi/client/loyalty.rb +57 -6
  30. data/lib/esi/client/mail.rb +262 -28
  31. data/lib/esi/client/market.rb +322 -34
  32. data/lib/esi/client/opportunities.rb +124 -13
  33. data/lib/esi/client/planetary_interaction.rb +124 -13
  34. data/lib/esi/client/routes.rb +34 -6
  35. data/lib/esi/client/search.rb +64 -7
  36. data/lib/esi/client/skills.rb +95 -9
  37. data/lib/esi/client/sovereignty.rb +69 -3
  38. data/lib/esi/client/status.rb +24 -1
  39. data/lib/esi/client/universe.rb +817 -194
  40. data/lib/esi/client/user_interface.rb +157 -14
  41. data/lib/esi/client/wallet.rb +199 -22
  42. data/lib/esi/client/wars.rb +81 -9
  43. data/lib/esi/client.rb +74 -82
  44. data/lib/esi/errors.rb +12 -1
  45. data/lib/esi/version.rb +1 -1
  46. data/package.json +19 -0
  47. data/release.config.js +2 -2
  48. data/yarn.lock +3695 -0
  49. metadata +10 -22
@@ -12,7 +12,7 @@ module ESI
12
12
  # @esi_version legacy
13
13
  # @esi_version v1
14
14
  #
15
- # @param war_id [Integer,String] ID for a war
15
+ # @param war_id [Integer] ID for a war
16
16
  # @param params [Hash] Additional query string parameters
17
17
  # @param headers [Hash] Additional headers
18
18
  #
@@ -24,11 +24,35 @@ module ESI
24
24
  # @raise [ESI::Errors::GatewayTimeoutError] Gateway timeout
25
25
  #
26
26
  # @see https://esi.evetech.net/ui/#/Wars/get_wars_war_id
27
- def get_war(war_id:, params: {}, headers: {})
28
- get("/wars/#{war_id}/", headers: headers, params: params)
27
+ def get_war(war_id:, headers: {}, params: {})
28
+ get_war_raw(war_id: war_id, headers: headers, params: params).json
29
29
  end
30
30
  alias get_wars_war_id get_war
31
31
 
32
+ # Return details about a war.
33
+ #
34
+ # This endpoint is cached for up to 3600 seconds.
35
+ #
36
+ # @esi_version dev
37
+ # @esi_version legacy
38
+ # @esi_version v1
39
+ #
40
+ # @param war_id [Integer] ID for a war
41
+ # @param params [Hash] Additional query string parameters
42
+ # @param headers [Hash] Additional headers
43
+ #
44
+ # @raise [ESI::Errors::BadRequestError] Bad request
45
+ # @raise [ESI::Errors::ErrorLimitedError] Error limited
46
+ # @raise [ESI::Errors::UnprocessableEntityError] War not found
47
+ # @raise [ESI::Errors::InternalServerError] Internal server error
48
+ # @raise [ESI::Errors::ServiceUnavailableError] Service unavailable
49
+ # @raise [ESI::Errors::GatewayTimeoutError] Gateway timeout
50
+ #
51
+ # @see https://esi.evetech.net/ui/#/Wars/get_wars_war_id
52
+ def get_war_raw(war_id:, headers: {}, params: {})
53
+ get("/wars/#{war_id}/", headers: headers, params: params)
54
+ end
55
+
32
56
  # Return a list of kills related to a war.
33
57
  #
34
58
  # This endpoint is cached for up to 3600 seconds.
@@ -37,7 +61,7 @@ module ESI
37
61
  # @esi_version legacy
38
62
  # @esi_version v1
39
63
  #
40
- # @param war_id [Integer,String] A valid war ID
64
+ # @param war_id [Integer] A valid war ID
41
65
  # @param params [Hash] Additional query string parameters
42
66
  # @param headers [Hash] Additional headers
43
67
  #
@@ -49,11 +73,59 @@ module ESI
49
73
  # @raise [ESI::Errors::GatewayTimeoutError] Gateway timeout
50
74
  #
51
75
  # @see https://esi.evetech.net/ui/#/Wars/get_wars_war_id_killmails
52
- def get_war_killmails(war_id:, params: {}, headers: {})
53
- get("/wars/#{war_id}/killmails/", headers: headers, params: params)
76
+ def get_war_killmails(war_id:, headers: {}, params: {})
77
+ responses = get_war_killmails_raw(war_id: war_id, headers: headers, params: params)
78
+ responses.map(&:json).reduce([], :concat)
54
79
  end
55
80
  alias get_wars_war_id_killmails get_war_killmails
56
81
 
82
+ # Return a list of kills related to a war.
83
+ #
84
+ # This endpoint is cached for up to 3600 seconds.
85
+ #
86
+ # @esi_version dev
87
+ # @esi_version legacy
88
+ # @esi_version v1
89
+ #
90
+ # @param war_id [Integer] A valid war ID
91
+ # @param params [Hash] Additional query string parameters
92
+ # @param headers [Hash] Additional headers
93
+ #
94
+ # @raise [ESI::Errors::BadRequestError] Bad request
95
+ # @raise [ESI::Errors::ErrorLimitedError] Error limited
96
+ # @raise [ESI::Errors::UnprocessableEntityError] War not found
97
+ # @raise [ESI::Errors::InternalServerError] Internal server error
98
+ # @raise [ESI::Errors::ServiceUnavailableError] Service unavailable
99
+ # @raise [ESI::Errors::GatewayTimeoutError] Gateway timeout
100
+ #
101
+ # @see https://esi.evetech.net/ui/#/Wars/get_wars_war_id_killmails
102
+ def get_war_killmails_raw(war_id:, headers: {}, params: {})
103
+ get("/wars/#{war_id}/killmails/", headers: headers, params: params)
104
+ end
105
+
106
+ # Return a list of wars.
107
+ #
108
+ # This endpoint is cached for up to 3600 seconds.
109
+ #
110
+ # @esi_version dev
111
+ # @esi_version legacy
112
+ # @esi_version v1
113
+ #
114
+ # @param max_war_id [Integer] Only return wars with ID smaller than this
115
+ # @param params [Hash] Additional query string parameters
116
+ # @param headers [Hash] Additional headers
117
+ #
118
+ # @raise [ESI::Errors::BadRequestError] Bad request
119
+ # @raise [ESI::Errors::ErrorLimitedError] Error limited
120
+ # @raise [ESI::Errors::InternalServerError] Internal server error
121
+ # @raise [ESI::Errors::ServiceUnavailableError] Service unavailable
122
+ # @raise [ESI::Errors::GatewayTimeoutError] Gateway timeout
123
+ #
124
+ # @see https://esi.evetech.net/ui/#/Wars/get_wars
125
+ def get_wars(max_war_id: nil, headers: {}, params: {})
126
+ get_wars_raw(max_war_id: max_war_id, headers: headers, params: params).json
127
+ end
128
+
57
129
  # Return a list of wars.
58
130
  #
59
131
  # This endpoint is cached for up to 3600 seconds.
@@ -73,9 +145,9 @@ module ESI
73
145
  # @raise [ESI::Errors::GatewayTimeoutError] Gateway timeout
74
146
  #
75
147
  # @see https://esi.evetech.net/ui/#/Wars/get_wars
76
- def get_wars(max_war_id:, params: {}, headers: {})
77
- query_string = URI.encode_www_form([["max_war_id", max_war_id]])
78
- get("/wars/?#{query_string}", headers: headers, params: params)
148
+ def get_wars_raw(max_war_id: nil, headers: {}, params: {})
149
+ params.merge!("max_war_id" => max_war_id)
150
+ get("/wars/", headers: headers, params: params)
79
151
  end
80
152
  end
81
153
  end
data/lib/esi/client.rb CHANGED
@@ -1,8 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "faraday"
4
- require "faraday-http-cache"
5
- require "faraday_middleware"
3
+ require "httpx"
6
4
  require "timeout"
7
5
 
8
6
  require_relative "./errors"
@@ -91,135 +89,129 @@ module ESI
91
89
  520 => ESI::Errors::EveServerError
92
90
  }.freeze
93
91
 
94
- attr_reader :base_url, :cache, :user_agent, :version
92
+ attr_reader :base_url, :cache, :instrumentation, :logger, :user_agent, :version
95
93
 
96
94
  # Returns a new {ESI::Client}.
97
95
  #
96
+ # See the [faraday-http-cache](https://github.com/sourcelevel/faraday-http-cache) documentation for information on
97
+ # how to set up caching via the `cache` parameter.
98
+ #
98
99
  # @param user_agent [String] Value of the `User-Agent` header for HTTP calls
99
100
  # @param base_url [String] The base URL of the ESI API
100
101
  # @param version [String] The version of the ESI API
102
+ # @param logger [Object] The logger to use
101
103
  # @param cache [Hash] The cache configuration to use
102
104
  # @option cache [Object] :store The cache store (e.g. `Rails.cache`)
103
105
  # @option cache [Object] :logger The logger (e.g. `Rails.logger`)
104
106
  # @option cache [Object] :instrumenter The instrumenter (e.g. `ActiveSupport::Notifications`)
105
- def initialize(user_agent:, base_url: DEFAULT_BASE_URL, version: DEFAULT_VERSION, cache: {})
107
+ # @param instrumentation [Hash] The instrumentation configuration to use
108
+ # @option instrumentation [String] :name The name to use for instrumentation
109
+ # @option instrumentation [Object] :instrumenter The instrumenter to use (e.g. `ActiveSupport::Notifications`)
110
+ def initialize(user_agent:, base_url: DEFAULT_BASE_URL, version: DEFAULT_VERSION, cache: {}, instrumentation: {}, logger: nil) # rubocop:disable Layout/LineLength, Metrics/ParameterLists
106
111
  @base_url = base_url
107
112
  @cache = cache
113
+ @instrumentation = instrumentation
108
114
  @user_agent = user_agent
109
115
  @version = version
116
+ @logger = logger
110
117
  end
111
118
 
112
119
  # Set the `Authorization` header for subsequent requests.
113
120
  #
114
121
  # @param token [String] The [EVE SSO JWT token](https://docs.esi.evetech.net/docs/sso/) to use
115
122
  def authorize(token)
116
- url_encoded_connection.authorization :Bearer, token
117
- json_encoded_connection.authorization :Bearer, token
123
+ session.authentication token
118
124
  end
119
125
 
120
- private
121
-
122
- ESI_RETRY_EXCEPTIONS = [Errno::ETIMEDOUT, Timeout::Error, Faraday::TimeoutError, Faraday::ConnectionFailed,
123
- Faraday::ParsingError, SocketError].freeze
124
-
125
126
  def delete(path, params: {}, headers: {})
126
- response = make_delete_request(path, params: params, headers: headers)
127
- response.body
127
+ params.delete_if { |_, v| v.nil? }
128
+ response = session.delete("/#{version}#{path}", params: params, headers: headers)
129
+ response.raise_for_status
130
+ response
131
+ rescue HTTPX::Error
132
+ raise_error(response)
128
133
  end
129
134
 
130
135
  def get(path, params: {}, headers: {})
131
- response = make_get_request(path, params: params, headers: headers)
136
+ params.delete_if { |_, v| v.nil? }
137
+ response = session.get("/#{version}#{path}", params: params, headers: headers)
138
+ response.raise_for_status
132
139
 
133
- return paginate(response, params, headers) if paginated?(response)
140
+ return paginate(response, "/#{version}#{path}", params, headers) if paginated?(response)
134
141
 
135
- response.body
142
+ response
143
+ rescue HTTPX::Error
144
+ raise_error(response)
136
145
  end
137
146
 
138
- def post(path, payload: {}, headers: {})
139
- response = make_post_request(path, payload: payload, headers: headers)
140
- response.body
147
+ def post(path, payload: {}, params: {}, headers: {})
148
+ params.delete_if { |_, v| v.nil? }
149
+ response = session.post("/#{version}#{path}",
150
+ params: params,
151
+ headers: headers,
152
+ json: payload)
153
+ response.raise_for_status
154
+ response
155
+ rescue HTTPX::Error
156
+ raise_error(response)
141
157
  end
142
158
 
143
- def put(path, payload: {}, headers: {})
144
- response = make_put_request(path, payload: payload, headers: headers)
145
- response.body
159
+ def put(path, payload: {}, params: {}, headers: {})
160
+ params.delete_if { |_, v| v.nil? }
161
+ response = session.put("/#{version}#{path}",
162
+ params: params,
163
+ headers: headers,
164
+ json: payload)
165
+ response.raise_for_status
166
+ response
167
+ rescue HTTPX::Error
168
+ raise_error(response)
146
169
  end
147
170
 
148
- def paginate(response, params, headers)
149
- all_items = response.body
150
- page_count = response.headers["X-Pages"].to_i - 1
151
- page_count.times do |n|
152
- page_number = n + 1
153
- params = params.merge(page: page_number)
154
- page = make_get_request(path, params: params, headers: headers)
155
- all_items += page.body
156
- end
157
-
158
- all_items
159
- end
160
-
161
- def make_delete_request(path, params: {}, headers: {})
162
- res = url_encoded_connection.delete("/#{version}#{path}", params, headers)
163
-
164
- raise_error(res) unless res.success?
165
-
166
- res
167
- end
168
-
169
- def make_get_request(path, params: {}, headers: {})
170
- res = url_encoded_connection.get("/#{version}#{path}", params, headers)
171
-
172
- raise_error(res) unless res.success?
173
-
174
- res
175
- end
176
-
177
- def make_post_request(path, payload: {}, headers: {})
178
- res = json_encoded_connection.post("/#{version}#{path}", payload, headers)
179
-
180
- raise_error(res) unless res.success?
171
+ private
181
172
 
182
- res
183
- end
173
+ def paginate(response, path, params, headers) # rubocop:disable Metrics/MethodLength
174
+ response_headers = normalize_headers(response.headers)
175
+ page_count = response_headers["x-pages"].to_i
184
176
 
185
- def make_put_request(path, payload: {}, headers: {})
186
- res = json_encoded_connection.put("/#{version}#{path}", payload, headers)
177
+ requests = (2..page_count).map do |n|
178
+ session.build_request(:get, path, params: params.merge(page: n), headers: headers)
179
+ end
180
+ responses = requests.any? ? session.request(*requests) : []
181
+ responses.unshift(response)
187
182
 
188
- raise_error(res) unless res.success?
183
+ if responses.any?(&:error)
184
+ raise ESI::Errors::PaginationError.new("Error paginating request", responses: responses)
185
+ end
189
186
 
190
- res
187
+ responses
191
188
  end
192
189
 
193
190
  def paginated?(response)
194
- response.headers["X-Pages"] && response.headers["X-Pages"].to_i <= 1
191
+ headers = normalize_headers(response.headers)
192
+ headers.key?("x-pages")
195
193
  end
196
194
 
197
- def raise_error(res)
198
- raise (ERROR_MAPPING[res.status] || Error).new("(#{res.status}) #{res["error"]}", response: res)
195
+ def normalize_headers(headers)
196
+ headers.to_h.transform_keys(&:downcase)
199
197
  end
200
198
 
201
- def url_encoded_connection
202
- @url_encoded_connection ||= Faraday.new(base_url, headers: default_headers) do |f|
203
- f.use :http_cache, cache unless cache.empty?
204
- f.request :url_encoded
205
- f.request :retry, { exceptions: ESI_RETRY_EXCEPTIONS }
206
- f.response :follow_redirects
207
- f.response :json
208
- end
199
+ def raise_error(res)
200
+ raise (ERROR_MAPPING[res.status] || ESI::Errors::ClientError).new("(#{res.status}) #{res.json["error"]}",
201
+ response: res)
209
202
  end
210
203
 
211
- def json_encoded_connection
212
- @json_encoded_connection ||= Faraday.new(base_url, headers: default_headers) do |f|
213
- f.use :http_cache, cache unless cache.empty?
214
- f.request :json
215
- f.request :retry, { exceptions: ESI_RETRY_EXCEPTIONS }
216
- f.response :follow_redirects
217
- f.response :json
218
- end
204
+ def session
205
+ @session ||= HTTPX.with(origin: base_url)
206
+ .with_headers(default_headers)
207
+ .plugin(:authentication)
208
+ .plugin(:persistent)
209
+ .plugin(:response_cache)
210
+ .plugin(:retries)
219
211
  end
220
212
 
221
213
  def default_headers
222
- { "User-Agent": user_agent }
214
+ { "User-Agent": user_agent, Accept: "application/json" }
223
215
  end
224
216
  end
225
217
  end
data/lib/esi/errors.rb CHANGED
@@ -9,7 +9,7 @@ module ESI
9
9
 
10
10
  # Base class for ESI client errors.
11
11
  class ClientError < Error
12
- attr_reader :response
12
+ attr_reader :response, :responses
13
13
 
14
14
  def initialize(msg, response:)
15
15
  super(msg)
@@ -18,6 +18,17 @@ module ESI
18
18
  end
19
19
  end
20
20
 
21
+ # ESI pagination error.
22
+ class PaginationError < ClientError
23
+ attr_reader :responses
24
+
25
+ def initialize(msg, responses:)
26
+ super(msg, response: nil)
27
+
28
+ @responses = responses
29
+ end
30
+ end
31
+
21
32
  # ESI unauthorized error.
22
33
  class UnauthorizedError < ClientError; end
23
34
 
data/lib/esi/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module ESI
4
- VERSION = "1.1.2"
4
+ VERSION = "2.1.0"
5
5
  end
data/package.json ADDED
@@ -0,0 +1,19 @@
1
+ {
2
+ "name": "esi-sdk",
3
+ "private": true,
4
+ "dependencies": {},
5
+ "version": "1.2.0",
6
+ "description": "API client for the EVE Swagger Interface (ESI)",
7
+ "repository": "https://github.com/bokoboshahni/esi-sdk-ruby.git",
8
+ "author": "Bokobo Shahni <shahni@bokobo.space>",
9
+ "license": "MIT",
10
+ "devDependencies": {
11
+ "@semantic-release/changelog": "^5.0.1",
12
+ "@semantic-release/exec": "^6.0.1",
13
+ "@semantic-release/git": "^9.0.1",
14
+ "semantic-release": "^17.4.7"
15
+ },
16
+ "scripts": {
17
+ "release": "semantic-release"
18
+ }
19
+ }
data/release.config.js CHANGED
@@ -21,10 +21,10 @@ module.exports = {
21
21
  changelogTitle: '# ESI SDK Changelog'
22
22
  }],
23
23
  ['@semantic-release/exec', {
24
- prepareCmd: "VERSION=${nextRelease.version} bundle exec rake set_version"
24
+ prepareCmd: "VERSION=${nextRelease.version} bundle exec rake set_version && bundle install"
25
25
  }],
26
26
  ['@semantic-release/git', {
27
- assets: ['CHANGELOG.md', 'lib/esi/version.rb']
27
+ assets: ['CHANGELOG.md', 'Gemfile.lock', 'lib/esi/version.rb']
28
28
  }],
29
29
  ['@semantic-release/exec', {
30
30
  publishCmd: "bundle exec rake build release:rubygem_push"