blizzard_api 0.3.10 → 0.5.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 (35) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +2 -1
  3. data/CHANGELOG.md +65 -0
  4. data/Gemfile.lock +23 -14
  5. data/README.md +45 -0
  6. data/blizzard_api.gemspec +2 -0
  7. data/lib/blizzard_api/diablo/community/item.rb +3 -4
  8. data/lib/blizzard_api/diablo/game_data/generic_data_endpoint.rb +2 -2
  9. data/lib/blizzard_api/diablo/request.rb +2 -2
  10. data/lib/blizzard_api/hearthstone/game_data/generic_data_endpoint.rb +2 -2
  11. data/lib/blizzard_api/hearthstone/request.rb +2 -2
  12. data/lib/blizzard_api/request.rb +46 -38
  13. data/lib/blizzard_api/starcraft/request.rb +2 -2
  14. data/lib/blizzard_api/version.rb +1 -1
  15. data/lib/blizzard_api/wow.rb +19 -0
  16. data/lib/blizzard_api/wow/game_data/azerite_essence.rb +2 -0
  17. data/lib/blizzard_api/wow/game_data/connected_realm.rb +2 -0
  18. data/lib/blizzard_api/wow/game_data/creature.rb +2 -0
  19. data/lib/blizzard_api/wow/game_data/generic_data_endpoint.rb +4 -4
  20. data/lib/blizzard_api/wow/game_data/item.rb +2 -0
  21. data/lib/blizzard_api/wow/game_data/journal.rb +15 -0
  22. data/lib/blizzard_api/wow/game_data/media.rb +37 -0
  23. data/lib/blizzard_api/wow/game_data/modified_crafting.rb +67 -0
  24. data/lib/blizzard_api/wow/game_data/mount.rb +2 -0
  25. data/lib/blizzard_api/wow/game_data/pet.rb +46 -0
  26. data/lib/blizzard_api/wow/game_data/realm.rb +2 -0
  27. data/lib/blizzard_api/wow/game_data/spell.rb +2 -0
  28. data/lib/blizzard_api/wow/profile/character_profile.rb +5 -1
  29. data/lib/blizzard_api/wow/profile/guild.rb +2 -0
  30. data/lib/blizzard_api/wow/profile/profile.rb +2 -2
  31. data/lib/blizzard_api/wow/request.rb +2 -2
  32. data/lib/blizzard_api/wow/search/search_composer.rb +97 -0
  33. data/lib/blizzard_api/wow/search/search_request.rb +24 -0
  34. data/lib/blizzard_api/wow/slug.rb +12 -0
  35. metadata +41 -8
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 5cf06d7b559908f9d323a4c7e2da059a9da60697f4048fdd53fe09e485acc229
4
- data.tar.gz: 8adc3dae8a36c1aae4a7a4aae51ba268af374dc8aff3e652c81159340374b2a0
3
+ metadata.gz: 81d6f1a66cf34191acfd15d00934934c29003a2f99367ccf7e9644382ebb89b9
4
+ data.tar.gz: 1d5a888c2b9505c501389a3e9bc718e6b88f643f23c52d6bceb36c61c8b13fe4
5
5
  SHA512:
6
- metadata.gz: 199eef0b6e579aeef8381b1f7e8577d63976115ad135e63591be8147d551d7bfef3ea6e9cfaf8ef823115b8ad8156ef3da2ead5e50ec67604ccdac28c2e85cf4
7
- data.tar.gz: bfa921cff79d09fc441f30196bba8132ac0c8a5f6e67b8fc824ac5596f6889ae36d732bb8b22cfd65400e3507bc2d8db70dfbf698be5cde096ca08b17382a65a
6
+ metadata.gz: fa2270714c47f2b5913f5a28b575e7a91e1b70c81ad34cb898fcb03d7c02e68c13ee02e3c4c95012ad6c7b1ac417fabd72c11072776ea28786319fc87089ff40
7
+ data.tar.gz: fd626a5eafa0630bc3003ace854f2adb65f383ac2e84f755f7325e670804aca1cfde9a82edea687ef99e06850a9e6c4b54d0462b45e265bc400c03d57b498e2a
@@ -1,6 +1,6 @@
1
1
  inherit_from: .rubocop_todo.yml
2
2
 
3
- Metrics/LineLength:
3
+ Layout/LineLength:
4
4
  Max: 140
5
5
 
6
6
  Metrics/ModuleLength:
@@ -12,6 +12,7 @@ Metrics/AbcSize:
12
12
 
13
13
  AllCops:
14
14
  TargetRubyVersion: 2.5
15
+ NewCops: enable
15
16
  Exclude:
16
17
  - 'vendor/**/*'
17
18
  - 'bin/**/*'
@@ -1,5 +1,70 @@
1
1
  Please view this file on the master branch, otherwise it may be outdated
2
2
 
