blizzard_api 0.6.3 → 3.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (55) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +30 -0
  3. data/Gemfile.lock +12 -14
  4. data/blizzard_api.gemspec +0 -1
  5. data/lib/blizzard_api/api_response.rb +24 -0
  6. data/lib/blizzard_api/api_standards.rb +55 -0
  7. data/lib/blizzard_api/configuration.rb +20 -17
  8. data/lib/blizzard_api/diablo/game_data/generic_data_endpoint.rb +2 -2
  9. data/lib/blizzard_api/diablo/request.rb +3 -3
  10. data/lib/blizzard_api/diablo.rb +33 -27
  11. data/lib/blizzard_api/hearthstone/game_data/generic_data_endpoint.rb +2 -2
  12. data/lib/blizzard_api/hearthstone/request.rb +3 -3
  13. data/lib/blizzard_api/hearthstone.rb +18 -12
  14. data/lib/blizzard_api/request.rb +45 -83
  15. data/lib/blizzard_api/starcraft/community/legacy.rb +6 -6
  16. data/lib/blizzard_api/starcraft/request.rb +3 -3
  17. data/lib/blizzard_api/starcraft.rb +20 -14
  18. data/lib/blizzard_api/token_manager.rb +49 -0
  19. data/lib/blizzard_api/version.rb +1 -1
  20. data/lib/blizzard_api/wow/game_data/achievement.rb +1 -16
  21. data/lib/blizzard_api/wow/game_data/azerite_essence.rb +2 -9
  22. data/lib/blizzard_api/wow/game_data/connected_realm.rb +1 -8
  23. data/lib/blizzard_api/wow/game_data/covenant.rb +2 -9
  24. data/lib/blizzard_api/wow/game_data/creature.rb +2 -13
  25. data/lib/blizzard_api/wow/game_data/generic_data_endpoint.rb +10 -37
  26. data/lib/blizzard_api/wow/game_data/guild_crest.rb +4 -10
  27. data/lib/blizzard_api/wow/game_data/item.rb +3 -18
  28. data/lib/blizzard_api/wow/game_data/journal.rb +2 -17
  29. data/lib/blizzard_api/wow/game_data/media.rb +2 -13
  30. data/lib/blizzard_api/wow/game_data/modified_crafting.rb +1 -12
  31. data/lib/blizzard_api/wow/game_data/mount.rb +1 -8
  32. data/lib/blizzard_api/wow/game_data/mythic_keystone.rb +2 -13
  33. data/lib/blizzard_api/wow/game_data/mythic_keystone_affix.rb +2 -9
  34. data/lib/blizzard_api/wow/game_data/pet.rb +2 -9
  35. data/lib/blizzard_api/wow/game_data/playable_class.rb +2 -48
  36. data/lib/blizzard_api/wow/game_data/playable_race.rb +1 -8
  37. data/lib/blizzard_api/wow/game_data/playable_specialization.rb +1 -18
  38. data/lib/blizzard_api/wow/game_data/power_type.rb +1 -8
  39. data/lib/blizzard_api/wow/game_data/profession.rb +2 -9
  40. data/lib/blizzard_api/wow/game_data/pvp_region.rb +82 -0
  41. data/lib/blizzard_api/wow/game_data/pvp_season.rb +7 -9
  42. data/lib/blizzard_api/wow/game_data/pvp_tier.rb +3 -10
  43. data/lib/blizzard_api/wow/game_data/quest.rb +2 -9
  44. data/lib/blizzard_api/wow/game_data/realm.rb +1 -8
  45. data/lib/blizzard_api/wow/game_data/region.rb +1 -8
  46. data/lib/blizzard_api/wow/game_data/reputation.rb +2 -9
  47. data/lib/blizzard_api/wow/game_data/spell.rb +2 -17
  48. data/lib/blizzard_api/wow/game_data/talent.rb +2 -9
  49. data/lib/blizzard_api/wow/game_data/tech_talent.rb +2 -9
  50. data/lib/blizzard_api/wow/game_data/title.rb +1 -16
  51. data/lib/blizzard_api/wow/profile/profile.rb +2 -2
  52. data/lib/blizzard_api/wow/request.rb +3 -3
  53. data/lib/blizzard_api/wow.rb +122 -108
  54. data/lib/blizzard_api.rb +10 -0
  55. metadata +6 -16
