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 ADDED
@@ -0,0 +1,6 @@
1
+ Gemfile.lock
2
+ .yardoc
3
+ coverage/*
4
+ doc/*
5
+ .bundle
6
+ *.gem
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --color
2
+ --order random
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gemspec
data/README.md ADDED
@@ -0,0 +1,4 @@
1
+ ArmoryApi
2
+ =========
3
+
4
+ A Ruby Gem for the World of Warcraft API.
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
@@ -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
@@ -0,0 +1,3 @@
1
+ module ArmoryApi
2
+ VERSION = "0.1.0" unless defined?(ArmoryApi::VERSION)
3
+ 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