3
+ **Version 0.5.1**
4
+
5
+ Added new endpoints: https://us.forums.blizzard.com/en/blizzard/t/wow-game-data-api-modified-crafting-support/12727
6
+
7
+ **Version 0.5.0**
8
+
9
+ This version brings a lot of internal changes to the way the gem works. While
10
+ there no breaking change is expected use it carefully.
11
+
12
+ ## New features:
13
+
14
+ ### Extended mode
15
+
16
+ When creating a request you can now specify **mode** as the last argument. Available modes:
17
+ * **regular**: No changes, should work as it always did.
18
+ * **extended**: All requests now return an array with two objects, the actual HTTPResponse object and the usual Hash.
19
+
20
+ ```ruby
21
+ api_client = BlizzardApi::Wow::Item.new 'us', :extended
22
+ response, item_data = api_client.get 35_000
23
+
24
+ puts response.code # 200
25
+ puts item_data[:name][:en_US] # Brutal Gladiator's Dragonhide Legguards
26
+ ```
27
+
28
+ This is intended to expose the response code and headers.
29
+
30
+ **Important**: Extended mode completely disables the cache.
31
+
32
+ ### Custom headers
33
+
34
+ You an now pass custom headers in the **options** hash.
35
+
36
+ There is also a new shorthand for the `If-Modified-Since` header.
37
+
38
+ ```ruby
39
+ # If-Modified-Since shorhand
40
+ auction_data = BlizzardApi::Wow.auction.get 1146, since: DateTime.parse('2099-01-01Z')
41
+
42
+ # Using custom headers
43
+ auction_data = BlizzardApi::Wow.auction.get 1146, headers: { 'If-Modified-Since' => 'Sun, 27 Sep 2020 02:17:03 GMT' }
44
+ ```
45
+
46
+ **Important**
47
+ * Headers are not part of the cache key, use the option `ignore_cache: true` when needed.
48
+ * The `since` shorthand will always disable the cache.
49
+
50
+ **Version 0.4.2**
51
+
52
+ Added new retail and classic search endpoints described here: https://us.forums.blizzard.com/en/blizzard/t/world-of-warcraft-api-patch-notes-20200708/10310
53
+
54
+ **Version 0.4.1**
55
+
56
+ Added new retail and classic endpoints described here: https://us.forums.blizzard.com/en/blizzard/t/world-of-warcraft-api-patch-notes-20200609/8902
57
+
58
+ **Version 0.4.0**
59
+
60
+ Added support to searchable endpoints
61
+
62
+ https://develop.battle.net/documentation/world-of-warcraft/guides/search
63
+
64
+ **Version 0.3.11**
65
+
66
+ Fixed D3 item URL.
67
+
3
68
  **Version 0.3.10**
4
69
 
5
70
  Really fixed D3 profile URLs this time.
@@ -1,39 +1,48 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- blizzard_api (0.3.9)
4
+ blizzard_api (0.5.1)
5
5
  redis (~> 4.1, >= 4.1.0)
6
6
 
7
7
  GEM
8
8
  remote: https://rubygems.org/
9
9
  specs:
10
- ast (2.4.0)
11
- jaro_winkler (1.5.3)
12
- minitest (5.11.3)
13
- parallel (1.17.0)
14
- parser (2.6.3.0)
15
- ast (~> 2.4.0)
10
+ ast (2.4.1)
11
+ dotenv (2.7.6)
12
+ minitest (5.14.2)
13
+ parallel (1.19.2)
14
+ parser (2.7.1.5)
15
+ ast (~> 2.4.1)
16
16
  rainbow (3.0.0)
17
17
  rake (13.0.1)
18
- redis (4.1.3)
19
- rubocop (0.74.0)
20
- jaro_winkler (~> 1.5.1)
18
+ redis (4.2.2)
19
+ regexp_parser (1.8.0)
20
+ rexml (3.2.4)
21
+ rubocop (0.92.0)
21
22
  parallel (~> 1.10)
22
- parser (>= 2.6)
23
+ parser (>= 2.7.1.5)
23
24
  rainbow (>= 2.2.2, < 4.0)
25
+ regexp_parser (>= 1.7)
26
+ rexml
27
+ rubocop-ast (>= 0.5.0)
24
28
  ruby-progressbar (~> 1.7)
25
- unicode-display_width (>= 1.4.0, < 1.7)
29
+ unicode-display_width (>= 1.4.0, < 2.0)
30
+ rubocop-ast (0.6.0)
31
+ parser (>= 2.7.1.5)
26
32
  ruby-progressbar (1.10.1)
27
- unicode-display_width (1.6.0)
33
+ unicode-display_width (1.7.0)
34
+ yard (0.9.25)
28
35
 
29
36
  PLATFORMS
30
37
  ruby
31
38
 
32
39
  DEPENDENCIES
33
40
  blizzard_api!
41
+ dotenv
34
42
  minitest (~> 5.0)
35
43
  rake (~> 13.0)
36
44
  rubocop (~> 0.61)
45
+ yard
37
46
 
38
47
  BUNDLED WITH
39
- 2.1.2
48
+ 2.1.4
data/README.md CHANGED
@@ -73,6 +73,46 @@ Most **data** endpoints will have always 3 methods available `index`, `get` and
73
73
  * `get` is used to get all information about a entry of the index returned data. It receives an id or slug as the first parameter, that depends on the endpoint.
74
74
  * `complete` is a complete information of all items listed in index. **This may perform various calls to the blizzard api** only use if you really need all information.
75
75
 
76
+ ### 3.1 Searchable endpoints
77
+
78
+ Some endpoints support search filters. To perform a search you can use the following formats:
79
+
80
+
81
+ To use the **or** operator you may pass an array of values as argument to `where` or `where_not` methods.
82
+ ```ruby
83
+ realm = BlizzardApi::Wow.realm
84
+ realm_data = realm.search(1, 100) do |options|
85
+ options.where 'name.en_US', %w[Azralon Nemesis]
86
+ end
87
+ ```
88
+
89
+ To use the **and** operator you may call `where` or `where_not` multiple times methods.
90
+ ```ruby
91
+ realm = BlizzardApi::Wow.realm
92
+ realm_data = realm.search(1, 100) do |options|
93
+ options.where 'name.en_US', 'Azralon'
94
+ options.where 'id', 3209
95
+ end
96
+ ```
97
+
98
+ To use the **range** operator you may pass a hash to `where` or `where_not`.
99
+ ```ruby
100
+ realm = BlizzardApi::Wow.realm
101
+ realm_data = realm.search(1, 100) do |options|
102
+ options.where 'id', min: 3209, max: 4000, mode: :exclusive
103
+ end
104
+ ```
105
+ *Note*: If you don't pass the `mode` key as `:exclusive` it will be `:inclusive` by default.
106
+
107
+ To **sort** fields you may call the `order_by` method multiple times:
108
+ ```ruby
109
+ realm = BlizzardApi::Wow.realm
110
+ realm_data = realm.search(1, 100) do |options|
111
+ options.where 'id', min: 3209, max: 4000, mode: :exclusive
112
+ options.order_by 'id', :desc
113
+ end
114
+ ```
115
+
76
116
  ## 4. Available endpoints