@@ -1,5 +1,11 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ ##
4
+ # @!macro [new] init_options
5
+ # @param [Hash] options
6
+ # @option options [String] :region API Region
7
+ # @option options [Symbol] :mode API Mode
8
+
3
9
  ##
4
10
  # @!macro [new] request_options
5
11
  # @param {Hash} options You can specify some options
@@ -9,31 +15,18 @@
9
15
  # @option options [Boolean] :ignore_cache If set to true the request will not use the cache
10
16
  # @option options [Integer] :ttl Override the default time (in seconds) a request should be cached
11
17
  # @option options [DateTime] :since Adds the If-modified-since headers. Will always ignore cache when set.
12
- # @option options [Integer] :concurrency How many threads to use for complete sets of data.
13
- # BEWARE: Might cause 429 responses, in this case lower the number.
14
-
15
- ##
16
- # @!macro [new] regions
17
- # @param {Symbol} region One of the valid API regions *:us*, *:eu*, *:ko*, and *:tw*
18
- # @note This gem do not support nor will support China endpoints
19
18
 
20
19
  ##
21
20
  # @!macro [new] response
22
21
  # @return [Hash] API Response. The actual type of the returned object depends on the *format* option
23
22
  # in the configuration module
24
23
 
25
- ##
26
- # @!macro [new] complete
27
- # Iterates through the {index} response data and fetch additional information using {get}, it results in a more
28
- # complete set of data
29
- # @note IT MAY PERFORM MANY REQUESTS TO FETCH ALL DATA
30
- # @!macro request_options
31
- # @!macro response
32
-
33
24
  module BlizzardApi
34
25
  ##
35
26
  # Simplifies the requests to Blizzard APIS
36
27
  class Request
28
+ include ApiStandards
29
+
37
30
  # One hour cache
38
31
  CACHE_HOUR = 3600
39
32
  # One day cache
@@ -41,16 +34,6 @@ module BlizzardApi
41
34
  # Three (commercial) months cache
42
35
  CACHE_TRIMESTER = CACHE_DAY * 90
43
36
 
44
- # Common endpoints
45
- BASE_URLS = {
46
- game_data: 'https://%s.api.blizzard.com/data/%s',
47
- community: 'https://%s.api.blizzard.com/%s',
48
- profile: 'https://%s.api.blizzard.com/profile/%s',
49
- media: 'https://%s.api.blizzard.com/data/%s/media',
50
- user_profile: 'https://%s.api.blizzard.com/profile/user/%s',
51
- search: 'https://%s.api.blizzard.com/data/%s/search'
52
- }.freeze
53
-
54
37
  ##
55
38
  # @!attribute region
56
39
  # @return [String] Api region
@@ -62,14 +45,14 @@ module BlizzardApi
62
45
  attr_accessor :mode
63
46
 
64
47
  ##
65
- # @!macro regions
66
- def initialize(region = nil, mode = :regular)
67
- self.region = region || BlizzardApi.region
68
- @redis = Redis.new(host: BlizzardApi.redis_host, port: BlizzardApi.redis_port) if BlizzardApi.use_cache
48
+ # @!macro init_options
49
+ def initialize(**options)
50
+ self.region = options[:region] || BlizzardApi.region
69
51
  # Use the shared access_token, or create one if it doesn't exists. This avoids unnecessary calls to create tokens.
70
- @access_token = BlizzardApi.access_token || create_access_token
52
+ create_access_token if BlizzardApi.access_token_expired?
53
+
71
54
  # Mode
