armory_api 0.1.0
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.
- data/.gitignore +6 -0
- data/.rspec +2 -0
- data/Gemfile +3 -0
- data/README.md +4 -0
- data/Rakefile +19 -0
- data/armory_api.gemspec +26 -0
- data/lib/armory_api/client/character.rb +24 -0
- data/lib/armory_api/client.rb +58 -0
- data/lib/armory_api/configuration.rb +63 -0
- data/lib/armory_api/error.rb +13 -0
- data/lib/armory_api/version.rb +3 -0
- data/lib/armory_api.rb +28 -0
- data/lib/faraday/response/raise_armory_api_error.rb +19 -0
- data/spec/armory_api/client/character_spec.rb +50 -0
- data/spec/armory_api/client_spec.rb +74 -0
- data/spec/armory_api_spec.rb +24 -0
- data/spec/faraday/response_spec.rb +24 -0
- data/spec/fixtures/character/character-feed.json +957 -0
- data/spec/fixtures/character/character.json +13 -0
- data/spec/helper.rb +24 -0
- metadata +176 -0
data/.gitignore
ADDED
data/.rspec
ADDED
data/Gemfile
ADDED
data/README.md
ADDED
data/Rakefile
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
require 'bundler'
|
2
|
+
Bundler::GemHelper.install_tasks
|
3
|
+
|
4
|
+
require 'rspec/core/rake_task'
|
5
|
+
RSpec::Core::RakeTask.new(:spec)
|
6
|
+
|
7
|
+
task test: :spec
|
8
|
+
task default: :spec
|
9
|
+
|
10
|
+
namespace :doc do
|
11
|
+
require 'yard'
|
12
|
+
YARD::Rake::YardocTask.new do |t|
|
13
|
+
t.files = ['README.md', 'LICENSE.txt', 'lib/**/*.rb']
|
14
|
+
t.options = [
|
15
|
+
'--output-dir', 'doc/yard',
|
16
|
+
'--markup', 'markdown'
|
17
|
+
]
|
18
|
+
end
|
19
|
+
end
|
data/armory_api.gemspec
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
require File.expand_path('../lib/armory_api/version', __FILE__)
|
2
|
+
|
3
|
+
Gem::Specification.new do |s|
|
4
|
+
s.name = 'armory_api'
|
5
|
+
s.version = ArmoryApi::VERSION
|
6
|
+
s.description = 'Wrapper for the World of Warcraft API'
|
7
|
+
s.summary = s.description
|
8
|
+
s.authors = ['Francesco Ceccon']
|
9
|
+
s.email = ['francesco@ceccon.me']
|
10
|
+
s.homepage = 'https://github.com/fracek/armory_api'
|
11
|
+
s.platform = Gem::Platform::RUBY
|
12
|
+
s.require_path = ['lib']
|
13
|
+
s.files = `git ls-files`.split("\n")
|
14
|
+
|
15
|
+
s.add_dependency 'faraday', '~> 0.8'
|
16
|
+
s.add_dependency 'faraday_middleware', '~> 0.8'
|
17
|
+
s.add_dependency 'hashie', '~> 1.2'
|
18
|
+
s.add_dependency 'multi_json', '~> 1.3'
|
19
|
+
|
20
|
+
s.add_development_dependency 'json', '~> 1.7'
|
21
|
+
s.add_development_dependency 'rake'
|
22
|
+
s.add_development_dependency 'rspec'
|
23
|
+
s.add_development_dependency 'webmock'
|
24
|
+
s.add_development_dependency 'simplecov'
|
25
|
+
s.add_development_dependency 'yard'
|
26
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module ArmoryApi
|
2
|
+
class Client
|
3
|
+
module Character
|
4
|
+
|
5
|
+
# Retrieves a character from the Armory
|
6
|
+
#
|
7
|
+
# @param [String] name
|
8
|
+
# @param [String] realm
|
9
|
+
# @param [Array] fields optional fields, a list can be found on the
|
10
|
+
# [official page](http://blizzard.github.com/api-wow-docs/#character-profile-api)
|
11
|
+
def character(name, realm=nil, fields=[])
|
12
|
+
if realm.class == Array
|
13
|
+
fields = realm
|
14
|
+
realm = nil
|
15
|
+
end
|
16
|
+
realm ||= @realm
|
17
|
+
raise ArmoryApi::RealmNotFound if realm.nil?
|
18
|
+
fields ||= []
|
19
|
+
params = { fields: fields.join(',') } unless fields.empty?
|
20
|
+
get("/api/wow/character/#{realm}/#{name}", params)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
require 'faraday'
|
2
|
+
require 'uri'
|
3
|
+
|
4
|
+
require 'armory_api/client/character'
|
5
|
+
|
6
|
+
module ArmoryApi
|
7
|
+
class Client
|
8
|
+
attr_accessor(*Configuration::VALID_OPTIONS_KEYS)
|
9
|
+
|
10
|
+
# Initializes a new Client object
|
11
|
+
#
|
12
|
+
# @param [Hash] options
|
13
|
+
# @return [ArmoryApi::Client]
|
14
|
+
def initialize(options={})
|
15
|
+
options = ArmoryApi.options.merge(options)
|
16
|
+
Configuration::VALID_OPTIONS_KEYS.each do |key|
|
17
|
+
send("#{key}=", options[key])
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
# Performs an HTTP GET request
|
22
|
+
def get(path, params={}, options={})
|
23
|
+
request(:get, path, params, options)
|
24
|
+
end
|
25
|
+
|
26
|
+
include ArmoryApi::Client::Character
|
27
|
+
private
|
28
|
+
def endpoint
|
29
|
+
"http://#{@region}.battle.net"
|
30
|
+
end
|
31
|
+
|
32
|
+
# TODO: don't make a new connection on each request
|
33
|
+
def connection
|
34
|
+
@connection = Faraday.new(endpoint,
|
35
|
+
@connection_options.merge(builder: @middleware))
|
36
|
+
end
|
37
|
+
|
38
|
+
def request(method, path, params={}, options={})
|
39
|
+
uri = options[:endpoint] || endpoint
|
40
|
+
uri = URI(uri) unless uri.respond_to?(:host)
|
41
|
+
uri += path
|
42
|
+
request_headers = {}
|
43
|
+
params ||= {}
|
44
|
+
connection.url_prefix = options[:endpoint] || endpoint
|
45
|
+
res = connection.run_request(method.to_sym, path, nil, request_headers) do |req|
|
46
|
+
unless params.empty?
|
47
|
+
case req.method
|
48
|
+
when :post, :put
|
49
|
+
req.body = params
|
50
|
+
else
|
51
|
+
req.params.update(params)
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
res.body
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
@@ -0,0 +1,63 @@
|
|
1
|
+
require 'faraday'
|
2
|
+
require 'faraday_middleware'
|
3
|
+
require 'faraday/response/raise_armory_api_error'
|
4
|
+
require 'armory_api/version'
|
5
|
+
|
6
|
+
module ArmoryApi
|
7
|
+
module Configuration
|
8
|
+
VALID_OPTIONS_KEYS = [
|
9
|
+
:region,
|
10
|
+
:locale,
|
11
|
+
:realm,
|
12
|
+
:endpoint,
|
13
|
+
:user_agent,
|
14
|
+
:connection_options,
|
15
|
+
:middleware
|
16
|
+
].freeze
|
17
|
+
|
18
|
+
DEFAULT_REGION = 'us'
|
19
|
+
DEFAULT_LOCALE = 'en_US'
|
20
|
+
DEFAULT_ENDPOINT = "http://#{DEFAULT_REGION}.battle.net"
|
21
|
+
DEFAULT_USER_AGENT = "ArmoryApi Ruby Gem #{ArmoryApi::VERSION}".freeze
|
22
|
+
DEFAULT_CONNECTION_OPTIONS = {
|
23
|
+
headers: {
|
24
|
+
accept: 'application/json',
|
25
|
+
user_agent: DEFAULT_USER_AGENT
|
26
|
+
},
|
27
|
+
raw: true
|
28
|
+
}
|
29
|
+
DEFAULT_MIDDLEWARE = Faraday::Builder.new do |builder|
|
30
|
+
builder.request :json
|
31
|
+
|
32
|
+
builder.use Faraday::Response::RaiseArmoryApiError
|
33
|
+
builder.use FaradayMiddleware::Mashify
|
34
|
+
builder.use FaradayMiddleware::ParseJson
|
35
|
+
|
36
|
+
builder.adapter Faraday.default_adapter
|
37
|
+
end
|
38
|
+
|
39
|
+
attr_accessor(*VALID_OPTIONS_KEYS)
|
40
|
+
|
41
|
+
def self.extended(base)
|
42
|
+
base.reset
|
43
|
+
end
|
44
|
+
|
45
|
+
def configure
|
46
|
+
yield self
|
47
|
+
end
|
48
|
+
|
49
|
+
def options
|
50
|
+
VALID_OPTIONS_KEYS.inject({}){|o,k| o.merge!(k => send(k)) }
|
51
|
+
end
|
52
|
+
|
53
|
+
def reset
|
54
|
+
self.region = DEFAULT_REGION
|
55
|
+
self.locale = DEFAULT_LOCALE
|
56
|
+
self.realm = nil
|
57
|
+
self.endpoint = DEFAULT_ENDPOINT
|
58
|
+
self.user_agent = DEFAULT_USER_AGENT
|
59
|
+
self.connection_options = DEFAULT_CONNECTION_OPTIONS
|
60
|
+
self.middleware = DEFAULT_MIDDLEWARE
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
module ArmoryApi
|
2
|
+
# Custom error class for rescuing from all Armory errors
|
3
|
+
class Error < StandardError; end
|
4
|
+
|
5
|
+
# Raised when the Armory returned a 404 status code
|
6
|
+
class NotFound < Error; end
|
7
|
+
|
8
|
+
# Raised when the Armory return a 500 status code
|
9
|
+
class InternalServerError < Error; end
|
10
|
+
|
11
|
+
# Raised when the realm is not set
|
12
|
+
class RealmNotFound < Error; end
|
13
|
+
end
|
data/lib/armory_api.rb
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
require 'armory_api/configuration'
|
2
|
+
require 'armory_api/client'
|
3
|
+
require 'armory_api/error'
|
4
|
+
|
5
|
+
module ArmoryApi
|
6
|
+
extend Configuration
|
7
|
+
class << self
|
8
|
+
|
9
|
+
# Shortcut for ArmoryApi::Client.new
|
10
|
+
#
|
11
|
+
# @return [ArmoryApi::Client]
|
12
|
+
def new(options={})
|
13
|
+
ArmoryApi::Client.new(options)
|
14
|
+
end
|
15
|
+
|
16
|
+
# Delegate to ArmoryApi::Client.new
|
17
|
+
def method_missing(method, *args, &block)
|
18
|
+
return super unless new.respond_to?(method)
|
19
|
+
new.send(method, *args, &block)
|
20
|
+
end
|
21
|
+
|
22
|
+
def respond_to?(method, include_private=false)
|
23
|
+
new.respond_to?(method, include_private) || super(method, include_private)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
ArmoryApi.reset
|
@@ -0,0 +1,19 @@
|
|
1
|
+
require 'faraday'
|
2
|
+
|
3
|
+
# @api private
|
4
|
+
module Faraday
|
5
|
+
class Response::RaiseArmoryApiError < Response::Middleware
|
6
|
+
def on_complete(res)
|
7
|
+
case res[:status].to_i
|
8
|
+
when 404
|
9
|
+
raise ArmoryApi::NotFound, error_message(res)
|
10
|
+
when 500
|
11
|
+
raise ArmoryApi::InternalServerError, error_message(res)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
def error_message(res)
|
16
|
+
"#{res[:method].to_s.upcase} #{res[:url].to_s}: #{res[:body]["reason"]}"
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
require 'helper'
|
2
|
+
|
3
|
+
describe ArmoryApi::Client::Character do
|
4
|
+
describe ".character" do
|
5
|
+
before do
|
6
|
+
@client = ArmoryApi::Client.new realm: 'realm'
|
7
|
+
end
|
8
|
+
|
9
|
+
context "without a realm passed" do
|
10
|
+
it "returns the character" do
|
11
|
+
stub_request(:get, 'http://us.battle.net/api/wow/character/realm/peratryn')
|
12
|
+
.to_return(body: fixture('character/character.json'))
|
13
|
+
char = @client.character('peratryn')
|
14
|
+
expect(char.name.downcase).to eq 'peratryn'
|
15
|
+
end
|
16
|
+
|
17
|
+
it "returns the character with additional fields" do
|
18
|
+
stub_request(:get, 'http://us.battle.net/api/wow/character/realm/peratryn?fields=feed')
|
19
|
+
.to_return(body: fixture('character/character-feed.json'))
|
20
|
+
char = @client.character('peratryn', ['feed'])
|
21
|
+
expect(char.feed).to be_an Array
|
22
|
+
end
|
23
|
+
|
24
|
+
it "raises an error if the client does not have a realm set" do
|
25
|
+
client = ArmoryApi::Client.new
|
26
|
+
expect{client.character('peratryn')}.to raise_error(ArmoryApi::RealmNotFound)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
context "with a realm passed" do
|
31
|
+
before do
|
32
|
+
@client = ArmoryApi::Client.new
|
33
|
+
end
|
34
|
+
|
35
|
+
it "returns the character" do
|
36
|
+
stub_request(:get, 'http://us.battle.net/api/wow/character/realm/peratryn')
|
37
|
+
.to_return(body: fixture('character/character.json'))
|
38
|
+
char = @client.character('peratryn', 'realm')
|
39
|
+
expect(char.name.downcase).to eq 'peratryn'
|
40
|
+
end
|
41
|
+
|
42
|
+
it "returns the character with additional fields" do
|
43
|
+
stub_request(:get, 'http://us.battle.net/api/wow/character/realm/peratryn?fields=feed')
|
44
|
+
.to_return(body: fixture('character/character-feed.json'))
|
45
|
+
char = @client.character('peratryn', 'realm', ['feed'])
|
46
|
+
expect(char.feed).to be_an Array
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
@@ -0,0 +1,74 @@
|
|
1
|
+
require 'helper'
|
2
|
+
|
3
|
+
describe ArmoryApi::Client do
|
4
|
+
describe "region" do
|
5
|
+
after :each do
|
6
|
+
ArmoryApi.reset
|
7
|
+
end
|
8
|
+
|
9
|
+
it "defaults to us" do
|
10
|
+
c = ArmoryApi::Client.new
|
11
|
+
expect(c.region).to eq 'us'
|
12
|
+
end
|
13
|
+
|
14
|
+
it "is settable" do
|
15
|
+
ArmoryApi.region = 'eu'
|
16
|
+
c = ArmoryApi::Client.new
|
17
|
+
expect(c.region).to eq 'eu'
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
describe "locale" do
|
22
|
+
after :each do
|
23
|
+
ArmoryApi.reset
|
24
|
+
end
|
25
|
+
|
26
|
+
it "defaults to en_US" do
|
27
|
+
c = ArmoryApi::Client.new
|
28
|
+
expect(c.locale).to eq 'en_US'
|
29
|
+
end
|
30
|
+
|
31
|
+
it "is settable" do
|
32
|
+
ArmoryApi.locale = 'en_GB'
|
33
|
+
c = ArmoryApi::Client.new
|
34
|
+
expect(c.locale).to eq 'en_GB'
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
describe "realm" do
|
39
|
+
after :each do
|
40
|
+
ArmoryApi.reset
|
41
|
+
end
|
42
|
+
|
43
|
+
it "defaults to nil" do
|
44
|
+
c = ArmoryApi::Client.new
|
45
|
+
expect(c.realm).to be_nil
|
46
|
+
end
|
47
|
+
|
48
|
+
it "is settable" do
|
49
|
+
ArmoryApi.realm = 'Stormrage'
|
50
|
+
c = ArmoryApi::Client.new
|
51
|
+
expect(c.realm).to eq 'Stormrage'
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
describe "connection" do
|
56
|
+
after :each do
|
57
|
+
ArmoryApi.reset
|
58
|
+
end
|
59
|
+
|
60
|
+
it "looks like a Farady connection" do
|
61
|
+
c = ArmoryApi::Client.new
|
62
|
+
expect(c.send('connection')).to respond_to(:run_request)
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
describe "request" do
|
67
|
+
it "encodes the params in the body" do
|
68
|
+
stub_request(:get, 'http://us.battle.net/api/wow/character/realm/name?fields=one,two')
|
69
|
+
.with(params: { fields: 'one,two' })
|
70
|
+
c = ArmoryApi::Client.new
|
71
|
+
c.character('name', 'realm', ['one', 'two'])
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
require 'helper'
|
2
|
+
|
3
|
+
describe ArmoryApi do
|
4
|
+
describe ".new" do
|
5
|
+
it "is an ArmoryApi::Client" do
|
6
|
+
expect(ArmoryApi.new).to be_a ArmoryApi::Client
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
describe ".configure" do
|
11
|
+
after :each do
|
12
|
+
ArmoryApi.reset
|
13
|
+
end
|
14
|
+
|
15
|
+
ArmoryApi.options.keys.each do |key|
|
16
|
+
it "sets the #{key.to_s.gsub('_', ' ')}" do
|
17
|
+
ArmoryApi.configure do |conf|
|
18
|
+
conf.send("#{key}=", key)
|
19
|
+
end
|
20
|
+
expect(ArmoryApi.instance_variable_get(:"@#{key}")).to eq key
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
require 'helper'
|
2
|
+
|
3
|
+
describe Faraday::Response do
|
4
|
+
before do
|
5
|
+
@client = ArmoryApi::Client.new
|
6
|
+
end
|
7
|
+
|
8
|
+
{
|
9
|
+
404 => ArmoryApi::NotFound,
|
10
|
+
500 => ArmoryApi::InternalServerError
|
11
|
+
}.each do |status, exception|
|
12
|
+
context "when HTTP status is #{status}" do
|
13
|
+
before do
|
14
|
+
stub_request(:get, 'http://us.battle.net/api/wow/character/realm/name')
|
15
|
+
.to_return(status: status,
|
16
|
+
body: '{"status":"nok", "reason": "When in doubt, blow it up. (page not found)"}')
|
17
|
+
end
|
18
|
+
|
19
|
+
it "raises #{exception.name} error" do
|
20
|
+
expect{@client.character('name', 'realm')}.to raise_exception(exception)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|