77
117
 
78
118
  **Hint**: All methods support an additional optional hash parameter that allows you to override the following configurations for a single call:
@@ -105,6 +145,7 @@ Most **data** endpoints will have always 3 methods available `index`, `get` and
105
145
  - types
106
146
  - type :id
107
147
  - display_media :id
148
+ - search
108
149
  * Blizzard::Wow::Guild
109
150
  - rewards
110
151
  - perks
@@ -171,6 +212,7 @@ Most **data** endpoints will have always 3 methods available `index`, `get` and
171
212
  - get :id
172
213
  - complete
173
214
  - status :realms
215
+ - search
174
216
  * Blizzard::Wow::Region
175
217
  - index
176
218
  - get :id
@@ -191,10 +233,12 @@ Most **data** endpoints will have always 3 methods available `index`, `get` and
191
233
  - class :id
192
234
  - subclass :class_id, :subclass_id
193
235
  - media :id
236
+ - search
194
237
  * Blizzard::Wow::AzeriteEssence
195
238
  - index
196
239
  - get :id
197
240
  - media :id
241
+ - search
198
242
  * Blizzard::Wow::ReputationTier
199
243
  - index
200
244
  - get :id
@@ -222,6 +266,7 @@ Most **data** endpoints will have always 3 methods available `index`, `get` and
222
266
  - get :id
223
267
  * Blizzard::Wow::Spell
224
268
  - get :id
269
+ - search
225
270
  * Blizzard::Wow::Zone
226
271
  - index
227
272
  - get :id
@@ -34,7 +34,9 @@ Gem::Specification.new do |spec|
34
34
 
35
35
  spec.add_runtime_dependency 'redis', '~> 4.1', '>= 4.1.0'
36
36
 
37
+ spec.add_development_dependency 'dotenv'
37
38
  spec.add_development_dependency 'minitest', '~> 5.0'
38
39
  spec.add_development_dependency 'rake', '~> 13.0'
39
40
  spec.add_development_dependency 'rubocop', '~> 0.61'
41
+ spec.add_development_dependency 'yard'
40
42
  end
@@ -13,13 +13,12 @@ module BlizzardApi
13
13
  ##
14
14
  # Return information about an item
15
15
  #
16
- # @param item_slug [String] Item slug
17
- # @param item_id [Integer] Item id
16
+ # @param item_slug_and_id [String] Item slug
18
17
  # @!macro request_options
19
18
  #
20
19
  # @!macro response
21
- def get(item_slug, item_id, options = {})
22
- api_request "#{base_url(:community)}/data/item/#{item_slug}-#{item_id}", { ttl: CACHE_TRIMESTER }.merge(options)
20
+ def get(item_slug_and_id, options = {})
21
+ api_request "#{base_url(:community)}/data/item/#{item_slug_and_id}", { ttl: CACHE_TRIMESTER }.merge(options)
23
22
  end
24
23
  end
25
24
  end
@@ -4,8 +4,8 @@ module BlizzardApi
4
4
  module Diablo
5
5
  # Generic endpoint to support most data requests with minor configurations
6
6
  class GenericDataEndpoint < Diablo::Request
7
- def initialize(region = nil)
8
- super region
7
+ def initialize(region = nil, mode = :regular)
8
+ super region, mode
9
9
  endpoint_setup
10
10
  @ttl ||= CACHE_DAY
11
11
  end
@@ -6,8 +6,8 @@ module BlizzardApi
6
6
  class Request < BlizzardApi::Request
7
7
  ##
8
8
  # @!macro regions
9
- def initialize(region = nil)
10
- super region
9
+ def initialize(region = nil, mode = :regular)
10
+ super region, mode
11
11
  @game = 'd3'
12
12
  end
13
13
  end
@@ -4,8 +4,8 @@ module BlizzardApi
4
4
  module Hearthstone
5
5
  # Generic endpoint to support most data requests with minor configurations
6
6
  class GenericDataEndpoint < Hearthstone::Request
7
- def initialize(region = nil)
8
- super region
7
+ def initialize(region = nil, mode = :regular)
8
+ super region, mode
9
9
  endpoint_setup
10
10
  @ttl ||= CACHE_DAY
11
11
  end
@@ -6,8 +6,8 @@ module BlizzardApi
6
6
  class Request < BlizzardApi::Request
7
7
  ##
8
8
  # @!macro regions
9
- def initialize(region = nil)
10
- super region
9
+ def initialize(region = nil, mode = :regular)
10
+ super region, mode
11
11
  @game = 'hearthstone'
12
12
  end
13
13
  end
@@ -8,6 +8,7 @@
8
8
  # @option options [String] :access_token Overrides the access_token for a single call
9
9
  # @option options [Boolean] :ignore_cache If set to true the request will not use the cache
10
10
  # @option options [Integer] :ttl Override the default time (in seconds) a request should be cached
11
+ # @option options [DateTime] :since Adds the If-modified-since headers. Will always ignore cache when set.
11
12
 
12
13
  ##
13
14
  # @!macro [new] regions
@@ -31,18 +32,12 @@ module BlizzardApi
31
32
  ##
32
33
  # Simplifies the requests to Blizzard APIS