72
- @mode = mode
55
+ @mode = options[:mode] || BlizzardApi.mode
73
56
  end
74
57
 
75
58
  require 'net/http'
@@ -79,45 +62,9 @@ module BlizzardApi
79
62
 
80
63
  protected
81
64
 
82
- def base_url(scope)
83
- raise ArgumentError, 'Invalid scope' unless BASE_URLS.include? scope
84
-
85
- format BASE_URLS[scope], region, @game
86
- end
87
-
88
- ##
89
- # Returns a valid version namespace
90
- #
91
- # @param [Hash] options A hash containing a valid namespace key
92
- def endpoint_version(options)
93
- if options.key? :classic
94
- 'classic-'
95
- elsif options.key? :classic1x
96
- 'classic1x-'
97
- else
98
- ''
99
- end
100
- end
101
-
102
- ##
103
- # Returns a valid namespace string for consuming the api endpoints
104
- #
105
- # @param [Hash] options A hash containing the namespace key
106
- def endpoint_namespace(options)
107
- version = endpoint_version(options)
108
- case options[:namespace]
109
- when :dynamic
110
- "dynamic-#{version}#{region}"
111
- when :static
112
- "static-#{version}#{region}"
113
- when :profile
114
- "profile-#{region}"
115
- else
116
- raise ArgumentError, 'Invalid namespace scope'
117
- end
118
- end
119
-
120
65
  def create_access_token
66
+ return if BlizzardApi.restore_access_token
67
+
121
68
  uri = URI.parse("https://#{BlizzardApi.region}.battle.net/oauth/token")
122
69
 
123
70
  http = Net::HTTP.new(uri.host, uri.port)
@@ -129,7 +76,7 @@ module BlizzardApi
129
76
  request.set_form_data grant_type: 'client_credentials'
130
77
 
131
78
  response = http.request(request)
132
- BlizzardApi.access_token = JSON.parse(response.body)['access_token']
79
+ BlizzardApi.save_access_token(JSON.parse(response.body))
133
80
  end
134
81
 
135
82
  def request(url, **options)
@@ -139,16 +86,14 @@ module BlizzardApi
139
86
  data = using_cache?(options) ? find_in_cache(parsed_url.to_s) : nil
140
87
 
141
88
  # If data was found that means cache is enabled and valid
142
- return JSON.parse(data, symbolize_names: true) if data
89
+ return prepare_response data if data
143
90
 
144
91
  response = consume_api parsed_url, **options
145
92
 
93
+ response_data = response.code.to_i.eql?(304) ? nil : response.body
146
94
  save_in_cache parsed_url.to_s, response.body, options[:ttl] || CACHE_DAY if using_cache? options
147
95
 
148
- response_data = response.code.to_i.eql?(304) ? nil : JSON.parse(response.body, symbolize_names: true)
149
- return [response, response_data] if mode.eql? :extended
150
-
151
- response_data
96
+ prepare_response response_data, response
152
97
  end
153
98
 
154
99
  def api_request(uri, **query_string)
@@ -163,7 +108,7 @@ module BlizzardApi
163
108
 
164
109
  # In case uri already have query string parameters joins them with &
165
110
  if query_string.size.positive?
166
- query_string = URI.encode_www_form(query_string, false)
111
+ query_string = URI.encode_www_form(query_string)
167
112
  uri = uri.include?('?') ? "#{uri}&#{query_string}" : "#{uri}?#{query_string}"
168
113
  end
169
114
 
@@ -172,24 +117,41 @@ module BlizzardApi
172
117
 
173
118
  private
174
119
 
120
+ ##
121
+ # Resolves the response based on the mode
122
+ def prepare_response(data, response = false)
123
+ parsed_data = data.nil? ? data : JSON.parse(data, symbolize_names: true)
124
+
125
+ return parsed_data unless mode.eql? :extended
126
+
127
+ response = ApiResponse.new(data) unless response
128
+
129
+ [response, parsed_data]
130
+ end
131
+
175
132
  ##
