esi 0.4.5 → 0.4.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/esi.gemspec +19 -15
- data/lib/esi/access_token.rb +3 -1
- data/lib/esi/api_error.rb +134 -0
- data/lib/esi/calls/info.rb +0 -0
- data/lib/esi/calls.rb +26 -19
- data/lib/esi/client.rb +125 -31
- data/lib/esi/o_auth.rb +8 -15
- data/lib/esi/response.rb +32 -8
- data/lib/esi/version.rb +3 -1
- data/lib/esi.rb +46 -45
- data/lib/omniauth/esi.rb +2 -0
- data/lib/omniauth/strategies/esi.rb +12 -8
- metadata +61 -15
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 4ef7c659090137fe7ff8581cdb6c6a9e9c240faa
|
4
|
+
data.tar.gz: 1e47ffce54eda2555fa7f64e3e841e0507162040
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 3354040d05b7f3d674c072081b30815bc63b1ced681d64933e24461b039839f424e29724e2e624320120b652a5e4e43dc7253a5eca4fd3371b0a745bc6db60c1
|
7
|
+
data.tar.gz: 318a635d10e008cd0fc1daf06f8cfe028c677f041af49db8261a8f6d08d535862ff1a25ac758835b2397d9d96f0cbc84dce9dbecfffbbe6c5c0f3f85e366d825
|
data/esi.gemspec
CHANGED
@@ -1,26 +1,30 @@
|
|
1
|
-
#
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
2
3
|
lib = File.expand_path('../lib', __FILE__)
|
3
4
|
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
5
|
require 'esi/version'
|
5
6
|
|
6
7
|
Gem::Specification.new do |spec|
|
7
|
-
spec.name =
|
8
|
+
spec.name = 'esi'
|
8
9
|
spec.version = Esi::VERSION
|
9
|
-
spec.authors = [
|
10
|
-
spec.email = [
|
10
|
+
spec.authors = ['Danny Hiemstra', 'Aaron Allen']
|
11
|
+
spec.email = ['dannyhiemstra@gmail.com', 'aaronmallen4@gmail.com']
|
11
12
|
|
12
|
-
spec.summary =
|
13
|
-
spec.description =
|
14
|
-
spec.homepage =
|
15
|
-
spec.license =
|
13
|
+
spec.summary = 'EVE ESI API wrapper'
|
14
|
+
spec.description = 'EVE ESI API wrapper'
|
15
|
+
spec.homepage = 'https://github.com/dhiemstra/esi'
|
16
|
+
spec.license = 'MIT'
|
16
17
|
|
17
18
|
spec.files = %w(LICENSE.txt README.md esi.gemspec) + Dir['lib/**/*.rb']
|
18
|
-
spec.require_paths = [
|
19
|
+
spec.require_paths = ['lib']
|
19
20
|
|
20
|
-
spec.add_dependency
|
21
|
-
spec.add_dependency
|
22
|
-
spec.add_dependency
|
23
|
-
spec.add_development_dependency
|
24
|
-
spec.add_development_dependency
|
25
|
-
spec.add_development_dependency
|
21
|
+
spec.add_dependency 'activesupport'
|
22
|
+
spec.add_dependency 'addressable', '~> 2.3'
|
23
|
+
spec.add_dependency 'oauth2', '~> 1.4'
|
24
|
+
spec.add_development_dependency 'bundler', '~> 1.14'
|
25
|
+
spec.add_development_dependency 'minitest', '~> 5.0'
|
26
|
+
spec.add_development_dependency 'rake', '~> 10.0'
|
27
|
+
spec.add_development_dependency 'rubocop', '~> 0.52'
|
28
|
+
spec.add_development_dependency 'shoulda', '~> 3.5'
|
29
|
+
spec.add_development_dependency 'yard', '~> 0.9'
|
26
30
|
end
|
data/lib/esi/access_token.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Esi
|
2
4
|
class AccessToken < OAuth2::AccessToken
|
3
5
|
EXPIRES_MARGIN = 30.seconds
|
@@ -13,7 +15,7 @@ module Esi
|
|
13
15
|
end
|
14
16
|
|
15
17
|
def verify
|
16
|
-
Esi::Response.new(get(
|
18
|
+
Esi::Response.new(get('/oauth/verify'))
|
17
19
|
end
|
18
20
|
|
19
21
|
def expired?
|
@@ -0,0 +1,134 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Esi
|
4
|
+
# ApiError base class
|
5
|
+
# @!attribute [r] response
|
6
|
+
# @return [Esi::Response] the ApiError Response
|
7
|
+
# @!attribute [r] key
|
8
|
+
# @return [String] the response.data[:key]
|
9
|
+
# @!attribute [r] message
|
10
|
+
# @return [String] the response error message
|
11
|
+
# @!attribute [r] type
|
12
|
+
# @return [String] the response.data[:exceptionType]
|
13
|
+
# @!attribute [r] original_exception
|
14
|
+
# @return [ExceptionClass|nil] the orginal raised exception
|
15
|
+
class ApiError < OAuth2::Error
|
16
|
+
attr_reader :response, :key, :message, :type, :original_exception
|
17
|
+
|
18
|
+
# Create a new instance of ApiError
|
19
|
+
# @param [Esi::Response] response the response that generated the exception
|
20
|
+
# @param [ExceptionClass|nil] the orginally raised exception
|
21
|
+
# @return [Esi::ApiError] an instance of ApiError
|
22
|
+
def initialize(response, original_exception = nil)
|
23
|
+
super(response.original_response)
|
24
|
+
|
25
|
+
@response = response
|
26
|
+
@original_exception = original_exception
|
27
|
+
@code = response.original_response.status
|
28
|
+
@key = response.data[:key]
|
29
|
+
@message = response.data[:message].presence || response.data[:error] || original_exception.try(:message)
|
30
|
+
@type = response.data[:exceptionType]
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
# ApiRequestError Class
|
35
|
+
# @!attribute [r] original_exception
|
36
|
+
# @return [ExceptionClass|nil] the orginal raised exception
|
37
|
+
class ApiRequestError < StandardError
|
38
|
+
attr_reader :original_exception
|
39
|
+
|
40
|
+
# Create a new instance of ApiRequestError
|
41
|
+
# @param [ExceptionClass|nil] the orginally raised exception
|
42
|
+
# @return [Esi::ApiRequestError] the instance of ApiRequestError
|
43
|
+
def initialize(original_exception)
|
44
|
+
@original_exception = original_exception
|
45
|
+
msg = "#{original_exception.class}: " \
|
46
|
+
"#{original_exception.try(:response).try(:status)}" \
|
47
|
+
' - ' \
|
48
|
+
"#{original_exception.try(:message)}"
|
49
|
+
super(msg)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
# ApiUnknowntError Class
|
54
|
+
# @!attribute [r] response
|
55
|
+
# @return [Esi::Response] the ApiError Response
|
56
|
+
# @!attribute [r] key
|
57
|
+
# @return [String] the response.data[:key]
|
58
|
+
# @!attribute [r] message
|
59
|
+
# @return [String] the response error message
|
60
|
+
# @!attribute [r] type
|
61
|
+
# @return [String] the response.data[:exceptionType]
|
62
|
+
# @!attribute [r] original_exception
|
63
|
+
# @return [ExceptionClass|nil] the orginal raised exception
|
64
|
+
class ApiUnknownError < ApiError; end
|
65
|
+
|
66
|
+
# ApiBadRequestError Class
|
67
|
+
# @!attribute [r] response
|
68
|
+
# @return [Esi::Response] the ApiError Response
|
69
|
+
# @!attribute [r] key
|
70
|
+
# @return [String] the response.data[:key]
|
71
|
+
# @!attribute [r] message
|
72
|
+
# @return [String] the response error message
|
73
|
+
# @!attribute [r] type
|
74
|
+
# @return [String] the response.data[:exceptionType]
|
75
|
+
# @!attribute [r] original_exception
|
76
|
+
# @return [ExceptionClass|nil] the orginal raised exception
|
77
|
+
class ApiBadRequestError < ApiError; end
|
78
|
+
|
79
|
+
# ApiRefreshTokenExpiredError Class
|
80
|
+
# @!attribute [r] response
|
81
|
+
# @return [Esi::Response] the ApiError Response
|
82
|
+
# @!attribute [r] key
|
83
|
+
# @return [String] the response.data[:key]
|
84
|
+
# @!attribute [r] message
|
85
|
+
# @return [String] the response error message
|
86
|
+
# @!attribute [r] type
|
87
|
+
# @return [String] the response.data[:exceptionType]
|
88
|
+
# @!attribute [r] original_exception
|
89
|
+
# @return [ExceptionClass|nil] the orginal raised exception
|
90
|
+
class ApiRefreshTokenExpiredError < ApiError; end
|
91
|
+
|
92
|
+
# ApiInvalidAppClientKeysError Class
|
93
|
+
# @!attribute [r] response
|
94
|
+
# @return [Esi::Response] the ApiError Response
|
95
|
+
# @!attribute [r] key
|
96
|
+
# @return [String] the response.data[:key]
|
97
|
+
# @!attribute [r] message
|
98
|
+
# @return [String] the response error message
|
99
|
+
# @!attribute [r] type
|
100
|
+
# @return [String] the response.data[:exceptionType]
|
101
|
+
# @!attribute [r] original_exception
|
102
|
+
# @return [ExceptionClass|nil] the orginal raised exception
|
103
|
+
class ApiInvalidAppClientKeysError < ApiError; end
|
104
|
+
|
105
|
+
# ApiNotFoundError Class
|
106
|
+
# @!attribute [r] response
|
107
|
+
# @return [Esi::Response] the ApiError Response
|
108
|
+
# @!attribute [r] key
|
109
|
+
# @return [String] the response.data[:key]
|
110
|
+
# @!attribute [r] message
|
111
|
+
# @return [String] the response error message
|
112
|
+
# @!attribute [r] type
|
113
|
+
# @return [String] the response.data[:exceptionType]
|
114
|
+
# @!attribute [r] original_exception
|
115
|
+
# @return [ExceptionClass|nil] the orginal raised exception
|
116
|
+
class ApiNotFoundError < ApiError; end
|
117
|
+
|
118
|
+
# ApiForbiddenError Class
|
119
|
+
# @!attribute [r] response
|
120
|
+
# @return [Esi::Response] the ApiError Response
|
121
|
+
# @!attribute [r] key
|
122
|
+
# @return [String] the response.data[:key]
|
123
|
+
# @!attribute [r] message
|
124
|
+
# @return [String] the response error message
|
125
|
+
# @!attribute [r] type
|
126
|
+
# @return [String] the response.data[:exceptionType]
|
127
|
+
# @!attribute [r] original_exception
|
128
|
+
# @return [ExceptionClass|nil] the orginal raised exception
|
129
|
+
class ApiForbiddenError < ApiError; end
|
130
|
+
|
131
|
+
# Error Class
|
132
|
+
# @see [StandardError](https://ruby-doc.org/core-2.3.2/StandardError.html)
|
133
|
+
class Error < StandardError; end
|
134
|
+
end
|
File without changes
|
data/lib/esi/calls.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Esi
|
2
4
|
class Calls
|
3
5
|
class << self
|
@@ -29,13 +31,18 @@ module Esi
|
|
29
31
|
end
|
30
32
|
|
31
33
|
class Base
|
34
|
+
CACHE_NAMESPACE = 'esi'
|
35
|
+
|
32
36
|
class_attribute :scope
|
33
37
|
class_attribute :cache_duration
|
34
38
|
|
35
39
|
attr_accessor :path, :params
|
36
40
|
|
37
41
|
def cache_key
|
38
|
-
@cache_key ||=
|
42
|
+
@cache_key ||= begin
|
43
|
+
cache_args = [CACHE_NAMESPACE, path.gsub(%r{^\/}, ''), params.sort].flatten
|
44
|
+
ActiveSupport::Cache.expand_cache_key(cache_args)
|
45
|
+
end
|
39
46
|
end
|
40
47
|
|
41
48
|
def method
|
@@ -52,13 +59,13 @@ module Esi
|
|
52
59
|
end
|
53
60
|
|
54
61
|
def paginated?
|
55
|
-
|
62
|
+
!@paginated
|
56
63
|
end
|
57
64
|
end
|
58
65
|
|
59
66
|
class Regions < Base
|
60
67
|
def initialize
|
61
|
-
@path =
|
68
|
+
@path = '/universe/regions/'
|
62
69
|
end
|
63
70
|
end
|
64
71
|
|
@@ -70,7 +77,7 @@ module Esi
|
|
70
77
|
|
71
78
|
class Constellations < Base
|
72
79
|
def initialize
|
73
|
-
@path =
|
80
|
+
@path = '/universe/constellations/'
|
74
81
|
end
|
75
82
|
end
|
76
83
|
|
@@ -88,7 +95,7 @@ module Esi
|
|
88
95
|
|
89
96
|
class SolarSystems < Base
|
90
97
|
def initialize
|
91
|
-
@path =
|
98
|
+
@path = '/universe/systems/'
|
92
99
|
end
|
93
100
|
end
|
94
101
|
|
@@ -124,7 +131,7 @@ module Esi
|
|
124
131
|
|
125
132
|
class Structures < Base
|
126
133
|
def initialize
|
127
|
-
@path =
|
134
|
+
@path = '/universe/structures/'
|
128
135
|
end
|
129
136
|
end
|
130
137
|
|
@@ -136,7 +143,7 @@ module Esi
|
|
136
143
|
|
137
144
|
class Types < Base
|
138
145
|
def initialize
|
139
|
-
@path =
|
146
|
+
@path = '/universe/types'
|
140
147
|
@paginated = true
|
141
148
|
end
|
142
149
|
end
|
@@ -149,7 +156,7 @@ module Esi
|
|
149
156
|
|
150
157
|
class DogmaAttributes < Base
|
151
158
|
def initialize
|
152
|
-
@path =
|
159
|
+
@path = '/dogma/attributes/'
|
153
160
|
end
|
154
161
|
end
|
155
162
|
|
@@ -161,7 +168,7 @@ module Esi
|
|
161
168
|
|
162
169
|
class DogmaEffects < Base
|
163
170
|
def initialize
|
164
|
-
@path =
|
171
|
+
@path = '/dogma/effects/'
|
165
172
|
end
|
166
173
|
end
|
167
174
|
|
@@ -176,7 +183,7 @@ module Esi
|
|
176
183
|
self.cache_duration = 3600
|
177
184
|
|
178
185
|
def initialize
|
179
|
-
@path =
|
186
|
+
@path = '/industry/facilities'
|
180
187
|
end
|
181
188
|
end
|
182
189
|
|
@@ -185,7 +192,7 @@ module Esi
|
|
185
192
|
self.cache_duration = 3600
|
186
193
|
|
187
194
|
def initialize
|
188
|
-
@path =
|
195
|
+
@path = '/industry/systems'
|
189
196
|
end
|
190
197
|
end
|
191
198
|
|
@@ -194,7 +201,7 @@ module Esi
|
|
194
201
|
# https://esi.tech.ccp.is/latest/characters/907452336/search/?categories=structure&datasource=tranquility&search=Kamela&strict=false&token=Fp3ThF7wjvYBIDIIrtWE_Ryjt9BhYwUP75y2EL5Eq9mHPm8tYt9I9NwgZz8o26FFQBKoUToh2DYVc-Q5Ws400g2
|
195
202
|
|
196
203
|
def initialize(character_id: nil, categories:, search:, strict: false)
|
197
|
-
@path = (character_id ? "/characters/#{character_id}" : '') +
|
204
|
+
@path = (character_id ? "/characters/#{character_id}" : '') + '/search'
|
198
205
|
@params = { categories: categories, search: search, strict: strict }
|
199
206
|
end
|
200
207
|
end
|
@@ -210,7 +217,7 @@ module Esi
|
|
210
217
|
self.cache_duration = 3600
|
211
218
|
|
212
219
|
def initialize(character_ids)
|
213
|
-
@path =
|
220
|
+
@path = '/characters/names'
|
214
221
|
@params = { character_ids: character_ids.join(',') }
|
215
222
|
end
|
216
223
|
end
|
@@ -412,7 +419,7 @@ module Esi
|
|
412
419
|
self.cache_duration = 3600
|
413
420
|
|
414
421
|
def initialize
|
415
|
-
@path =
|
422
|
+
@path = '/alliances'
|
416
423
|
end
|
417
424
|
end
|
418
425
|
|
@@ -420,7 +427,7 @@ module Esi
|
|
420
427
|
self.cache_duration = 3600
|
421
428
|
|
422
429
|
def initialize(alliance_ids)
|
423
|
-
@path =
|
430
|
+
@path = '/alliances/names'
|
424
431
|
@params = { alliance_ids: alliance_ids.join(',') }
|
425
432
|
end
|
426
433
|
end
|
@@ -437,7 +444,7 @@ module Esi
|
|
437
444
|
self.cache_duration = 3600
|
438
445
|
|
439
446
|
def initialize(corporation_ids)
|
440
|
-
@path =
|
447
|
+
@path = '/corporations/names'
|
441
448
|
@params = { corporation_ids: corporation_ids.join(',') }
|
442
449
|
end
|
443
450
|
end
|
@@ -526,7 +533,7 @@ module Esi
|
|
526
533
|
|
527
534
|
class MarketGroups < Base
|
528
535
|
def initialize
|
529
|
-
@path =
|
536
|
+
@path = '/markets/groups'
|
530
537
|
@paginated = true
|
531
538
|
end
|
532
539
|
end
|
@@ -539,7 +546,7 @@ module Esi
|
|
539
546
|
|
540
547
|
class MarketPrices < Base
|
541
548
|
def initialize
|
542
|
-
@path =
|
549
|
+
@path = '/markets/prices'
|
543
550
|
end
|
544
551
|
end
|
545
552
|
|
@@ -605,7 +612,7 @@ module Esi
|
|
605
612
|
self.scope = 'esi-ui.open_window.v1'
|
606
613
|
|
607
614
|
def initialize(type_id)
|
608
|
-
@path =
|
615
|
+
@path = '/ui/openwindow/marketdetails'
|
609
616
|
@method = :post
|
610
617
|
@params = { type_id: type_id }
|
611
618
|
end
|
data/lib/esi/client.rb
CHANGED
@@ -1,17 +1,90 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Esi
|
4
|
+
# The Esi Client class
|
5
|
+
# @!attribute [rw] refresh_callback
|
6
|
+
# @return [#callback] the refresh_token callback method
|
7
|
+
# @!attribute [rw] access_token
|
8
|
+
# @return [String] the esi access_token
|
9
|
+
# @!attribute [rw] refresh_token
|
10
|
+
# @return [String] the esi refresh_token string
|
11
|
+
# @!attribute [rw] expires_at
|
12
|
+
# @return [Time] the timestamp of the esi token expire
|
13
|
+
# @!attribute [r] logger
|
14
|
+
# @return [Logger] the logger class for the gem
|
15
|
+
# @!attribute [r] oauth
|
16
|
+
# @return [Esi::Oauth] the oauth instance for the client
|
2
17
|
class Client
|
18
|
+
# @return [Fixnum] The max amount of request attempst Client will make
|
3
19
|
MAX_ATTEMPTS = 2
|
4
20
|
|
5
21
|
attr_accessor :refresh_callback, :access_token, :refresh_token, :expires_at
|
6
22
|
attr_reader :logger, :oauth
|
7
23
|
|
24
|
+
# Create a new instance of Client
|
25
|
+
# @param [String] token the esi access_token
|
26
|
+
# @param [String] refresh_token the esi refresh_token
|
27
|
+
# @param [Time] expires_at the time stamp the esi token expires_at
|
8
28
|
def initialize(token: nil, refresh_token: nil, expires_at: nil)
|
9
29
|
@logger = Esi.logger
|
10
30
|
@access_token = token
|
11
31
|
@refresh_token = refresh_token
|
12
32
|
@expires_at = expires_at
|
33
|
+
@oauth = init_oauth
|
34
|
+
end
|
35
|
+
|
36
|
+
# Set the current thread's Esi::Client
|
37
|
+
# @params [Esi::Client] the client to set
|
38
|
+
# @return [Esi::Client] the current thread's Esi::Client
|
39
|
+
def self.current=(client)
|
40
|
+
Thread.current[:esi_client] = client
|
41
|
+
end
|
42
|
+
|
43
|
+
# Get the current thread's Esi::Client
|
44
|
+
# @return [Esi::Client] the current thread's Esi::Client
|
45
|
+
def self.current
|
46
|
+
Thread.current[:esi_client] ||= new
|
47
|
+
end
|
48
|
+
|
49
|
+
# Switch to default Esi::Client (Esi::Client.new)
|
50
|
+
# @return [Esi::Client] the current thread's Esi::Client
|
51
|
+
def self.switch_to_default
|
52
|
+
self.current = new
|
53
|
+
end
|
54
|
+
|
55
|
+
# Switch current thread's client to instance of Esi::Client
|
56
|
+
# @return [self] the instance calling switch to
|
57
|
+
def switch_to
|
58
|
+
Esi::Client.current = self
|
59
|
+
end
|
60
|
+
|
61
|
+
# Yield block with instance of Esi::Client and revert to
|
62
|
+
# previous client or default client
|
63
|
+
#
|
64
|
+
# @example Call an Esi::Client method using an instance of client
|
65
|
+
# new_client = Esi::Client.new(token: 'foo', refresh_token: 'foo', expires_at: 30.minutes.from_now)
|
66
|
+
# new_client.with_client do |client|
|
67
|
+
# client.character(1234)
|
68
|
+
# end
|
69
|
+
# #=> Esi::Response<#>
|
70
|
+
#
|
71
|
+
# @yieldreturn [#block] the passed block.
|
72
|
+
def with_client
|
73
|
+
initial_client = Esi::Client.current
|
74
|
+
switch_to
|
75
|
+
yield(self) if block_given?
|
76
|
+
ensure
|
77
|
+
initial_client.switch_to if initial_client
|
78
|
+
Esi::Client.switch_to_default unless initial_client
|
13
79
|
end
|
14
80
|
|
81
|
+
# Intercept Esi::Client method_missing and attempt to call an Esi::Request
|
82
|
+
# with an Esi::Calls
|
83
|
+
# @param [Symbol|String] name the name of the method called
|
84
|
+
# @param [Array] *args the arguments to call the method with
|
85
|
+
# @param [#block] &block the block to pass to the underlying method
|
86
|
+
# @raise [NameError] If the Esi::Calls does not exist
|
87
|
+
# @return [Esi::Response] the response given for the call
|
15
88
|
def method_missing(name, *args, &block)
|
16
89
|
klass = nil
|
17
90
|
ActiveSupport::Notifications.instrument('esi.client.detect_call') do
|
@@ -25,6 +98,9 @@ module Esi
|
|
25
98
|
cached_response(klass, *args, &block)
|
26
99
|
end
|
27
100
|
|
101
|
+
# Test if the Esi::Client has a method
|
102
|
+
# @param [Symbol] name the name of the method to test
|
103
|
+
# @return [Boolean] wether or not the method exists
|
28
104
|
def method?(name)
|
29
105
|
begin
|
30
106
|
klass = Esi::Calls.const_get(method_to_class_name(name))
|
@@ -34,15 +110,24 @@ module Esi
|
|
34
110
|
!klass.nil?
|
35
111
|
end
|
36
112
|
|
113
|
+
# Test if the Esi::Client has a pluralized version of a method
|
114
|
+
# @param [Symbol] name the name of the method to test
|
115
|
+
# @return [Boolean] wether or not the pluralized method exists
|
37
116
|
def plural_method?(name)
|
38
117
|
plural = name.to_s.pluralize.to_sym
|
39
118
|
method? plural
|
40
119
|
end
|
41
120
|
|
121
|
+
# Log a message
|
122
|
+
# @param [String] message the message to log
|
123
|
+
# @return [void] the Logger.info method with message
|
42
124
|
def log(message)
|
43
125
|
logger.info message
|
44
126
|
end
|
45
127
|
|
128
|
+
# Log a message with debug
|
129
|
+
# @param [String] message the message to log
|
130
|
+
# @return [void] the Logger.debug method with message
|
46
131
|
def debug(message)
|
47
132
|
logger.debug message
|
48
133
|
end
|
@@ -64,46 +149,45 @@ module Esi
|
|
64
149
|
name.dup.to_s.split('_').map(&:capitalize).join
|
65
150
|
end
|
66
151
|
|
67
|
-
def
|
152
|
+
def init_oauth
|
68
153
|
@oauth ||= OAuth.new(
|
69
154
|
access_token: @access_token,
|
70
155
|
refresh_token: @refresh_token,
|
71
156
|
expires_at: @expires_at,
|
72
|
-
callback:
|
157
|
+
callback: lambda { |token, expires_at|
|
73
158
|
@access_token = token
|
74
159
|
@expires_at = expires_at
|
75
|
-
if refresh_callback.respond_to?(:call)
|
76
|
-
refresh_callback.call(token, expires_at)
|
77
|
-
end
|
160
|
+
refresh_callback.call(token, expires_at) if refresh_callback.respond_to?(:call)
|
78
161
|
}
|
79
162
|
)
|
80
163
|
end
|
81
164
|
|
82
165
|
def request_paginated(call, &block)
|
166
|
+
call.page = 1
|
83
167
|
response = nil
|
84
|
-
page = 1
|
85
|
-
|
86
168
|
ActiveSupport::Notifications.instrument('esi.client.request.paginated') do
|
87
|
-
|
88
|
-
call.page = page
|
89
|
-
page_response = request(call, &block)
|
90
|
-
|
91
|
-
if page_response.data.blank?
|
92
|
-
break
|
93
|
-
elsif response
|
94
|
-
response.merge(page_response)
|
95
|
-
else
|
96
|
-
response = page_response
|
97
|
-
end
|
98
|
-
|
99
|
-
page += 1
|
100
|
-
end
|
169
|
+
response = paginated_response(response, call, &block)
|
101
170
|
end
|
102
|
-
|
103
171
|
response
|
104
172
|
end
|
105
173
|
|
174
|
+
def paginated_response(response, call, &block)
|
175
|
+
loop do
|
176
|
+
page_response = request(call, &block)
|
177
|
+
break response if page_response.data.blank?
|
178
|
+
response = response ? response.merge(page_response) : page_response
|
179
|
+
call.page += 1
|
180
|
+
end
|
181
|
+
end
|
182
|
+
|
106
183
|
# FIXME: esi should not retry
|
184
|
+
# FIXME: make rubocop compliant
|
185
|
+
# rubocop:disable Lint/ShadowedException
|
186
|
+
# rubocop:disable Metrics/AbcSize
|
187
|
+
# rubocop:disable Metrics/BlockLength
|
188
|
+
# rubocop:disable Metrics/CyclomaticComplexity
|
189
|
+
# rubocop:disable Metrics/MethodLength
|
190
|
+
# rubocop:disable Metrics/PerceivedComplexity
|
107
191
|
def request(call, &block)
|
108
192
|
response = nil
|
109
193
|
last_ex = nil
|
@@ -113,12 +197,12 @@ module Esi
|
|
113
197
|
debug "Starting request: #{url}"
|
114
198
|
|
115
199
|
ActiveSupport::Notifications.instrument('esi.client.request') do
|
116
|
-
1.upto(MAX_ATTEMPTS) do |
|
200
|
+
1.upto(MAX_ATTEMPTS) do |_try|
|
117
201
|
last_ex = nil
|
118
202
|
response = nil
|
119
203
|
|
120
204
|
begin
|
121
|
-
response = Timeout
|
205
|
+
response = Timeout.timeout(Esi.config.timeout) do
|
122
206
|
oauth.request(call.method, url, options)
|
123
207
|
end
|
124
208
|
rescue Faraday::SSLError, Faraday::ConnectionFailed, Timeout::Error, Net::ReadTimeout => e
|
@@ -136,7 +220,7 @@ module Esi
|
|
136
220
|
sleep 5
|
137
221
|
next
|
138
222
|
when 503 # Rate Limit
|
139
|
-
logger.error
|
223
|
+
logger.error 'RateLimit error, sleeping for 5 seconds'
|
140
224
|
sleep 5
|
141
225
|
next
|
142
226
|
when 404 # Not Found
|
@@ -166,34 +250,44 @@ module Esi
|
|
166
250
|
break if response
|
167
251
|
end
|
168
252
|
end
|
253
|
+
# rubocop:enable Lint/ShadowedException
|
254
|
+
# rubocop:enable Metrics/AbcSize
|
255
|
+
# rubocop:enable Metrics/BlockLength
|
256
|
+
# rubocop:enable Metrics/CyclomaticComplexity
|
257
|
+
# rubocop:enable Metrics/MethodLength
|
258
|
+
# rubocop:enable Metrics/PerceivedComplexity
|
169
259
|
|
170
260
|
if last_ex
|
171
261
|
logger.error "Request failed with #{last_ex.class}"
|
172
262
|
debug_error(last_ex.class, url, response)
|
173
|
-
raise Esi::ApiRequestError
|
263
|
+
raise Esi::ApiRequestError, last_ex
|
174
264
|
end
|
175
265
|
|
176
|
-
debug
|
266
|
+
debug 'Request successful'
|
177
267
|
|
178
268
|
ActiveSupport::Notifications.instrument('esi.client.response.render') do
|
179
269
|
response = Response.new(response, call)
|
180
270
|
response.save
|
181
271
|
end
|
182
272
|
ActiveSupport::Notifications.instrument('esi.client.response.callback') do
|
183
|
-
response.data.each { |item|
|
273
|
+
response.data.each { |item| yield(item) } if block
|
184
274
|
end
|
185
275
|
response
|
186
276
|
end
|
187
277
|
|
188
278
|
def debug_error(klass, url, response)
|
189
279
|
[
|
190
|
-
'-'*60,
|
280
|
+
'-' * 60,
|
191
281
|
"#{klass}(#{response.error})",
|
192
282
|
"STATUS: #{response.status}",
|
193
|
-
"MESSAGE: #{
|
283
|
+
"MESSAGE: #{debug_message_for_response(response)}",
|
194
284
|
"URL: #{url}",
|
195
|
-
'-'*60
|
285
|
+
'-' * 60
|
196
286
|
].each { |msg| logger.error(msg) }
|
197
287
|
end
|
288
|
+
|
289
|
+
def debug_message_for_response(response)
|
290
|
+
response.respond_to?(:data) ? (response.data[:message].presence || response.data[:error]) : response.try(:body)
|
291
|
+
end
|
198
292
|
end
|
199
293
|
end
|
data/lib/esi/o_auth.rb
CHANGED
@@ -1,9 +1,11 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Esi
|
2
4
|
class OAuth
|
3
5
|
extend Forwardable
|
4
6
|
|
5
7
|
attr_reader :access_token, :refresh_token, :expires_at
|
6
|
-
def_delegators :token, :get, :post, :delete, :patch, :put
|
8
|
+
def_delegators :token, :request, :get, :post, :delete, :patch, :put
|
7
9
|
|
8
10
|
class << self
|
9
11
|
def authorize_url(redirect_uri:, scopes: nil)
|
@@ -20,15 +22,13 @@ module Esi
|
|
20
22
|
def client
|
21
23
|
@client ||= OAuth2::Client.new(
|
22
24
|
Esi.config.client_id, Esi.config.client_secret,
|
23
|
-
|
25
|
+
site: Esi.config.oauth_host
|
24
26
|
)
|
25
27
|
end
|
26
28
|
end
|
27
29
|
|
28
30
|
def initialize(access_token:, refresh_token:, expires_at:, callback: nil)
|
29
|
-
if callback && !callback.respond_to?(:call)
|
30
|
-
raise Esi::Error.new("Callback should be a callable Proc")
|
31
|
-
end
|
31
|
+
raise Esi::Error, 'Callback should be a callable Proc' if callback && !callback.respond_to?(:call)
|
32
32
|
|
33
33
|
@access_token = access_token
|
34
34
|
@refresh_token = refresh_token
|
@@ -36,28 +36,21 @@ module Esi
|
|
36
36
|
@callback = callback if callback
|
37
37
|
end
|
38
38
|
|
39
|
-
def request(*args)
|
40
|
-
token.request(*args)
|
41
|
-
end
|
42
|
-
|
43
39
|
private
|
44
40
|
|
45
41
|
def token
|
46
|
-
@token = Esi::AccessToken.new(OAuth.client, @access_token,
|
47
|
-
|
48
|
-
})
|
42
|
+
@token = Esi::AccessToken.new(OAuth.client, @access_token,
|
43
|
+
refresh_token: @refresh_token, expires_at: @expires_at)
|
49
44
|
refresh_access_token if @token.expired?
|
50
45
|
@token
|
51
46
|
end
|
52
47
|
|
53
48
|
def refresh_access_token
|
54
|
-
Esi.logger.debug "Refreshing access token"
|
55
|
-
|
56
49
|
ActiveSupport::Notifications.instrument('esi.oauth.refresh_token') do
|
57
50
|
@token = @token.refresh!
|
58
51
|
@access_token = @token.token
|
59
52
|
@expires_at = @token.expires_at.integer? ? Time.at(@token.expires_at) : @token.expires_at
|
60
|
-
@callback
|
53
|
+
@callback&.call(@access_token, @expires_at)
|
61
54
|
end
|
62
55
|
end
|
63
56
|
end
|
data/lib/esi/response.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Esi
|
2
4
|
class Response
|
3
5
|
extend Forwardable
|
@@ -6,10 +8,10 @@ module Esi
|
|
6
8
|
def_delegators :original_response, :status, :body, :headers
|
7
9
|
def_delegators :data, :each
|
8
10
|
|
9
|
-
def initialize(response, call=nil)
|
11
|
+
def initialize(response, call = nil)
|
10
12
|
@original_response = response
|
13
|
+
@data = normalize_response_body
|
11
14
|
@call = call
|
12
|
-
@data = MultiJson.load(body || {}, symbolize_keys: true, object_class: OpenStruct) # rescue OpenStruct.new
|
13
15
|
end
|
14
16
|
|
15
17
|
def merge(other_response)
|
@@ -29,18 +31,40 @@ module Esi
|
|
29
31
|
@cached_until ||= headers[:expires] ? Time.parse(headers[:expires]) : nil
|
30
32
|
end
|
31
33
|
|
34
|
+
def response_json
|
35
|
+
@response_json ||= begin
|
36
|
+
MultiJson.load(body, symbolize_keys: true)
|
37
|
+
rescue StandardError
|
38
|
+
{}
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
32
42
|
def save
|
33
|
-
return
|
34
|
-
|
43
|
+
return unless should_log_response?
|
44
|
+
File.write(log_directroy.join("#{Time.now.to_i}.json"), to_json)
|
45
|
+
end
|
35
46
|
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
47
|
+
def log_directory
|
48
|
+
call.class.to_s.split('::').last.underscore
|
49
|
+
dir = Pathname.new(Esi.config.response_log_path).join(call_name)
|
50
|
+
FileUtils.mkdir_p(dir)
|
51
|
+
dir
|
52
|
+
end
|
53
|
+
|
54
|
+
def should_log_response?
|
55
|
+
return false if call.nil?
|
56
|
+
return false if Esi.config.response_log_path.blank? || !Dir.exist?(Esi.config.response_log_path)
|
57
|
+
true
|
40
58
|
end
|
41
59
|
|
42
60
|
def method_missing(method, *args, &block)
|
43
61
|
data.send(method, *args, &block)
|
44
62
|
end
|
63
|
+
|
64
|
+
private
|
65
|
+
|
66
|
+
def normalize_response_body
|
67
|
+
MultiJson.load(body || {}, symbolize_keys: true, object_class: OpenStruct)
|
68
|
+
end
|
45
69
|
end
|
46
70
|
end
|
data/lib/esi/version.rb
CHANGED
data/lib/esi.rb
CHANGED
@@ -1,12 +1,19 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
require
|
4
|
-
require
|
5
|
-
require
|
6
|
-
require
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'oauth2'
|
4
|
+
require 'forwardable'
|
5
|
+
require 'ostruct'
|
6
|
+
require 'addressable/uri'
|
7
|
+
require 'active_support/cache'
|
8
|
+
require 'active_support/notifications'
|
7
9
|
require 'active_support/core_ext/string'
|
8
|
-
require
|
10
|
+
require 'active_support/core_ext/class/attribute'
|
9
11
|
|
12
|
+
# The main Esi Module
|
13
|
+
# @!attribute [w] api_version
|
14
|
+
# @return [Symbol] the Esi Api version used by the gem
|
15
|
+
# @!attribute [w] logger
|
16
|
+
# @return [Logger] the logger class for the gem
|
10
17
|
module Esi
|
11
18
|
autoload :VERSION, 'esi/version'
|
12
19
|
autoload :AccessToken, 'esi/access_token'
|
@@ -15,6 +22,10 @@ module Esi
|
|
15
22
|
autoload :Client, 'esi/client'
|
16
23
|
autoload :Response, 'esi/response'
|
17
24
|
|
25
|
+
require_relative 'esi/api_error'
|
26
|
+
|
27
|
+
# Default ESI access scopes
|
28
|
+
# @return [Array<String>] the default scopes
|
18
29
|
SCOPES = %w(
|
19
30
|
esi-assets.read_assets.v1
|
20
31
|
esi-bookmarks.read_character_bookmarks.v1
|
@@ -61,7 +72,10 @@ module Esi
|
|
61
72
|
esi-universe.read_structures.v1
|
62
73
|
esi-wallet.read_character_wallet.v1
|
63
74
|
esi-wallet.read_corporation_wallets.v1
|
64
|
-
)
|
75
|
+
).freeze
|
76
|
+
|
77
|
+
# The default Esi gem configuration
|
78
|
+
# @return [Hash{Symbol => Symbol|String|Fixnum|Object|Array}] the default configuration
|
65
79
|
DEFAULT_CONFIG = {
|
66
80
|
datasource: :tranquility,
|
67
81
|
oauth_host: 'https://login.eveonline.com',
|
@@ -75,21 +89,27 @@ module Esi
|
|
75
89
|
client_secret: nil,
|
76
90
|
cache: ActiveSupport::Cache::MemoryStore.new,
|
77
91
|
scopes: SCOPES
|
78
|
-
}
|
92
|
+
}.freeze
|
79
93
|
|
80
94
|
class << self
|
81
95
|
attr_writer :api_version, :config, :logger, :cache
|
82
96
|
|
97
|
+
# The Esi Configuration
|
98
|
+
# @return [OpenStruct] the configuration object
|
83
99
|
def config
|
84
100
|
@config ||= OpenStruct.new(DEFAULT_CONFIG)
|
85
101
|
end
|
86
102
|
|
103
|
+
# The Esi logger class instance
|
104
|
+
# @return [MyLoggerInstance|Logger] an instance of the logger class
|
87
105
|
def logger
|
88
106
|
@logger ||= Esi.config.logger || Logger.new(Esi.config.log_target).tap do |l|
|
89
107
|
l.level = Logger.const_get(Esi.config.log_level.upcase)
|
90
108
|
end
|
91
109
|
end
|
92
110
|
|
111
|
+
# The Esi cache class instance
|
112
|
+
# @return [ActiveSupport::Cache::Store] an instance of cache
|
93
113
|
def cache
|
94
114
|
if Esi.config.cache.nil?
|
95
115
|
@cache ||= ActiveSupport::Cache::NullStore.new
|
@@ -98,54 +118,35 @@ module Esi
|
|
98
118
|
end
|
99
119
|
end
|
100
120
|
|
121
|
+
# The Esi Api version to interface with
|
122
|
+
# @return [Symbol] the esi api version
|
101
123
|
def api_version
|
102
124
|
@api_version || :latest
|
103
125
|
end
|
104
126
|
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
127
|
+
# Generate an Esi url for a given path
|
128
|
+
# @param [String] path the path to generate an esi url for
|
129
|
+
# @param [Hash{Symbol => String|Fixnum}] params the params for the url query
|
130
|
+
# @return [String] the generated url
|
131
|
+
def generate_url(path, params = {})
|
132
|
+
url = url_for_path(path)
|
110
133
|
uri = Addressable::URI.parse(url)
|
111
|
-
uri.query_values = {datasource: config.datasource}.merge(params.to_h)
|
134
|
+
uri.query_values = { datasource: config.datasource }.merge(params.to_h)
|
112
135
|
uri.to_s
|
113
136
|
end
|
114
137
|
|
138
|
+
# The current Esi client
|
139
|
+
# @return [Esi::Client] the current client
|
115
140
|
def client
|
116
|
-
@client ||= Client.
|
117
|
-
end
|
118
|
-
end
|
119
|
-
|
120
|
-
class ApiError < OAuth2::Error
|
121
|
-
attr_reader :response, :key, :message, :type, :original_exception
|
122
|
-
|
123
|
-
def initialize(response, original_exception=nil)
|
124
|
-
super(response.original_response)
|
125
|
-
|
126
|
-
@response = response
|
127
|
-
@original_exception = original_exception
|
128
|
-
@code = response.original_response.status
|
129
|
-
@key = response.data[:key]
|
130
|
-
@message = response.data[:message].presence || response.data[:error] || original_exception.try(:message)
|
131
|
-
@type = response.data[:exceptionType]
|
141
|
+
@client ||= Client.current
|
132
142
|
end
|
133
|
-
end
|
134
143
|
|
135
|
-
|
136
|
-
attr_reader :original_exception
|
144
|
+
private
|
137
145
|
|
138
|
-
def
|
139
|
-
|
140
|
-
|
146
|
+
def url_for_path(path)
|
147
|
+
path = path[1..-1] if path.start_with?('/')
|
148
|
+
path += '/' unless path.end_with?('/')
|
149
|
+
[config.api_host, config.api_version, path].join('/')
|
141
150
|
end
|
142
151
|
end
|
143
|
-
|
144
|
-
class ApiUnknownError < ApiError; end
|
145
|
-
class ApiBadRequestError < ApiError; end
|
146
|
-
class ApiRefreshTokenExpiredError < ApiError; end
|
147
|
-
class ApiInvalidAppClientKeysError < ApiError; end
|
148
|
-
class ApiNotFoundError < ApiError; end
|
149
|
-
class ApiForbiddenError < ApiError; end
|
150
|
-
class Error < StandardError; end
|
151
152
|
end
|
data/lib/omniauth/esi.rb
CHANGED
@@ -1,11 +1,13 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'omniauth/strategies/oauth2'
|
2
4
|
|
3
5
|
module OmniAuth
|
4
6
|
module Strategies
|
5
7
|
class Esi < OmniAuth::Strategies::OAuth2
|
6
8
|
option :name, 'esi'
|
7
|
-
option :client_options,
|
8
|
-
option :authorize_options,
|
9
|
+
option :client_options, site: ::Esi.config.oauth_host, verify_url: '/oauth/verify'
|
10
|
+
option :authorize_options, %i(scope callback_url)
|
9
11
|
|
10
12
|
uid { extra_info[:character_id] }
|
11
13
|
|
@@ -19,11 +21,11 @@ module OmniAuth
|
|
19
21
|
end
|
20
22
|
|
21
23
|
credentials do
|
22
|
-
hash = {token: access_token.token}
|
23
|
-
hash
|
24
|
-
hash
|
25
|
-
hash
|
26
|
-
hash
|
24
|
+
hash = { token: access_token.token }
|
25
|
+
hash[:refresh_token] = access_token.refresh_token if access_token.refresh_token
|
26
|
+
hash[:expires_at] = access_token.expires_at if access_token.expires?
|
27
|
+
hash[:expires] = access_token.expires?
|
28
|
+
hash[:scopes] = extra_info[:scopes].split(' ') if extra_info[:scopes]
|
27
29
|
hash
|
28
30
|
end
|
29
31
|
|
@@ -32,7 +34,9 @@ module OmniAuth
|
|
32
34
|
end
|
33
35
|
|
34
36
|
def extra_info
|
35
|
-
@extra_info ||= deep_symbolize(
|
37
|
+
@extra_info ||= deep_symbolize(
|
38
|
+
access_token.get(options.client_options.verify_url).parsed.transform_keys!(&:underscore)
|
39
|
+
)
|
36
40
|
end
|
37
41
|
|
38
42
|
def authorize_params
|
metadata
CHANGED
@@ -1,29 +1,30 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: esi
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.4.
|
4
|
+
version: 0.4.6
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Danny Hiemstra
|
8
|
+
- Aaron Allen
|
8
9
|
autorequire:
|
9
10
|
bindir: bin
|
10
11
|
cert_chain: []
|
11
|
-
date: 2018-02-
|
12
|
+
date: 2018-02-22 00:00:00.000000000 Z
|
12
13
|
dependencies:
|
13
14
|
- !ruby/object:Gem::Dependency
|
14
|
-
name:
|
15
|
+
name: activesupport
|
15
16
|
requirement: !ruby/object:Gem::Requirement
|
16
17
|
requirements:
|
17
|
-
- - "
|
18
|
+
- - ">="
|
18
19
|
- !ruby/object:Gem::Version
|
19
|
-
version: '
|
20
|
+
version: '0'
|
20
21
|
type: :runtime
|
21
22
|
prerelease: false
|
22
23
|
version_requirements: !ruby/object:Gem::Requirement
|
23
24
|
requirements:
|
24
|
-
- - "
|
25
|
+
- - ">="
|
25
26
|
- !ruby/object:Gem::Version
|
26
|
-
version: '
|
27
|
+
version: '0'
|
27
28
|
- !ruby/object:Gem::Dependency
|
28
29
|
name: addressable
|
29
30
|
requirement: !ruby/object:Gem::Requirement
|
@@ -39,19 +40,19 @@ dependencies:
|
|
39
40
|
- !ruby/object:Gem::Version
|
40
41
|
version: '2.3'
|
41
42
|
- !ruby/object:Gem::Dependency
|
42
|
-
name:
|
43
|
+
name: oauth2
|
43
44
|
requirement: !ruby/object:Gem::Requirement
|
44
45
|
requirements:
|
45
|
-
- - "
|
46
|
+
- - "~>"
|
46
47
|
- !ruby/object:Gem::Version
|
47
|
-
version: '
|
48
|
+
version: '1.4'
|
48
49
|
type: :runtime
|
49
50
|
prerelease: false
|
50
51
|
version_requirements: !ruby/object:Gem::Requirement
|
51
52
|
requirements:
|
52
|
-
- - "
|
53
|
+
- - "~>"
|
53
54
|
- !ruby/object:Gem::Version
|
54
|
-
version: '
|
55
|
+
version: '1.4'
|
55
56
|
- !ruby/object:Gem::Dependency
|
56
57
|
name: bundler
|
57
58
|
requirement: !ruby/object:Gem::Requirement
|
@@ -66,6 +67,20 @@ dependencies:
|
|
66
67
|
- - "~>"
|
67
68
|
- !ruby/object:Gem::Version
|
68
69
|
version: '1.14'
|
70
|
+
- !ruby/object:Gem::Dependency
|
71
|
+
name: minitest
|
72
|
+
requirement: !ruby/object:Gem::Requirement
|
73
|
+
requirements:
|
74
|
+
- - "~>"
|
75
|
+
- !ruby/object:Gem::Version
|
76
|
+
version: '5.0'
|
77
|
+
type: :development
|
78
|
+
prerelease: false
|
79
|
+
version_requirements: !ruby/object:Gem::Requirement
|
80
|
+
requirements:
|
81
|
+
- - "~>"
|
82
|
+
- !ruby/object:Gem::Version
|
83
|
+
version: '5.0'
|
69
84
|
- !ruby/object:Gem::Dependency
|
70
85
|
name: rake
|
71
86
|
requirement: !ruby/object:Gem::Requirement
|
@@ -81,22 +96,51 @@ dependencies:
|
|
81
96
|
- !ruby/object:Gem::Version
|
82
97
|
version: '10.0'
|
83
98
|
- !ruby/object:Gem::Dependency
|
84
|
-
name:
|
99
|
+
name: rubocop
|
85
100
|
requirement: !ruby/object:Gem::Requirement
|
86
101
|
requirements:
|
87
102
|
- - "~>"
|
88
103
|
- !ruby/object:Gem::Version
|
89
|
-
version: '
|
104
|
+
version: '0.52'
|
90
105
|
type: :development
|
91
106
|
prerelease: false
|
92
107
|
version_requirements: !ruby/object:Gem::Requirement
|
93
108
|
requirements:
|
94
109
|
- - "~>"
|
95
110
|
- !ruby/object:Gem::Version
|
96
|
-
version: '
|
111
|
+
version: '0.52'
|
112
|
+
- !ruby/object:Gem::Dependency
|
113
|
+
name: shoulda
|
114
|
+
requirement: !ruby/object:Gem::Requirement
|
115
|
+
requirements:
|
116
|
+
- - "~>"
|
117
|
+
- !ruby/object:Gem::Version
|
118
|
+
version: '3.5'
|
119
|
+
type: :development
|
120
|
+
prerelease: false
|
121
|
+
version_requirements: !ruby/object:Gem::Requirement
|
122
|
+
requirements:
|
123
|
+
- - "~>"
|
124
|
+
- !ruby/object:Gem::Version
|
125
|
+
version: '3.5'
|
126
|
+
- !ruby/object:Gem::Dependency
|
127
|
+
name: yard
|
128
|
+
requirement: !ruby/object:Gem::Requirement
|
129
|
+
requirements:
|
130
|
+
- - "~>"
|
131
|
+
- !ruby/object:Gem::Version
|
132
|
+
version: '0.9'
|
133
|
+
type: :development
|
134
|
+
prerelease: false
|
135
|
+
version_requirements: !ruby/object:Gem::Requirement
|
136
|
+
requirements:
|
137
|
+
- - "~>"
|
138
|
+
- !ruby/object:Gem::Version
|
139
|
+
version: '0.9'
|
97
140
|
description: EVE ESI API wrapper
|
98
141
|
email:
|
99
142
|
- dannyhiemstra@gmail.com
|
143
|
+
- aaronmallen4@gmail.com
|
100
144
|
executables: []
|
101
145
|
extensions: []
|
102
146
|
extra_rdoc_files: []
|
@@ -106,7 +150,9 @@ files:
|
|
106
150
|
- esi.gemspec
|
107
151
|
- lib/esi.rb
|
108
152
|
- lib/esi/access_token.rb
|
153
|
+
- lib/esi/api_error.rb
|
109
154
|
- lib/esi/calls.rb
|
155
|
+
- lib/esi/calls/info.rb
|
110
156
|
- lib/esi/client.rb
|
111
157
|
- lib/esi/o_auth.rb
|
112
158
|
- lib/esi/response.rb
|