33
34
  class Request
34
- # One minute cache
35
- CACHE_MINUTE = 60
36
35
  # One hour cache
37
- CACHE_HOUR = 60 * CACHE_MINUTE
36
+ CACHE_HOUR = 3600
38
37
  # One day cache
39
38
  CACHE_DAY = 24 * CACHE_HOUR
40
- # One week cache
41
- CACHE_WEEK = CACHE_DAY * 7
42
- # One (commercial) month cache
43
- CACHE_MONTH = CACHE_DAY * 30
44
39
  # Three (commercial) months cache
45
- CACHE_TRIMESTER = CACHE_MONTH * 3
40
+ CACHE_TRIMESTER = CACHE_DAY * 90
46
41
 
47
42
  # Common endpoints
48
43
  BASE_URLS = {
@@ -50,7 +45,8 @@ module BlizzardApi
50
45
  community: 'https://%s.api.blizzard.com/%s',
51
46
  profile: 'https://%s.api.blizzard.com/profile/%s',
52
47
  media: 'https://%s.api.blizzard.com/data/%s/media',
53
- user_profile: 'https://%s.api.blizzard.com/profile/user/%s'
48
+ user_profile: 'https://%s.api.blizzard.com/profile/user/%s',
49
+ search: 'https://%s.api.blizzard.com/data/%s/search'
54
50
  }.freeze
55
51
 
56
52
  ##
@@ -58,13 +54,20 @@ module BlizzardApi
58
54
  # @return [String] Api region
59
55
  attr_accessor :region
60
56
 
57
+ ##
58
+ # @!attribute mode
59
+ # @return [:regular, :extended]
60
+ attr_accessor :mode
61
+
61
62
  ##
62
63
  # @!macro regions
63
- def initialize(region = nil)
64
+ def initialize(region = nil, mode = :regular)
64
65
  self.region = region || BlizzardApi.region
65
66
  @redis = Redis.new(host: BlizzardApi.redis_host, port: BlizzardApi.redis_port) if BlizzardApi.use_cache
66
67
  # Use the shared access_token, or create one if it doesn't exists. This avoids unnecessary calls to create tokens.
67
68
  @access_token = BlizzardApi.access_token || create_access_token
69
+ # Mode
70
+ @mode = mode
68
71
  end
69
72
 
70
73
  require 'net/http'
@@ -87,7 +90,7 @@ module BlizzardApi
87
90
  def endpoint_namespace(options)
88
91
  case options[:namespace]
89
92
  when :dynamic
90
- "dynamic-#{region}"
93
+ options.include?(:classic) ? "dynamic-classic-#{region}" : "dynamic-#{region}"
91
94
  when :static
92
95
  options.include?(:classic) ? "static-classic-#{region}" : "static-#{region}"
93
96
  when :profile
@@ -97,10 +100,6 @@ module BlizzardApi
97
100
  end
98
101
  end
99
102
 
100
- def string_to_slug(string)
101
- CGI.escape(string.downcase.tr(' ', '-'))
102
- end
103
-
104
103
  def create_access_token
105
104
  uri = URI.parse("https://#{BlizzardApi.region}.battle.net/oauth/token")
106
105
 
@@ -120,26 +119,24 @@ module BlizzardApi
120
119
  # Creates the whole url for request
121
120
  parsed_url = URI.parse(url)
122
121
 
123
- data = options[:ignore_cache] ? nil : find_in_cache(parsed_url.to_s)
122
+ data = using_cache?(options) ? find_in_cache(parsed_url.to_s) : nil
123
+
124
124
  # If data was found that means cache is enabled and valid
125
- return format_response data if data
125
+ return JSON.parse(data, symbolize_names: true) if data
126
126
 
127
- # Override access_token
128
- @access_token = options[:access_token] if options.include? :access_token
127
+ response = consume_api parsed_url, options
129
128
 
130
- response = consume_api parsed_url
129
+ save_in_cache parsed_url.to_s, response.body, options[:ttl] || CACHE_DAY if using_cache? options
131
130
 
132
- unless options[:ignore_cache]
133
- ttl = options[:ttl] || CACHE_DAY
134
- save_in_cache parsed_url.to_s, response.body, ttl
135
- end
131
+ response_data = response.code.to_i.eql?(304) ? nil : JSON.parse(response.body, symbolize_names: true)
132
+ return [response, response_data] if mode.eql? :extended
136
133
 
137
- format_response response.body
134
+ response_data
138
135
  end
139
136
 
140
137
  def api_request(uri, query_string = {})
141
138
  # List of request options
142
- options_key = %i[ignore_cache ttl format access_token namespace classic]
139
+ options_key = %i[ignore_cache ttl format access_token namespace classic headers since]
143
140
 
144
141
  # Separates request options from api fields and options. Any user-defined option will be treated as api field.
145
142
  options = query_string.select { |k, _v| query_string.delete(k) || true if options_key.include? k }
@@ -158,35 +155,46 @@ module BlizzardApi
158
155
 
159
156
  private
160
157
 
161
- def consume_api(url)
158
+ ##
159
+ # @param options [Hash] Request options
160
+ def using_cache?(options)
161
+ return false if mode.eql?(:extended) || options.key?(:since)
162
+
163
+ !options.fetch(:ignore_cache, false)
164
+ end
165
+
166
+ def consume_api(url, options = {})
162
167
  # Creates a HTTP connection and request to ensure thread safety
163
168
  http = Net::HTTP.new(url.host, url.port)
164
169
  http.use_ssl = true
165
170
  request = Net::HTTP::Get.new(url)
166
171
 
167
- # Blizzard API documentation states the preferred way to send the access_token is using Bearer token on header
168
- request['Authorization'] = "Bearer #{@access_token}"
172
+ add_headers request, options
169
173
 
