eve_api 0.0.1

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/.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: []