eve 1.0.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.
Files changed (175) hide show
  1. data/History.txt +4 -0
  2. data/Manifest.txt +174 -0
  3. data/PostInstall.txt +6 -0
  4. data/README.rdoc +126 -0
  5. data/Rakefile +128 -0
  6. data/features/support/env.rb +1 -0
  7. data/lib/eve.rb +31 -0
  8. data/lib/eve/api.rb +247 -0
  9. data/lib/eve/api/connectivity.rb +39 -0
  10. data/lib/eve/api/request.rb +74 -0
  11. data/lib/eve/api/response.rb +100 -0
  12. data/lib/eve/api/response/inspection.rb +62 -0
  13. data/lib/eve/api/response/rowset.rb +56 -0
  14. data/lib/eve/api/response/rowsets.rb +42 -0
  15. data/lib/eve/api/response/wrap_object.rb +15 -0
  16. data/lib/eve/api/services.rb +20 -0
  17. data/lib/eve/api/services/account.rb +12 -0
  18. data/lib/eve/api/services/character.rb +96 -0
  19. data/lib/eve/api/services/corporation.rb +150 -0
  20. data/lib/eve/api/services/eve.rb +76 -0
  21. data/lib/eve/api/services/map.rb +45 -0
  22. data/lib/eve/api/services/misc.rb +24 -0
  23. data/lib/eve/api/services/server.rb +20 -0
  24. data/lib/eve/core_extensions.rb +3 -0
  25. data/lib/eve/core_extensions/hash.rb +51 -0
  26. data/lib/eve/core_extensions/string.rb +11 -0
  27. data/lib/eve/dependencies.rb +18 -0
  28. data/lib/eve/errors.rb +129 -0
  29. data/lib/eve/errors/authentication_errors.rb +33 -0
  30. data/lib/eve/errors/internal_errors.rb +64 -0
  31. data/lib/eve/errors/miscellaneous_errors.rb +19 -0
  32. data/lib/eve/errors/user_input_errors.rb +62 -0
  33. data/lib/eve/helpers.rb +12 -0
  34. data/lib/eve/helpers/javascript_helper.rb +198 -0
  35. data/lib/eve/helpers/view_helper.rb +13 -0
  36. data/lib/eve/trust.rb +88 -0
  37. data/lib/eve/trust/controller_helpers.rb +90 -0
  38. data/lib/eve/trust/igb_interface.rb +88 -0
  39. data/lib/eve/trust/mime_types.rb +4 -0
  40. data/script/console +10 -0
  41. data/script/console.cmd +1 -0
  42. data/script/destroy +14 -0
  43. data/script/destroy.cmd +1 -0
  44. data/script/generate +14 -0
  45. data/script/generate.cmd +1 -0
  46. data/spec/lib/eve/api/calls/account/characters_spec.rb +22 -0
  47. data/spec/lib/eve/api/calls/character/account_balance_spec.rb +21 -0
  48. data/spec/lib/eve/api/calls/character/asset_list_spec.rb +23 -0
  49. data/spec/lib/eve/api/calls/character/character_sheet_spec.rb +51 -0
  50. data/spec/lib/eve/api/calls/character/fac_war_stats_spec.rb +31 -0
  51. data/spec/lib/eve/api/calls/character/industry_jobs_spec.rb +27 -0
  52. data/spec/lib/eve/api/calls/character/kill_log_spec.rb +27 -0
  53. data/spec/lib/eve/api/calls/character/mail_messages_spec.rb +21 -0
  54. data/spec/lib/eve/api/calls/character/mailing_lists_spec.rb +21 -0
  55. data/spec/lib/eve/api/calls/character/market_orders_spec.rb +21 -0
  56. data/spec/lib/eve/api/calls/character/medals_spec.rb +24 -0
  57. data/spec/lib/eve/api/calls/character/research_spec.rb +21 -0
  58. data/spec/lib/eve/api/calls/character/skill_in_training_spec.rb +44 -0
  59. data/spec/lib/eve/api/calls/character/skill_queue_spec.rb +21 -0
  60. data/spec/lib/eve/api/calls/character/standings_spec.rb +26 -0
  61. data/spec/lib/eve/api/calls/character/wallet_journal_spec.rb +21 -0
  62. data/spec/lib/eve/api/calls/character/wallet_transactions_spec.rb +21 -0
  63. data/spec/lib/eve/api/calls/character_portrait_spec.rb +17 -0
  64. data/spec/lib/eve/api/calls/corporation/account_balances_spec.rb +21 -0
  65. data/spec/lib/eve/api/calls/corporation/asset_list_spec.rb +25 -0
  66. data/spec/lib/eve/api/calls/corporation/container_log_spec.rb +23 -0
  67. data/spec/lib/eve/api/calls/corporation/corporation_sheet_spec.rb +36 -0
  68. data/spec/lib/eve/api/calls/corporation/fac_war_stats_spec.rb +23 -0
  69. data/spec/lib/eve/api/calls/corporation/industry_jobs_spec.rb +30 -0
  70. data/spec/lib/eve/api/calls/corporation/kill_log_spec.rb +27 -0
  71. data/spec/lib/eve/api/calls/corporation/market_orders_spec.rb +22 -0
  72. data/spec/lib/eve/api/calls/corporation/medals_spec.rb +21 -0
  73. data/spec/lib/eve/api/calls/corporation/member_medals_spec.rb +21 -0
  74. data/spec/lib/eve/api/calls/corporation/member_security_log_spec.rb +24 -0
  75. data/spec/lib/eve/api/calls/corporation/member_security_spec.rb +25 -0
  76. data/spec/lib/eve/api/calls/corporation/member_tracking_spec.rb +22 -0
  77. data/spec/lib/eve/api/calls/corporation/shareholders_spec.rb +23 -0
  78. data/spec/lib/eve/api/calls/corporation/standings_spec.rb +30 -0
  79. data/spec/lib/eve/api/calls/corporation/starbase_detail_spec.rb +32 -0
  80. data/spec/lib/eve/api/calls/corporation/starbase_list_spec.rb +22 -0
  81. data/spec/lib/eve/api/calls/corporation/titles_spec.rb +26 -0
  82. data/spec/lib/eve/api/calls/corporation/wallet_journal_spec.rb +22 -0
  83. data/spec/lib/eve/api/calls/corporation/wallet_transactions_spec.rb +22 -0
  84. data/spec/lib/eve/api/calls/empty_call_spec.rb +29 -0
  85. data/spec/lib/eve/api/calls/eve/alliance_list_spec.rb +26 -0
  86. data/spec/lib/eve/api/calls/eve/certificate_tree_spec.rb +18 -0
  87. data/spec/lib/eve/api/calls/eve/character_id_spec.rb +27 -0
  88. data/spec/lib/eve/api/calls/eve/conquerable_station_list_spec.rb +11 -0
  89. data/spec/lib/eve/api/calls/eve/error_list_spec.rb +21 -0
  90. data/spec/lib/eve/api/calls/eve/fac_war_stats_spec.rb +25 -0
  91. data/spec/lib/eve/api/calls/eve/fac_war_top_stats_spec.rb +54 -0
  92. data/spec/lib/eve/api/calls/eve/ref_types_spec.rb +11 -0
  93. data/spec/lib/eve/api/calls/eve/skill_tree_spec.rb +17 -0
  94. data/spec/lib/eve/api/calls/map/fac_war_systems_spec.rb +11 -0
  95. data/spec/lib/eve/api/calls/map/jumps_spec.rb +11 -0
  96. data/spec/lib/eve/api/calls/map/kills_spec.rb +15 -0
  97. data/spec/lib/eve/api/calls/map/sovereignty_spec.rb +11 -0
  98. data/spec/lib/eve/api/calls/server_status_spec.rb +24 -0
  99. data/spec/lib/eve/api/request_spec.rb +17 -0
  100. data/spec/lib/eve/api/response/error_spec.rb +13 -0
  101. data/spec/lib/eve/api/response/rowset_spec.rb +28 -0
  102. data/spec/lib/eve/api/response_spec.rb +79 -0
  103. data/spec/lib/eve/api_spec.rb +13 -0
  104. data/spec/lib/eve/core_extensions/hash_spec.rb +23 -0
  105. data/spec/lib/eve/core_extensions/string_spec.rb +8 -0
  106. data/spec/lib/eve/helpers/javascript_helper_spec.rb +80 -0
  107. data/spec/lib/eve/helpers/view_helper_spec.rb +12 -0
  108. data/spec/lib/eve/trust/controller_helpers_spec.rb +70 -0
  109. data/spec/lib/eve/trust/igb_interface_spec.rb +102 -0
  110. data/spec/rcov.opts +2 -0
  111. data/spec/readme_spec.rb +36 -0
  112. data/spec/sample_api_key.yml +20 -0
  113. data/spec/spec.opts +4 -0
  114. data/spec/spec_helper.rb +22 -0
  115. data/spec/support/behaves_like_rowset.rb +50 -0
  116. data/spec/support/controllers/trust_controller.rb +7 -0
  117. data/spec/support/jpg/mock_portrait.jpg +0 -0
  118. data/spec/support/mock_api_helpers.rb +41 -0
  119. data/spec/support/xml/account/characters.xml +15 -0
  120. data/spec/support/xml/character/account_balance.xml +10 -0
  121. data/spec/support/xml/character/asset_list.xml +50 -0
  122. data/spec/support/xml/character/character_sheet.xml +65 -0
  123. data/spec/support/xml/character/fac_war_stats.xml +20 -0
  124. data/spec/support/xml/character/industry_jobs.xml +70 -0
  125. data/spec/support/xml/character/kill_log.xml +51 -0
  126. data/spec/support/xml/character/mail_messages.xml +12 -0
  127. data/spec/support/xml/character/mailing_lists.xml +12 -0
  128. data/spec/support/xml/character/market_orders.xml +11 -0
  129. data/spec/support/xml/character/medals.xml +13 -0
  130. data/spec/support/xml/character/research.xml +13 -0
  131. data/spec/support/xml/character/skill_in_training.xml +14 -0
  132. data/spec/support/xml/character/skill_not_in_training.xml +7 -0
  133. data/spec/support/xml/character/skill_queue.xml +11 -0
  134. data/spec/support/xml/character/standings.xml +32 -0
  135. data/spec/support/xml/character/wallet_journal.xml +39 -0
  136. data/spec/support/xml/character/wallet_transactions.xml +44 -0
  137. data/spec/support/xml/corporation/account_balance.xml +15 -0
  138. data/spec/support/xml/corporation/asset_list.xml +50 -0
  139. data/spec/support/xml/corporation/container_log.xml +32 -0
  140. data/spec/support/xml/corporation/fac_war_stats.xml +19 -0
  141. data/spec/support/xml/corporation/industry_jobs.xml +70 -0
  142. data/spec/support/xml/corporation/kill_log.xml +51 -0
  143. data/spec/support/xml/corporation/market_orders.xml +37 -0
  144. data/spec/support/xml/corporation/medals.xml +8 -0
  145. data/spec/support/xml/corporation/member_corporation_sheet.xml +51 -0
  146. data/spec/support/xml/corporation/member_medals.xml +10 -0
  147. data/spec/support/xml/corporation/member_security.xml +21 -0
  148. data/spec/support/xml/corporation/member_security_log.xml +55 -0
  149. data/spec/support/xml/corporation/member_tracking.xml +18 -0
  150. data/spec/support/xml/corporation/non_member_corporation_sheet.xml +30 -0
  151. data/spec/support/xml/corporation/shareholders.xml +11 -0
  152. data/spec/support/xml/corporation/standings.xml +33 -0
  153. data/spec/support/xml/corporation/starbase_detail.xml +33 -0
  154. data/spec/support/xml/corporation/starbase_list.xml +17 -0
  155. data/spec/support/xml/corporation/titles.xml +34 -0
  156. data/spec/support/xml/corporation/wallet_journal.xml +40 -0
  157. data/spec/support/xml/corporation/wallet_transactions.xml +12 -0
  158. data/spec/support/xml/errors/106.xml +5 -0
  159. data/spec/support/xml/errors/516.xml +5 -0
  160. data/spec/support/xml/eve/alliance_list.xml +22 -0
  161. data/spec/support/xml/eve/certificate_tree.xml +49 -0
  162. data/spec/support/xml/eve/character_id.xml +15 -0
  163. data/spec/support/xml/eve/conquerable_station_list.xml +24 -0
  164. data/spec/support/xml/eve/error_list.xml +78 -0
  165. data/spec/support/xml/eve/fac_war_stats.xml +31 -0
  166. data/spec/support/xml/eve/fac_war_top_stats.xml +238 -0
  167. data/spec/support/xml/eve/ref_types.xml +105 -0
  168. data/spec/support/xml/eve/skill_tree.xml +52 -0
  169. data/spec/support/xml/map/fac_war_systems.xml +180 -0
  170. data/spec/support/xml/map/jumps.xml +166 -0
  171. data/spec/support/xml/map/kills.xml +191 -0
  172. data/spec/support/xml/map/sovereignty.xml +20 -0
  173. data/spec/support/xml/rowset_with_mismatched_attributes.xml +6 -0
  174. data/spec/support/xml/server/server_status.xml +9 -0
  175. metadata +364 -0
