eaal 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/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
|