170
174
  # Executes the request
171
175
  http.request(request).tap do |response|
172
- raise BlizzardApi::ApiException.new 'Request failed', response.code.to_i unless response.code.to_i == 200
176
+ if mode.eql?(:regular) && ![200, 304].include?(response.code.to_i)
177
+ raise BlizzardApi::ApiException.new 'Request failed', response.code.to_i
178
+ end
173
179
  end
174
180
  end
175
181
 
176
- def save_in_cache(resource_url, data, ttl)
177
- return nil unless BlizzardApi.use_cache
182
+ def add_headers(request, options)
183
+ # Blizzard API documentation states the preferred way to send the access_token is using Bearer token on header
184
+ request['Authorization'] = "Bearer #{options.fetch(:access_token, @access_token)}"
185
+ # Format If-modified-since option
186
+ request['If-Modified-Since'] = options[:since].httpdate if options.key? :since
187
+ options[:headers]&.each { |header, content| request[header] = content }
188
+ end
178
189
 
179
- @redis.setex resource_url, ttl, data
190
+ def save_in_cache(resource_url, data, ttl)
191
+ @redis.setex resource_url, ttl, data if BlizzardApi.use_cache
180
192
  end
181
193
 
182
194
  def find_in_cache(resource_url)
183
195
  return false unless BlizzardApi.use_cache
184
196
 
185
- @redis.get resource_url if @redis.exists resource_url
186
- end
187
-
188
- def format_response(data)
189
- JSON.parse(data, symbolize_names: true)
197
+ @redis.get resource_url if @redis.exists? resource_url
190
198
  end
191
199
  end
192
200
  end
@@ -15,8 +15,8 @@ module BlizzardApi
15
15
 
16
16
  ##
17
17
  # @!macro regions
18
- def initialize(region = nil)
19
- super region
18
+ def initialize(region = nil, mode = :regular)
19
+ super region, mode
20
20
  @game = 'sc2'
21
21
  end
22
22
 
@@ -2,5 +2,5 @@
2
2
 
3
3
  module BlizzardApi
4
4
  # Gem version
5
- VERSION = '0.3.10'
5
+ VERSION = '0.5.1'
6
6
  end
@@ -5,6 +5,9 @@ module BlizzardApi
5
5
  module Wow
6
6
  require_relative 'wow/request'
7
7
  require_relative 'wow/game_data/generic_data_endpoint'
8
+ require_relative 'wow/search/search_composer'
9
+ require_relative 'wow/search/search_request'
10
+ require_relative 'wow/slug'
8
11
 
9
12
  # WoW data api
10
13
  require_relative 'wow/game_data/achievement'
@@ -15,6 +18,8 @@ module BlizzardApi
15
18
  require_relative 'wow/game_data/guild_crest'
16
19
  require_relative 'wow/game_data/item'
17
20
  require_relative 'wow/game_data/journal'
21
+ require_relative 'wow/game_data/media'
22
+ require_relative 'wow/game_data/modified_crafting'
18
23
  require_relative 'wow/game_data/mount'
19
24
  require_relative 'wow/game_data/mythic_keystone_affix'
20
25
  require_relative 'wow/game_data/mythic_keystone'
@@ -93,6 +98,20 @@ module BlizzardApi
93
98
  BlizzardApi::Wow::Journal.new(region)
94
99
  end
95
100
 
101
+ ##
102
+ # @param region [String] API Region
103
+ # @return {Media}
104
+ def self.media(region = BlizzardApi.region)
105
+ BlizzardApi::Wow::Media.new(region)
106
+ end
107
+
108
+ ##
109
+ # @param region [String] API Region
110
+ # @return {ModifiedCrafting}
111
+ def self.modified_crafting(region = BlizzardApi.region)
112
+ BlizzardApi::Wow::ModifiedCrafting.new(region)
113
+ end
114
+
96
115
  ##
97
116
  # @param region [String] API Region
98
117
  # @return {Mount}
@@ -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 AzeriteEssence < Wow::GenericDataEndpoint
13
+ include BlizzardApi::Wow::Searchable
14
+
13
15
  ##
14
16
  # Fetch media for one of the azerite essences listed by the {#index} using its *id*
15
17
  #
@@ -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.connected_realm
12
12
  class ConnectedRealm < Wow::GenericDataEndpoint
13
+ include BlizzardApi::Wow::Searchable
14
+
13
15
  protected
14
16
 
15
17
  def endpoint_setup
@@ -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.creature
12
12
  class Creature < Wow::GenericDataEndpoint
13
+ include BlizzardApi::Wow::Searchable
14
+
13
15
  def index
14
16
  raise BlizzardApi::ApiException, 'Creatures endpoint doesn\'t have a index method'
15
17
  end
@@ -7,8 +7,8 @@ module BlizzardApi
7
7
  class GenericDataEndpoint < Wow::Request
8
8
  ##
9
9
  # @!macro regions
10
- def initialize(region = nil)
11
- super region
10
+ def initialize(region = nil, mode = :regular)
11
+ super region, mode
12
12
  endpoint_setup
13
13
  @ttl ||= CACHE_DAY
14
14
  end
@@ -48,9 +48,9 @@ module BlizzardApi
48
48
 
49
49
  protected
50
50
 
51
- def endpoint_uri(variant = nil)
51
+ def endpoint_uri(variant = nil, scope = :game_data)
52
52
  endpoint = variant ? "#{@endpoint}-#{variant}" : @endpoint
53
- "#{base_url(:game_data)}/#{endpoint}"
53
+ "#{base_url(scope)}/#{endpoint}"
54
54
  end
55
55
 
56
56
  def endpoint_setup
