armory_api 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
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