176
133
  # @param options [Hash] Request options
177
134
  def using_cache?(options)
178
- return false if mode.eql?(:extended) || options.key?(:since)
135
+ return false if options.key?(:since)
179
136
 
180
137
  !options.fetch(:ignore_cache, false)
181
138
  end
182
139
 
140
+ def http_connection(url)
141
+ Net::HTTP.new(url.host, url.port).tap do |http|
142
+ http.use_ssl = true
143
+ http.keep_alive_timeout = 30
144
+ end
145
+ end
146
+
183
147
  def consume_api(url, **options)
184
148
  # Creates a HTTP connection and request to ensure thread safety
185
- http = Net::HTTP.new(url.host, url.port)
186
- http.use_ssl = true
187
149
  request = Net::HTTP::Get.new(url)
188
150
 
189
151
  add_headers request, options
190
152
 
191
153
  # Executes the request
192
- http.request(request).tap do |response|
154
+ http_connection(url).request(request).tap do |response|
193
155
  if mode.eql?(:regular) && ![200, 304].include?(response.code.to_i)
194
156
  raise BlizzardApi::ApiException.new "Request failed with code '#{response.code}' details: #{response.to_hash}", response.code.to_i
195
157
  end
@@ -198,20 +160,20 @@ module BlizzardApi
198
160
 
199
161
  def add_headers(request, options)
200
162
  # Blizzard API documentation states the preferred way to send the access_token is using Bearer token on header
201
- request['Authorization'] = "Bearer #{options.fetch(:access_token, @access_token)}"
163
+ request['Authorization'] = "Bearer #{options.fetch(:access_token, BlizzardApi.access_token)}"
202
164
  # Format If-modified-since option
203
165
  request['If-Modified-Since'] = options[:since].httpdate if options.key? :since
204
166
  options[:headers]&.each { |header, content| request[header] = content }
205
167
  end
206
168
 
207
169
  def save_in_cache(resource_url, data, ttl)
208
- @redis.setex resource_url, ttl, data if BlizzardApi.use_cache
170
+ BlizzardApi.redis_connection.setex resource_url, ttl, data if BlizzardApi.use_cache
209
171
  end
210
172
 
211
173
  def find_in_cache(resource_url)
212
174
  return false unless BlizzardApi.use_cache
213
175
 
214
- @redis.get resource_url if @redis.exists? resource_url
176
+ BlizzardApi.redis_connection.get resource_url if BlizzardApi.redis_connection.exists? resource_url
215
177
  end
216
178
  end
217
179
  end
@@ -20,7 +20,7 @@ module BlizzardApi
20
20
  def profile(region_id, realm_id, profile_id, **options)
21
21
  reg = resolve_region(region_id)
22
22
  opts = { ttl: CACHE_DAY }.merge(options)
23
- api_request "#{base_url(:community)}/legacy/profile/#{reg}/#{realm_id}/#{profile_id}", opts
23
+ api_request "#{base_url(:community)}/legacy/profile/#{reg}/#{realm_id}/#{profile_id}", **opts
24
24
  end
25
25
 
26
26
  ##
@@ -33,7 +33,7 @@ module BlizzardApi
33
33
  def ladders(region_id, realm_id, profile_id, **options)
34
34
  reg = resolve_region(region_id)
35
35
  opts = { ttl: CACHE_DAY }.merge(options)
36
- api_request "#{base_url(:community)}/legacy/profile/#{reg}/#{realm_id}/#{profile_id}/ladder ", opts
36
+ api_request "#{base_url(:community)}/legacy/profile/#{reg}/#{realm_id}/#{profile_id}/ladder ", **opts
37
37
  end
38
38
 
39
39
  ##
@@ -46,7 +46,7 @@ module BlizzardApi
46
46
  def match(region_id, realm_id, profile_id, **options)
47
47
  reg = resolve_region(region_id)
