eve_badger 0.1.1 → 0.1.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +65 -34
- data/VERSION +1 -1
- data/lib/eve_badger.rb +8 -9
- data/lib/eve_badger/cache.rb +50 -0
- data/lib/eve_badger/endpoints.rb +59 -0
- data/lib/eve_badger/eve_api.rb +51 -55
- data/lib/eve_badger/response.rb +43 -0
- metadata +9 -42
- data/lib/eve_badger/endpoint_data.rb +0 -40
- data/lib/eve_badger/request_cache.rb +0 -33
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 2bc45c7eb50a097472bc492371e1e500712dfca9
|
4
|
+
data.tar.gz: 9a0307ae74ba1477a86911ebf27f252ec77982f0
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6d4ebf620cbc554ba9eb5066e4bc43c6d284c16377e0dbef12bb23e44b601506724504bdfcd7a5875519f134be148d91ef71ba3225186ec9c3e22be385db8416
|
7
|
+
data.tar.gz: 72ed8c09f93b607f7db34483d23d564f7285374d12fe35c5242919ef1fb32d1b6418c08d3216aff4bc05b4a375d3cdca4d278b8d93b3e3740bcdf05c04b3c055
|
data/README.md
CHANGED
@@ -1,65 +1,80 @@
|
|
1
1
|
# EveBadger
|
2
2
|
|
3
|
-
It badgers the Eve: Online API for [badgerfish](http://badgerfish.ning.com/) responses. Get it?
|
3
|
+
It badgers the Eve: Online API for [badgerfish](http://badgerfish.ning.com/) responses. Get it? (Don't worry. You can still get plain XML if you want to.)
|
4
4
|
|
5
5
|
## About
|
6
6
|
|
7
|
-
EveBadger is a lightweight interface to the Eve: Online API. Build an EveAPI object to represent your API key and call out to the endpoint you're interested in. It'll return a JSON
|
7
|
+
EveBadger is a lightweight interface to the Eve: Online XML API. Build an EveAPI object to represent your API key and call out to the endpoint you're interested in. It'll return a response object that you can can easily consume as JSON or XML. EveBadger also respects access masks automatically and makes caching and throttling responses as easy as flipping a switch.
|
8
8
|
|
9
9
|
I wrote this for 3 reasons:
|
10
10
|
|
11
11
|
* I prefer working with JSON over XML
|
12
12
|
* I wasn't in love with existing EveAPI solutions
|
13
13
|
* I wanted to learn how to build a custom Gem (Ruby packaging is awesome, btw)
|
14
|
-
|
14
|
+
|
15
15
|
## What does it do?
|
16
16
|
|
17
17
|
* Obeys CCP's default request rate limit (can be disabled if you have an exception)
|
18
|
-
*
|
19
|
-
*
|
20
|
-
*
|
18
|
+
* Uses Moneta to cache responses with whatever supported backend you prefer. (Disabled by default.)
|
19
|
+
* Automatically fetches missing access_mask and key_type values from the API Key Info endpoint.
|
20
|
+
* Respects access masks for keys and endpoints (it will raise an exception instead of making an HTTP request if you try to access an endpoint that isn't allowed by the key's access mask)
|
21
|
+
* Probably annoys OO purists a little.
|
21
22
|
|
22
23
|
## What doesn't it do?
|
23
24
|
|
24
|
-
* EveBadger won't wrap each response inside a nice endpoint specific object, it just gives you the JSON.
|
25
|
-
* Doesn't cover the entire EveAPI (just Account, Character and Corporation endpoints this will improve in time)
|
26
|
-
* It doesn't install from rubygems yet, because I haven't published it (but you can add a git entry to your Gemfile if you want to use it before I do)
|
25
|
+
* EveBadger won't wrap each response inside a nice endpoint specific object, it just gives you the JSON or XML and can truncate the response to the <result> section if you prefer.
|
27
26
|
|
28
27
|
## Planned Improvements
|
29
28
|
|
30
29
|
* **Full API Coverage** Right now EveBadger covers the stuff I use the most. Eventually I'll go through and add all the remaining endpoints.
|
31
|
-
* **Cache Configuration** EveBadger uses the Moneta gem for caching. Currently it's pretty dumb and only tries to link up with an unprotected redis instance on localhost, if this fails it'll fall back to an in-memory Moneta store. I'd like to allow users to configure most aspects of the Moneta store.
|
32
30
|
* **Rowset Extraction** *(Maybe)* I'm happy with JSON responses for the most part. I don't want or need a full object for every endpoint, but a single basic response object which does a nice job of extracting rowsets and delegating indexes might be nice.
|
33
|
-
* **RubyGems** Once I polish a few things and settle on a handful of decisions I'll publish this to rubygems.
|
34
31
|
|
35
|
-
## Usage
|
32
|
+
## Basic Usage
|
36
33
|
|
37
|
-
The basic idea is to make an EveAPI object and call the appropriate category method with the symbol representing the name of the endpoint. It'll spit back
|
34
|
+
The basic idea is to make an EveAPI object and call the appropriate category method with the symbol representing the name of the endpoint. It'll spit back a response object you can take JSON or XML from and use however you want.
|
38
35
|
|
39
|
-
I think you'll find that the category methods and endpoint names map directly to the EveAPI documentation at [this location](https://neweden-dev.com/API).
|
36
|
+
I think you'll find that the category methods and endpoint names map directly to the EveAPI documentation at [this location](https://neweden-dev.com/API).
|
40
37
|
|
41
|
-
|
38
|
+
|
39
|
+
### Getting Key Info as JSON
|
42
40
|
```ruby
|
43
41
|
api = EveBadger::EveAPI.new(key_id: my_key_id, vcode: my_vcode)
|
44
|
-
response = api.account(:
|
45
|
-
response['rowset']['row'].each do |row|
|
46
|
-
puts row['@name']
|
47
|
-
end
|
42
|
+
response = api.account(:api_key_info).as_json
|
48
43
|
```
|
49
44
|
|
50
|
-
### Getting Key Info
|
45
|
+
### Getting Key Info as XML
|
51
46
|
```ruby
|
52
47
|
api = EveBadger::EveAPI.new(key_id: my_key_id, vcode: my_vcode)
|
53
|
-
response = api.account(:api_key_info)
|
54
|
-
|
55
|
-
|
48
|
+
response = api.account(:api_key_info).as_xml
|
49
|
+
document = MyFavoriteXMLParser.new(response)
|
50
|
+
```
|
51
|
+
|
52
|
+
## More Examples
|
53
|
+
|
54
|
+
You'll notice that these examples all use `.result_as_json` and `.result_as_xml`. Instead of `.as_json` or `.as_xml`. This isn't a typo. The response object allows you to take the whole response as JSON/XML or only the contents enclosed in `<result></result>` tags.
|
55
|
+
|
56
|
+
The full responses from `.as_*` are good if you need the timestamp data for your own uses.
|
57
|
+
|
58
|
+
The truncated responses from `.result_as_*` are nice if you don't need the extra stuff and just want to skip the `<eveapi>` and `<result>` nodes.
|
59
|
+
|
60
|
+
### Getting a Character List
|
61
|
+
```ruby
|
62
|
+
api = EveBadger::EveAPI.new(key_id: my_key_id, vcode: my_vcode)
|
63
|
+
response = api.account(:list_of_characters).result_as_json
|
64
|
+
response['rowset']['row'].each do |row|
|
65
|
+
puts row['@name']
|
66
|
+
end
|
56
67
|
```
|
57
68
|
|
58
69
|
### Getting a Tower List
|
59
70
|
```ruby
|
60
|
-
#
|
61
|
-
|
62
|
-
|
71
|
+
# Corporation endpoints expect you to also pass
|
72
|
+
# the character_id for the character on the key.
|
73
|
+
api = EveBadger::EveAPI.new
|
74
|
+
api.key_id = my_key_id
|
75
|
+
api.vcode = my_vcode
|
76
|
+
api.character_id = my_character_id
|
77
|
+
response = api.corporation(:starbase_list).result_as_json
|
63
78
|
response['rowset']['row'].each |starbase|
|
64
79
|
puts starbase['@state']
|
65
80
|
end
|
@@ -67,20 +82,36 @@ end
|
|
67
82
|
|
68
83
|
### Getting the Details of a Specific Object
|
69
84
|
```ruby
|
70
|
-
|
71
|
-
#
|
72
|
-
#
|
73
|
-
|
74
|
-
|
85
|
+
# Detail endpoints are the only exception to the category/endpoint pattern.
|
86
|
+
# Any endpoint that pulls the details of a particular thing is accessed via
|
87
|
+
# the details method by passing an extra argument for id_of_interest.
|
88
|
+
api = EveBadger::EveAPI.new
|
89
|
+
api.key_id = my_key_id
|
90
|
+
api.vcode = my_vcode
|
91
|
+
api.character_id my_character_id
|
92
|
+
response = api.details(:starbase_detail, my_id_of_interest).result_as_json
|
75
93
|
response['rowset']['row'].each |fuel_row|
|
76
94
|
puts "#{fuel_row['@typeID']} - #{fuel_row['@quantity']}"
|
77
95
|
end
|
78
96
|
```
|
79
97
|
|
80
|
-
### Creating an Object for
|
98
|
+
### Creating an Object for the Test Server API
|
99
|
+
```ruby
|
100
|
+
api = EveBadger::EveAPI.new(server: :sisi)
|
101
|
+
api.key_id = my_key_id
|
102
|
+
api.vcode = my_vcode
|
103
|
+
api.character_id = my_character_id)
|
104
|
+
# then continue as normal
|
105
|
+
```
|
106
|
+
|
107
|
+
### Enable Request Caching
|
81
108
|
```ruby
|
82
|
-
|
83
|
-
#
|
109
|
+
# EveBadger::Cache.enable! takes the same arguments as Moneta.new
|
110
|
+
# See Moneta API docs for possible configurations:
|
111
|
+
# http://www.rubydoc.info/gems/moneta/frames
|
112
|
+
# Note: EveBadger will automatically merge in {expires: true} if the
|
113
|
+
# chosen adapter doesn't support expiration natively.
|
114
|
+
EveBadger::Cache.enable!(:Redis)
|
84
115
|
```
|
85
116
|
|
86
117
|
### Tips for Edge Cases
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.1.
|
1
|
+
0.1.2
|
data/lib/eve_badger.rb
CHANGED
@@ -3,11 +3,13 @@ require 'eve_badger/eve_api'
|
|
3
3
|
|
4
4
|
module EveBadger
|
5
5
|
def self.version
|
6
|
-
@version ||= File.read(File.expand_path(File.join(File.dirname(__FILE__), '..', 'VERSION')))
|
6
|
+
@version ||= File.read(File.expand_path(File.join(File.dirname(__FILE__), '..', 'VERSION'))).chomp
|
7
7
|
end
|
8
|
-
|
8
|
+
|
9
|
+
def self.default_user_agent
|
9
10
|
"EveBadger-#{EveBadger.version}/Ruby-#{RUBY_VERSION}"
|
10
11
|
end
|
12
|
+
|
11
13
|
def self.tq_domain
|
12
14
|
'https://api.eveonline.com/'
|
13
15
|
end
|
@@ -25,16 +27,13 @@ module EveBadger
|
|
25
27
|
end
|
26
28
|
|
27
29
|
def self.enable_default_throttling
|
28
|
-
SlowWeb.limit(
|
29
|
-
SlowWeb.limit(
|
30
|
+
SlowWeb.limit(tq_domain, 30, 60)
|
31
|
+
SlowWeb.limit(sisi_domain, 30, 60)
|
30
32
|
end
|
31
33
|
|
32
34
|
def self.enable_custom_throttling(requests_per_minute)
|
33
35
|
SlowWeb.reset
|
34
|
-
SlowWeb.limit(
|
35
|
-
SlowWeb.limit(
|
36
|
-
end
|
37
|
-
|
38
|
-
class CCPPleaseError < StandardError
|
36
|
+
SlowWeb.limit(tq_domain, requests_per_minute, 60)
|
37
|
+
SlowWeb.limit(sisi_domain, requests_per_minute, 60)
|
39
38
|
end
|
40
39
|
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
require 'moneta'
|
2
|
+
require 'digest/sha1'
|
3
|
+
|
4
|
+
module EveBadger
|
5
|
+
# A wrapper around a Moneta object that provides automatic request caching for Evebadger::EveAPI when enabled.
|
6
|
+
module Cache
|
7
|
+
# Cache is disabled by default
|
8
|
+
@cache = nil
|
9
|
+
# These adapters support expiration natively and don't need to be wrapped in Moneta::Expires
|
10
|
+
@native_expires = [:Mongo, :MongoOfficial, :MongoMoped, :Redis, :Cassandra, :MemcachedDalli, :Memcached, :MemcachedNative, :Cookie]
|
11
|
+
|
12
|
+
# Enable the cache with a specified Moneta adapter.
|
13
|
+
# See Moneta API documentation for possible configurations: http://www.rubydoc.info/gems/moneta/frames
|
14
|
+
def self.enable!(*args, **kwargs)
|
15
|
+
unless @native_expires.any? { |name| args.include?(name) }
|
16
|
+
# unless false
|
17
|
+
kwargs.merge!({expires: true})
|
18
|
+
end
|
19
|
+
@cache = Moneta.new(*args, **kwargs)
|
20
|
+
end
|
21
|
+
|
22
|
+
def self.disable!
|
23
|
+
@cache = nil
|
24
|
+
end
|
25
|
+
|
26
|
+
def self.enabled?
|
27
|
+
@cache ? true : false
|
28
|
+
end
|
29
|
+
|
30
|
+
def self.type
|
31
|
+
@cache.class
|
32
|
+
end
|
33
|
+
|
34
|
+
def self.store(key, value, options={})
|
35
|
+
if @cache
|
36
|
+
@cache.store(key, value, options)
|
37
|
+
else
|
38
|
+
raise "Cannot store when cache is disabled."
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def self.get(key)
|
43
|
+
if @cache
|
44
|
+
@cache[key]
|
45
|
+
else
|
46
|
+
raise "Cannot get when cache is disabled."
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
require 'json'
|
2
|
+
|
3
|
+
module EveBadger
|
4
|
+
class Endpoint
|
5
|
+
attr_reader :path, :access_mask, :detail_id
|
6
|
+
|
7
|
+
def initialize(data)
|
8
|
+
@path = data[:path]
|
9
|
+
@access_mask = data[:access_mask]
|
10
|
+
@detail_id = data[:detail_id] if data[:detail_id]
|
11
|
+
end
|
12
|
+
|
13
|
+
def permitted?(other_mask)
|
14
|
+
@access_mask.zero? or (other_mask & @access_mask != 0)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
module Endpoints
|
19
|
+
open(File.join(File.dirname(__FILE__), 'json', 'account_endpoints.json'), 'r') do |file|
|
20
|
+
@account_endpoints = JSON.parse(file.read.to_s, :symbolize_names => true)
|
21
|
+
end
|
22
|
+
|
23
|
+
open(File.join(File.dirname(__FILE__), 'json', 'character_endpoints.json'), 'r') do |file|
|
24
|
+
@character_endpoints = JSON.parse(file.read.to_s, :symbolize_names => true)
|
25
|
+
end
|
26
|
+
|
27
|
+
open(File.join(File.dirname(__FILE__), 'json', 'corporation_endpoints.json'), 'r') do |file|
|
28
|
+
@corporation_endpoints = JSON.parse(file.read.to_s, :symbolize_names => true)
|
29
|
+
end
|
30
|
+
|
31
|
+
open(File.join(File.dirname(__FILE__), 'json', 'detail_endpoints.json'), 'r') do |file|
|
32
|
+
@detail_endpoints = JSON.parse(file.read.to_s, :symbolize_names => true)
|
33
|
+
end
|
34
|
+
|
35
|
+
def self.account(endpoint)
|
36
|
+
data = @account_endpoints[endpoint]
|
37
|
+
raise ArgumentError, "unsupported endpoint: #{endpoint}" unless data
|
38
|
+
Endpoint.new(data)
|
39
|
+
end
|
40
|
+
|
41
|
+
def self.character(endpoint)
|
42
|
+
data = @character_endpoints[endpoint]
|
43
|
+
raise ArgumentError, "unsupported endpoint: #{endpoint}" unless data
|
44
|
+
Endpoint.new(data)
|
45
|
+
end
|
46
|
+
|
47
|
+
def self.corporation(endpoint)
|
48
|
+
data = @corporation_endpoints[endpoint]
|
49
|
+
raise ArgumentError, "unsupported endpoint: #{endpoint}" unless data
|
50
|
+
Endpoint.new(data)
|
51
|
+
end
|
52
|
+
|
53
|
+
def self.detail(endpoint)
|
54
|
+
data = @detail_endpoints[endpoint]
|
55
|
+
raise ArgumentError, "unsupported endpoint: #{endpoint}" unless data
|
56
|
+
Endpoint.new(data)
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
data/lib/eve_badger/eve_api.rb
CHANGED
@@ -1,20 +1,24 @@
|
|
1
1
|
require 'nokogiri'
|
2
2
|
require 'time'
|
3
|
-
require 'badgerfish'
|
4
3
|
require 'open-uri'
|
5
|
-
require 'eve_badger
|
6
|
-
require 'eve_badger/
|
4
|
+
require 'eve_badger'
|
5
|
+
require 'eve_badger/endpoints'
|
6
|
+
require 'eve_badger/response'
|
7
|
+
require 'eve_badger/cache'
|
8
|
+
require 'digest/sha1'
|
7
9
|
|
8
10
|
module EveBadger
|
9
11
|
class EveAPI
|
10
12
|
attr_accessor :user_agent
|
11
|
-
attr_reader :key_id, :vcode, :character_id
|
12
|
-
include EveBadger::EndpointData
|
13
|
-
include EveBadger::RequestCache
|
13
|
+
attr_reader :key_id, :vcode, :character_id, :domain
|
14
14
|
|
15
15
|
def initialize(args={})
|
16
|
-
|
17
|
-
|
16
|
+
if args[:server] == :sisi
|
17
|
+
@domain = EveBadger.sisi_domain
|
18
|
+
else
|
19
|
+
@domain = EveBadger.tq_domain
|
20
|
+
end
|
21
|
+
@user_agent = EveBadger.default_user_agent
|
18
22
|
@key_id = args[:key_id].to_s if args[:key_id]
|
19
23
|
@vcode = args[:vcode].to_s if args[:vcode]
|
20
24
|
@character_id = args[:character_id].to_s if args[:character_id]
|
@@ -51,52 +55,48 @@ module EveBadger
|
|
51
55
|
end
|
52
56
|
|
53
57
|
def account(endpoint_name)
|
54
|
-
raise 'missing required key_id or vcode' unless @key_id && @vcode
|
55
|
-
endpoint =
|
56
|
-
|
58
|
+
raise EveBadger::APIKeyError, 'missing required key_id or vcode' unless @key_id && @vcode
|
59
|
+
endpoint = EveBadger::Endpoints.account(endpoint_name.to_sym)
|
60
|
+
api_request(endpoint)
|
57
61
|
end
|
58
62
|
|
59
63
|
def character(endpoint_name)
|
60
|
-
raise 'missing required character_id key_id or_vcode' unless @character_id && @key_id && @vcode
|
61
|
-
raise 'wrong key type' unless
|
62
|
-
endpoint =
|
63
|
-
|
64
|
+
raise EveBadger::APIKeyError, 'missing required character_id key_id or_vcode' unless @character_id && @key_id && @vcode
|
65
|
+
raise EveBadger::APIKeyError, 'wrong key type' unless [:Character, :Account].include?(key_type)
|
66
|
+
endpoint = EveBadger::Endpoints.character(endpoint_name.to_sym)
|
67
|
+
api_request(endpoint)
|
64
68
|
end
|
65
69
|
|
66
70
|
def corporation(endpoint_name)
|
67
|
-
raise 'missing required character_id key_id or_vcode' unless @character_id && @key_id && @vcode
|
68
|
-
raise 'wrong key type' unless key_type == :Corporation
|
69
|
-
endpoint =
|
70
|
-
|
71
|
+
raise EveBadger::APIKeyError, 'missing required character_id key_id or_vcode' unless @character_id && @key_id && @vcode
|
72
|
+
raise EveBadger::APIKeyError, 'wrong key type' unless key_type == :Corporation
|
73
|
+
endpoint = EveBadger::Endpoints.corporation(endpoint_name.to_sym)
|
74
|
+
api_request(endpoint)
|
71
75
|
end
|
72
76
|
|
73
77
|
def details(endpoint_name, id_of_interest, fromid=nil, rowcount=nil)
|
74
|
-
raise 'wrong key type' unless
|
75
|
-
endpoint =
|
76
|
-
if
|
78
|
+
raise EveBadger::APIKeyError, 'wrong key type' unless [:Character, :Corporation, :Account].include?(key_type)
|
79
|
+
endpoint = EveBadger::Endpoints.detail(endpoint_name.to_sym)
|
80
|
+
if endpoint.permitted?(access_mask)
|
77
81
|
uri = build_uri(endpoint)
|
78
|
-
uri << "&#{endpoint
|
82
|
+
uri << "&#{endpoint.detail_id}=#{id_of_interest}"
|
79
83
|
uri << "&fromID=#{fromid}" if fromid
|
80
84
|
uri << "&rowCount=#{rowcount}" if rowcount
|
81
|
-
|
85
|
+
get_response(uri)
|
82
86
|
else
|
83
|
-
raise "#{endpoint
|
87
|
+
raise EveBadger::APIKeyError, "#{endpoint.path} not permitted by access mask"
|
84
88
|
end
|
85
89
|
end
|
86
90
|
|
87
91
|
private
|
88
92
|
def api_request(endpoint)
|
89
|
-
if
|
93
|
+
if endpoint.access_mask.zero? or endpoint.permitted?(access_mask)
|
90
94
|
get_response(build_uri(endpoint))
|
91
95
|
else
|
92
|
-
raise "#{endpoint
|
96
|
+
raise EveBadger::APIKeyError, "#{endpoint.path} not permitted by access mask"
|
93
97
|
end
|
94
98
|
end
|
95
99
|
|
96
|
-
def endpoint_permitted?(endpoint)
|
97
|
-
endpoint[:access_mask].zero? or (access_mask & endpoint[:access_mask] != 0)
|
98
|
-
end
|
99
|
-
|
100
100
|
def get_access_mask
|
101
101
|
fetch_key_info unless @access_mask
|
102
102
|
@access_mask
|
@@ -108,13 +108,13 @@ module EveBadger
|
|
108
108
|
end
|
109
109
|
|
110
110
|
def fetch_key_info
|
111
|
-
info = account(:api_key_info)
|
111
|
+
info = account(:api_key_info).result_as_json
|
112
112
|
@access_mask = info['key']['@accessMask'].to_i
|
113
113
|
@key_type = info['key']['@type'].to_sym
|
114
114
|
end
|
115
115
|
|
116
116
|
def build_uri(endpoint)
|
117
|
-
"#{@domain}#{endpoint
|
117
|
+
"#{@domain}#{endpoint.path}.xml.aspx#{params}"
|
118
118
|
end
|
119
119
|
|
120
120
|
def params
|
@@ -123,13 +123,12 @@ module EveBadger
|
|
123
123
|
|
124
124
|
def get_response(uri)
|
125
125
|
response = cache_get(uri) || http_get(uri)
|
126
|
-
|
127
|
-
response
|
126
|
+
EveBadger::Response.new(response)
|
128
127
|
end
|
129
128
|
|
130
129
|
def cache_get(uri)
|
131
|
-
if
|
132
|
-
|
130
|
+
if EveBadger::Cache.enabled?
|
131
|
+
EveBadger::Cache.get(hash_of(uri))
|
133
132
|
end
|
134
133
|
end
|
135
134
|
|
@@ -139,32 +138,29 @@ module EveBadger
|
|
139
138
|
rescue OpenURI::HTTPError => error
|
140
139
|
response = error.io.string
|
141
140
|
end
|
142
|
-
|
143
|
-
cache_get(uri)
|
141
|
+
store_response(uri, response)
|
142
|
+
response || cache_get(uri)
|
144
143
|
end
|
145
144
|
|
146
|
-
def
|
147
|
-
if
|
148
|
-
|
145
|
+
def store_response(uri, response)
|
146
|
+
if EveBadger::Cache.enabled?
|
147
|
+
EveBadger::Cache.store(hash_of(uri), response, expires: cached_until(response))
|
149
148
|
end
|
150
149
|
end
|
151
150
|
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
cached_until.to_i - Time.now.to_i
|
151
|
+
# Hash URI's before use as a cache key so that API key/vcode combinations don't leak from the cache monitor or logs.
|
152
|
+
def hash_of(uri)
|
153
|
+
Digest::SHA1.hexdigest(uri)
|
156
154
|
end
|
157
155
|
|
158
|
-
def
|
159
|
-
noko = Nokogiri::XML
|
160
|
-
|
161
|
-
|
162
|
-
end
|
156
|
+
def cached_until(xml)
|
157
|
+
noko = Nokogiri::XML xml
|
158
|
+
seconds_until_expire = Time.parse(noko.xpath('//cachedUntil').text)
|
159
|
+
seconds_until_expire.to_i - Time.now.to_i
|
163
160
|
end
|
161
|
+
end
|
164
162
|
|
165
|
-
|
166
|
-
|
167
|
-
Badgerfish::Parser.new.load(response.xpath('//result/*').to_s)
|
168
|
-
end
|
163
|
+
# Exception to raise when an EveAPI object needs attributes which are missing or invalid.
|
164
|
+
class APIKeyError < StandardError
|
169
165
|
end
|
170
166
|
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
require 'badgerfish'
|
2
|
+
require 'nokogiri'
|
3
|
+
require 'time'
|
4
|
+
|
5
|
+
module EveBadger
|
6
|
+
class Response
|
7
|
+
def initialize(content)
|
8
|
+
@content = content
|
9
|
+
end
|
10
|
+
|
11
|
+
# returns json in badgerfish notation
|
12
|
+
def as_json
|
13
|
+
Badgerfish::Parser.new.load(@content)
|
14
|
+
end
|
15
|
+
|
16
|
+
# returns the response content as xml string
|
17
|
+
def as_xml
|
18
|
+
@content
|
19
|
+
end
|
20
|
+
|
21
|
+
# same as #as_xml but truncates to just <result> data
|
22
|
+
def result_as_xml
|
23
|
+
Nokogiri::XML(@content).xpath("//result/*").to_s
|
24
|
+
end
|
25
|
+
|
26
|
+
# same as #as_json but truncates to just <result> data
|
27
|
+
def result_as_json
|
28
|
+
Badgerfish::Parser.new.load(@content)['eveapi']['result']
|
29
|
+
end
|
30
|
+
|
31
|
+
# raise an exception if the response contains an Eve API error
|
32
|
+
def raise_for_api_errors!(response)
|
33
|
+
document = Nokogiri::XML(response)
|
34
|
+
if document.xpath('//error').any?
|
35
|
+
raise EveBadger::CCPPleaseError, "#{document.xpath('//error').first}"
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
# Exception to raise when the Eve API returns an error code in the response.
|
41
|
+
class CCPPleaseError < StandardError
|
42
|
+
end
|
43
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: eve_badger
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Corey Smedstad
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-
|
11
|
+
date: 2015-06-30 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: nokogiri
|
@@ -66,41 +66,8 @@ dependencies:
|
|
66
66
|
- - "~>"
|
67
67
|
- !ruby/object:Gem::Version
|
68
68
|
version: 0.8.0
|
69
|
-
|
70
|
-
|
71
|
-
requirement: !ruby/object:Gem::Requirement
|
72
|
-
requirements:
|
73
|
-
- - "~>"
|
74
|
-
- !ruby/object:Gem::Version
|
75
|
-
version: '3.2'
|
76
|
-
- - ">="
|
77
|
-
- !ruby/object:Gem::Version
|
78
|
-
version: 3.2.0
|
79
|
-
type: :runtime
|
80
|
-
prerelease: false
|
81
|
-
version_requirements: !ruby/object:Gem::Requirement
|
82
|
-
requirements:
|
83
|
-
- - "~>"
|
84
|
-
- !ruby/object:Gem::Version
|
85
|
-
version: '3.2'
|
86
|
-
- - ">="
|
87
|
-
- !ruby/object:Gem::Version
|
88
|
-
version: 3.2.0
|
89
|
-
- !ruby/object:Gem::Dependency
|
90
|
-
name: rspec
|
91
|
-
requirement: !ruby/object:Gem::Requirement
|
92
|
-
requirements:
|
93
|
-
- - "~>"
|
94
|
-
- !ruby/object:Gem::Version
|
95
|
-
version: '3'
|
96
|
-
type: :development
|
97
|
-
prerelease: false
|
98
|
-
version_requirements: !ruby/object:Gem::Requirement
|
99
|
-
requirements:
|
100
|
-
- - "~>"
|
101
|
-
- !ruby/object:Gem::Version
|
102
|
-
version: '3'
|
103
|
-
description: For more information look at the README on the github repository.
|
69
|
+
description: For more information look at the README in the github repository (homepage
|
70
|
+
link).
|
104
71
|
email: smedstadc@gmail.com
|
105
72
|
executables: []
|
106
73
|
extensions: []
|
@@ -110,13 +77,14 @@ files:
|
|
110
77
|
- README.md
|
111
78
|
- VERSION
|
112
79
|
- lib/eve_badger.rb
|
113
|
-
- lib/eve_badger/
|
80
|
+
- lib/eve_badger/cache.rb
|
81
|
+
- lib/eve_badger/endpoints.rb
|
114
82
|
- lib/eve_badger/eve_api.rb
|
115
83
|
- lib/eve_badger/json/account_endpoints.json
|
116
84
|
- lib/eve_badger/json/character_endpoints.json
|
117
85
|
- lib/eve_badger/json/corporation_endpoints.json
|
118
86
|
- lib/eve_badger/json/detail_endpoints.json
|
119
|
-
- lib/eve_badger/
|
87
|
+
- lib/eve_badger/response.rb
|
120
88
|
homepage: https://github.com/smedstadc/eve_badger
|
121
89
|
licenses:
|
122
90
|
- MIT
|
@@ -137,9 +105,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
137
105
|
version: '0'
|
138
106
|
requirements: []
|
139
107
|
rubyforge_project:
|
140
|
-
rubygems_version: 2.4.
|
108
|
+
rubygems_version: 2.4.8
|
141
109
|
signing_key:
|
142
110
|
specification_version: 4
|
143
|
-
summary: 'A gem for interacting with the Eve: Online API.'
|
111
|
+
summary: 'A gem for interacting with the Eve: Online XML API.'
|
144
112
|
test_files: []
|
145
|
-
has_rdoc:
|
@@ -1,40 +0,0 @@
|
|
1
|
-
require 'json'
|
2
|
-
|
3
|
-
module EveBadger
|
4
|
-
module EndpointData
|
5
|
-
def self.included(base)
|
6
|
-
base.extend(EndpointData)
|
7
|
-
end
|
8
|
-
|
9
|
-
module EndpointData
|
10
|
-
open(File.join(File.dirname(__FILE__), 'json', 'account_endpoints.json'), 'r') do |file|
|
11
|
-
@@account_endpoint = JSON.parse(file.read.to_s, :symbolize_names => true)
|
12
|
-
end
|
13
|
-
open(File.join(File.dirname(__FILE__), 'json', 'character_endpoints.json'), 'r') do |file|
|
14
|
-
@@character_endpoint = JSON.parse(file.read.to_s, :symbolize_names => true)
|
15
|
-
end
|
16
|
-
open(File.join(File.dirname(__FILE__), 'json', 'corporation_endpoints.json'), 'r') do |file|
|
17
|
-
@@corporation_endpoint = JSON.parse(file.read.to_s, :symbolize_names => true)
|
18
|
-
end
|
19
|
-
open(File.join(File.dirname(__FILE__), 'json', 'detail_endpoints.json'), 'r') do |file|
|
20
|
-
@@detail_endpoint = JSON.parse(file.read.to_s, :symbolize_names => true)
|
21
|
-
end
|
22
|
-
|
23
|
-
def account_endpoint
|
24
|
-
@@account_endpoint
|
25
|
-
end
|
26
|
-
|
27
|
-
def character_endpoint
|
28
|
-
@@character_endpoint
|
29
|
-
end
|
30
|
-
|
31
|
-
def corporation_endpoint
|
32
|
-
@@corporation_endpoint
|
33
|
-
end
|
34
|
-
|
35
|
-
def detail_endpoint
|
36
|
-
@@detail_endpoint
|
37
|
-
end
|
38
|
-
end
|
39
|
-
end
|
40
|
-
end
|
@@ -1,33 +0,0 @@
|
|
1
|
-
require 'moneta'
|
2
|
-
|
3
|
-
module EveBadger
|
4
|
-
module RequestCache
|
5
|
-
def self.included(base)
|
6
|
-
base.extend(RequestCache)
|
7
|
-
end
|
8
|
-
|
9
|
-
module RequestCache
|
10
|
-
begin
|
11
|
-
@@request_cache = Moneta.new(:Redis)
|
12
|
-
rescue
|
13
|
-
@@request_cache = Moneta.new(:File, dir: File.expand_path(File.join(File.dirname(__FILE__), '..', 'cache')))
|
14
|
-
end
|
15
|
-
|
16
|
-
def request_cache
|
17
|
-
@@request_cache
|
18
|
-
end
|
19
|
-
|
20
|
-
def disable_request_cache
|
21
|
-
@@request_cache = nil
|
22
|
-
end
|
23
|
-
|
24
|
-
def enable_request_cache
|
25
|
-
begin
|
26
|
-
@@request_cache = Moneta.new(:Redis)
|
27
|
-
rescue
|
28
|
-
@@request_cache = Moneta.new(:File, dir: File.expand_path(File.join(File.dirname(__FILE__), '..', 'cache')))
|
29
|
-
end
|
30
|
-
end
|
31
|
-
end
|
32
|
-
end
|
33
|
-
end
|