eve_api 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1,17 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
data/Gemfile ADDED
@@ -0,0 +1,7 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in eve_api.gemspec
4
+ gemspec
5
+
6
+ gem 'awesome_print'
7
+ gem 'addressable'
data/LICENSE.txt ADDED
@@ -0,0 +1,16 @@
1
+ EveApi: Library to access eve online api
2
+ Copyright (C) 2013 Femaref
3
+ femaref@googlemail.com
4
+
5
+ This program is free software; you can redistribute it and/or
6
+ modify it under the terms of the GNU General Public License
7
+ as published by the Free Software Foundation; limited to version 2.
8
+
9
+ This program is distributed in the hope that it will be useful,
10
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
11
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
+ GNU General Public License for more details.
13
+
14
+ You should have received a copy of the GNU General Public License
15
+ along with this program; if not, write to the Free Software
16
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
data/README.md ADDED
@@ -0,0 +1,29 @@
1
+ # EveApi
2
+
3
+ TODO: Write a gem description
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ gem 'eve_api'
10
+
11
+ And then execute:
12
+
13
+ $ bundle
14
+
15
+ Or install it yourself as:
16
+
17
+ $ gem install eve_api
18
+
19
+ ## Usage
20
+
21
+ TODO: Write usage instructions here
22
+
23
+ ## Contributing
24
+
25
+ 1. Fork it
26
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
27
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
28
+ 4. Push to the branch (`git push origin my-new-feature`)
29
+ 5. Create new Pull Request
data/Rakefile ADDED
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
data/eve_api.gemspec ADDED
@@ -0,0 +1,23 @@
1
+ # -*- encoding: utf-8 -*-
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'eve_api/version'
5
+
6
+ Gem::Specification.new do |gem|
7
+ gem.name = "eve_api"
8
+ gem.version = EveApi::VERSION
9
+ gem.authors = ["Femaref"]
10
+ gem.email = ["femaref@googlemail.com"]
11
+ gem.description = %q{Generic way to query the eve online api }
12
+ gem.summary = %q{Generic way to query the eve online api }
13
+ gem.homepage = ""
14
+
15
+ gem.files = `git ls-files`.split($/)
16
+ gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
17
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
18
+ gem.require_paths = ["lib"]
19
+
20
+ gem.add_dependency("addressable", "~> 2.3.5")
21
+ gem.add_dependency("nokogiri", "~> 1.6.0")
22
+ gem.add_dependency("faraday", "~> 0.8.8")
23
+ end
@@ -0,0 +1,84 @@
1
+ module EveApi
2
+ class Api
3
+ BASE_URI = "https://api.eveonline.com"
4
+
5
+ def initialize(keyID, vCode)
6
+ @keyID = keyID
7
+ @vCode = vCode
8
+ end
9
+
10
+ def account
11
+ ScopedApi.new(@keyID, @vCode, :account)
12
+ end
13
+
14
+ def char
15
+ ScopedApi.new(@keyID, @vCode, :char)
16
+ end
17
+
18
+ def corp
19
+ ScopedApi.new(@keyID, @vCode, :corp)
20
+ end
21
+
22
+ def eve
23
+ ScopedApi.new(@keyID, @vCode, :eve)
24
+ end
25
+
26
+ def map
27
+ ScopedApi.new(@keyID, @vCode, :map)
28
+ end
29
+
30
+ def server
31
+ ScopedApi.new(@keyID, @vCode, :map)
32
+ end
33
+
34
+ def self.canonic_path(path)
35
+ path.to_s.downcase.split("_").map{ |m| m.capitalize }.reduce(:+)
36
+ end
37
+
38
+ def self.uri(path, scope)
39
+ scope_uri = Addressable::URI.parse("/#{scope.to_s}/")
40
+
41
+ path_capitalized = self.canonic_path(path)
42
+ path_capitalized += ".xml.aspx"
43
+
44
+ path_uri = Addressable::URI.parse(path_capitalized)
45
+
46
+ final_uri = scope_uri + path_uri
47
+
48
+ return final_uri
49
+ end
50
+
51
+ protected
52
+
53
+ def call(path, scope, args)
54
+ canonic_name = self.class.canonic_path(path)
55
+ uri = self.class.uri(path, scope)
56
+ args = args.merge({ :keyID => @keyID, :vCode => @vCode })
57
+
58
+ characterID = (args[:characterID] || args[:character_id] || 0)
59
+
60
+ if cache = EveApi.cache.retrieve(@keyID, scope, canonic_name, characterID)
61
+ document= Nokogiri::XML(cache)
62
+ else
63
+ @connection ||= Faraday.new(:url => BASE_URI) do |faraday|
64
+ faraday.request :url_encoded
65
+ faraday.response :logger
66
+ faraday.adapter Faraday.default_adapter
67
+ end
68
+
69
+ result = @connection.get uri, args
70
+
71
+ if result.status != 200
72
+ raise "Status Code not equal 200"
73
+ end
74
+
75
+ cache = result.body
76
+ EveApi.cache.store!(@keyID, scope, canonic_name, characterID, cache)
77
+
78
+ document = Nokogiri::XML(cache)
79
+ end
80
+
81
+ EveApi::Parsers::Default.new(canonic_name, document).parse
82
+ end
83
+ end
84
+ end
@@ -0,0 +1,24 @@
1
+ module EveApi
2
+ module Caches
3
+ class Default
4
+ def initialize
5
+ end
6
+
7
+ def path(keyID, scope, canonic_name, characterID)
8
+ "#{keyID}/#{scope}/#{canonic_name}/#{characterID}"
9
+ end
10
+
11
+ def cached?(keyID, scope, canonic_name, characterID)
12
+ return false
13
+ end
14
+
15
+ def retrieve(keyID, scope, canonic_name, characterID)
16
+ return nil
17
+ end
18
+
19
+ def store!(keyID, scope, canonic_name, characterID, content)
20
+ return false
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,58 @@
1
+ module EveApi
2
+ module Caches
3
+ class File < Default
4
+ def initialize(cache_path)
5
+ @root = cache_path
6
+ end
7
+
8
+ def cached?(keyID, scope, canonic_name, characterID)
9
+ file_path = render_path(keyID, scope, canonic_name, characterID)
10
+
11
+ return false if !::File.exists?(file_path)
12
+
13
+ cached = ::File.open(file_path) do |f|
14
+ parser = EveApi::Parsers::Cache.new(f.read)
15
+
16
+ cached_until, _ = parser.parse
17
+
18
+ Time.now <= cached_until
19
+ end
20
+
21
+ return cached
22
+ end
23
+
24
+ def retrieve(keyID, scope, canonic_name, characterID)
25
+ rendered_path = render_path(keyID, scope, canonic_name, characterID)
26
+
27
+ if cached?(keyID, scope, canonic_name, characterID)
28
+ return ::File.open(rendered_path) do |f|
29
+ f.read
30
+ end
31
+ else
32
+ return nil
33
+ end
34
+ end
35
+
36
+ def store!(keyID, scope, canonic_name, characterID, content)
37
+ rendered_path = render_path(keyID, scope, canonic_name, characterID)
38
+
39
+ FileUtils.mkdir_p(::File.dirname(rendered_path))
40
+
41
+ ::File.open(rendered_path, "w+") do |f|
42
+ f.write(content.to_s)
43
+ end
44
+
45
+ return true
46
+ end
47
+
48
+ private
49
+
50
+ def render_path(keyID, scope, canonic_name, characterID)
51
+ rendered_path = path(keyID, scope, canonic_name, characterID)
52
+
53
+ return ::File.join(@root, rendered_path)
54
+ end
55
+
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,98 @@
1
+ module EveApi
2
+ module Data
3
+ class Generic
4
+ def initialize(data)
5
+ @data = data
6
+ end
7
+
8
+ def method_missing(name, *args)
9
+ if !@data.has_key?(name.to_sym)
10
+ return super
11
+ end
12
+
13
+ return @data[name.to_sym]
14
+ end
15
+
16
+ def keys
17
+ @data.keys
18
+ end
19
+
20
+ def inspect
21
+ "<# EveApi::Data::Generic keys: #{keys} >"
22
+ end
23
+ end
24
+
25
+ class Result < Generic
26
+ attr_accessor :current_time, :cached_until, :outdated
27
+
28
+ def initialize(current_time, cached_until, data, outdated = false)
29
+ @current_time = current_time
30
+ @cached_until = cached_until
31
+ @outdated = outdated
32
+ super(data)
33
+ end
34
+ end
35
+
36
+ class Rowset
37
+ include Enumerable
38
+ extend Forwardable
39
+
40
+ def_delegator :@rows, :each, :each
41
+
42
+ def initialize(rows)
43
+ @rows = rows
44
+ end
45
+ end
46
+
47
+ class Row < Generic
48
+ end
49
+
50
+ def self.result(canonic_name)
51
+ name = "#{canonic_name}Result".to_sym
52
+
53
+ if const_defined?(name)
54
+ return const_get name
55
+ end
56
+
57
+ klass = Class.new(Result)
58
+
59
+ const_set name, klass
60
+
61
+ return klass
62
+ end
63
+
64
+ def self.rowset(canonic_name, keys, fields = [])
65
+ name = "#{canonic_name}Rowset".to_sym
66
+ if const_defined?(name)
67
+ return const_get name
68
+ end
69
+
70
+ klass = Class.new(Rowset)
71
+
72
+ klass.const_set("NAME", canonic_name)
73
+ klass.const_set("FIELDS", fields)
74
+ klass.const_set("KEYS", keys)
75
+
76
+ const_set name, klass
77
+
78
+ return klass
79
+ end
80
+
81
+ def self.row(canonic_name, keys, fields = [])
82
+ name = "#{canonic_name}Row".to_sym
83
+ if const_defined?(name)
84
+ return const_get name
85
+ end
86
+
87
+ klass = Class.new(Row)
88
+
89
+ klass.const_set("NAME", canonic_name)
90
+ klass.const_set("FIELDS", fields)
91
+ klass.const_set("KEYS", keys)
92
+
93
+ const_set name, klass
94
+
95
+ return klass
96
+ end
97
+ end
98
+ end
@@ -0,0 +1,16 @@
1
+ module EveApi
2
+ module Parsers
3
+ class Cache
4
+ def initialize(result)
5
+ @document = result.is_a?(Nokogiri::XML::Document) ? result : Nokogiri::XML(result)
6
+ end
7
+
8
+ def parse
9
+ cached_until = Time.parse(@document.css("cachedUntil").first.inner_text + " UTC")
10
+ current_time = Time.parse(@document.css("currentTime").first.inner_text + " UTC")
11
+
12
+ return [cached_until, current_time]
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,107 @@
1
+ module EveApi
2
+ module Parsers
3
+ class Default < Cache
4
+ STRING_DETECTION = /[^\d.]+/
5
+
6
+ def initialize(canonic_name, result)
7
+ @canonic_name = canonic_name
8
+ super(result)
9
+ end
10
+
11
+ def parse
12
+ rowsets = @document.css("result > rowset").map do |rowset|
13
+ parsed = parse_rowset(rowset)
14
+ [ parsed.class::NAME.downcase.to_sym, parsed ]
15
+ end
16
+
17
+ cached_until, current_time = super
18
+
19
+ result_klass = EveApi::Data.result(@canonic_name)
20
+
21
+ data = rowsets
22
+
23
+ single_fields = @document.css("result > *").select do |node|
24
+ node.name != "rowset"
25
+ end
26
+
27
+ single_fields = single_fields.map do |node|
28
+ parse_node(node)
29
+ end
30
+
31
+ data += single_fields
32
+
33
+ data = Hash[data]
34
+
35
+ result_klass.new(current_time, cached_until, data)
36
+ end
37
+
38
+ private
39
+
40
+ def parse_rowset(data)
41
+ fields = data.attribute("columns").value.split(",")
42
+ keys = data.attribute("key").value.split(",")
43
+ name = data.attribute("name").value.capitalize
44
+
45
+ rowset_klass = EveApi::Data.rowset(name, keys, fields)
46
+
47
+ rows = data.css("> row").map do |row|
48
+ parse_row(name, keys, fields, row)
49
+ end
50
+
51
+ rowset_klass.new(rows)
52
+ end
53
+
54
+ def parse_row(rowset_name, keys, fields, data)
55
+ row_klass = EveApi::Data.row(rowset_name, keys, fields)
56
+
57
+ ary = data.map do |k, v|
58
+ [k.to_sym, parse_attribute(k, v)]
59
+ end
60
+
61
+ hash = Hash[ary]
62
+
63
+ row_klass.new(hash)
64
+ end
65
+
66
+ def parse_attribute(key, value)
67
+ sym_key = key.to_sym
68
+
69
+ if value == nil || value == ""
70
+ return EveApi.default_for_empty
71
+ end
72
+
73
+ if sym_key == :date
74
+ return Time.parse(value)
75
+ end
76
+
77
+ if key.downcase.include?("singleton")
78
+ return value == "1"
79
+ end
80
+
81
+ if self.class::STRING_DETECTION.match(value)
82
+ return value
83
+ end
84
+
85
+ value = value.to_f
86
+
87
+ if value.to_i == value
88
+ return value.to_i
89
+ end
90
+
91
+ return value
92
+ end
93
+
94
+ def parse_node(node)
95
+ if node.children.count == 0
96
+ return [node.name.to_sym, nil ]
97
+ end
98
+
99
+ if node.children.count == 1 && node.children.first.text?
100
+ return [node.name.to_sym, parse_attribute(node.name, node.inner_text)]
101
+ end
102
+
103
+ return [ node.name.to_sym, EveApi::Data::Generic.new(Hash[node.css(" > *").map{ |m| parse_node(m) }]) ]
104
+ end
105
+ end
106
+ end
107
+ end
@@ -0,0 +1,12 @@
1
+ module EveApi
2
+ class ScopedApi < Api
3
+ def initialize(keyID, vCode, scope)
4
+ @scope = scope
5
+ super(keyID, vCode)
6
+ end
7
+
8
+ def method_missing(method, args = {})
9
+ self.call(method, @scope, args)
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,3 @@
1
+ module EveApi
2
+ VERSION = "0.0.1"
3
+ end
data/lib/eve_api.rb ADDED
@@ -0,0 +1,41 @@
1
+ require 'eve_api/version'
2
+ require 'addressable/uri'
3
+ require 'faraday'
4
+ require 'nokogiri'
5
+
6
+ module EveApi
7
+
8
+ autoload :Api, 'eve_api/api.rb'
9
+ autoload :ScopedApi, 'eve_api/scoped_api.rb'
10
+
11
+ autoload :Data, 'eve_api/data.rb'
12
+
13
+ module Parsers
14
+ autoload :Default, 'eve_api/parsers/default.rb'
15
+ autoload :Cache, 'eve_api/parsers/cache.rb'
16
+ end
17
+
18
+ module Caches
19
+ autoload :Default, 'eve_api/caches/default.rb'
20
+ autoload :File, 'eve_api/caches/file.rb'
21
+ end
22
+
23
+ def self.cache
24
+ @cache
25
+ end
26
+
27
+ def self.cache=(value)
28
+ @cache = value
29
+ end
30
+
31
+ def self.default_for_empty
32
+ @default_for_empty
33
+ end
34
+
35
+ def self.default_for_empty=(value)
36
+ @default_for_empty = value
37
+ end
38
+
39
+ @cache ||= EveApi::Caches::Default.new
40
+ @default_for_empty = nil
41
+ end
metadata ADDED
@@ -0,0 +1,108 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: eve_api
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Femaref
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2013-08-11 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: addressable
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ~>
20
+ - !ruby/object:Gem::Version
21
+ version: 2.3.5
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ~>
28
+ - !ruby/object:Gem::Version
29
+ version: 2.3.5
30
+ - !ruby/object:Gem::Dependency
31
+ name: nokogiri
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ~>
36
+ - !ruby/object:Gem::Version
37
+ version: 1.6.0
38
+ type: :runtime
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ~>
44
+ - !ruby/object:Gem::Version
45
+ version: 1.6.0
46
+ - !ruby/object:Gem::Dependency
47
+ name: faraday
48
+ requirement: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ~>
52
+ - !ruby/object:Gem::Version
53
+ version: 0.8.8
54
+ type: :runtime
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ~>
60
+ - !ruby/object:Gem::Version
61
+ version: 0.8.8
62
+ description: ! 'Generic way to query the eve online api '
63
+ email:
64
+ - femaref@googlemail.com
65
+ executables: []
66
+ extensions: []
67
+ extra_rdoc_files: []
68
+ files:
69
+ - .gitignore
70
+ - Gemfile
71
+ - LICENSE.txt
72
+ - README.md
73
+ - Rakefile
74
+ - eve_api.gemspec
75
+ - lib/eve_api.rb
76
+ - lib/eve_api/api.rb
77
+ - lib/eve_api/caches/default.rb
78
+ - lib/eve_api/caches/file.rb
79
+ - lib/eve_api/data.rb
80
+ - lib/eve_api/parsers/cache.rb
81
+ - lib/eve_api/parsers/default.rb
82
+ - lib/eve_api/scoped_api.rb
83
+ - lib/eve_api/version.rb
84
+ homepage: ''
85
+ licenses: []
86
+ post_install_message:
87
+ rdoc_options: []
88
+ require_paths:
89
+ - lib
90
+ required_ruby_version: !ruby/object:Gem::Requirement
91
+ none: false
92
+ requirements:
93
+ - - ! '>='
94
+ - !ruby/object:Gem::Version
95
+ version: '0'
96
+ required_rubygems_version: !ruby/object:Gem::Requirement
97
+ none: false
98
+ requirements:
99
+ - - ! '>='
100
+ - !ruby/object:Gem::Version
101
+ version: '0'
102
+ requirements: []
103
+ rubyforge_project:
104
+ rubygems_version: 1.8.24
105
+ signing_key:
106
+ specification_version: 3
107
+ summary: Generic way to query the eve online api
108
+ test_files: []