@@ -0,0 +1,247 @@
1
+ require 'eve/api/request'
2
+ require 'eve/api/response'
3
+ require 'eve/api/services'
4
+ require 'eve/api/connectivity'
5
+
6
+ module Eve
7
+ # = Eve API Libraries
8
+ #
9
+ # EVE Online has made available various APIs which allow for querying the server for information about the server's
10
+ # current status, general game information such as skill and certificate trees, top player rankings, and the players
11
+ # and characters themselves. This library interfaces with that API to provide an intuitive way of retrieving this
12
+ # data.
13
+ #
14
+ # == The Basics
15
+ #
16
+ # There are two forms of authentication that the API uses: a limited API key and a full API key. For some information,
17
+ # such as the server's current status, no API key at all is required; for other information, such as which characters
18
+ # are owned by a particular user account, a limited API key will suffice. For more personal information, such as
19
+ # a character's transaction history, a full API key is required. Using an inappropriate or missing API key will result
20
+ # in an error being raised.
21
+ #
22
+ # === Instantiation & [Re]Configuration
23
+ # To interface with the Eve API, you need to instantiate the API object. This is simple:
24
+ # api = Eve::API.new
25
+ #
26
+ # If you plan to make use of information requiring an API key, you'll need to pass in those options:
27
+ # api = Eve::API.new(:user_id => 'a_user_id', :api_key => 'an_api_key')
28
+ #
29
+ # If you need to make use of Character-specific API calls, then you should also pass a +:character_id+ key. Same goes
30
+ # for Corporation-specific API calls: pass a +corporation_id+ key. If you don't know those yet (for instance, because
31
+ # you need the user to make a selection), then don't fret. You can always instantiate a new API object, or simply
32
+ # set the option directly on the API object you've already got:
33
+ # api.set(:character_id => 'a_character_id')
34
+ # # -or-
35
+ # api[:character_id] = 'a_character_id'
36
+ #
37
+ # === Making API Calls
38
+ # Actually retrieving information is just as straightforward as instantiation of the API object was, though the syntax
39
+ # does sometimes vary from one call to the next. Here's how to get the current server status:
40
+ # status = api.server_status
41
+ #
42
+ # And retrieving the list of characters belonging to :user_id is done like so:
43
+ # charlist = api.account.characters
44
+ #
45
+ # === List of API Calls
46
+ # This section is split into 3 subsections, one for each level of API key required for the call in question. This
47
+ # table assumes the presence of an "api" object, which is an instantiation of the API object as shown above. For
48
+ # more information on a particular subset of calls, including the exact return values, click on the corresponding
49
+ # class name to the left.
50
+ #
51
+ # ==== No API Key
52
+ # Eve::API::Services::Corporation:: api.corporation.corporation_sheet
53
+ # Eve::API::Services::Eve:: api.eve.alliance_list
54
+ # Eve::API::Services::Eve:: api.eve.certificate_tree
55
+ # Eve::API::Services::Eve:: api.eve.conquerable_station_list
56
+ # Eve::API::Services::Eve:: api.eve.error_list
57
+ # Eve::API::Services::Eve:: api.eve.fac_war_stats / api.eve.factional_warfare_stats
58
+ # Eve::API::Services::Eve:: api.eve.fac_war_top_stats / api.eve.factional_warfare_top100
59
+ # Eve::API::Services::Eve:: api.eve.character_name(*ids)
60
+ # Eve::API::Services::Eve:: api.eve.character_id(*names)
61
+ # Eve::API::Services::Eve:: api.eve.corporation_name(*ids)
62
+ # Eve::API::Services::Eve:: api.eve.corporation_id(*names)
63
+ # Eve::API::Services::Eve:: api.eve.alliance_name(*ids)
64
+ # Eve::API::Services::Eve:: api.eve.alliance_id(*names)
65
+ # Eve::API::Services::Eve:: api.eve.ref_types
66
+ # Eve::API::Services::Eve:: api.eve.skill_tree
67
+ # Eve::API::Services::Map:: api.map.fac_war_systems / api.map.contested_systems
68
+ # Eve::API::Services::Map:: api.map.sovereignty
69
+ # Eve::API::Services::Map:: api.map.kills
70
+ # Eve::API::Services::Map:: api.map.jumps
71
+ # Eve::API::Services::Misc:: api.misc.character_portrait
72
+ # Eve::API::Services::Server:: api.server.server_status
73
+ #
74
+ # ==== Limited API Key
75
+ # Eve::API::Services::Account:: api.account.characters
76
+ # Eve::API::Services::Character:: api.character.character_sheet
77
+ # Eve::API::Services::Character:: api.character.fac_war_stats
78
+ # Eve::API::Services::Character:: api.character.medals
79
+ # Eve::API::Services::Character:: api.character.skill_in_training
80
+ # Eve::API::Services::Character:: api.character.skill_queue
81
+ # Eve::API::Services::Character:: api.character.standings
82
+ # Eve::API::Services::Corporation:: api.corporation.corporation_sheet
83
+ # Eve::API::Services::Corporation:: api.corporation.fac_war_stats
84
+ # Eve::API::Services::Corporation:: api.corporation.medals
85
+ # Eve::API::Services::Corporation:: api.corporation.member_medals
86
+ #
87
+ # ==== Full API Key
88
+ # Eve::API::Services::Character:: api.character.account_balance
89
+ # Eve::API::Services::Character:: api.character.asset_list(version = nil)
90
+ # Eve::API::Services::Character:: api.character.industry_jobs
91
+ # Eve::API::Services::Character:: api.character.kill_log(options = {})
92
+ # Eve::API::Services::Character:: api.character.mailing_lists
93
+ # Eve::API::Services::Character:: api.character.mail_messages
94
+ # Eve::API::Services::Character:: api.character.market_orders
95
+ # Eve::API::Services::Character:: api.character.notifications
96
+ # Eve::API::Services::Character:: api.character.research
97
+ # Eve::API::Services::Character:: api.character.wallet_journal(account_key = 1000, options = {})
98
+ # Eve::API::Services::Character:: api.character.journal_entries(account_key = 1000, options = {})
99
+ # Eve::API::Services::Character:: api.character.wallet_transactions(options = {})
100
+ # Eve::API::Services::Corporation:: api.corporation.account_balance
101
+ # Eve::API::Services::Corporation:: api.corporation.asset_list
102
+ # Eve::API::Services::Corporation:: api.corporation.container_log
103
+ # Eve::API::Services::Corporation:: api.corporation.corporation_sheet(corporation_id = nil)
104
+ # Eve::API::Services::Corporation:: api.corporation.fac_war_stats
105
+ # Eve::API::Services::Corporation:: api.corporation.industry_jobs
106
+ # Eve::API::Services::Corporation:: api.corporation.kill_log(options = {})
107
+ # Eve::API::Services::Corporation:: api.corporation.market_orders
108
+ # Eve::API::Services::Corporation:: api.corporation.member_security
109
+ # Eve::API::Services::Corporation:: api.corporation.member_security_log
110
+ # Eve::API::Services::Corporation:: api.corporation.member_tracking
111
+ # Eve::API::Services::Corporation:: api.corporation.starbase_detail(item_id, version = 2)
112
+ # Eve::API::Services::Corporation:: api.corporation.starbase_list
113
+ # Eve::API::Services::Corporation:: api.corporation.shareholders
114
+ # Eve::API::Services::Corporation:: api.corporation.standings
115
+ # Eve::API::Services::Corporation:: api.corporation.titles
116
+ # Eve::API::Services::Corporation:: api.corporation.wallet_journal(account_key = 1000, options = {})
117
+ # Eve::API::Services::Corporation:: api.corporation.wallet_transactions(account_key = 1000, options = {})
118
+ #
119
+ # === Interpreting Responses
120
+ # Response objects are generated automatically, and should be able to accommodate any changes in the API reasonably
121
+ # well.
122
+ #
123
+ # The classes listed above attempt to document the API calls. However, if you are unsure of
124
+ # how to process the return value of a particular API call, don't be afraid to check it out directly:
125
+ # irb(main):004:0> puts api.server_status.to_yaml
126
+ # ---
127
+ # current_time: 2010-03-14T04:41:51+00:00
128
+ # cached_until: 2010-03-14T04:44:51+00:00
129
+ # online_players: 30694
130
+ # server_open: true
131
+ # api_version: "2"
132
+ #
133
+ # In this example, #server_status provides 5 fields: #api_version, #cached_until, #current_time, #online_players,
134
+ # and #server_open.
135
+ #
136
+ # Some fields in a given response are essentially arrays with some additional fields. These are called Rowsets. For
137
+ # instance, the call to +api.account.characters+, above, returned a response with a #characters method, which
138
+ # contained up to 3 characters. Each element, or Row, in a Rowset has in turn its own fields and/or Rowsets. Each
139
+ # character in this example includes a #character_id, #corporation_id, and #corporation_name.
140
+ #
141
+ # Additionally, all responses always have a #name field. For basic responses, the #name is "(Response)", and
142
+ # probably doesn't mean much to you. For Rowsets, the #name is the name of the Rowset (for example, "characters").
143
+ # For individual Rows, the #name might mean something more useful -- the name of a character, for instance.
144
+ #
145
+ class API
146
+ include Eve::API::Connectivity
147
+ include Eve::API::Services
148
+ attr_reader :options
149
+ attr_reader :map
150
+
151
+ def initialize(options = {})
152
+ @options = default_options.merge(options)
153
+ send_includes
154
+ instantiate_submodules
155
+ end
156
+
157
+ def set(key, value = nil)
158
+ raise "Key can't be nil" unless key
159
+ if key.kind_of?(Hash)
160
+ key.each { |k, v| set(k, v) }
161
+ else
162
+ if value then @options[key] = value
163
+ else @options.delete key
164
+ end
165
+ [@options[:submodules]].flatten.each do |sub|
166
+ self.send(sub).set(key, value) if sub
167
+ end
168
+ end
169
+ end
170
+
171
+ def [](key); @options[key]; end
172
+ def []=(key, value); set(key, value); end
173
+
174
+ private
175
+ class << self
176
+ def validate_credentials(key_type, *args)
177
+ case key_type
178
+ when :limited, :full
179
+ args.flatten!
180
+ options = args.extract_options!
181
+ method_names = options.delete(:for)
182
+ raise ArgumentError, "Unexpected options: #{options.keys.inspect}" unless options.empty?
183
+
184
+ method_names.each do |method_name|
185
+ define_method "#{method_name}_with_credential_validation" do |*a|
186
+ validate_credentials(key_type, *args)
187
+ send("#{method_name}_without_credential_validation", *a)
188
+ end
189
+ alias_method_chain method_name, :credential_validation
190
+ end
191
+
192
+ else raise ArgumentError, "Expected :limited or :full credential type"
193
+ end
194
+ end
195
+ end
196
+
197
+ def validate_credentials(type, *additional_requirements)
198
+ raise ArgumentError, "user_id is required" unless options[:user_id]
199
+ raise ArgumentError, "api_key is required" unless options[:api_key]
200
+ additional_requirements.each do |r|
201
+ raise ArgumentError, "#{r} is required" unless options[r]
202
+ end
203
+
204
+ case type
205
+ when :limited, :full # currently no difference. Wish we could validate on this.
206
+ else raise ArgumentError, "Expected :limited or :full credential type"
207
+ end
208
+ end
209
+
210
+ def validate_options(options, *keys)
211
+ options.keys.each do |key|
212
+ raise ArgumentError, "Options should only include #{keys.inspect}" unless keys.include?(key)
213
+ end
214
+ end
215
+
216
+ def send_includes
217
+ [@options[:includes]].flatten.each do |mod|
218
+ next unless mod
219
+ mod = mod.to_s unless mod.kind_of?(String)
220
+ eigenclass.send(:include, "::Eve::API::Services::#{mod.camelize}".constantize)
221
+ end
222
+ end
223
+
224
+ def instantiate_submodules
225
+ [@options[:submodules]].flatten.each do |mod|
226
+ next unless mod
227
+ instance_variable_set("@#{mod}", ::Eve::API.new(options.merge(:includes => mod, :submodules => nil)))
228
+ eigenclass.send(:attr_reader, mod)
229
+ end
230
+ end
231
+
232
+ def eigenclass
233
+ class << self; self; end
234
+ end
235
+
236
+ def default_options
237
+ {
238
+ :submodules => [:map, :eve, :account, :character, :corporation],
239
+ :cache => true
240
+ }
241
+ end
242
+
243
+ def cache_namespace
244
+ self.class.name.underscore
245
+ end
246
+ end
247
+ end
@@ -0,0 +1,39 @@
1
+ module Eve
2
+ class API
3
+ module Connectivity
4
+ MAX_JOURNAL_ENTRIES = 1000
5
+
6
+ def walk(walk_id, walk_association, options = {}, &block)
7
+ raise ArgumentError, "Requires :walk_id" if walk_id.blank?
8
+ raise ArgumentError, "Requires :walk_association" if walk_association.blank?
9
+ options[walk_id] ||= 0
10
+ return_value = yield options
11
+ array = return_value.send(walk_association)
12
+ if array.size >= MAX_JOURNAL_ENTRIES
13
+ begin
14
+ min_id = nil
15
+ primary_key = array.primary_key
16
+ array.each { |txn| min_id = txn.send(primary_key) if min_id.nil? || min_id > txn.send(primary_key) }
17
+ array.concat walk(walk_id, options.merge(walk_id => min_id), &block).send(walk_association)
18
+ rescue Eve::Errors::UserInputErrors::InvalidBeforeTransID, Eve::Errors::UserInputErrors::InvalidBeforeRefID,
19
+ Eve::Errors::UserInputErrors::InvalidBeforeKillID
20
+ # walking is internal, so we should catch the error internally too.
21
+ end
22
+ end
23
+ return_value
24
+ end
25
+
26
+ def request(namespace, service_name, options = {})
27
+ walk_id = options.delete(:walk_id) # we don't want these being sent to the server; it messes with the cache.
28
+ walk_association = options.delete(:walk_association)
29
+ if options.delete(:walk)
30
+ walk(walk_id.to_s, walk_association, options) do |walk_options|
31
+ Eve::API::Request.new(namespace, service_name, self.options.merge(walk_options)).dispatch
32
+ end
33
+ else
34
+ Eve::API::Request.new(namespace, service_name, self.options.merge(options)).dispatch
35
+ end
36
+ end
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,74 @@
1
+ module Eve
2
+ class API
3
+ class Request
4
+ extend ActiveSupport::Memoizable
5
+ attr_reader :response, :uri, :options, :namespace, :service
6
+
7
+ def initialize(namespace, service, options = {})
8
+ options.reverse_merge! default_options
9
+ namespace = namespace.to_s if namespace.is_a?(Symbol)
10
+ service = service.to_s if service.is_a?(Symbol)
11
+
12
+ unless [:xml,:string].include? options[:response_type]
13
+ raise ArgumentError, "Expected :response_type to be :xml or :string"
14
+ end
15
+
16
+ @options = options.dup
17
+ @service = options[:camelize] ? service.camelize : service
18
+ @namespace = namespace
19
+ @response_type = options[:response_type]
20
+
21
+ @uri = File.join(@options.delete(:base_uri), @namespace, "#{@service}.#{options[:extension]}")
22
+ end
23
+
24
+ def dispatch
25
+ r = (cached_response || cache_response(Net::HTTP.post_form(URI.parse(uri), post_options).body))
26
+ if r.respond_to?(:error) && r.error
27
+ Eve::Errors.raise(:code => r.error.code, :message => r.error)
28
+ end
29
+ r
30
+ end
31
+
32
+ def cached_response
33
+ if xml = (options[:cache] ? Eve.cache.read(cache_key) : nil)
34
+ potential_response = response_for(xml)
35
+ if !potential_response.respond_to?(:cached_until) || potential_response.cached_until >= Time.now
36
+ return potential_response
37
+ end
38
+ end
39
+ nil
40
+ end
41
+
42
+ def response_for(body)
43
+ @response_type == :xml ? Eve::API::Response.new(body, options) : body
44
+ end
45
+
46
+ def cache_response(xml)
47
+ Eve.cache.write(cache_key, xml) if options[:cache]
48
+ response_for xml
49
+ end
50
+
51
+ def cache_key
52
+ ActiveSupport::Cache.expand_cache_key(post_options, @uri)
53
+ end
54
+
55
+ memoize :cache_key
56
+
57
+ private
58
+ def post_options
59
+ options.without(default_options.keys).camelize_keys
60
+ end
61
+
62
+ def default_options
63
+ {
64
+ :base_uri => "http://api.eve-online.com",
65
+ :extension => "xml.aspx",
66
+ :camelize => true,
67
+ :response_type => :xml,
68
+ :column_mapping => nil,
69
+ :cache => true
70
+ }
71
+ end
72
+ end
73
+ end
74
+ end
@@ -0,0 +1,100 @@
1
+ require 'eve/api/response/inspection'
2
+ require 'eve/api/response/wrap_object'
3
+ require 'eve/api/response/rowsets'
4
+ require 'eve/api/response/rowset'
5
+
6
+ module Eve
7
+ class API
8
+ class Response
9
+ include Eve::API::Response::WrapObject
10
+ include Eve::API::Response::Rowsets
11
+ include Eve::API::Response::Inspection
12
+ attr_reader :api_version, :content
13
+
14
+ def initialize(xml, options = {})
15
+ @options = options
16
+ xml = Hpricot::XML(xml).root if xml.kind_of?(String)
17
+ @xml = xml
18
+ #@attributes = {}
19
+
20
+ parse_xml unless options[:process_xml] == false
21
+ end
22
+
23
+ def to_hash
24
+ hash = {}
25
+ (instance_variables - protected_instance_variables + (@name.blank? ? [] : ["@name"])).each do |ivar|
26
+ value = instance_variable_get(ivar)
27
+ value = case value
28
+ when Rowset then value.to_a
29
+ when Response then value.to_hash
30
+ else value
31
+ end
32
+ hash[ivar[1..-1]] = value
33
+ end
34
+ hash
35
+ end
36
+
37
+ def to_yaml(*args)
38
+ to_hash.to_yaml(*args)
39
+ end
40
+
41
+ def [](key)
42
+ key = key.to_s if !key.kind_of?(String)
43
+ key = key.underscore
44
+ instance_variable_get("@#{key}") ||
45
+ raise(ArgumentError, "No attribute called '#{key}' seems to exist in #{self.inspect}")
46
+ end
47
+
48
+ protected
49
+ def parse_xml(node = @xml)
50
+ case node
51
+ when Hpricot::Elem
52
+ parse_elem(node)
53
+ end
54
+ end
55
+
56
+ def check_for_datetime(value)
57
+ if value =~ /\A[0-9]{4}\-[0-9]{2}\-[0-9]{2} [0-9]{2}\:[0-9]{2}\:[0-9]{2}\z/
58
+ DateTime.parse(value)
59
+ else
60
+ value
61
+ end
62
+ end
63
+
64
+ def wrap_method_around_node(node = @xml)
65
+ # TODO: refactor me.
66
+ if !node.children || !node.children.select { |c| c.is_a?(Hpricot::Elem) }.empty?
67
+ @content = node.inner_text.strip if !node.children
68
+ value = Eve::API::Response.new(node, @options.merge(:process_xml => false))
69
+ value.send(:copy_attributes, node.attributes.to_hash.keys, node)
70
+ value.parse_children
71
+ else
72
+ value = value_for(node.inner_text)
73
+ value = check_for_datetime(value)
74
+ # now define any attributes as methods on the resultant object
75
+ node_attributes = node.attributes.to_hash
76
+ copy_attributes(node_attributes.keys, node, value)
77
+ end
78
+
79
+ wrap_object(node.name, value)
80
+ end
81
+
82
+ def parse_elem(node = @xml)
83
+ case node.name
84
+ when 'eveapi' then
85
+ @api_version = node['version']
86
+ parse_children(node)
87
+ when 'result' then
88
+ parse_children(node)
89
+ when 'rowset' then
90
+ add_rowset Rowset.new(node, @options)
91
+ else wrap_method_around_node(node)
92
+ end
93
+ end
94
+
95
+ def parse_children(node = @xml)
96
+ node.children.each { |child| parse_xml(child) } if node.children
97
+ end
98
+ end
99
+ end
100
+ end