48
48
  opts = { ttl: CACHE_DAY }.merge(options)
49
- api_request "#{base_url(:community)}/legacy/profile/#{reg}/#{realm_id}/#{profile_id}/matches", opts
49
+ api_request "#{base_url(:community)}/legacy/profile/#{reg}/#{realm_id}/#{profile_id}/matches", **opts
50
50
  end
51
51
 
52
52
  ##
@@ -58,7 +58,7 @@ module BlizzardApi
58
58
  def ladder(region_id, ladder_id, **options)
59
59
  reg = resolve_region(region_id)
60
60
  opts = { ttl: CACHE_DAY }.merge(options)
61
- api_request "#{base_url(:community)}/legacy/ladder/#{reg}/#{ladder_id}", opts
61
+ api_request "#{base_url(:community)}/legacy/ladder/#{reg}/#{ladder_id}", **opts
62
62
  end
63
63
 
64
64
  ##
@@ -69,7 +69,7 @@ module BlizzardApi
69
69
  def achievements(region_id, **options)
70
70
  reg = resolve_region(region_id)
71
71
  opts = { ttl: CACHE_DAY }.merge(options)
72
- api_request "#{base_url(:community)}/legacy/data/achievements/#{reg}", opts
72
+ api_request "#{base_url(:community)}/legacy/data/achievements/#{reg}", **opts
73
73
  end
74
74
 
75
75
  ##
@@ -80,7 +80,7 @@ module BlizzardApi
80
80
  def rewards(region_id, **options)
81
81
  reg = resolve_region(region_id)
82
82
  opts = { ttl: CACHE_DAY }.merge(options)
83
- api_request "#{base_url(:community)}/legacy/data/rewards/#{reg}", opts
83
+ api_request "#{base_url(:community)}/legacy/data/rewards/#{reg}", **opts
84
84
  end
85
85
  end
86
86
  end
@@ -14,9 +14,9 @@ module BlizzardApi
14
14
  SC_REGION = { US: 1, EU: 2, KO: 3, TW: 3 }.freeze
15
15
 
16
16
  ##
17
- # @!macro regions
18
- def initialize(region = nil, mode = :regular)
19
- super region, mode
17
+ # @!macro init_options
18
+ def initialize(**options)
19
+ super(**options)
20
20
  @game = 'sc2'
21
21
  end
22
22
 
@@ -1,5 +1,11 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ ##
4
+ # @!macro [new] init_options
5
+ # @param options [Hash] Initialization options
6
+ # @option options [String] :region API region
7
+ # @option options [Symbol] :model API mode (:regular, :extended)
8
+
3
9
  module BlizzardApi
4
10
  # Starcraft II related classes
5
11
  module Starcraft
@@ -9,10 +15,10 @@ module BlizzardApi
9
15
  require_relative 'starcraft/game_data/league'
10
16
 
11
17
  ##
12
- # @param region [String] API Region
18
+ # @!macro init_options
13
19
  # @return {League}
14
- def self.league(region = BlizzardApi.region)
15
- BlizzardApi::Starcraft::League.new(region)
20
+ def self.league(**options)
21
+ BlizzardApi::Starcraft::League.new(**options)
16
22
  end
17
23
 
18
24
  # Starcraft community api
@@ -22,30 +28,30 @@ module BlizzardApi
22
28
  require_relative 'starcraft/community/legacy'
23
29
 
24
30
  ##
25
- # @param region [String] API Region
31
+ # @!macro init_options
26
32
  # @return {Profile}
27
- def self.profile(region = BlizzardApi.region)
28
- BlizzardApi::Starcraft::Profile.new(region)
33
+ def self.profile(**options)
34
+ BlizzardApi::Starcraft::Profile.new(**options)
29
35
  end
30
36
 
31
37
  ##
32
- # @param region [String] API Region
38
+ # @!macro init_options
33
39
  # @return {Ladder}
