eaal 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/History.txt +4 -0
- data/LICENSE.txt +22 -0
- data/Manifest.txt +19 -0
- data/README.rdoc +96 -0
- data/Rakefile +27 -0
- data/lib/eaal.rb +6 -0
- data/lib/eaal/eaal.rb +114 -0
- data/lib/eaal/eaal_cache.rb +86 -0
- data/lib/eaal/eaal_exception.rb +42 -0
- data/lib/eaal/eaal_result.rb +120 -0
- data/lib/eaal/eaal_rowset.rb +63 -0
- data/script/console +10 -0
- data/script/destroy +14 -0
- data/script/generate +14 -0
- data/test/fixtures/test/test/account/Characters/Request_.xml +11 -0
- data/test/fixtures/test/test/char/Killlog/Request_.xml +6 -0
- data/test/fixtures/test/test/char/Killlog/Request_characterID:12345.xml +19 -0
- data/test/test_eaal.rb +36 -0
- data/test/test_helper.rb +3 -0
- metadata +116 -0
data/History.txt
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2008 Peter Petermann <PeterPetermann@gmx.net>
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person
|
4
|
+
obtaining a copy of this software and associated documentation
|
5
|
+
files (the "Software"), to deal in the Software without
|
6
|
+
restriction, including without limitation the rights to use,
|
7
|
+
copy, modify, merge, publish, distribute, sublicense, and/or sell
|
8
|
+
copies of the Software, and to permit persons to whom the
|
9
|
+
Software is furnished to do so, subject to the following
|
10
|
+
conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be
|
13
|
+
included in all copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
16
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
17
|
+
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
18
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
19
|
+
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
20
|
+
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
21
|
+
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
22
|
+
OTHER DEALINGS IN THE SOFTWARE.
|
data/Manifest.txt
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
History.txt
|
2
|
+
Manifest.txt
|
3
|
+
README.rdoc
|
4
|
+
LICENSE.txt
|
5
|
+
Rakefile
|
6
|
+
lib/eaal.rb
|
7
|
+
lib/eaal/eaal.rb
|
8
|
+
lib/eaal/eaal_cache.rb
|
9
|
+
lib/eaal/eaal_exception.rb
|
10
|
+
lib/eaal/eaal_result.rb
|
11
|
+
lib/eaal/eaal_rowset.rb
|
12
|
+
script/console
|
13
|
+
script/destroy
|
14
|
+
script/generate
|
15
|
+
test/test_helper.rb
|
16
|
+
test/test_eaal.rb
|
17
|
+
test/fixtures/test/test/account/Characters/Request_.xml
|
18
|
+
test/fixtures/test/test/char/Killlog/Request_characterID:12345.xml
|
19
|
+
test/fixtures/test/test/char/Killlog/Request_.xml
|
data/README.rdoc
ADDED
@@ -0,0 +1,96 @@
|
|
1
|
+
= eaal
|
2
|
+
* http://eaal.rubyforge.org
|
3
|
+
|
4
|
+
== DESCRIPTION:
|
5
|
+
|
6
|
+
EAAL (Eve API Access Layer) is a ruby library for accessing data of the API of
|
7
|
+
the game Eve Online
|
8
|
+
|
9
|
+
== FEATURES/PROBLEMS:
|
10
|
+
|
11
|
+
* does not need to change when EVE API gets new pages
|
12
|
+
* has a build in file cache which respects eve caching times (usage= EAAL.cache = EAAL::Cache::FileCache.new('path/to/save/files/in'))
|
13
|
+
|
14
|
+
== SYNOPSIS:
|
15
|
+
|
16
|
+
Usage:
|
17
|
+
Initialize the API Object
|
18
|
+
|
19
|
+
api = EAAL::API.new("my Userid", "my API key"[, "scope for requests"])
|
20
|
+
|
21
|
+
the scope is the one used for the API requests,
|
22
|
+
ex. account/char/corp/eve/map/server
|
23
|
+
see http://wiki.eve-id.net/APIv2_Page_Index
|
24
|
+
the scope can be changed during runtime and defaults to account
|
25
|
+
|
26
|
+
Request Information
|
27
|
+
result = api.ApiPage
|
28
|
+
this will return an Object of type ScopeApiPageResult which then
|
29
|
+
can be used to do read the api result
|
30
|
+
|
31
|
+
Example 1, getting a list of characters on the account:
|
32
|
+
|
33
|
+
api = EAAL::API.new("my userid", "my API key")
|
34
|
+
result = api.Characters
|
35
|
+
result.characters.each{|character|
|
36
|
+
puts character.name
|
37
|
+
}
|
38
|
+
|
39
|
+
Example 2, getting the id for a given character name
|
40
|
+
api = EAAL::API.new("my userid", "my API key")
|
41
|
+
api.scope = "eve"
|
42
|
+
result = api.CharacterID(:names => "Peter Powers")
|
43
|
+
puts result.characters.name
|
44
|
+
|
45
|
+
Example 3, Example 2 in short
|
46
|
+
puts EAAL::Api.new("my userid", "my API key", "eve").CharacterID(:names => "Peter Powers").characters.name
|
47
|
+
|
48
|
+
|
49
|
+
Errors returned by the EVE API are handled a bit unique,
|
50
|
+
since i wanted to have them pretty much dynamic (so i dont need to hack EAAL
|
51
|
+
whenever CCP adds a new Error) you have to use dynamic created classes to catch 'em
|
52
|
+
(if you dont want to catch EAAL::Exception::EveAPIException in general)
|
53
|
+
so what you do is:
|
54
|
+
|
55
|
+
Example 4, catching a specific EVE API Exception
|
56
|
+
begin
|
57
|
+
api.Killlog("characterID" => "12345") #this example offcourse
|
58
|
+
# assumes your not having the key for character 12345 loaded ;)
|
59
|
+
rescue EAAL::Exception.EveAPIException(201)
|
60
|
+
#dosomething
|
61
|
+
end
|
62
|
+
|
63
|
+
|
64
|
+
== REQUIREMENTS:
|
65
|
+
|
66
|
+
* hpricot
|
67
|
+
* activesupport
|
68
|
+
|
69
|
+
== INSTALL:
|
70
|
+
|
71
|
+
* sudo gem install eaal
|
72
|
+
|
73
|
+
== LICENSE:
|
74
|
+
|
75
|
+
(The MIT License)
|
76
|
+
|
77
|
+
Copyright (c) 2008 Peter Petermann
|
78
|
+
|
79
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
80
|
+
a copy of this software and associated documentation files (the
|
81
|
+
'Software'), to deal in the Software without restriction, including
|
82
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
83
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
84
|
+
permit persons to whom the Software is furnished to do so, subject to
|
85
|
+
the following conditions:
|
86
|
+
|
87
|
+
The above copyright notice and this permission notice shall be
|
88
|
+
included in all copies or substantial portions of the Software.
|
89
|
+
|
90
|
+
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
|
91
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
92
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
93
|
+
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
94
|
+
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
95
|
+
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
96
|
+
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/Rakefile
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
%w[rubygems rake rake/clean fileutils newgem rubigen].each { |f| require f }
|
2
|
+
require File.dirname(__FILE__) + '/lib/eaal.rb'
|
3
|
+
|
4
|
+
# Generate all the Rake tasks
|
5
|
+
# Run 'rake -T' to see list of generated tasks (from gem root directory)
|
6
|
+
$hoe = Hoe.new('eaal', EAAL.version) do |p|
|
7
|
+
p.developer('Peter Petermann', 'PeterPetermann@gmx.net')
|
8
|
+
p.changes = p.paragraphs_of("History.txt", 0..1).join("\n\n")
|
9
|
+
p.rubyforge_name = p.name # TODO this is default value
|
10
|
+
p.extra_deps = [
|
11
|
+
['activesupport','>= 2.0.2'], ['hpricot', '>= 0.6']
|
12
|
+
]
|
13
|
+
p.extra_dev_deps = [
|
14
|
+
['newgem', ">= #{::Newgem::VERSION}"]
|
15
|
+
]
|
16
|
+
|
17
|
+
p.clean_globs |= %w[**/.DS_Store tmp *.log]
|
18
|
+
path = (p.rubyforge_name == p.name) ? p.rubyforge_name : "\#{p.rubyforge_name}/\#{p.name}"
|
19
|
+
p.remote_rdoc_dir = File.join(path.gsub(/^#{p.rubyforge_name}\/?/,''), 'rdoc')
|
20
|
+
p.rsync_args = '-av --delete --ignore-errors'
|
21
|
+
end
|
22
|
+
|
23
|
+
require 'newgem/tasks' # load /tasks/*.rake
|
24
|
+
Dir['tasks/**/*.rake'].each { |t| load t }
|
25
|
+
|
26
|
+
# TODO - want other tests/tasks run by default? Add them to the list
|
27
|
+
# task :default => [:spec, :features]
|
data/lib/eaal.rb
ADDED
data/lib/eaal/eaal.rb
ADDED
@@ -0,0 +1,114 @@
|
|
1
|
+
#--
|
2
|
+
# EAAL by Peter Petermann <PeterPetermann@gmx.net>
|
3
|
+
# This library is licensed under the terms found in
|
4
|
+
# the LICENSE file distributed with it
|
5
|
+
#
|
6
|
+
# TODO:
|
7
|
+
# - more documenation
|
8
|
+
# - write tests (i know, i know, i fail badly)
|
9
|
+
# - more error handling (im certain i missed a few possibles)
|
10
|
+
# - cleanup (you can see that this is my first project in ruby, cant you?)
|
11
|
+
#
|
12
|
+
# THANKS:
|
13
|
+
# thanks go to all people on irc.coldfront.net, channel #eve-dev
|
14
|
+
# special thanks go to lisa (checkout her eve api library, reve,
|
15
|
+
# much more mature then mine) for answering my endless questions
|
16
|
+
# about ruby stuff (and for one or two snippets i stole from reve)
|
17
|
+
#++
|
18
|
+
|
19
|
+
require 'rubygems'
|
20
|
+
require 'hpricot'
|
21
|
+
require 'activesupport'
|
22
|
+
|
23
|
+
require 'net/http'
|
24
|
+
require 'uri'
|
25
|
+
require 'cgi'
|
26
|
+
|
27
|
+
module EAAL
|
28
|
+
|
29
|
+
mattr_reader :version_string, :version
|
30
|
+
|
31
|
+
@@version = "0.1.0"
|
32
|
+
@@version_string = "EAAL" + EAAL.version # the version string, used as client name in http requests
|
33
|
+
|
34
|
+
mattr_accessor :api_base, :additional_request_parameters, :cache
|
35
|
+
@@api_base = "http://api.eve-online.com/" # the url used as basis for all requests, you might want to use gatecamper url or a personal proxy instead
|
36
|
+
@@additional_request_parameters = {} # hash, if :key => value pairs are added those will be added to each request
|
37
|
+
@@cache = EAAL::Cache::NoCache.new # caching object, see EAAL::Cache::FileCache for an Example
|
38
|
+
|
39
|
+
# EAAL::API class
|
40
|
+
# Usage Example:
|
41
|
+
# api = EAAL::API.new("my userid", "my API key")
|
42
|
+
# result = api.Characters
|
43
|
+
# result.characters.each{|character|
|
44
|
+
# puts character.name
|
45
|
+
# }
|
46
|
+
class API
|
47
|
+
attr_accessor :userid, :key, :scope
|
48
|
+
|
49
|
+
# constructor
|
50
|
+
# Expects:
|
51
|
+
# * userid (String | Integer) the users id
|
52
|
+
# * key (String) the apikey Full or Restricted
|
53
|
+
# * scope (String) defaults to account
|
54
|
+
def initialize(userid, key, scope="account")
|
55
|
+
self.userid = userid.to_s
|
56
|
+
self.key = key.to_s
|
57
|
+
self.scope = scope.to_s
|
58
|
+
end
|
59
|
+
|
60
|
+
# create an xml request according to the method called
|
61
|
+
# this is used to dynamicaly create api calls and
|
62
|
+
# should usually not be called directly
|
63
|
+
# * method (const)
|
64
|
+
# * args
|
65
|
+
def method_missing(method, *args)
|
66
|
+
scope = self.scope
|
67
|
+
args_hash = args.first
|
68
|
+
args_hash = {} unless args_hash
|
69
|
+
self.request_xml(scope, method.id2name, args_hash)
|
70
|
+
end
|
71
|
+
|
72
|
+
# make a request to the api. will use cache if set.
|
73
|
+
# usually not called by the user directly
|
74
|
+
# * scope (String)
|
75
|
+
# * name (String)
|
76
|
+
# * opts (Hash)
|
77
|
+
def request_xml(scope, name, opts)
|
78
|
+
opts = EAAL.additional_request_parameters.merge(opts)
|
79
|
+
xml = EAAL.cache.load(self.userid, self.key, scope, name,opts)
|
80
|
+
if not xml
|
81
|
+
source = URI.parse(EAAL.api_base + scope + '/' + name +'.xml.aspx')
|
82
|
+
req_path = source.path + format_url_request(opts.merge({
|
83
|
+
:userid => self.userid,
|
84
|
+
:apikey => self.key}))
|
85
|
+
req = Net::HTTP::Get.new(req_path)
|
86
|
+
req[EAAL.version_string]
|
87
|
+
res = Net::HTTP.new(source.host, source.port).start {|http| http.request(req) } #one request for now
|
88
|
+
case res
|
89
|
+
when Net::HTTPOK
|
90
|
+
when Net::HTTPNotFound
|
91
|
+
raise EAAL::Exception::APINotFoundError.new("The requested API (#{scope} / #{name}) could not be found.")
|
92
|
+
else
|
93
|
+
raise EAAL::Exception::HTTPError.new("An HTTP Error occured, body: " + res.body)
|
94
|
+
end
|
95
|
+
EAAL.cache.save(self.userid, self.key, scope,name,opts, res.body)
|
96
|
+
xml = res.body
|
97
|
+
end
|
98
|
+
doc = Hpricot.XML(xml)
|
99
|
+
result = EAAL::Result.new(scope.capitalize + name, doc)
|
100
|
+
end
|
101
|
+
|
102
|
+
# Turns a hash into ?var=baz&bam=boo
|
103
|
+
# stolen from Reve (thx lisa)
|
104
|
+
# * opts (Hash)
|
105
|
+
def format_url_request(opts)
|
106
|
+
req = "?"
|
107
|
+
opts.stringify_keys!
|
108
|
+
opts.keys.sort.each do |key|
|
109
|
+
req += "#{CGI.escape(key.to_s)}=#{CGI.escape(opts[key].to_s)}&" if opts[key]
|
110
|
+
end
|
111
|
+
req.chop # We are lazy and append a & to each pair even if it's the last one. FIXME: Don't do this.
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|
@@ -0,0 +1,86 @@
|
|
1
|
+
#--
|
2
|
+
# EAAL by Peter Petermann <PeterPetermann@gmx.net>
|
3
|
+
# This library is licensed under the terms found in
|
4
|
+
# the LICENSE file distributed with it
|
5
|
+
#++
|
6
|
+
require 'fileutils'
|
7
|
+
|
8
|
+
module EAAL
|
9
|
+
# The Classes in this module are objects that may be used as value
|
10
|
+
# of EAAL.cache.
|
11
|
+
# By default EAAL uses the NoCache class, where no caching is done.
|
12
|
+
# If a working cache class is used it will store the xml data
|
13
|
+
# and return it, so no requests to the API are done (as long as valid xml is available)
|
14
|
+
module Cache
|
15
|
+
|
16
|
+
# EAAL::Cache::FileCache
|
17
|
+
# File based xml cache which respects the cachedUntil of the Eve API
|
18
|
+
# Usage:
|
19
|
+
# EAAL.cache = EAAL::Cache::FileCache.new
|
20
|
+
# Or
|
21
|
+
# EAAL.cache = EAAL::Cache::FileCache.new("/path/to/place/to/store/xml/data")
|
22
|
+
class FileCache
|
23
|
+
attr_accessor :basepath
|
24
|
+
|
25
|
+
# constructor, takes one argument which is the path
|
26
|
+
# where files should be written
|
27
|
+
# * basepath (String) path which should be used to store cached data. defaults to $HOME/.eaal/cache/
|
28
|
+
def initialize(basepath = "#{ENV['HOME']}/.eaal/cache")
|
29
|
+
if basepath[(basepath.length) -1, basepath.length] != "/"
|
30
|
+
basepath += "/"
|
31
|
+
end
|
32
|
+
@basepath = basepath
|
33
|
+
end
|
34
|
+
|
35
|
+
# create the path/filename for the cache file
|
36
|
+
def filename(userid, apikey, scope, name, args)
|
37
|
+
ret =""
|
38
|
+
args.delete_if { |k,v| (v || "").to_s.length == 0 }
|
39
|
+
h = args.stringify_keys
|
40
|
+
ret += h.sort.flatten.collect{ |e| e.to_s }.join(':')
|
41
|
+
hash = ret.gsub(/:$/,'')
|
42
|
+
"#{@basepath}#{userid}/#{apikey}/#{scope}/#{name}/Request_#{hash}.xml"
|
43
|
+
end
|
44
|
+
|
45
|
+
# load xml if available, return false if not available, or cachedUntil ran out
|
46
|
+
def load(userid, apikey, scope, name, args)
|
47
|
+
filename = self.filename(userid, apikey,scope,name,args)
|
48
|
+
if not File.exist?(filename)
|
49
|
+
ret = false
|
50
|
+
else
|
51
|
+
xml = File.open(filename).read
|
52
|
+
if self.validate_cache(xml)
|
53
|
+
ret = xml
|
54
|
+
else
|
55
|
+
ret = false
|
56
|
+
end
|
57
|
+
end
|
58
|
+
ret
|
59
|
+
end
|
60
|
+
|
61
|
+
# validate cached datas cachedUntil
|
62
|
+
def validate_cache(xml)
|
63
|
+
doc = Hpricot.XML(xml)
|
64
|
+
(doc/"/eveapi/cachedUntil").inner_html.to_time > Time.now
|
65
|
+
end
|
66
|
+
|
67
|
+
# save xml data to file
|
68
|
+
def save(userid, apikey, scope, name, args, xml)
|
69
|
+
filename = self.filename(userid, apikey,scope,name,args)
|
70
|
+
FileUtils.mkdir_p(File.dirname(filename))
|
71
|
+
File.open(filename,'w') { |f| f.print xml }
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
# NoCache class
|
76
|
+
# dummy class which is used for non-caching behaviour (default)
|
77
|
+
class NoCache
|
78
|
+
def load(userid, apikey, scope, name, args)
|
79
|
+
false
|
80
|
+
end
|
81
|
+
def save(userid, apikey, scope, name, args, xml)
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
end
|
86
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
#--
|
2
|
+
# EAAL by Peter Petermann <PeterPetermann@gmx.net>
|
3
|
+
# This library is licensed under the terms found in
|
4
|
+
# the LICENSE file distributed with it
|
5
|
+
#++
|
6
|
+
module EAAL
|
7
|
+
module Exception
|
8
|
+
# creates the class for an EveAPIException
|
9
|
+
def self.EveAPIException(nr)
|
10
|
+
classname = "EveAPIException#{nr}"
|
11
|
+
if not Object.const_defined? classname
|
12
|
+
klass = Object.const_set(classname, Class.new(EAAL::Exception::EveAPIException))
|
13
|
+
else
|
14
|
+
klass = Object.const_get(classname)
|
15
|
+
end
|
16
|
+
klass
|
17
|
+
end
|
18
|
+
|
19
|
+
# raise the eve API exceptions, class will be dynamicaly created by classname
|
20
|
+
# EveAPIException followed by the APIs exception Number
|
21
|
+
def self.raiseEveAPIException(nr, msg)
|
22
|
+
raise EAAL::Exception.EveAPIException(nr).new(msg)
|
23
|
+
end
|
24
|
+
|
25
|
+
# all EAAL exceptions should extend this.
|
26
|
+
class EAALError < StandardError
|
27
|
+
end
|
28
|
+
|
29
|
+
# Used when an http error is encountered
|
30
|
+
class HTTPError < EAALError
|
31
|
+
end
|
32
|
+
|
33
|
+
# Used when the Eve API returns a 404
|
34
|
+
class APINotFoundError < HTTPError
|
35
|
+
end
|
36
|
+
|
37
|
+
# All API Errors should be derived from this
|
38
|
+
class EveAPIException < EAALError
|
39
|
+
end
|
40
|
+
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,120 @@
|
|
1
|
+
#--
|
2
|
+
# EAAL by Peter Petermann <PeterPetermann@gmx.net>
|
3
|
+
# This library is licensed under the terms found in
|
4
|
+
# the LICENSE file distributed with it
|
5
|
+
#++
|
6
|
+
module EAAL
|
7
|
+
|
8
|
+
module Result
|
9
|
+
|
10
|
+
# base class for automated result class creation
|
11
|
+
class ResultBase
|
12
|
+
attr_accessor :request_time, :cached_until
|
13
|
+
end
|
14
|
+
|
15
|
+
# Result Container class, ...
|
16
|
+
class ResultContainer
|
17
|
+
attr_accessor :container
|
18
|
+
|
19
|
+
def initialize
|
20
|
+
self.container = {}
|
21
|
+
end
|
22
|
+
|
23
|
+
def add_element(key, val)
|
24
|
+
self.container.merge!({key => val})
|
25
|
+
end
|
26
|
+
|
27
|
+
def method_missing(method, *args)
|
28
|
+
self.container[method.id2name]
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
# result element
|
33
|
+
class ResultElement
|
34
|
+
attr_accessor :name, :value, :attribs
|
35
|
+
def initialize(name, value)
|
36
|
+
self.name = name
|
37
|
+
self.value = value
|
38
|
+
self.attribs = {}
|
39
|
+
end
|
40
|
+
|
41
|
+
def add_attrib(key, val)
|
42
|
+
self.attribs.merge!({key => val})
|
43
|
+
end
|
44
|
+
|
45
|
+
def method_missing(method, *args)
|
46
|
+
if self.attribs.has_key?(method.id2name)
|
47
|
+
self.attribs[method.id2name]
|
48
|
+
else
|
49
|
+
self.value.send(method, *args)
|
50
|
+
end
|
51
|
+
|
52
|
+
end
|
53
|
+
|
54
|
+
# parses an xml element to create either the ResultElement, ResultContainer or Rowset
|
55
|
+
# necessary
|
56
|
+
def self.parse_element(prefix, element)
|
57
|
+
if element.name == "rowset"
|
58
|
+
value = EAAL::Rowset.new(prefix, element)
|
59
|
+
key = value.name
|
60
|
+
else
|
61
|
+
key = element.name
|
62
|
+
if element.containers.length > 0
|
63
|
+
container = ResultContainer.new
|
64
|
+
element.containers.each { |celement|
|
65
|
+
cel = EAAL::Result::ResultElement.parse_element(prefix, celement)
|
66
|
+
if element.attributes.length > 0
|
67
|
+
container.add_element(cel.name, cel)
|
68
|
+
else
|
69
|
+
container.add_element(cel.name, cel.value)
|
70
|
+
end
|
71
|
+
}
|
72
|
+
value = container
|
73
|
+
else
|
74
|
+
value = element.inner_html
|
75
|
+
end
|
76
|
+
end
|
77
|
+
re = ResultElement.new(key, value)
|
78
|
+
if element.attributes.length > 0
|
79
|
+
re.attribs.merge!(element.attributes)
|
80
|
+
end
|
81
|
+
re
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
|
86
|
+
def self.new(prefix, xml)
|
87
|
+
classname = prefix + 'Result'
|
88
|
+
members = []
|
89
|
+
values = {}
|
90
|
+
if (xml/"eveapi/error").length > 0
|
91
|
+
error = (xml/"eveapi/error").first
|
92
|
+
raise EAAL::Exception.raiseEveAPIException(error["code"], error.inner_html)
|
93
|
+
end
|
94
|
+
if (xml/"eveapi/result").length < 1
|
95
|
+
raise EAAL::Exception::EAALError.new("Unknown API error, no result element was found")
|
96
|
+
end
|
97
|
+
elements = (xml/"eveapi/result").first.containers
|
98
|
+
elements.each {|element|
|
99
|
+
el = EAAL::Result::ResultElement.parse_element(prefix, element)
|
100
|
+
members << el.name
|
101
|
+
values.merge!({el.name => el.value})
|
102
|
+
}
|
103
|
+
if not Object.const_defined? classname
|
104
|
+
klass = Object.const_set(classname, Class.new(EAAL::Result::ResultBase))
|
105
|
+
klass.class_eval do
|
106
|
+
attr_accessor *members
|
107
|
+
end
|
108
|
+
else
|
109
|
+
klass = Object.const_get(classname)
|
110
|
+
end
|
111
|
+
result = klass.new
|
112
|
+
result.request_time = (xml/"eveapi/currentTime").first.inner_html
|
113
|
+
result.cached_until = (xml/"eveapi/cachedUntil").first.inner_html
|
114
|
+
values.each { |key,value|
|
115
|
+
result.send(key + "=", value)
|
116
|
+
}
|
117
|
+
result
|
118
|
+
end
|
119
|
+
end
|
120
|
+
end
|
@@ -0,0 +1,63 @@
|
|
1
|
+
#--
|
2
|
+
# EAAL by Peter Petermann <PeterPetermann@gmx.net>
|
3
|
+
# This library is licensed under the terms found in
|
4
|
+
# the LICENSE file distributed with it
|
5
|
+
#++
|
6
|
+
module EAAL
|
7
|
+
|
8
|
+
module Rowset
|
9
|
+
|
10
|
+
class RowsetBase < Array
|
11
|
+
attr_accessor :name, :columns, :rowclass
|
12
|
+
|
13
|
+
def create_row(xml)
|
14
|
+
row = self.rowclass.new
|
15
|
+
self.columns.each { |colname|
|
16
|
+
row.send(colname +"=", xml[colname]) # row content ignored so far (needs to be added!!!)
|
17
|
+
}
|
18
|
+
if xml.containers.length > 0
|
19
|
+
xml.containers.each { |child|
|
20
|
+
el = EAAL::Result::ResultElement.parse_element(self.rowclass.name, child)
|
21
|
+
row.add_element(el.name, el)
|
22
|
+
}
|
23
|
+
end
|
24
|
+
row
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
class RowBase < EAAL::Result::ResultContainer
|
29
|
+
end
|
30
|
+
|
31
|
+
def self.new(prefix, xml)
|
32
|
+
name = xml['name']
|
33
|
+
columns = xml['columns'].split(',')
|
34
|
+
|
35
|
+
classname = prefix + 'Rowset' + name.capitalize
|
36
|
+
rowname = classname + 'Row'
|
37
|
+
|
38
|
+
if not Object.const_defined? classname
|
39
|
+
klass = Object.const_set(classname, Class.new(EAAL::Rowset::RowsetBase))
|
40
|
+
else
|
41
|
+
klass = Object.const_get(classname)
|
42
|
+
end
|
43
|
+
rowset = klass.new
|
44
|
+
|
45
|
+
if not Object.const_defined? rowname
|
46
|
+
klass = Object.const_set(rowname, Class.new(EAAL::Rowset::RowBase))
|
47
|
+
klass.class_eval do
|
48
|
+
attr_accessor *columns
|
49
|
+
end
|
50
|
+
else
|
51
|
+
klass = Object.const_get(rowname)
|
52
|
+
end
|
53
|
+
|
54
|
+
rowset.name = name
|
55
|
+
rowset.columns = columns
|
56
|
+
rowset.rowclass = klass
|
57
|
+
xml.containers.each{ |row|
|
58
|
+
rowset << rowset.create_row(row)
|
59
|
+
}
|
60
|
+
rowset
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
data/script/console
ADDED
@@ -0,0 +1,10 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# File: script/console
|
3
|
+
irb = RUBY_PLATFORM =~ /(:?mswin|mingw)/ ? 'irb.bat' : 'irb'
|
4
|
+
|
5
|
+
libs = " -r irb/completion"
|
6
|
+
# Perhaps use a console_lib to store any extra methods I may want available in the cosole
|
7
|
+
# libs << " -r #{File.dirname(__FILE__) + '/../lib/console_lib/console_logger.rb'}"
|
8
|
+
libs << " -r #{File.dirname(__FILE__) + '/../lib/eaal.rb'}"
|
9
|
+
puts "Loading eaal gem"
|
10
|
+
exec "#{irb} #{libs} --simple-prompt"
|
data/script/destroy
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
APP_ROOT = File.expand_path(File.join(File.dirname(__FILE__), '..'))
|
3
|
+
|
4
|
+
begin
|
5
|
+
require 'rubigen'
|
6
|
+
rescue LoadError
|
7
|
+
require 'rubygems'
|
8
|
+
require 'rubigen'
|
9
|
+
end
|
10
|
+
require 'rubigen/scripts/destroy'
|
11
|
+
|
12
|
+
ARGV.shift if ['--help', '-h'].include?(ARGV[0])
|
13
|
+
RubiGen::Base.use_component_sources! [:rubygems, :newgem, :newgem_theme, :test_unit]
|
14
|
+
RubiGen::Scripts::Destroy.new.run(ARGV)
|
data/script/generate
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
APP_ROOT = File.expand_path(File.join(File.dirname(__FILE__), '..'))
|
3
|
+
|
4
|
+
begin
|
5
|
+
require 'rubigen'
|
6
|
+
rescue LoadError
|
7
|
+
require 'rubygems'
|
8
|
+
require 'rubigen'
|
9
|
+
end
|
10
|
+
require 'rubigen/scripts/generate'
|
11
|
+
|
12
|
+
ARGV.shift if ['--help', '-h'].include?(ARGV[0])
|
13
|
+
RubiGen::Base.use_component_sources! [:rubygems, :newgem, :newgem_theme, :test_unit]
|
14
|
+
RubiGen::Scripts::Generate.new.run(ARGV)
|
@@ -0,0 +1,11 @@
|
|
1
|
+
<?xml version='1.0' encoding='UTF-8'?>
|
2
|
+
<eveapi version="2">
|
3
|
+
<currentTime>2008-12-08 15:02:25</currentTime>
|
4
|
+
<result>
|
5
|
+
<rowset name="characters" key="characterID" columns="name,characterID,corporationName,corporationID">
|
6
|
+
<row name="Test Tester" characterID="12345" corporationName="Test Corp" corporationID="54321" />
|
7
|
+
<row name="Tester2" characterID="0987" corporationName="Test2 Corp" corporationID="7890" />
|
8
|
+
</rowset>
|
9
|
+
</result>
|
10
|
+
<cachedUntil>2020-12-08 16:02:25</cachedUntil>
|
11
|
+
</eveapi>
|
@@ -0,0 +1,19 @@
|
|
1
|
+
<?xml version='1.0' encoding='UTF-8'?>
|
2
|
+
<eveapi version="2">
|
3
|
+
<currentTime>2008-12-08 15:22:26</currentTime>
|
4
|
+
<result>
|
5
|
+
<rowset name="kills" key="killID" columns="killID,solarSystemID,killTime,moonID">
|
6
|
+
<row killID="1" solarSystemID="1" killTime="2008-12-07 14:11:00" moonID="0">
|
7
|
+
<victim characterID="179004085" characterName="Peter Powers" corporationID="402487260" corporationName="FinFleet" allianceID="632866070" allianceName="Band of Brothers" factionID="0" factionName="" damageTaken="15909" shipTypeID="22448" />
|
8
|
+
<rowset name="attackers" columns="characterID,characterName,corporationID,corporationName,allianceID,allianceName,factionID,factionName,securityStatus,damageDone,finalBlow,weaponTypeID,shipTypeID">
|
9
|
+
<row characterID="12345" characterName="Test Tester" corporationID="54321" corporationName="Test Corp" allianceID="1" allianceName="Test Alliance" factionID="0" factionName="" securityStatus="4" damageDone="15909" finalBlow="1" weaponTypeID="14286" shipTypeID="24688" />
|
10
|
+
</rowset>
|
11
|
+
<rowset name="items" columns="typeID,flag,qtyDropped,qtyDestroyed">
|
12
|
+
<row typeID="2048" flag="0" qtyDropped="1" qtyDestroyed="0" />
|
13
|
+
<row typeID="12814" flag="5" qtyDropped="0" qtyDestroyed="6" />
|
14
|
+
</rowset>
|
15
|
+
</row>
|
16
|
+
</rowset>
|
17
|
+
</result>
|
18
|
+
<cachedUntil>2020-12-08 16:22:26</cachedUntil>
|
19
|
+
</eveapi>
|
data/test/test_eaal.rb
ADDED
@@ -0,0 +1,36 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/test_helper.rb'
|
2
|
+
|
3
|
+
class TestEaal < Test::Unit::TestCase
|
4
|
+
|
5
|
+
# prepare the api object. sets EAAL to use FileCache to load fixtures
|
6
|
+
def setup
|
7
|
+
EAAL.cache = EAAL::Cache::FileCache.new(File.dirname(__FILE__) + '/fixtures/')
|
8
|
+
@api = EAAL::API.new('test','test')
|
9
|
+
end
|
10
|
+
# test if we realy got an API Object
|
11
|
+
def test_api_class
|
12
|
+
assert_instance_of EAAL::API, @api
|
13
|
+
end
|
14
|
+
|
15
|
+
# some random tests if parsing the xml builds the right class
|
16
|
+
def test_api_classes
|
17
|
+
@api.scope = "char"
|
18
|
+
assert_raise (EAAL::Exception.EveAPIException(105)) { @api.Killlog }
|
19
|
+
assert_equal @api.Killlog(:characterID => 12345).class.name, "CharKilllogResult"
|
20
|
+
assert_equal @api.Killlog(:characterID => 12345).kills.class.name, "CharKilllogRowsetKills"
|
21
|
+
assert_equal @api.Killlog(:characterID => 12345).kills.first.class.name, "CharKilllogRowsetKillsRow"
|
22
|
+
assert_equal @api.Killlog(:characterID => 12345).kills.first.victim.class.name, "EAAL::Result::ResultElement"
|
23
|
+
assert_equal @api.Killlog(:characterID => 12345).kills.first.attackers.first.class.name, "CharKilllogRowsetKillsRowRowsetAttackersRow"
|
24
|
+
end
|
25
|
+
|
26
|
+
# some random data checks to ensure stuff can be read
|
27
|
+
def test_api_parse_data
|
28
|
+
@api.scope = "account"
|
29
|
+
assert_equal @api.Characters.characters.first.name, "Test Tester"
|
30
|
+
assert_equal @api.Characters.characters.second.corporationID, "7890"
|
31
|
+
@api.scope = "char"
|
32
|
+
assert_equal @api.Killlog(:characterID => 12345).kills.length, 1
|
33
|
+
assert_equal @api.Killlog(:characterID => 12345).kills.first.victim.characterName, "Peter Powers"
|
34
|
+
assert_equal @api.Killlog(:characterID => 12345).kills.first.attackers.first.characterID, "12345"
|
35
|
+
end
|
36
|
+
end
|
data/test/test_helper.rb
ADDED
metadata
ADDED
@@ -0,0 +1,116 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: eaal
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Peter Petermann
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
|
12
|
+
date: 2008-12-09 00:00:00 +01:00
|
13
|
+
default_executable:
|
14
|
+
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
16
|
+
name: activesupport
|
17
|
+
type: :runtime
|
18
|
+
version_requirement:
|
19
|
+
version_requirements: !ruby/object:Gem::Requirement
|
20
|
+
requirements:
|
21
|
+
- - ">="
|
22
|
+
- !ruby/object:Gem::Version
|
23
|
+
version: 2.0.2
|
24
|
+
version:
|
25
|
+
- !ruby/object:Gem::Dependency
|
26
|
+
name: hpricot
|
27
|
+
type: :runtime
|
28
|
+
version_requirement:
|
29
|
+
version_requirements: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: "0.6"
|
34
|
+
version:
|
35
|
+
- !ruby/object:Gem::Dependency
|
36
|
+
name: newgem
|
37
|
+
type: :development
|
38
|
+
version_requirement:
|
39
|
+
version_requirements: !ruby/object:Gem::Requirement
|
40
|
+
requirements:
|
41
|
+
- - ">="
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
version: 1.1.0
|
44
|
+
version:
|
45
|
+
- !ruby/object:Gem::Dependency
|
46
|
+
name: hoe
|
47
|
+
type: :development
|
48
|
+
version_requirement:
|
49
|
+
version_requirements: !ruby/object:Gem::Requirement
|
50
|
+
requirements:
|
51
|
+
- - ">="
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: 1.8.0
|
54
|
+
version:
|
55
|
+
description: EAAL (Eve API Access Layer) is a ruby library for accessing data of the API of the game Eve Online
|
56
|
+
email:
|
57
|
+
- PeterPetermann@gmx.net
|
58
|
+
executables: []
|
59
|
+
|
60
|
+
extensions: []
|
61
|
+
|
62
|
+
extra_rdoc_files:
|
63
|
+
- History.txt
|
64
|
+
- Manifest.txt
|
65
|
+
- README.rdoc
|
66
|
+
- LICENSE.txt
|
67
|
+
files:
|
68
|
+
- History.txt
|
69
|
+
- Manifest.txt
|
70
|
+
- README.rdoc
|
71
|
+
- LICENSE.txt
|
72
|
+
- Rakefile
|
73
|
+
- lib/eaal.rb
|
74
|
+
- lib/eaal/eaal.rb
|
75
|
+
- lib/eaal/eaal_cache.rb
|
76
|
+
- lib/eaal/eaal_exception.rb
|
77
|
+
- lib/eaal/eaal_result.rb
|
78
|
+
- lib/eaal/eaal_rowset.rb
|
79
|
+
- script/console
|
80
|
+
- script/destroy
|
81
|
+
- script/generate
|
82
|
+
- test/test_helper.rb
|
83
|
+
- test/test_eaal.rb
|
84
|
+
- test/fixtures/test/test/account/Characters/Request_.xml
|
85
|
+
- test/fixtures/test/test/char/Killlog/Request_characterID:12345.xml
|
86
|
+
- test/fixtures/test/test/char/Killlog/Request_.xml
|
87
|
+
has_rdoc: true
|
88
|
+
homepage: " http://eaal.rubyforge.org"
|
89
|
+
post_install_message:
|
90
|
+
rdoc_options:
|
91
|
+
- --main
|
92
|
+
- README.rdoc
|
93
|
+
require_paths:
|
94
|
+
- lib
|
95
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
96
|
+
requirements:
|
97
|
+
- - ">="
|
98
|
+
- !ruby/object:Gem::Version
|
99
|
+
version: "0"
|
100
|
+
version:
|
101
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
102
|
+
requirements:
|
103
|
+
- - ">="
|
104
|
+
- !ruby/object:Gem::Version
|
105
|
+
version: "0"
|
106
|
+
version:
|
107
|
+
requirements: []
|
108
|
+
|
109
|
+
rubyforge_project: eaal
|
110
|
+
rubygems_version: 1.3.1
|
111
|
+
signing_key:
|
112
|
+
specification_version: 2
|
113
|
+
summary: EAAL (Eve API Access Layer) is a ruby library for accessing data of the API of the game Eve Online
|
114
|
+
test_files:
|
115
|
+
- test/test_helper.rb
|
116
|
+
- test/test_eaal.rb
|