@@ -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.item
12
12
  class Item < Wow::GenericDataEndpoint
13
+ include BlizzardApi::Wow::Searchable
14
+
13
15
  ##
14
16
  # This method overrides the inherited default behavior to prevent high server load and fetch time
15
17
  #
@@ -97,6 +97,21 @@ module BlizzardApi
97
97
  api_request "#{endpoint_uri('encounter')}/#{id}", default_options.merge(options)
98
98
  end
99
99
 
100
+ ##
101
+ # Fetch data base on search criteria
102
+ #
103
+ # @param page [Integer] Page o return
104
+ # @param page_size [Integer] Amount of items per page
105
+ #
106
+ # @!macro request_options
107
+ # @!macro response
108
+ def encounter_search(page = 1, page_size = 100, options = {})
109
+ search_options = SearchComposer.new(page, page_size)
110
+ yield search_options if block_given?
111
+
112
+ api_request "#{endpoint_uri('encounter', :search)}?#{search_options.to_search_query}", default_options.merge(options)
113
+ end
114
+
100
115
  protected
101
116
 
102
117
  def endpoint_setup
@@ -0,0 +1,37 @@
1
+ # frozen_string_literal: true
2
+
3
+ module BlizzardApi
4
+ module Wow
5
+ ##
6
+ # This class allows access to World of Warcraft mounts
7
+ #
8
+ # @see https://develop.battle.net/documentation/api-reference/world-of-warcraft-game-data-api
9
+ #
10
+ # You can get an instance of this class using the default region as follows:
11
+ # api_instance = BlizzardApi::Wow.mount
12
+ class Media < Wow::GenericDataEndpoint
13
+ include BlizzardApi::Wow::Searchable
14
+
15
+ def index(_options = nil)
16
+ raise BlizzardApi::ApiException, 'This endpoint does not have a index method'
17
+ end
18
+
19
+ def get(_options = nil)
20
+ raise BlizzardApi::ApiException, 'This endpoint does not have a get method'
21
+ end
22
+
23
+ def complete(_options = nil)
24
+ raise BlizzardApi::ApiException, 'This endpoint does not have a complete method'
25
+ end
26
+
27
+ protected
28
+
29
+ def endpoint_setup
30
+ @endpoint = 'media'
31
+ @namespace = :static
32
+ @collection = 'medias'
33
+ @ttl = CACHE_TRIMESTER
34
+ end
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,67 @@
1
+ # frozen_string_literal: true
2
+
3
+ module BlizzardApi
4
+ module Wow
5
+ ##
6
+ # This class allows access to World of Warcraft professions
7
+ #
8
+ # @see https://develop.battle.net/documentation/api-reference/world-of-warcraft-game-data-api
9
+ #
10
+ # You can get an instance of this class using the default region as follows:
11
+ # api_instance = BlizzardApi::Wow.modified_crafting
12
+ class ModifiedCrafting < Wow::GenericDataEndpoint
13
+ def complete
14
+ raise BlizzardApi::ApiException, 'This endpoint does not have a complete method.'
15
+ end
16
+
17
+ ##
18
+ # Fetch modified crafting category index
19
+ #
20
+ # @!macro request_options
21
+ def categories(options = {})
22
+ api_request "#{base_url(:game_data)}/modified-crafting/category/index", default_options.merge(options)
23
+ end
24
+
25
+ ##
26
+ # Fetch a modified crafting category
27
+ #
28
+ # @param id [Integer] Modified crafting category id
29
+ #
30
+ # @!macro request_options
31
+ #
32
+ # @!macro response
33
+ def category(id, options = {})
34
+ api_request "#{base_url(:game_data)}/modified-crafting/category/#{id}", default_options.merge(options)
35
+ end
36
+
37
+ ##
38
+ # Fetch modified crafting slot type index
39
+ #
40
+ # @!macro request_options
41
+ def slot_types(options = {})
42
+ api_request "#{base_url(:game_data)}/modified-crafting/reagent-slot-type/index", default_options.merge(options)
43
+ end
44
+
45
+ ##
46
+ # Fetch a modified crafting slot type
47
+ #
48
+ # @param id [Integer] Modified crafting slot type id
49
+ #
50
+ # @!macro request_options
51
+ #
52
+ # @!macro response
53
+ def slot_type(id, options = {})
54
+ api_request "#{base_url(:game_data)}/modified-crafting/reagent-slot-type/#{id}", default_options.merge(options)
55
+ end
56
+
57
+ protected
58
+
59
+ def endpoint_setup
60
+ @endpoint = 'modified-crafting'
61
+ @namespace = :static
62
+ @collection = 'professions'
63
+ @ttl = CACHE_TRIMESTER
64
+ end
65
+ end
66
+ end
67
+ 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.mount
12
12
  class Mount < Wow::GenericDataEndpoint
13
+ include BlizzardApi::Wow::Searchable
14
+
13
15
  protected
14
16
 
15
17
  def endpoint_setup
@@ -10,6 +10,52 @@ module BlizzardApi
10
10
  # You can get an instance of this class using the default region as follows:
11
11
  # api_instance = BlizzardApi::Wow.pet
12
12
  class Pet < Wow::GenericDataEndpoint