34
- def self.ladder(region = BlizzardApi.region)
35
- BlizzardApi::Starcraft::Ladder.new(region)
40
+ def self.ladder(**options)
41
+ BlizzardApi::Starcraft::Ladder.new(**options)
36
42
  end
37
43
 
38
44
  ##
39
- # @param region [String] API Region
45
+ # @!macro init_options
40
46
  # @return {Account}
41
- def self.account(region = BlizzardApi.region)
42
- BlizzardApi::Starcraft::Account.new(region)
47
+ def self.account(**options)
48
+ BlizzardApi::Starcraft::Account.new(**options)
43
49
  end
44
50
 
45
51
  ##
46
52
  # @return {Legacy}
47
- def self.legacy(region = BlizzardApi.region)
48
- BlizzardApi::Starcraft::Legacy.new(region)
53
+ def self.legacy(**options)
54
+ BlizzardApi::Starcraft::Legacy.new(**options)
49
55
  end
50
56
  end
51
57
  end
@@ -0,0 +1,49 @@
1
+ # frozen_string_literal: true
2
+
3
+ module BlizzardApi
4
+ ##
5
+ # Manages the current token and expiration date
6
+ module TokenManager
7
+ REDIS_TOKEN_KEY = 'access_token'
8
+
9
+ ##
10
+ # @!attribute access_token
11
+ # Current access token.
12
+ # @return [String] access_token
13
+ attr_accessor :access_token
14
+
15
+ ##
16
+ # @!attribute expires_at
17
+ # Current access token expiration date.
18
+ # @return [String] expires_at
19
+ attr_accessor :expires_at
20
+
21
+ ##
22
+ # Returns if the current token has expired
23
+ #
24
+ # @return [Boolean]
25
+ def access_token_expired?
26
+ return true if access_token.nil?
27
+
28
+ expires_at < Time.now
29
+ end
30
+
31
+ def restore_access_token
32
+ return false unless use_cache && cache_access_token
33
+
34
+ return false unless redis_connection.exists? REDIS_TOKEN_KEY
35
+
36
+ self.access_token = redis_connection.get REDIS_TOKEN_KEY
37
+ self.expires_at = Time.now + redis_connection.ttl(REDIS_TOKEN_KEY)
38
+ true
39
+ end
40
+
41
+ def save_access_token(token_data)
42
+ ttl = token_data['expires_in'].to_i
43
+ self.expires_at = Time.now + ttl
44
+ self.access_token = token_data['access_token']
45
+
46
+ redis_connection.setex REDIS_TOKEN_KEY, ttl, access_token if use_cache && cache_access_token
47
+ end
48
+ end
49
+ end
@@ -2,5 +2,5 @@
2
2
 
3
3
  module BlizzardApi
4
4
  # Gem version
5
- VERSION = '0.6.3'
5
+ VERSION = '3.0.0'
6
6
  end
@@ -10,13 +10,7 @@ module BlizzardApi
10
10
  # You can get an instance of this class using the default region as follows:
11
11
  # api_instance = BlizzardApi::Wow.achievement
12
12
  class Achievement < Wow::GenericDataEndpoint
13
- ##
14
- # This method overrides the inherited default behavior to prevent high server load and fetch time
15
- #
16
- # @!macro response
17
- def complete
18
- raise BlizzardApi::ApiException, 'There are too many achievements to fetch complete data'
19
- end
13
+ setup 'achievement', :static, CACHE_TRIMESTER
20
14
 
21
15
  ##
22
16
  # Return a list of possible achievement categories.
@@ -47,15 +41,6 @@ module BlizzardApi
47
41
  def media(id, **options)
48
42
  api_request "#{base_url(:media)}/achievement/#{id}", **default_options.merge(options)
49
43
  end
50
-
51
- protected
52
-
53
- def endpoint_setup
54
- @endpoint = 'achievement'
55
- @namespace = :static
56
- @collection = 'achievements'
57
- @ttl = CACHE_TRIMESTER
58
- end
59
44
  end
