bn 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 2822afc6d969ba0f64f38060a6408eaa684b9ef8
4
+ data.tar.gz: 0d13387ecc63fdfa99d4ccdd8d4a061f614cdae1
5
+ SHA512:
6
+ metadata.gz: 5d7f33cb1db092af1f8bd7add060a4424cbfa4e1b5990d37c7dc44e9d35f7ca6c3db8b16a36c627a69682378210774552c4fc551c2b66206e5f92c1f069a8b5d
7
+ data.tar.gz: 7424238727dd121b472b3e0c5d7b78a32a860bc44d2d24891c75ad5790eb585a588e914f4053043b9aeda41b7a890f376c8b779cfd59c5fb25d9d46854d1df60
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source "https://rubygems.org"
2
+
3
+ gemspec
@@ -0,0 +1,22 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ bn (0.0.1)
5
+ httpi (~> 2.4.1)
6
+ version (~> 1.0.0)
7
+
8
+ GEM
9
+ remote: https://rubygems.org/
10
+ specs:
11
+ httpi (2.4.1)
12
+ rack
13
+ rack (1.6.4)
14
+ rake (10.4.2)
15
+ version (1.0.0)
16
+
17
+ PLATFORMS
18
+ ruby
19
+
20
+ DEPENDENCIES
21
+ bn!
22
+ rake (~> 10.4.2)
@@ -0,0 +1,202 @@
1
+ # BN
2
+
3
+ BN is a [Battle.net](http://battle.net) API adapter and entity mapper.
4
+
5
+ ## Install
6
+
7
+ ### Bundler: `gem 'bn'`
8
+
9
+ ### RubyGems: `gem install bn`
10
+
11
+ ## Usage
12
+
13
+ ### Requiring
14
+
15
+ You can require the whole library with
16
+
17
+ ```rb
18
+ require "bn"
19
+ ```
20
+
21
+ Or you can require individual files/groups of files with
22
+
23
+ ```rb
24
+ require "bn/api/d3"
25
+ require "bn/entity/d3"
26
+ ```
27
+
28
+ ### API
29
+
30
+ **Mapping**
31
+
32
+ The `BN::API::Mapper` will send an HTTP request, parse the JSON response body, and create a new instance of
33
+ the entity associated with the API call.
34
+
35
+ ```rb
36
+ require "bn/api/mapper"
37
+
38
+ mapper = BN::API::Mapper.new(key: "00000000000000000000000000000000")
39
+
40
+ p mapper.d3.profile(battle_tag: "Example#0000") #=> #<BN::Entity::D3::Profile:0x007fa2a10e29a0 @battle_tag="Example#0000" ...>
41
+ ```
42
+
43
+ If called without arguments, the mapper will return a `BN::API::Mapping` instance, which associates API calls with
44
+ `Entity` instances. It also holds the list of middleware which the API HTTP response will go through before returning:
45
+
46
+ ```rb
47
+ require "bn/api/mapper"
48
+
49
+ mapper = BN::API::Mapper.new(key: "00000000000000000000000000000000")
50
+ mapping = mapper.d3.profile
51
+
52
+ p mapping.api_class # => BN::API::D3
53
+ p mapping.api_method # => :profile
54
+ p mapping.middleware # => [BN::Middleware::HTTPResponse, BN::Middleware::KeyConverter, BN::Middleware::APIError, BN::Middleware::D3::Profile]
55
+
56
+ mapping.execute(battle_tag: "Example#0000") #=> #<BN::Entity::D3::Profile:0x007fa2a10e29a0 @battle_tag="Example#0000" ...>
57
+ ```
58
+
59
+ This would allow you to manipulate the middleware before executing.
60
+
61
+ [Read more about middleware here.](#middleware)
62
+
63
+ **HTTP**
64
+
65
+ This simply sends an HTTP request to the API and returns it.
66
+ Useful for when you do not need entities or middleware.
67
+
68
+ ```rb
69
+ require "bn/api/d3"
70
+
71
+ api = BN::API::D3.new(key: "00000000000000000000000000000000")
72
+
73
+ p api.profile(battle_tag: "Example#0000") #=> #<HTTPI::Response:0x007fa2a0d0a5d0 @code=301 ...>
74
+ ```
75
+
76
+ ### Entity
77
+
78
+ An entity is a subclass of `BN::Entity::Base` for profiles, characters, items, and other game items.
79
+
80
+ You can initialize entities with an object responding to `#to_h` or use attribute setters after initialization.
81
+
82
+ ```rb
83
+ require "bn/entity/d3/hero"
84
+
85
+ hero = BN::Entity::D3::Hero.new(name: "Gronc")
86
+ hero.level = 70
87
+ ```
88
+
89
+ Some entities also come with some helper methods for calculations:
90
+
91
+ ```rb
92
+ hero.strength = 220
93
+
94
+ # Calculate the damage per second based on hero attributes
95
+ p hero.damage # => 12345
96
+ ```
97
+
98
+ ### Middleware
99
+
100
+ Middleware converts data from one form to another, raising an error on failure.
101
+
102
+ For example, the `BN::Middleware::HTTPResponse` accepts anything that responds to `#body` and attempts to parse
103
+ the body as JSON. If the response body could not be parsed or the JSON API response returned an error, then an error
104
+ will be raised.
105
+
106
+ This is useful if you're not using `BN::API` to send HTTP requests to the Battle.net API.
107
+
108
+ ```rb
109
+ require "net/http"
110
+ require "uri"
111
+ require "bn/middleware/http_response"
112
+
113
+ uri = URI("https://us.api.battle.net/d3/profile/Example-0000")
114
+ uri.query = URI.encode_www_form(apikey: "00000000000000000000000000000000", locale: "en_US")
115
+
116
+ response = Net::HTTP.get_response(uri)
117
+ data = BN::Middleware::HTTPResponse.execute(response)
118
+
119
+ p data # => { battle_tag: "Example#0000" }
120
+ ```
121
+
122
+ **Chaining**
123
+
124
+ Middleware can be chained together if the result of one conforms to the requirements of another:
125
+
126
+ ```rb
127
+ require "bn/api/d3"
128
+ require "bn/middleware/http_response"
129
+ require "bn/middleware/d3/profile"
130
+
131
+ api = BN::API::D3.new(key: "00000000000000000000000000000000")
132
+
133
+ response = api.profile(battle_tag: "Example#0000")
134
+
135
+ data = BN::Middleware::HTTPResponse.execute(response)
136
+ profile = BN::Middleware::D3::Profile.execute(data)
137
+
138
+ p profile #=> #<BN::Entity::D3::Profile:0x007fa2a10e29a0 @battle_tag="Example#0000" ...>
139
+ ```
140
+
141
+ To make chaining easier, there is a helper method on `BN::Middleware`:
142
+
143
+ ```rb
144
+ require "bn/api/d3"
145
+ require "bn/middleware"
146
+
147
+ api = BN::API::D3.new(key: "00000000000000000000000000000000")
148
+
149
+ response = api.profile(battle_tag: "Example#0000")
150
+
151
+ data = BN::Middleware::HTTPResponse.execute(response)
152
+ profile = BN::Middleware::D3::Profile.execute(data)
153
+ profile = BN::Middleware.execute(data, BN::Middleware::HTTPResponse, BN::Middleware::D3::Profile)
154
+
155
+ p profile #=> #<BN::Entity::D3::Profile:0x007fa2a10e29a0 @battle_tag="Example#0000" ...>
156
+ ```
157
+
158
+ Middleware given can either be classes or instances. Usually subclassed from `BN::Middleware::Base`, but can be anything
159
+ responding to `#execute`.
160
+
161
+ **Subclassing**
162
+
163
+ You can subclass `BN::Middleware::Base` to create your own transformations, such as manipulating JSON API responses
164
+ or initializing your own profile/item/etc objects:
165
+
166
+ ```rb
167
+ require "bn/middleware/base"
168
+
169
+ class HeroMiddleware < BN::Middleware::Base
170
+ def execute(data)
171
+ hero_data = data[:heroes].first
172
+
173
+ Hero.new(data[:hero_data])
174
+ end
175
+ end
176
+
177
+ class Hero
178
+ def initialize(name)
179
+ @name = name
180
+ end
181
+
182
+ attr_reader :name
183
+ end
184
+
185
+ require "bn/api/d3"
186
+ require "bn/middleware/http_response"
187
+
188
+ api = BN::API::D3.new(key: "00000000000000000000000000000000")
189
+
190
+ response = api.hero(battle_tag: "Example#0000", id: 1234)
191
+
192
+ data = BN::Transform::HTTPResponse.execute(response)
193
+ hero = HeroTransform.execute(data)
194
+
195
+ p hero #=> #<Hero:0x007fa2a10e29a0 @name="Gronc">
196
+ ```
197
+
198
+ ## Copyright
199
+
200
+ Copyright © 2015 Ryan Scott Lewis <ryan@rynet.us>.
201
+
202
+ The MIT License (MIT) - See LICENSE for further details.
@@ -0,0 +1,14 @@
1
+ require "pathname"
2
+ require "rake/version_task"
3
+ require "rubygems/package_task"
4
+
5
+ gemspec = Pathname.glob(Pathname.new(__FILE__).join("..", "*.gemspec")).first
6
+ $spec = Gem::Specification.load(gemspec.to_s)
7
+
8
+ Gem::PackageTask.new($spec) do |task|
9
+ task.need_zip = false
10
+ end
11
+
12
+ Rake::VersionTask.new do |task|
13
+ task.with_git_tag = true
14
+ end
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.0.1
@@ -0,0 +1,23 @@
1
+ require "pathname"
2
+
3
+ Gem::Specification.new do |s|
4
+ # Variables
5
+ s.author = "Ryan Scott Lewis"
6
+ s.email = "ryan@rynet.us"
7
+ s.summary = "A Battle.net API adapter and entity mapper."
8
+ s.license = "MIT"
9
+
10
+ # Dependencies
11
+ s.add_dependency "version", "~> 1.0.0"
12
+ s.add_dependency "httpi", "~> 2.4.1"
13
+ s.add_development_dependency "rake", "~> 10.4.2"
14
+
15
+ # Pragmatically set variables
16
+ s.homepage = "http://github.com/RyanScottLewis/#{s.name}"
17
+ s.version = Pathname.glob("VERSION*").first.read rescue "0.0.0"
18
+ s.description = s.summary
19
+ s.name = Pathname.new(__FILE__).basename(".gemspec").to_s
20
+ s.require_paths = ["lib"]
21
+ s.files = Dir["{{Rake,Gem}file{.lock,},README*,VERSION,LICENSE,*.gemspec,{lib,bin,examples,spec,test}/**/*}"]
22
+ s.test_files = Dir["{examples,spec,test}/**/*"]
23
+ end
@@ -0,0 +1,9 @@
1
+ require "version"
2
+
3
+ # Battle.net adapter and entity mapper.
4
+ module BN
5
+ is_versioned
6
+ end
7
+
8
+ require "bn/api"
9
+ require "bn/middleware"
@@ -0,0 +1,19 @@
1
+ module BN
2
+ # The API requestors.
3
+ module API
4
+ # The valid regions for the API.
5
+ # Contains name, host, and valid locales for each region.
6
+ REGIONS = {
7
+ us: { name: "US", uri: "https://us.api.battle.net", locales: %w(en_US es_MX pt_BR) },
8
+ eu: { name: "Europe", uri: "https://us.api.battle.net", locales: %w(en_GB es_ES fr_FR ru_RU de_DE pt_PT it_IT) },
9
+ kr: { name: "Korea", uri: "https://kr.api.battle.net", locales: %w(ko_KR) },
10
+ tw: { name: "Taiwan", uri: "https://tw.api.battle.net", locales: %w(zh_TW) },
11
+ cn: { name: "China", uri: "https://api.battlenet.com.cn", locales: %w(zh_CN) },
12
+ sea: { name: "South East Asia", uri: "https://sea.api.battle.net", locales: %w(en_US) }
13
+ }
14
+ end
15
+ end
16
+
17
+ require "bn/api/d3"
18
+ require "bn/api/sc2"
19
+ require "bn/api/wow"
@@ -0,0 +1,78 @@
1
+ require "httpi"
2
+ require "bn/helpers/has_attributes"
3
+ require "bn/error/api/invalid_key"
4
+ require "bn/error/api/invalid_region"
5
+ require "bn/error/api/invalid_locale"
6
+
7
+ module BN
8
+ module API
9
+ # The base class for API requesters.
10
+ class Base
11
+ include Helpers::HasAttributes
12
+
13
+ def initialize(attributes={})
14
+ self.region = :us
15
+
16
+ super
17
+
18
+ raise Error::API::InvalidKey if @key.nil?
19
+ end
20
+
21
+ attribute(:key) { |value| validate_key(value) }
22
+
23
+ attribute(:region) { |value| validate_and_convert_region(value) }
24
+
25
+ attribute(:locale) { |value| validate_locale(value) }
26
+
27
+ protected
28
+
29
+ # Send an HTTP GET request.
30
+ #
31
+ # @param [#to_s] url
32
+ # @param [#to_h] query
33
+ # @return [HTTPI::Response]
34
+ def get(url, query={})
35
+ url = url.to_s.gsub(%r{^/}, "")
36
+ query = query.to_h
37
+
38
+ request = HTTPI::Request.new
39
+ request.url = "#{@region[:host]}/#{url}"
40
+ request.query = { apikey: @key, locale: @locale }.merge(query)
41
+
42
+ HTTPI.get(request)
43
+ end
44
+
45
+ def validate_key(value)
46
+ value = value.to_s.delete(" ")
47
+
48
+ raise Error::API::InvalidKey if value.empty?
49
+
50
+ value
51
+ end
52
+
53
+ def validate_and_convert_region(region_key)
54
+ region_key = region_key.to_sym
55
+
56
+ raise Error::API::InvalidRegion unless BN::API::REGIONS.keys.include?(region_key)
57
+
58
+ region = REGIONS[region_key]
59
+ @locale = region[:locales].first
60
+
61
+ region
62
+ end
63
+
64
+ def validate_locale(locale)
65
+ locale = locale.to_s.strip
66
+ locale = @region[:locales].first if locale.empty?
67
+
68
+ raise Error::API::InvalidLocale, region: @region unless @region[:locales].include?(locale)
69
+
70
+ locale
71
+ end
72
+
73
+ def sanitize_battle_tag(value)
74
+ value.to_s.delete(" ").gsub(/#/, "-")
75
+ end
76
+ end
77
+ end
78
+ end
@@ -0,0 +1,44 @@
1
+ require "bn/api/base"
2
+
3
+ module BN
4
+ module API
5
+ # The the Diablo 3 API requester.
6
+ class D3 < Base
7
+ # Request a profile.
8
+ #
9
+ # @param [#to_h] options
10
+ # @option options [#to_s] :battle_tag The battle tag.
11
+ # @return [HTTPI::Response]
12
+ def profile(options={})
13
+ options = options.to_h
14
+
15
+ battle_tag = sanitize_battle_tag(options.delete(:battle_tag))
16
+
17
+ get("/d3/profile/#{battle_tag}", options)
18
+ end
19
+
20
+ # Request a hero.
21
+ #
22
+ # @param [#to_h] options
23
+ # @option options [#to_s] :battle_tag The battle tag.
24
+ # @option options [#to_s] :id The hero's ID.
25
+ # @return [HTTPI::Response]
26
+ def hero(options={})
27
+ options = options.to_h
28
+
29
+ battle_tag = sanitize_battle_tag(options.delete(:battle_tag))
30
+ id = sanitize_id(options.delete(:id))
31
+
32
+ get("/d3/profile/#{battle_tag}/hero/#{id}", options)
33
+ end
34
+
35
+ protected
36
+
37
+ def sanitize_id(id)
38
+ id = id.to_s.gsub(/[^0-9]/, "") unless id.is_a?(Integer)
39
+
40
+ id.to_i
41
+ end
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,74 @@
1
+ require "bn/api/base"
2
+
3
+ module BN
4
+ module API
5
+ # The the StarCraft 3 API requester.
6
+ class SC3 < Base
7
+ # Request a profile.
8
+ #
9
+ # @param [#to_h] options
10
+ # @option options [#to_s] :id The ID of the profile.
11
+ # @option options [#to_s] :region The region of the profile.
12
+ # @option options [#to_s] :name The name of the profile
13
+ # @return [HTTPI::Response]
14
+ def profile(options={})
15
+ get(profile_uri(options))
16
+ end
17
+
18
+ # Request a profile's ladders.
19
+ #
20
+ # @param [#to_h] options
21
+ # @option options [#to_s] :id The ID of the profile.
22
+ # @option options [#to_s] :region The region of the profile.
23
+ # @option options [#to_s] :name The name of the profile
24
+ # @return [HTTPI::Response]
25
+ def ladders(options={})
26
+ get(profile_uri(options, "ladders"))
27
+ end
28
+
29
+ # Request a profile's matches.
30
+ #
31
+ # @param [#to_h] options
32
+ # @option options [#to_s] :id The ID of the profile.
33
+ # @option options [#to_s] :region The region of the profile.
34
+ # @option options [#to_s] :name The name of the profile
35
+ # @return [HTTPI::Response]
36
+ def matches(options={})
37
+ get(profile_uri(options, "matches"))
38
+ end
39
+
40
+ # Request a ladder.
41
+ #
42
+ # @param [#to_h] options
43
+ # @option options [#to_s] :id The ID of the ladder.
44
+ # @return [HTTPI::Response]
45
+ def ladder(options={})
46
+ options = options.to_h
47
+
48
+ get("/sc2/ladder/#{options[:id]}")
49
+ end
50
+
51
+ # Request achievements.
52
+ #
53
+ # @return [HTTPI::Response]
54
+ def achievements
55
+ get("/sc2/data/achievements")
56
+ end
57
+
58
+ # Request rewards.
59
+ #
60
+ # @return [HTTPI::Response]
61
+ def achievements
62
+ get("/sc2/data/rewards")
63
+ end
64
+
65
+ protected
66
+
67
+ def profile_uri(options, path=nil)
68
+ options = options.to_h
69
+
70
+ "/sc2/profile/#{options[:id]}/#{options[:region]}/#{options[:name]}#{"/#{path}" unless path.nil?}"
71
+ end
72
+ end
73
+ end
74
+ end