13
+ ##
14
+ # Fetch media for one of the pets listed by the {#index} using its *id*
15
+ #
16
+ # @param id [Integer] Pet id
17
+ #
18
+ # @!macro request_options
19
+ #
20
+ # @!macro response
21
+ def media(id, options = {})
22
+ api_request "#{base_url(:media)}/pet/#{id}", default_options.merge(options)
23
+ end
24
+
25
+ ##
26
+ # Fetch all pet abilities
27
+ #
28
+ # @!macro request_options
29
+ #
30
+ # @!macro response
31
+ def abilities(options = {})
32
+ api_request "#{endpoint_uri('ability')}/index", default_options.merge(options)
33
+ end
34
+
35
+ ##
36
+ # Fetch a pet ability
37
+ #
38
+ # @param id [Integer] Pet id
39
+ #
40
+ # @!macro request_options
41
+ #
42
+ # @!macro response
43
+ def ability(id, options = {})
44
+ api_request "#{endpoint_uri('ability')}/#{id}", default_options.merge(options)
45
+ end
46
+
47
+ ##
48
+ # Fetch media for one of the pet abilities listed by the {#abilities} using its *id*
49
+ #
50
+ # @param id [Integer] Pet ability id
51
+ #
52
+ # @!macro request_options
53
+ #
54
+ # @!macro response
55
+ def ability_media(id, options = {})
56
+ api_request "#{base_url(:media)}/pet-ability/#{id}", default_options.merge(options)
57
+ end
58
+
13
59
  protected
14
60
 
15
61
  def endpoint_setup
@@ -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.realm
12
12
  class Realm < Wow::GenericDataEndpoint
13
+ include BlizzardApi::Wow::Searchable
14
+
13
15
  protected
14
16
 
15
17
  def endpoint_setup
@@ -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.spell
12
12
  class Spell < Wow::GenericDataEndpoint
13
+ include BlizzardApi::Wow::Searchable
14
+
13
15
  ##
14
16
  # This method overrides the inherited default behavior to prevent high server load and fetch time
15
17
  #
@@ -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.achievement
12
12
  class CharacterProfile < Wow::Request
13
+ include BlizzardApi::Wow::Slug
14
+
13
15
  ##
14
16
  # Return character achievements
15
17
  #
@@ -287,9 +289,11 @@ module BlizzardApi
287
289
  # @param realm [String] The character realm's slug
288
290
  # @param character [String] The character name
289
291
  # @!macro request_options
292
+ # @option options [Boolean] :completed Should return completed quests
290
293
  #
291
294
  # @!macro response
292
- def quests(realm, character, completed = false, options = {})
295
+ def quests(realm, character, options = {})
296
+ completed = options.delete(:completed) || false
293
297
  return character_request realm, character, options, 'quests/completed' if completed
294
298
 
295
299
  character_request realm, character, options, 'quests'
@@ -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
12
12
  class Guild < Wow::Request
13
+ include BlizzardApi::Wow::Slug
14
+
13
15
  ##
14
16
  # Return data about the specified guild
15
17
  #
@@ -7,8 +7,8 @@ module BlizzardApi
7
7
  class AccountProfile < Request
8
8
  ##
9
9
  # @param token [String] A token obtained using the authorization_code flow
10
- def initialize(token, region = nil)
11
- super region
10
+ def initialize(token, region = nil, mode = :regular)
11
+ super region, mode
12
12
  @token = token
13
13
  end
14
14
 
@@ -7,8 +7,8 @@ module BlizzardApi
7
7
  class Request < BlizzardApi::Request
8
8
  ##
9
9
  # @!macro regions
10
- def initialize(region = nil)
11
- super region
10
+ def initialize(region = nil, mode = :regular)
11
+ super region, mode
12
12
  @game = 'wow'
13
13
  end
14
14
  end
@@ -0,0 +1,97 @@
1
+ # frozen_string_literal: true
2
+
3
+ module BlizzardApi
4
+ module Wow
5
+ ##
6
+ # Composer for search endpoint arguments
7
+ class SearchComposer
8
+ attr_accessor :fields, :order, :page, :page_size
9
+
10
+ def initialize(page, page_size)
11
+ self.page = page
12
+ self.page_size = page_size
13
+ self.fields = []
14
+ self.order = []
15
+ end
16
+
17
+ ##
18
+ # Add a search field
19
+ #
20
+ # The second argument takes a simple value, an array of values or a hash for range searches.
21
+ #
22
+ # @param field [String] Field name
23
+ # @param value [String|Integer|Hash|Array<Integer>|Array<String>]
24
+ # @option value [Integer] :min Range start
25
+ # @option value [Integer] :max Range end
26
+ # @option value [Integer] :mode Range mode (:inclusive|:exclusive)
27
+ #
28
+ # @return {SearchComposer}
29
+ def where(field, value)
30
+ fields.push "#{field}=#{resolve_value(value)}"
31
+ self
32
+ end
33
+
34
+ ##
35
+ # Add a search field
36
+ #
37
+ # The second argument takes a simple value, an array of values or a hash for range searches.
38
+ #
39
+ # @param field [String] Field name
40
+ # @param value [String|Integer|Hash|Array<Integer>|Array<String>]
41
+ # @option value [Integer] :min Range start
42
+ # @option value [Integer] :max Range end
43
+ # @option value [Integer] :mode Range mode (:inclusive|:exclusive)
44
+ #
45
+ # @return {SearchComposer}
46
+ def where_not(field, value)
47
+ fields.push "#{field}!=#{resolve_value(value)}"
48
+ self
49
+ end
50
+
51
+ ##
52
+ # Add a sort field
53
+ #
54
+ # @param field [String] Field name
55
+ # @param mode [Symbol] :asc or :desc
56
+ #
57
+ # @return {SearchComposer}
58
+ def order_by(field, mode = :asc)
59
+ raise ArgumentError, 'Invalid order mode.' unless %i[asc desc].include? mode
60
+
61
+ order.push "#{field}:#{mode}"
62
+ self
63
+ end
64
+
65
+ ##
66
+ # Returns a valid queryString based on the options
67
+ #
68
+ # @return {String}
69
+ def to_search_query
70
+ query_string = "_page=#{page}&_pageSize=#{page_size}"
71
+ query_string += "&#{fields.join('&')}" unless fields.size.zero?
72
+ query_string += "&orderby=#{order.join(',')}" unless order.size.zero?
73
+ query_string
74
+ end
75
+
76
+ protected
77
+
78
+ def resolve_value(value)
79
+ return value.join '||' if value.is_a? Array
80
+
81
+ return value.to_s unless value.is_a? Hash
82
+
83
+ resolve_hash value
84
+ end
85
+
86
+ def resolve_hash(value)
87
+ min = value.key?(:min) ? value[:min] : ''
88
+ max = value.key?(:max) ? value[:max] : ''
89
+ mode = value.key?(:mode) ? value[:mode] : :inclusive
90
+
91
+ return "[#{min},#{max}]" if mode.eql? :inclusive
92
+
93
+ "(#{min},#{max})"
94
+ end
95
+ end
96
+ end
97
+ end
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ module BlizzardApi
4
+ module Wow
5
+ ##
6
+ # Added search support to an endpoint
7
+ module Searchable
8
+ ##
9
+ # Fetch data based on search criteria
10
+ #
11
+ # @param page [Integer] Page o return
12
+ # @param page_size [Integer] Amount of items per page
13
+ #
14
+ # @!macro request_options
15
+ # @!macro response
16
+ def search(page = 1, page_size = 100, options = {})
17
+ search_options = SearchComposer.new(page, page_size)
18
+ yield search_options if block_given?
19
+
20
+ api_request "#{endpoint_uri(nil, :search)}?#{search_options.to_search_query}", default_options.merge(options)
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ module BlizzardApi
4
+ module Wow
5
+ # Support for slugs
6
+ module Slug
7
+ def string_to_slug(string)
8
+ CGI.escape(string.downcase.tr(' ', '-'))
9
+ end
10
+ end
11
+ end
12
+ end
metadata CHANGED
@@ -1,35 +1,49 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: blizzard_api
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.10
4
+ version: 0.5.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Francis Schiavo
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2020-04-17 00:00:00.000000000 Z
11
+ date: 2020-10-24 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: redis
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - ">="
18
- - !ruby/object:Gem::Version
19
- version: 4.1.0
20
17
  - - "~>"