60
45
  end
61
46
  end
@@ -12,6 +12,8 @@ module BlizzardApi
12
12
  class AzeriteEssence < Wow::GenericDataEndpoint
13
13
  include BlizzardApi::Wow::Searchable
14
14
 
15
+ setup 'azerite-essence', :static, CACHE_TRIMESTER
16
+
15
17
  ##
16
18
  # Fetch media for one of the azerite essences listed by the {#index} using its *id*
17
19
  #
@@ -23,15 +25,6 @@ module BlizzardApi
23
25
  def media(id, **options)
24
26
  api_request "#{base_url(:media)}/azerite-essence/#{id}", **default_options.merge(options)
25
27
  end
26
-
27
- protected
28
-
29
- def endpoint_setup
30
- @endpoint = 'azerite-essence'
31
- @namespace = :static
32
- @collection = 'azerite_essences'
33
- @ttl = CACHE_TRIMESTER
34
- end
35
28
  end
36
29
  end
37
30
  end
@@ -12,14 +12,7 @@ module BlizzardApi
12
12
  class ConnectedRealm < Wow::GenericDataEndpoint
13
13
  include BlizzardApi::Wow::Searchable
14
14
 
15
- protected
16
-
17
- def endpoint_setup
18
- @endpoint = 'connected-realm'
19
- @namespace = :dynamic
20
- @collection = 'connected_realms'
21
- @ttl = CACHE_TRIMESTER
22
- end
15
+ setup 'connected-realm', :dynamic, CACHE_TRIMESTER
23
16
  end
24
17
  end
25
18
  end
@@ -10,6 +10,8 @@ module BlizzardApi
10
10
  # You can get an instance of this class using the default region as follows:
11
11
  # api_instance = BlizzardApi::Wow.azerite_essence
12
12
  class Covenant < Wow::GenericDataEndpoint
13
+ setup 'covenant', :static, CACHE_TRIMESTER
14
+
13
15
  ##
14
16
  # Fetch media for one of the covenants listed by the {#index} using its *id*
15
17
  #
@@ -65,15 +67,6 @@ module BlizzardApi
65
67
  def conduit(id, **options)
66
68
  api_request "#{base_url(:game_data)}/covenant/conduit/#{id}", **default_options.merge(options)
67
69
  end
68
-
69
- protected
70
-
71
- def endpoint_setup
72
- @endpoint = 'covenant'
73
- @namespace = :static
74
- @collection = 'covenants'
75
- @ttl = CACHE_TRIMESTER
76
- end
77
70
  end
78
71
  end
79
72
  end
@@ -12,14 +12,12 @@ module BlizzardApi
12
12
  class Creature < Wow::GenericDataEndpoint
13
13
  include BlizzardApi::Wow::Searchable
14
14
 
15
+ setup 'creature', :static, CACHE_TRIMESTER
16
+
15
17
  def index
16
18
  raise BlizzardApi::ApiException, 'Creatures endpoint doesn\'t have an index method'
17
19
  end
18
20
 
19
- def complete
20
- raise BlizzardApi::ApiException, 'There are too many creatures to fetch complete data'
21
- end
22
-
23
21
  ##
24
22
  # Fetch all creature families
25
23
  #
@@ -99,15 +97,6 @@ module BlizzardApi
99
97
  def display_media(id, **options)
100
98
  api_request "#{base_url(:media)}/creature-display/#{id}", **default_options.merge(options)
101
99
  end
102
-
103
- protected
104
-
105
- def endpoint_setup
106
- @endpoint = 'creature'
107
- @namespace = :static
108
- @collection = 'achievements'
109
- @ttl = CACHE_TRIMESTER
110
- end
111
100
  end
112
101
  end
113
102
  end
@@ -1,18 +1,18 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'thwait'
4
-
5
3
  module BlizzardApi
6
4
  module Wow
7
5
  ##
8
6
  # Generic endpoint to support most data requests with minor configurations