21
18
  - !ruby/object:Gem::Version
22
19
  version: '4.1'
20
+ - - ">="
21
+ - !ruby/object:Gem::Version
22
+ version: 4.1.0
23
23
  type: :runtime
24
24
  prerelease: false
25
25
  version_requirements: !ruby/object:Gem::Requirement
26
26
  requirements:
27
+ - - "~>"
28
+ - !ruby/object:Gem::Version
29
+ version: '4.1'
27
30
  - - ">="
28
31
  - !ruby/object:Gem::Version
29
32
  version: 4.1.0
30
- - - "~>"
33
+ - !ruby/object:Gem::Dependency
34
+ name: dotenv
35
+ requirement: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - ">="
31
38
  - !ruby/object:Gem::Version
32
- version: '4.1'
39
+ version: '0'
40
+ type: :development
41
+ prerelease: false
42
+ version_requirements: !ruby/object:Gem::Requirement
43
+ requirements:
44
+ - - ">="
45
+ - !ruby/object:Gem::Version
46
+ version: '0'
33
47
  - !ruby/object:Gem::Dependency
34
48
  name: minitest
35
49
  requirement: !ruby/object:Gem::Requirement
@@ -72,6 +86,20 @@ dependencies:
72
86
  - - "~>"
73
87
  - !ruby/object:Gem::Version
74
88
  version: '0.61'
89
+ - !ruby/object:Gem::Dependency
90
+ name: yard
91
+ requirement: !ruby/object:Gem::Requirement
92
+ requirements:
93
+ - - ">="
94
+ - !ruby/object:Gem::Version
95
+ version: '0'
96
+ type: :development
97
+ prerelease: false
98
+ version_requirements: !ruby/object:Gem::Requirement
99
+ requirements:
100
+ - - ">="
101
+ - !ruby/object:Gem::Version
102
+ version: '0'
75
103
  description: This is a simple interface to obtain data from Blizzard API
76
104
  email:
77
105
  - francis.schiavo@francisschiavo.com
@@ -132,6 +160,8 @@ files:
132
160
  - lib/blizzard_api/wow/game_data/guild_crest.rb
133
161
  - lib/blizzard_api/wow/game_data/item.rb
134
162
  - lib/blizzard_api/wow/game_data/journal.rb
163
+ - lib/blizzard_api/wow/game_data/media.rb
164
+ - lib/blizzard_api/wow/game_data/modified_crafting.rb
135
165
  - lib/blizzard_api/wow/game_data/mount.rb
136
166
  - lib/blizzard_api/wow/game_data/mythic_keystone.rb
137
167
  - lib/blizzard_api/wow/game_data/mythic_keystone_affix.rb
@@ -157,6 +187,9 @@ files:
157
187
  - lib/blizzard_api/wow/profile/guild.rb
158
188
  - lib/blizzard_api/wow/profile/profile.rb
159
189
  - lib/blizzard_api/wow/request.rb
190
+ - lib/blizzard_api/wow/search/search_composer.rb
191
+ - lib/blizzard_api/wow/search/search_request.rb
192
+ - lib/blizzard_api/wow/slug.rb
160
193
  homepage: https://gitlab.com/francisschiavo/blizzard_api
161
194
  licenses:
162
195
  - MIT
@@ -179,7 +212,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
179
212
  - !ruby/object:Gem::Version
180
213
  version: '0'
181
214
  requirements: []
182
- rubygems_version: 3.0.6
215
+ rubygems_version: 3.1.2
183
216
  signing_key:
184
217
  specification_version: 4
185
218
  summary: Unofficial Ruby client for Blizzard Entertainment API