9
7
  class GenericDataEndpoint < Wow::Request
10
- ##
11
- # @!macro regions
12
- def initialize(region = nil, mode = :regular)
13
- super region, mode
14
- endpoint_setup
15
- @ttl ||= CACHE_DAY
8
+ class << self
9
+ attr_accessor :endpoint, :namespace, :ttl
10
+
11
+ def setup(endpoint, namespace, ttl)
12
+ self.endpoint = endpoint
13
+ self.namespace = namespace
14
+ self.ttl = ttl
15
+ end
16
16
  end
17
17
 
18
18
  ##
@@ -35,42 +35,15 @@ module BlizzardApi
35
35
  api_request "#{endpoint_uri}/#{id}", **default_options.merge(options)
36
36
  end
37
37
 
38
- ##
39
- # @!macro complete
40
- def complete(**options)
41
- payload = [].tap do |complete_data|
42
- index_data = index(**options)
43
- threads = []
44
-
45
- concurrency = options.key?(:concurrency) ? options[:concurrency].to_i : BlizzardApi.concurrency
46
- concurrency.times do
47
- threads << Thread.new do
48
- while index_data[@collection.to_sym].size.positive?
49
- item = index_data[@collection.to_sym].pop
50
- link = item.key?(:key) ? item[:key][:href] : item[:href]
51
- item_data = request link
52
- complete_data.push item_data
53
- end
54
- end
55
- end
56
- ThreadsWait.all_waits threads
57
- end
58
- payload.sort { |a, b| a[:id] <=> b[:id] }
59
- end
60
-
61
38
  protected
62
39
 
63
40
  def endpoint_uri(variant = nil, scope = :game_data)
64
- endpoint = variant ? "#{@endpoint}-#{variant}" : @endpoint
41
+ endpoint = variant ? "#{self.class.endpoint}-#{variant}" : self.class.endpoint
65
42
  "#{base_url(scope)}/#{endpoint}"
66
43
  end
67
44
 
68
- def endpoint_setup
69
- raise NotImplementedError, 'You must override this method to properly set up the endpoint'
70
- end
71
-
72
45
  def default_options
73
- { namespace: @namespace, ttl: @ttl }
46
+ { namespace: self.class.namespace, ttl: self.class.ttl }
74
47
  end
75
48
  end
76
49
  end
@@ -10,6 +10,8 @@ module BlizzardApi
10
10
  # You can get an instance of this class using the default region as follows:
11
11
  # api_instance = BlizzardApi::Wow.guild_crest
12
12
  class GuildCrest < Wow::GenericDataEndpoint
13
+ setup 'guild-crest', :static, CACHE_TRIMESTER
14
+
13
15
  def get
14
16
  raise BlizzardApi::ApiException, 'This endpoint doens\'t have a get method'
15
17
  end
@@ -25,7 +27,7 @@ module BlizzardApi
25
27
  #
26
28
  # @!macro response
27
29
  def border_media(id, **options)
28
- api_request "#{base_url(:media)}/#{@endpoint}/border/#{id}", **default_options.merge(options)
30
+ api_request "#{base_url(:media)}/#{self.class.endpoint}/border/#{id}", **default_options.merge(options)
29
31
  end
30
32
 
31
33
  ##
@@ -39,15 +41,7 @@ module BlizzardApi
39
41
  #
40
42
  # @!macro response
41
43
  def emblem_media(id, **options)
42
- api_request "#{base_url(:media)}/#{@endpoint}/emblem/#{id}", **default_options.merge(options)
43
- end
44
-
45
- protected
46
-
47
- def endpoint_setup
48
- @endpoint = 'guild-crest'
49
- @namespace = :static
50
- @ttl = CACHE_TRIMESTER
44
+ api_request "#{base_url(:media)}/#{self.class.endpoint}/emblem/#{id}", **default_options.merge(options)
51
45
  end
52
46
  end
53
47
  end