dsander-reve 0.0.116

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 (128) hide show
  1. data/ChangeLog +155 -0
  2. data/LICENSE +22 -0
  3. data/Rakefile +79 -0
  4. data/init.rb +1 -0
  5. data/lib/reve/classes.rb +1341 -0
  6. data/lib/reve/exceptions.rb +353 -0
  7. data/lib/reve/extensions.rb +108 -0
  8. data/lib/reve.rb +1001 -0
  9. data/reve.rb +1 -0
  10. data/test/test_reve.rb +1191 -0
  11. data/test/xml/alliances.xml +171 -0
  12. data/test/xml/assets.xml +32 -0
  13. data/test/xml/badxml.xml +6 -0
  14. data/test/xml/certificate_tree.xml +231 -0
  15. data/test/xml/char_facwarstats.xml +18 -0
  16. data/test/xml/char_medals.xml +12 -0
  17. data/test/xml/character_sheet.xml +288 -0
  18. data/test/xml/characterid.xml +11 -0
  19. data/test/xml/charactername.xml +11 -0
  20. data/test/xml/characters.xml +13 -0
  21. data/test/xml/conqurable_stations.xml +12 -0
  22. data/test/xml/corp_facwarstats.xml +17 -0
  23. data/test/xml/corp_medals.xml +23 -0
  24. data/test/xml/corp_member_medals.xml +20 -0
  25. data/test/xml/corp_membersecurity.xml +49 -0
  26. data/test/xml/corporate_assets_list.xml +16 -0
  27. data/test/xml/corporate_market_orders.xml +10 -0
  28. data/test/xml/corporate_wallet_balance.xml +16 -0
  29. data/test/xml/corporate_wallet_journal.xml +11 -0
  30. data/test/xml/corporate_wallet_transactions.xml +10 -0
  31. data/test/xml/corporation_sheet.xml +52 -0
  32. data/test/xml/errors/error_100.xml +5 -0
  33. data/test/xml/errors/error_101.xml +5 -0
  34. data/test/xml/errors/error_102.xml +5 -0
  35. data/test/xml/errors/error_103.xml +5 -0
  36. data/test/xml/errors/error_104.xml +5 -0
  37. data/test/xml/errors/error_105.xml +5 -0
  38. data/test/xml/errors/error_106.xml +5 -0
  39. data/test/xml/errors/error_107.xml +5 -0
  40. data/test/xml/errors/error_108.xml +5 -0
  41. data/test/xml/errors/error_109.xml +5 -0
  42. data/test/xml/errors/error_110.xml +5 -0
  43. data/test/xml/errors/error_111.xml +5 -0
  44. data/test/xml/errors/error_112.xml +5 -0
  45. data/test/xml/errors/error_113.xml +5 -0
  46. data/test/xml/errors/error_114.xml +5 -0
  47. data/test/xml/errors/error_115.xml +5 -0
  48. data/test/xml/errors/error_116.xml +5 -0
  49. data/test/xml/errors/error_117.xml +5 -0
  50. data/test/xml/errors/error_118.xml +5 -0
  51. data/test/xml/errors/error_119.xml +5 -0
  52. data/test/xml/errors/error_120.xml +5 -0
  53. data/test/xml/errors/error_121.xml +5 -0
  54. data/test/xml/errors/error_122.xml +5 -0
  55. data/test/xml/errors/error_123.xml +5 -0
  56. data/test/xml/errors/error_124.xml +5 -0
  57. data/test/xml/errors/error_125.xml +5 -0
  58. data/test/xml/errors/error_200.xml +5 -0
  59. data/test/xml/errors/error_201.xml +5 -0
  60. data/test/xml/errors/error_202.xml +5 -0
  61. data/test/xml/errors/error_203.xml +5 -0
  62. data/test/xml/errors/error_204.xml +5 -0
  63. data/test/xml/errors/error_205.xml +5 -0
  64. data/test/xml/errors/error_206.xml +5 -0
  65. data/test/xml/errors/error_207.xml +5 -0
  66. data/test/xml/errors/error_208.xml +5 -0
  67. data/test/xml/errors/error_209.xml +5 -0
  68. data/test/xml/errors/error_210.xml +5 -0
  69. data/test/xml/errors/error_211.xml +5 -0
  70. data/test/xml/errors/error_212.xml +5 -0
  71. data/test/xml/errors/error_213.xml +5 -0
  72. data/test/xml/errors/error_214.xml +5 -0
  73. data/test/xml/errors/error_500.xml +5 -0
  74. data/test/xml/errors/error_501.xml +5 -0
  75. data/test/xml/errors/error_502.xml +5 -0
  76. data/test/xml/errors/error_503.xml +5 -0
  77. data/test/xml/errors/error_504.xml +5 -0
  78. data/test/xml/errors/error_505.xml +5 -0
  79. data/test/xml/errors/error_506.xml +5 -0
  80. data/test/xml/errors/error_507.xml +5 -0
  81. data/test/xml/errors/error_508.xml +5 -0
  82. data/test/xml/errors/error_509.xml +5 -0
  83. data/test/xml/errors/error_510.xml +5 -0
  84. data/test/xml/errors/error_511.xml +5 -0
  85. data/test/xml/errors/error_512.xml +5 -0
  86. data/test/xml/errors/error_513.xml +5 -0
  87. data/test/xml/errors/error_514.xml +5 -0
  88. data/test/xml/errors/error_515.xml +5 -0
  89. data/test/xml/errors/error_516.xml +5 -0
  90. data/test/xml/errors/error_517.xml +5 -0
  91. data/test/xml/errors/error_518.xml +5 -0
  92. data/test/xml/errors/error_519.xml +5 -0
  93. data/test/xml/errors/error_520.xml +5 -0
  94. data/test/xml/errors/error_521.xml +5 -0
  95. data/test/xml/errors/error_522.xml +5 -0
  96. data/test/xml/errors/error_523.xml +5 -0
  97. data/test/xml/errors/error_524.xml +5 -0
  98. data/test/xml/errors/error_525.xml +5 -0
  99. data/test/xml/errors/error_900.xml +5 -0
  100. data/test/xml/errors/error_901.xml +5 -0
  101. data/test/xml/errors/error_902.xml +5 -0
  102. data/test/xml/errors/error_903.xml +5 -0
  103. data/test/xml/errors/error_999.xml +5 -0
  104. data/test/xml/errors.xml +70 -0
  105. data/test/xml/eve_facwarstats.xml +35 -0
  106. data/test/xml/eve_facwartopstats.xml +178 -0
  107. data/test/xml/industryjobs.xml +11 -0
  108. data/test/xml/kills.xml +569 -0
  109. data/test/xml/map_facwarsystems.xml +13 -0
  110. data/test/xml/mapjumps.xml +15 -0
  111. data/test/xml/mapkills.xml +16 -0
  112. data/test/xml/market_transactions.xml +79 -0
  113. data/test/xml/marketorders.xml +43 -0
  114. data/test/xml/member_tracking.xml +22 -0
  115. data/test/xml/nonmember_corpsheet.xml +30 -0
  116. data/test/xml/reftypes.xml +14 -0
  117. data/test/xml/server_status.xml +9 -0
  118. data/test/xml/skill_in_training-amarr-titan.xml +15 -0
  119. data/test/xml/skill_in_training-none.xml +7 -0
  120. data/test/xml/skill_queue.xml +18 -0
  121. data/test/xml/skilltree.xml +41 -0
  122. data/test/xml/sovereignty.xml +29 -0
  123. data/test/xml/starbase_fuel.xml +23 -0
  124. data/test/xml/starbases.xml +12 -0
  125. data/test/xml/wallet_balance.xml +17 -0
  126. data/test/xml/wallet_journal.xml +48 -0
  127. data/tester.rb +17 -0
  128. metadata +187 -0
data/lib/reve.rb ADDED
@@ -0,0 +1,1001 @@
1
+ #--
2
+ # Code copyright Lisa Seelye, 2007-2008. www.crudvision.com
3
+ # This library is licensed under the terms of the MIT license. For full text
4
+ # see the LICENSE file distributed with this package.
5
+ # (Also, send Raquel Smith some ISK if you would like to show appreciation ;-)
6
+ #++
7
+
8
+ begin
9
+ require 'hpricot'
10
+ rescue LoadError
11
+ require 'rubygems'
12
+ require 'hpricot'
13
+ end
14
+ require 'net/http'
15
+ require 'uri'
16
+ require 'cgi'
17
+ require 'fileutils'
18
+
19
+ $:.unshift(File.dirname(__FILE__)) unless $:.include?(File.dirname(__FILE__)) || $:.include?(File.expand_path(File.dirname(__FILE__)))
20
+
21
+ require 'reve/exceptions'
22
+ require 'reve/extensions'
23
+ require 'reve/classes'
24
+
25
+
26
+ module Reve
27
+ # API Class.
28
+ # Basic Usage:
29
+ # api = Reve::API.new('my_UserID', 'my_apiKey')
30
+ # alliances = api.alliances # Returns an array of Reve::Classes::Alliance
31
+ #
32
+ # api.personal_wallet_blanace(:characterid => 892008733) # Returns an array of
33
+ # Reve::Classes::WalletBalance. Note that the CharacterID Number is required
34
+ # here.
35
+ #
36
+ # api.sovereignty :just_hash => true # Returns the hash for this call with no
37
+ # Alliance data with it.
38
+ #
39
+ # As of Revision 22 (28 August 2007) all API calls take a parameter,
40
+ # :just_hash, to just get the hash that represents that particular API call;
41
+ # No data related to the call is returned if :just_hash is present
42
+ #
43
+ # All API methods have the functionality to read XML from an arbitrary location. This could be another webserver, or a XML file on disk.
44
+ # To use this pass the hash option :url => +location+ where +location+ is a String or URI class. See format_url_request documentation for more details.
45
+ class API
46
+
47
+ @@alliances_url = 'http://api.eve-online.com/eve/AllianceList.xml.aspx'
48
+ @@sovereignty_url = 'http://api.eve-online.com/map/Sovereignty.xml.aspx'
49
+ @@reftypes_url = 'http://api.eve-online.com/eve/RefTypes.xml.aspx'
50
+ @@skill_tree_url = 'http://api.eve-online.com/eve/SkillTree.xml.aspx'
51
+ @@member_tracking_url = 'http://api.eve-online.com/corp/MemberTracking.xml.aspx'
52
+ @@corporate_wallet_balance_url = 'http://api.eve-online.com/corp/AccountBalance.xml.aspx'
53
+ @@personal_wallet_balance_url = 'http://api.eve-online.com/char/AccountBalance.xml.aspx'
54
+ @@corporate_wallet_trans_url = 'http://api.eve-online.com/corp/WalletTransactions.xml.aspx'
55
+ @@personal_wallet_trans_url = 'http://api.eve-online.com/char/WalletTransactions.xml.aspx'
56
+ @@corporate_wallet_journal_url = 'http://api.eve-online.com/corp/WalletJournal.xml.aspx'
57
+ @@personal_wallet_journal_url = 'http://api.eve-online.com/char/WalletJournal.xml.aspx'
58
+ @@characters_url = 'http://api.eve-online.com/account/Characters.xml.aspx'
59
+ @@training_skill_url = 'http://api.eve-online.com/char/SkillInTraining.xml.aspx'
60
+ @@skill_queue_url = 'http://api.eve-online.com/char/SkillQueue.xml.aspx'
61
+ @@character_sheet_url = 'http://api.eve-online.com/char/CharacterSheet.xml.aspx'
62
+ @@starbases_url = 'http://api.eve-online.com/corp/StarbaseList.xml.aspx'
63
+ @@starbasedetail_url = 'http://api.eve-online.com/corp/StarbaseDetail.xml.aspx'
64
+ @@conqurable_outposts_url = 'http://api.eve-online.com/eve/ConquerableStationList.xml.aspx'
65
+ @@corporation_sheet_url = 'http://api.eve-online.com/corp/CorporationSheet.xml.aspx'
66
+ @@errors_url = 'http://api.eve-online.com/eve/ErrorList.xml.aspx'
67
+ @@map_jumps_url = 'http://api.eve-online.com/map/Jumps.xml.aspx'
68
+ @@map_kills_url = 'http://api.eve-online.com/map/Kills.xml.aspx'
69
+ @@personal_market_orders_url = 'http://api.eve-online.com/char/MarketOrders.xml.aspx'
70
+ @@corporate_market_orders_url = 'http://api.eve-online.com/corp/MarketOrders.xml.aspx'
71
+ @@personal_industry_jobs_url = 'http://api.eve-online.com/char/IndustryJobs.xml.aspx'
72
+ @@corporate_industry_jobs_url = 'http://api.eve-online.com/corp/IndustryJobs.xml.aspx'
73
+ @@personal_assets_url = 'http://api.eve-online.com/char/AssetList.xml.aspx'
74
+ @@corporate_assets_url = 'http://api.eve-online.com/corp/AssetList.xml.aspx'
75
+ @@personal_kills_url = 'http://api.eve-online.com/char/KillLog.xml.aspx'
76
+ @@corporate_kills_url = 'http://api.eve-online.com/corp/KillLog.xml.aspx'
77
+ @@character_id_url = 'http://api.eve-online.com/eve/CharacterID.xml.aspx' # ?names=CCP%20Garthagk,Raquel%20Smith
78
+ @@character_name_url = 'http://api.eve-online.com/eve/CharacterName.xml.aspx' # ?ids=797400947,892008733
79
+ @@personal_faction_war_stats_url= 'http://api.eve-online.com/char/FacWarStats.xml.aspx'
80
+ @@corporate_faction_war_stats_url= 'http://api.eve-online.com/corp/FacWarStats.xml.aspx'
81
+ @@general_faction_war_stats_url= 'http://api.eve-online.com/eve/FacWarStats.xml.aspx'
82
+ @@top_faction_war_stats_url = 'http://api.eve-online.com/eve/FacWarTopStats.xml.aspx'
83
+ @@faction_war_occupancy_url = 'http://api.eve-online.com/map/FacWarSystems.xml.aspx'
84
+ @@certificate_tree_url = 'http://api.eve-online.com/eve/CertificateTree.xml.aspx'
85
+ @@character_medals_url = 'http://api.eve-online.com/char/Medals.xml.aspx'
86
+ @@corporate_medals_url = 'http://api.eve-online.com/corp/Medals.xml.aspx'
87
+ @@corp_member_medals_url = 'http://api.eve-online.com/corp/MemberMedals.xml.aspx'
88
+ @@server_status_url = 'http://api.eve-online.com/Server/ServerStatus.xml.aspx'
89
+
90
+ cattr_accessor :character_sheet_url, :training_skill_url, :characters_url, :personal_wallet_journal_url,
91
+ :corporate_wallet_journal_url, :personal_wallet_trans_url, :corporate_wallet_trans_url,
92
+ :personal_wallet_balance_url, :corporate_wallet_balance_url, :member_tracking_url,
93
+ :skill_tree_url, :reftypes_url, :sovereignty_url, :alliances_url, :starbases_url,
94
+ :starbasedetail_url, :conqurable_outposts_url, :corporation_sheet_url, :map_jumps_url,
95
+ :map_kills_url, :personal_market_orders_url, :corporate_market_orders_url,
96
+ :personal_industry_jobs_url, :corporate_industry_jobs_url, :personal_assets_url,
97
+ :corporate_assets_url, :personal_kills_url, :corporate_kills_url,
98
+ :personal_faction_war_stats_url, :corporate_faction_war_stats_url,
99
+ :general_faction_war_stats_url, :top_faction_war_stats_url, :faction_war_occupancy_url,
100
+ :certificate_tree_url, :character_medals_url, :corporate_medals_url,
101
+ :corp_member_medals_url, :server_status_url, :skill_queue_url
102
+
103
+
104
+ attr_accessor :key, :userid, :charid
105
+ attr_accessor :http_user_agent, :save_path
106
+ attr_reader :current_time, :cached_until, :last_hash
107
+
108
+ # Create a new API instance.
109
+ # current_time and cached_until are meaningful only for the LAST call made.
110
+ # Expects:
111
+ # * userid ( Integer | String ) - Your API userID
112
+ # * key ( String ) - Your API key (Full key or restricted key)
113
+ # * charid ( Integer | String ) - Default characterID for calls requiring it.
114
+ # NOTE: All values passed to the constructor are typecasted to a String for safety.
115
+ def initialize(userid = "", key = "", charid = "")
116
+ @userid = (userid || "").to_s
117
+ @key = (key || "").to_s
118
+ @charid = (charid || "").to_s
119
+
120
+ @save_path = nil
121
+
122
+ @http_user_agent = "Reve"
123
+ @max_tries = 3
124
+
125
+ @current_time = nil
126
+ @cached_until = nil
127
+ @last_hash = nil
128
+ end
129
+ # Save XML to this directory with the format:
130
+ # :save_path/:userid/:method/:expires_at_in_unixtime.xml
131
+ # eg: ./xml/12345/characters/1200228878.xml
132
+ # or: ./xml/alliances/1200228878.xml
133
+ # If @save_path is nil then XML is not saved.
134
+ def save_path=(p)
135
+ @save_path = p
136
+ end
137
+
138
+ # Get the server status of Tranquility as a Reve::Classes::ServerStatus
139
+ # object.
140
+ # See Also: Reve::Classes::ServerStatus
141
+ def server_status(opts = {})
142
+ args = postfields(opts)
143
+ h = compute_hash( opts.merge(:url => @@server_status_url) )
144
+ return h if h
145
+ xml = process_query(nil,opts[:url] || @@server_status_url,true,opts)
146
+ Reve::Classes::ServerStatus.new(
147
+ xml.search("/eveapi/result/serverOpen/").first.to_s,
148
+ xml.search("/eveapi/result/onlinePlayers/").first.to_s
149
+ )
150
+ end
151
+
152
+ # Convert a list of names to their ids.
153
+ # Expects a Hash as a parameter with these keys:
154
+ # * names ( Array ) - An Array of Names to fetch the IDs of.
155
+ # See Also: character_name, Reve::Classes::Character, character_sheet
156
+ def names_to_ids(opts = {} )
157
+ names = opts[:names] || []
158
+ return [] if names.empty? # No names were passed.
159
+ opts[:names] = names.join(',')
160
+ args = postfields(opts)
161
+ h = compute_hash( opts.merge(:url => @@character_id_url) )
162
+ return h if h
163
+ xml = process_query(nil,opts[:url] || @@character_id_url, true,opts)
164
+ ret = []
165
+ xml.search("//rowset/row").each do |elem|
166
+ ret << Reve::Classes::Character.new(elem)
167
+ end
168
+ ret
169
+ end
170
+
171
+ alias_method :character_id, :names_to_ids
172
+
173
+ # Convert ids to Character names.
174
+ # Expects a Hash as a parameter with these keys:
175
+ # * ids ( Array ) - An Array of Character IDs to fetch the names of.
176
+ # See Also: character_name, Reve::Classes::Character, character_sheet
177
+ def character_name(opts = {})
178
+ ids = opts[:ids] || []
179
+ return [] if ids.empty?
180
+ opts[:ids] = ids.join(',')
181
+ compute_hash( opts.merge(:url => @@character_name_url) ) ||
182
+ process_query(Reve::Classes::Character,opts[:url] || @@character_name_url,false,opts)
183
+ end
184
+
185
+ # Return a list of Alliances and member Corporations from
186
+ # http://api.eve-online.com/eve/AllianceList.xml.aspx
187
+ # Use the corporation_sheet method to get information for each member
188
+ # Corporation
189
+ # See also: Reve::Classes::Alliance, Reve::Classes::Corporation and
190
+ # corporation_sheet
191
+ def alliances(opts = {})
192
+ args = postfields(opts)
193
+ h = compute_hash(args.merge(:url => @@alliances_url))
194
+ return h if h
195
+ xml = process_query(nil,opts[:url] || @@alliances_url,true,args)
196
+ alliances = []
197
+ xml.search("/eveapi/result/rowset[@name='alliances']/row").each do |alliance|
198
+ alliance_obj = Reve::Classes::Alliance.new(alliance)
199
+ alliance.search("rowset[@name='memberCorporations']/row").each do |corporation|
200
+ alliance_obj.member_corporations << Reve::Classes::Corporation.new(corporation)
201
+ end
202
+ alliances << alliance_obj
203
+ end
204
+ alliances
205
+ end
206
+
207
+ # Returns a list of the number of jumps for each system. If there are no
208
+ # jumps for a system it will not be included. See also Reve::Classes::MapJump
209
+ def map_jumps(opts = {})
210
+ compute_hash( opts.merge(:url => @@map_jumps_url) ) ||
211
+ process_query(Reve::Classes::MapJump,opts[:url] || @@map_jumps_url,false)
212
+ end
213
+
214
+ # Returns a list of the number of kills for each system. If there are no
215
+ # kills for a system it will not be included. See also Reve::Classes::MapKill
216
+ def map_kills(opts = {})
217
+ compute_hash( opts.merge(:url => @@map_kills_url) ) ||
218
+ process_query(Reve::Classes::MapKill,opts[:url] || @@map_kills_url,false)
219
+ end
220
+
221
+ # Returns a list of API Errors
222
+ def errors(opts = {})
223
+ compute_hash( opts.merge(:url => @@errors_url) ) ||
224
+ process_query(Reve::Classes::APIError,opts[:url] || @@errors_url,false)
225
+ end
226
+
227
+ # Returns the Sovereignty list from
228
+ # http://api.eve-online.com/map/Sovereignty.xml.aspx
229
+ # See also: Reve::Classes::Sovereignty
230
+ def sovereignty(opts = {})
231
+ compute_hash( opts.merge(:url => @@sovereignty_url) ) ||
232
+ process_query(Reve::Classes::Sovereignty,opts[:url] || @@sovereignty_url,false)
233
+ end
234
+
235
+ # Returns a RefType list (whatever they are) from
236
+ # http://api.eve-online.com/eve/RefTypes.xml.aspx
237
+ # See also: Reve::Classes::RefType
238
+ def ref_types(opts = {})
239
+ compute_hash( opts.merge(:url => @@reftypes_url) ) ||
240
+ process_query(Reve::Classes::RefType,opts[:url] || @@reftypes_url,false)
241
+ end
242
+
243
+ # Returns a list of ConqurableStations and outposts from
244
+ # http://api.eve-online.com/eve/ConquerableStationList.xml.aspx
245
+ # See also: Reve::Classes::ConqurableStation
246
+ def conquerable_stations(opts = {})
247
+ compute_hash( opts.merge(:url => @@conqurable_outposts_url) ) ||
248
+ process_query(Reve::Classes::ConquerableStation, opts[:url] || @@conqurable_outposts_url, false)
249
+ end
250
+
251
+ alias_method :conqurable_stations, :conquerable_stations
252
+
253
+ # Returns a list of Reve::Classes::MarketOrder objects for market orders that are up
254
+ # Pass the characterid of the Character to check for
255
+ def personal_market_orders(opts = {:characterid => nil})
256
+ args = postfields(opts)
257
+ h = compute_hash(args.merge(:url => @@personal_market_orders_url))
258
+ return h if h
259
+ process_query(Reve::Classes::PersonalMarketOrder, opts[:url] || @@personal_market_orders_url, false, args)
260
+ end
261
+
262
+ # Returns a list of Reve::Classes::MarketOrder objects for market orders that are up on behalf of a Corporation
263
+ # Pass the characterid of the Character of whose corporation to check for
264
+ def corporate_market_orders(opts = {:characterid => nil})
265
+ args = postfields(opts)
266
+ h = compute_hash(args.merge(:url => @@corporate_market_orders_url))
267
+ return h if h
268
+ process_query(Reve::Classes::CorporateMarketOrder, opts[:url] || @@corporate_market_orders_url, false, args)
269
+ end
270
+
271
+ # Returns a list of Reve::Classes::PersonalIndustryJob objects.
272
+ def personal_industry_jobs(opts = {:characterid => nil})
273
+ args = postfields(opts)
274
+ h = compute_hash(args.merge(:url => @@personal_industry_jobs_url))
275
+ return h if h
276
+ process_query(Reve::Classes::PersonalIndustryJob, opts[:url] || @@personal_industry_jobs_url,false,args)
277
+ end
278
+
279
+ # Returns a list of Reve::Classes::CorporateIndustryJob objects.
280
+ def corporate_industry_jobs(opts = {:characterid => nil})
281
+ args = postfields(opts)
282
+ h = compute_hash(args.merge(:url => @@corporate_industry_jobs_url))
283
+ return h if h
284
+ process_query(Reve::Classes::CorporateIndustryJob, opts[:url] || @@corporate_industry_jobs_url,false,args)
285
+ end
286
+
287
+ # Returns the SkillTree from
288
+ # http://api.eve-online.com/eve/SkillTree.xml.aspx
289
+ # See also: Reve::Classes::SkillTree
290
+ # NOTE: This doesn't actually return a 'tree' yet.
291
+ def skill_tree(opts = {})
292
+ h = compute_hash(opts.merge(:url => @@skill_tree_url) )
293
+ return h if h
294
+ doc = process_query(nil,opts[:url] || @@skill_tree_url,true)
295
+ skills = []
296
+ (doc/'rowset[@name=skills]/row').each do |skill|
297
+ name = skill['typeName']
298
+ type_id = skill['typeID']
299
+ group_id = skill['groupID']
300
+ rank = (skill/:rank).inner_html
301
+ desc = (skill/:description).inner_html
302
+ required_skills = []
303
+ reqs = (skill/'rowset@name=[requiredskills]/row')
304
+ reqs.each do |required|
305
+ next if required.kind_of? Hpricot::Text # why is this needed? Why is this returned? How can I only get stuff with typeid and skilllevel?
306
+ required_skills << Reve::Classes::SkillRequirement.new(required) if required['typeID'] && required['skillLevel']
307
+ end
308
+ required_attribs = []
309
+ (skill/'requiredAttributes').each do |req|
310
+ pri = doc.at(req.xpath + "/primaryAttribute")
311
+ sec = doc.at(req.xpath + "/secondaryAttribute")
312
+ required_attribs << Reve::Classes::PrimaryAttribute.new(pri.inner_html)
313
+ required_attribs << Reve::Classes::SecondaryAttribute.new(sec.inner_html)
314
+ end
315
+ bonuses = []
316
+ res = (skill/'rowset@name=[skillBonusCollection]/row')
317
+ res.each do |bonus|
318
+ next if bonus.kind_of? Hpricot::Text
319
+ bonuses << Reve::Classes::SkillBonus.new(bonus) if bonus['bonusType'] && bonus['bonusValue']
320
+ end
321
+ skills << Reve::Classes::SkillTree.new(name,type_id,group_id,desc,rank,required_attribs,required_skills,bonuses)
322
+ end
323
+ skills
324
+ end
325
+
326
+ # Does big brother tracking from
327
+ # http://api.eve-online.com/corp/MemberTracking.xml.aspx
328
+ # Expects:
329
+ # * characterid ( Integer | String ) - Look at players in this Character's Corporation
330
+ # See also: Reve::Classes::MemberTracking
331
+ def member_tracking(opts = {:characterid => nil})
332
+ args = postfields(opts)
333
+ h = compute_hash(args.merge(:url => @@member_tracking_url))
334
+ return h if h
335
+ process_query(Reve::Classes::MemberTracking,opts[:url] || @@member_tracking_url,false,args)
336
+ end
337
+
338
+ # Gets one's own personal WalletBalance from
339
+ # http://api.eve-online.com/char/AccountBalance.xml.aspx
340
+ # Expects:
341
+ # * characterid ( Integer | String ) - Look at this player's WalletBalance
342
+ # See also: Reve::Classes::WalletBalance and corporate_wallet_balance
343
+ def personal_wallet_balance(opts = { :characterid => nil })
344
+ args = postfields(opts)
345
+ h = compute_hash(args.merge(:url => @@personal_wallet_balance_url))
346
+ return h if h
347
+ process_query(Reve::Classes::WalletBalance,opts[:url] || @@personal_wallet_balance_url,false,args)
348
+ end
349
+
350
+ # Gets one's corporate WalletBalance from
351
+ # http://api.eve-online.com/corp/AccountBalance.xml.aspx
352
+ # Expects:
353
+ # * characterid ( Integer | String ) - Look at WalletBalance objects from this Character's Corporation
354
+ # See also: Reve::Classes::WalletBalance and personal_wallet_balance
355
+ def corporate_wallet_balance(opts = { :characterd => nil })
356
+ args = postfields(opts)
357
+ h = compute_hash(args.merge(:url => @@corporate_wallet_balance_url))
358
+ return h if h
359
+ process_query(Reve::Classes::WalletBalance,opts[:url] || @@corporate_wallet_balance_url,false,args)
360
+ end
361
+
362
+ # Gets one's own personal WalletTransaction list from
363
+ # http://api.eve-online.com/char/WalletTransactions.xml.aspx
364
+ # Expects:
365
+ # * characterid ( Integer | String ) - Look at this player's WalletTransaction list
366
+ # * beforetransid ( Integer | String ) - Gets a list of WalletTransaction objects from before this Transaction ID.
367
+ # See also: Reve::Classes::WalletTransaction and
368
+ # corporate_wallet_transactions
369
+ def personal_wallet_transactions(opts = { :characterid => nil, :beforetransid => nil })
370
+ args = postfields(opts)
371
+ h = compute_hash(args.merge(:url => @@personal_wallet_trans_url) )
372
+ return h if h
373
+ process_query(Reve::Classes::PersonalWalletTransaction,opts[:url] || @@personal_wallet_trans_url,false,args)
374
+ end
375
+
376
+ # Gets one's corporate WalletTransaction list from
377
+ # http://api.eve-online.com/corp/WalletTransactions.xml.aspx
378
+ # Expects:
379
+ # * account_key ( Integer | String ) - Account key (1000-1006) to look at.
380
+ # * characterid ( Integer | String ) - Look at WalletTransaction objects from this Character's Corporation
381
+ # * beforetransid ( Integer | String ) - Gets a list of WalletTransaction objects from before this Transaction ID.
382
+ # See also: Reve::Classes::WalletTransaction and
383
+ # personal_wallet_transactions
384
+ def corporate_wallet_transactions(opts = {:accountkey => nil, :characterid => nil, :beforerefid => nil})
385
+ args = postfields(opts)
386
+ h = compute_hash(args.merge(:url => @@corporate_wallet_trans_url))
387
+ return h if h
388
+ process_query(Reve::Classes::CorporateWalletTransaction,opts[:url] || @@corporate_wallet_trans_url,false,args)
389
+ end
390
+
391
+ # Gets one's own corporate WalletJournal list from
392
+ # http://api.eve-online.com/corp/WalletJournal.xml.aspx
393
+ # Expects:
394
+ # * account_key ( Integer | String ) - Account key (1000-1006) to look at.
395
+ # * characterid ( Integer | String ) - Look at WalletJournal objects from this Character's Corporation
396
+ # * beforerefid ( Integer | String ) - Gets a list of WalletTransaction objects from before this RefID.
397
+ # See also: Reve::Classes::WalletJournal and personal_wallet_journal
398
+ def corporate_wallet_journal(opts = {:accountkey => nil, :characterid => nil, :beforerefid => nil})
399
+ args = postfields(opts)
400
+ h = compute_hash(args.merge(:url => @@corporate_wallet_journal_url))
401
+ return h if h
402
+ process_query(Reve::Classes::WalletJournal,opts[:url] || @@corporate_wallet_journal_url,false,args)
403
+ end
404
+
405
+ # Gets one's own personal WalletJournal list from
406
+ # http://api.eve-online.com/char/WalletJournal.xml.aspx
407
+ # Expects:
408
+ # * characterid ( Integer | String ) - Look at this player's WalletJournal list
409
+ # * beforerefid ( Integer | String ) - Gets a list of WalletJournal objects from before this RefID.
410
+ # See also: Reve::Classes::WalletJournal and corporate_wallet_journal
411
+ def personal_wallet_journal(opts = { :characterid => nil, :beforerefid => nil} )
412
+ args = postfields(opts)
413
+ h = compute_hash(args.merge(:url => @@personal_wallet_journal_url))
414
+ return h if h
415
+ process_query(Reve::Classes::WalletJournal,opts[:url] || @@personal_wallet_journal_url,false,args)
416
+ end
417
+
418
+ # Get the medals a Corporation can give out. Returns a list of
419
+ # Reve::Classes::CorporateMedal objects.
420
+ # Expects:
421
+ # * characterid ( Integer | String ) - Get this Medals this Character's Corporation can give out
422
+ # See also: Reve::Classes::CorporateMedal, Reve::Classes::Medal
423
+ def corporate_medals(opts = { :characterid => nil })
424
+ args = postfields(opts)
425
+ h = compute_hash(args.merge(:url => @@corporate_medals_url))
426
+ return h if h
427
+ process_query(Reve::Classes::CorporateMedal, opts[:url] || @@corporate_medals_url,false,args)
428
+ end
429
+
430
+
431
+ # Gets the medals the Corporation has given out. Returns a list of
432
+ # Reve::Classes::CorporateMemberMedal
433
+ # Expects:
434
+ # * characterid ( Integer | String ) - Get this Medals this Character's Corporation has given out
435
+ # See also: Reve::Classes::CorporateMedal, Reve::Classes::Medal
436
+ def corporate_member_medals(opts = { :characterid => nil })
437
+ args = postfields(opts)
438
+ h = compute_hash(args.merge(:url => @@corp_member_medals_url))
439
+ return h if h
440
+ process_query(Reve::Classes::CorporateMemberMedal, opts[:url] || @@corp_member_medals_url,false,args)
441
+ end
442
+
443
+
444
+ # Gets the list of Medals awarded to a Character. Returns a
445
+ # Reve::Classes::CharacterMedals object.
446
+ def character_medals(opts = { :characterid => nil })
447
+ args = postfields(opts)
448
+ h = compute_hash(args.merge(:url => @@character_medals_url))
449
+ return h if h
450
+ xml = process_query(nil,opts[:url] || @@character_medals_url,true,args)
451
+ current = xml.search("/eveapi/result/rowset[@name=currentCorporation]/row").inject([]) do |cur,elem|
452
+ cur << Reve::Classes::CharacterMedal.new(elem)
453
+ end
454
+ other = xml.search("/eveapi/result/rowset[@name=otherCorporations]/row").inject([]) do |cur,elem|
455
+ cur << Reve::Classes::CharacterMedal.new(elem)
456
+ end
457
+ Reve::Classes::CharacterMedals.new(current,other)
458
+ end
459
+
460
+ # Gets the Reve::Classes::PersonalFactionWarStat for a character.
461
+ # Expects:
462
+ # * characterid ( Integer | String ) - Get this character's PersonalFactionWarStat.
463
+ # See Also Reve::Classes::PersonalFactionWarStat and corporate_faction_war_stats
464
+ def personal_faction_war_stats(opts = { :characterid => nil })
465
+ args = postfields(opts)
466
+ h = compute_hash(args.merge(:url => @@personal_faction_war_stats_url))
467
+ return h if h
468
+ xml = process_query(nil,opts[:url] || @@personal_faction_war_stats_url,true,args)
469
+ elems = {}
470
+ [ :factionID, :factionName, :enlisted, :currentRank, :highestRank,
471
+ :killsYesterday, :killsLastWeek, :killsTotal, :victoryPointsYesterday,
472
+ :victoryPointsLastWeek, :victoryPointsTotal ].each do |elem|
473
+ elems[elem.to_s] = xml.search("/eveapi/result/" + elem.to_s).first.inner_html
474
+ end
475
+ Reve::Classes::PersonalFactionWarParticpant.new(elems)
476
+ end
477
+
478
+ # Gets the CorporateFactionWarStat for the Corporation a Character belongs to.
479
+ # Expects:
480
+ # * characterid ( Integer | String ) - Get this character's corp's CorporateFactionWarStat.
481
+ # See Also Reve::Classes::CorporateFactionWarStat and personal_faction_war_stats
482
+ def corporate_faction_war_stats(opts = { :characterid => nil })
483
+ args = postfields(opts)
484
+ h = compute_hash(args.merge(:url => @@corporate_faction_war_stats_url))
485
+ return h if h
486
+ xml = process_query(nil,opts[:url] || @@corporate_faction_war_stats_url,true,args)
487
+ elems = {}
488
+ [ :factionID, :factionName, :enlisted, :pilots,
489
+ :killsYesterday, :killsLastWeek, :killsTotal, :victoryPointsYesterday,
490
+ :victoryPointsLastWeek, :victoryPointsTotal ].each do |elem|
491
+ elems[elem.to_s] = xml.search("/eveapi/result/" + elem.to_s).first.inner_html
492
+ end
493
+ Reve::Classes::CorporateFactionWarParticpant.new(elems)
494
+ end
495
+
496
+ # Gets Faction-wide war stats.
497
+ # See also: Reve::Classes::EveFactionWarStat, Reve::Classes::FactionwideFactionWarParticpant,
498
+ # Reve::Classes::FactionWar
499
+ def faction_war_stats(opts = {} )
500
+ args = postfields(opts)
501
+ h = compute_hash(args.merge(:url => @@general_faction_war_stats_url))
502
+ return h if h
503
+ xml = process_query(nil,opts[:url] || @@general_faction_war_stats_url,true,args)
504
+ participants = xml.search("/eveapi/result/rowset[@name='factions']/row").collect do |faction|
505
+ Reve::Classes::FactionwideFactionWarParticpant.new(faction)
506
+ end
507
+ wars = xml.search("/eveapi/result/rowset[@name='factionWars']/row").collect do |faction_war|
508
+ Reve::Classes::FactionWar.new(faction_war)
509
+ end
510
+ totals = {}
511
+ [ :killsYesterday, :killsLastWeek, :killsTotal, :victoryPointsYesterday,
512
+ :victoryPointsLastWeek, :victoryPointsTotal ].each do |elem|
513
+ totals[elem.to_s] = xml.search("/eveapi/result/totals/" + elem.to_s).first.inner_html
514
+ end
515
+ Reve::Classes::EveFactionWarStat.new(totals, wars, participants)
516
+ end
517
+
518
+ # Returns the occupancy data for each System.
519
+ # See also: Reve::Classes::FactionWarSystemStatus
520
+ def faction_war_system_stats(opts = {})
521
+ args = postfields(opts)
522
+ h = compute_hash(args.merge(:url => @@faction_war_occupancy_url))
523
+ return h if h
524
+ process_query(Reve::Classes::FactionWarSystemStatus,opts[:url] || @@faction_war_occupancy_url,false,args)
525
+ end
526
+ alias_method :faction_war_occupancy, :faction_war_system_stats
527
+
528
+ # Gets a list of the top 10 statistics for Characters, Corporations and
529
+ # Factions in factional warfare. Read the notes on Reve::Classes::FactionWarTopStats.
530
+ def faction_war_top_stats(opts = {})
531
+ args = postfields(opts)
532
+ h = compute_hash(args.merge(:url => @@top_faction_war_stats_url))
533
+ return h if h
534
+ xml = process_query(nil,opts[:url] || @@top_faction_war_stats_url,true,args)
535
+ template = { :yesterday_kills => "KillsYesterday", :last_week_kills => "KillsLastWeek", :total_kills => "KillsTotal",
536
+ :yesterday_victory_points => 'VictoryPointsYesterday', :last_week_victory_points => 'VictoryPointsLastWeek', :total_victory_points => 'VictoryPointsTotal' }
537
+ # Inject here to save 60 lines.
538
+ characters = template.inject({}) do |h,(key,val)|
539
+ klass = key.to_s =~ /kills/ ? Reve::Classes::CharacterFactionKills : Reve::Classes::CharacterFactionVictoryPoints
540
+ h[key] = pull_out_top_10_data(xml,klass,'characters',val)
541
+ h
542
+ end
543
+ corporations = template.inject({}) do |h,(key,val)|
544
+ klass = key.to_s =~ /kills/ ? Reve::Classes::CorporationFactionKills : Reve::Classes::CorporationFactionVictoryPoints
545
+ h[key] = pull_out_top_10_data(xml,klass,'corporations',val)
546
+ h
547
+ end
548
+ factions = template.inject({}) do |h,(key,val)|
549
+ klass = key.to_s =~ /kills/ ? Reve::Classes::FactionKills : Reve::Classes::FactionVictoryPoints
550
+ h[key] = pull_out_top_10_data(xml,klass,'factions',val)
551
+ h
552
+ end
553
+ Reve::Classes::FactionWarTopStats.new(characters,corporations,factions)
554
+ end
555
+
556
+ # Get a list of personal assets for the characterid.
557
+ # See the Reve::Classes::Asset and Reve::Classes::AssetContainer classes
558
+ # for attributes available.
559
+ def personal_assets_list(opts = { :characterid => nil })
560
+ args = postfields(opts)
561
+ h = compute_hash(args.merge(:url => @@personal_assets_url))
562
+ return h if h
563
+ xml = process_query(nil,opts[:url] || @@personal_assets_url,true,args)
564
+ assets = []
565
+ xml.search("/eveapi/result/rowset[@name='assets']/row").each do |container|
566
+ asset_container = Reve::Classes::AssetContainer.new(container)
567
+ container.search("rowset[@name='contents']/row").each do |asset|
568
+ asset_container.assets << Reve::Classes::Asset.new(asset)
569
+ end
570
+ assets << asset_container
571
+ end
572
+ assets
573
+ end
574
+
575
+ # Get a list of the Corporate Assets. Pass the characterid of the Corporate member See also assets_list method
576
+ def corporate_assets_list(opts = { :characterid => nil})
577
+ args = postfields(opts)
578
+ h = compute_hash(args.merge(:url => @@corporate_assets_url))
579
+ return h if h
580
+ xml = process_query(nil,opts[:url] || @@corporate_assets_url,true,args)
581
+ assets = []
582
+ xml.search("/eveapi/result/rowset/row").each do |container|
583
+ asset_container = Reve::Classes::AssetContainer.new(container)
584
+ container.search("rowset[@name='contents']/row").each do |asset|
585
+ asset_container.assets << Reve::Classes::Asset.new(asset)
586
+ end
587
+ assets << asset_container
588
+ end
589
+ assets
590
+ end
591
+
592
+ # Returns a Character list for the associated key and userid from
593
+ # http://api.eve-online.com/account/Characters.xml.aspx
594
+ # See also: Reve::Classes::Character
595
+ def characters(opts = {})
596
+ args = postfields(opts)
597
+ h = compute_hash(args.merge(:url => @@characters_url))
598
+ return h if h
599
+ process_query(Reve::Classes::Character,opts[:url] || @@characters_url,false,args)
600
+ end
601
+
602
+ # Gets the SkillInTraining from
603
+ # http://api.eve-online.com/char/SkillInTraining.xml.aspx
604
+ # Expects:
605
+ # * characterid ( Integer | String ) - Get the SkillInTraining for this Character
606
+ # See also: Reve::Classes::SkillInTraining
607
+ def skill_in_training(opts = {:characterid => nil})
608
+ args = postfields(opts)
609
+ ch = compute_hash(args.merge(:url => @@training_skill_url))
610
+ return ch if ch
611
+ h = {}
612
+ xml = process_query(nil,opts[:url] || @@training_skill_url,true,args)
613
+ xml.search("//result").each do |elem|
614
+ for field in [ 'currentTQTime', 'trainingEndTime','trainingStartTime','trainingTypeID','trainingStartSP','trainingDestinationSP','trainingToLevel','skillInTraining' ]
615
+ h[field] = (elem/field.intern).inner_html
616
+ end
617
+ end
618
+ Reve::Classes::SkillInTraining.new(h)
619
+ end
620
+
621
+ # Returns a list of Reve::Classes::QueuedSkill for characterid
622
+ # http://api.eve-online.com/char/SkillQueue.xml.aspx
623
+ # Expects:
624
+ # * characterid ( Integer | String ) - Get the QueuedSkill list for this character
625
+ # See also Reve::Classes::QueuedSkill
626
+ def skill_queue(opts = {:characterid => nil})
627
+ args = postfields(opts)
628
+ ch = compute_hash(args.merge(:url => @@skill_queue_url))
629
+ return ch if ch
630
+ process_query(Reve::Classes::QueuedSkill,opts[:url] || @@skill_queue_url,false,args)
631
+ end
632
+
633
+ # Returns a list of Reve::Classes::Starbase for characterid's Corporation.
634
+ # http://api.eve-online.com/corp/StarbaseList.xml.aspx
635
+ # Expects:
636
+ # * characterid ( Integer | String ) - Get the Starbase list for this character's Corporation
637
+ # See also Reve::Classes::Starbase
638
+ def starbases(opts = { :characterid => nil})
639
+ args = postfields(opts)
640
+ h = compute_hash(args.merge(:url => @@starbases_url))
641
+ return h if h
642
+ process_query(Reve::Classes::Starbase,opts[:url] || @@starbases_url,false,args)
643
+ end
644
+
645
+ # Returns the fuel status for the Starbase whose item id is starbase_id
646
+ # http://api.eve-online.com/corp/StarbaseDetail.xml.aspx
647
+ # Expects:
648
+ # * characterid ( Integer | String ) - Get the Starbase associated wih this character's Corporation
649
+ # * starbase_id ( Integer ) - Get the fuel for this Starbase. This is the Starbase's itemid.
650
+ # See also Reve::Classes::StarbaseFuel
651
+ def starbase_fuel(opts = { :characterid => nil, :starbaseid => nil })
652
+ args = postfields(opts)
653
+ h = compute_hash(args.merge(:url => @@starbasedetail_url))
654
+ return h if h
655
+ ret = process_query(Reve::Classes::StarbaseFuel,opts[:url] || @@starbasedetail_url, false, args)
656
+ ret.each { |r| r.starbase_id = opts[:starbaseid] }
657
+ ret
658
+ end
659
+
660
+
661
+ # Get the last kills for the characterid passed.
662
+ # Expects:
663
+ # * Hash of arguments
664
+ # * * characterid ( Integer ) - The Character whose Kills to retrieve
665
+ # * * beforekillid ( Integer ) - (Optional) - Return the most recent kills before this killid.
666
+ def personal_kills(opts = { :characterid => nil })
667
+ args = postfields(opts)
668
+ h = compute_hash(args.merge(:url => @@personal_kills_url))
669
+ return h if h
670
+ xml = process_query(nil,opts[:url] || @@personal_kills_url,true,args)
671
+ kills = []
672
+ xml.search("/eveapi/result/rowset/row").each do |e|
673
+ victim = Reve::Classes::KillVictim.new(e.search("victim").first) rescue next # cant find victim
674
+ attackers = []
675
+ losses = []
676
+ e.search("rowset[@name='attackers']/row").each do |attacker|
677
+ attackers << Reve::Classes::KillAttacker.new(attacker)
678
+ end
679
+ e.search("rowset[@name='items']/row").each do |lost_item|
680
+ lost = Reve::Classes::KillLoss.new(lost_item)
681
+ lost_item.search("rowset[@name='items']/row").each do |contained|
682
+ lost.contained_losses << Reve::Classes::KillLoss.new(contained)
683
+ end
684
+ losses << lost
685
+ end
686
+ kills << Reve::Classes::Kill.new(e, victim, attackers, losses)
687
+ end
688
+ kills
689
+ end
690
+
691
+ # See the options for personal_kills
692
+ def corporate_kills(opts = { :characterid => nil })
693
+ args = postfields(opts)
694
+ h = compute_hash(args.merge(:url => @@corporate_kills_url))
695
+ return h if h
696
+ xml = process_query(nil,opts[:url] || @@corporate_kills_url,true,args)
697
+ kills = []
698
+ xml.search("/eveapi/result/rowset/row").each do |e|
699
+ victim = Reve::Classes::KillVictim.new(e.search("victim").first) rescue next # cant find victim
700
+ attackers = []
701
+ losses = []
702
+ e.search("rowset[@name='attackers']/row").each do |attacker|
703
+ attackers << Reve::Classes::KillAttacker.new(attacker)
704
+ end
705
+ e.search("rowset[@name='items']/row").each do |lost_item|
706
+ lost = Reve::Classes::KillLoss.new(lost_item)
707
+ lost_item.search("rowset[@name='items']/row").each do |contained|
708
+ lost.contained_losses << Reve::Classes::KillLoss.new(contained)
709
+ end
710
+ losses << lost
711
+ end
712
+ kills << Reve::Classes::Kill.new(e, victim, attackers, losses)
713
+ end
714
+ kills
715
+ end
716
+
717
+ # Gets the CorporationSheet from http://api.eve-online.com/corp/CorporationSheet.xml.aspx
718
+ # Expects:
719
+ # * Hash of arguments:
720
+ # * * characterid ( Integer | String ) - Gets the CorporationSheet for this Character
721
+ # * * corporationid ( Integer ) - If the characterid isn't passed then send the corporation's id
722
+ # (See the alliances method for a list) to get the details of a Corporation that belongs to an Alliance.
723
+ # See also: Reve::Classes::CorporationSheet
724
+ def corporation_sheet(opts = { :characterid => nil })
725
+ args = postfields(opts)
726
+ h = compute_hash(args.merge(:url => @@corporation_sheet_url))
727
+ return h if h
728
+ xml = process_query(nil,opts[:url] || @@corporation_sheet_url,true,args)
729
+
730
+ h = { 'graphicid' => 0, 'shape1' => 0, 'shape2' => 0, 'shape3' => 0, 'color1' => 0, 'color2' => 0, 'color3' => 0, }
731
+ h.keys.each { |k| h[k] = xml.search("//result/logo/" + k + "/").to_s.to_i }
732
+ corporate_logo = Reve::Classes::CorporateLogo.new h
733
+
734
+ wallet_divisions = xml.search("//result/rowset[@name='walletDivisions']/").collect { |k| k if k.kind_of? Hpricot::Elem } - [ nil ]
735
+ divisions = xml.search("//result/rowset[@name='divisions']/").collect { |k| k if k.kind_of? Hpricot::Elem } - [ nil ]
736
+ divisions.collect! { |d| Reve::Classes::CorporateDivision.new(d) }
737
+ wallet_divisions.collect! { |w| Reve::Classes::WalletDivision.new(w) }
738
+
739
+ # Map the XML names to our own names and assign them to the temporary
740
+ # hash +res+ to pass to Reve::Classes::CorporationSheet#new
741
+ res = Hash.new
742
+ { :corporationid => :id, :corporationname => :name, :ticker => :ticker, :ceoid => :ceo_id,
743
+ :ceoname => :ceo_name, :stationid => :station_id, :stationname => :station_name,
744
+ :description => :description, :url => :url, :allianceid => :alliance_id,
745
+ :alliancename => :alliance_name, :taxrate => :tax_rate, :membercount => :member_count,
746
+ :memberlimit => :member_limit, :shares => :shares }.each do |k,v|
747
+ res[v] = xml.search("//result/#{k.to_s}/").first.to_s.strip
748
+ end
749
+
750
+ Reve::Classes::CorporationSheet.new res, divisions, wallet_divisions, corporate_logo
751
+ end
752
+
753
+
754
+ # Returns a Reve::Classes::CertificateTree object that contains the
755
+ # Certificate tree structure. See the rdoc for Reve::Classes::CertificateTree
756
+ # for details.
757
+ # See also: Reve::Classes::CertificateTree
758
+ def certificate_tree(opts = {})
759
+ args = postfields(opts)
760
+ h = compute_hash(args.merge(:url => @@certificate_tree_url))
761
+ return h if h
762
+ xml = process_query(nil,opts[:url] || @@certificate_tree_url,true,args)
763
+
764
+ tree = Reve::Classes::CertificateTree.new
765
+ xml.search("/eveapi/result/rowset[@name=categories]/row").each do |category|
766
+ cat = Reve::Classes::CertificateCategory.new(category)
767
+ category.search("rowset[@name=classes]/row").each do |klass|
768
+ kl = Reve::Classes::CertificateClass.new(klass)
769
+ klass.search("rowset[@name=certificates]/row").each do |certificate|
770
+ cert = Reve::Classes::Certificate.new(certificate)
771
+ certificate.search("rowset[@name=requiredSkills]/row").each do |skill|
772
+ cert.required_skills << Reve::Classes::CertificateRequiredSkill.new(skill)
773
+ end
774
+ certificate.search("rowset[@name=requiredCertificates]/row").each do |requiredcert|
775
+ cert.required_certificates << Reve::Classes::CertificateRequiredCertificate.new(requiredcert)
776
+ end
777
+ kl.certificates << cert
778
+ end
779
+ cat.classes << kl
780
+ end
781
+ tree.categories << cat
782
+ end
783
+ tree
784
+ end
785
+
786
+ # Gets the CharacterSheet from
787
+ # http://api.eve-online.com/char/CharacterSheet.xml.aspx
788
+ # Expects:
789
+ # * characterid ( Fixnum ) - Get the CharacterSheet for this Character
790
+ # See also: Reve::Classes::CharacterSheet
791
+ def character_sheet(opts = { :characterid => nil })
792
+ args = postfields(opts)
793
+ h = compute_hash(args.merge(:url => @@character_sheet_url))
794
+ return h if h
795
+
796
+ xml = process_query(nil,opts[:url] || @@character_sheet_url,true,args)
797
+ cs = Reve::Classes::CharacterSheet.new
798
+
799
+ [ Reve::Classes::IntelligenceEnhancer, Reve::Classes::MemoryEnhancer, Reve::Classes::CharismaEnhancer,
800
+ Reve::Classes::PerceptionEnhancer, Reve::Classes::WillpowerEnhancer
801
+ ].each do |klass|
802
+ xml_attr = klass.to_s.split("::").last.sub("Enhancer",'').downcase + "Bonus"
803
+ i = klass.new(xml.search("/eveapi/result/attributeEnhancers/#{xml_attr}").search("augmentatorName/").first.to_s,
804
+ xml.search("/eveapi/result/attributeEnhancers/#{xml_attr}").search("augmentatorValue/").first.to_s.to_i)
805
+ cs.enhancers << i
806
+ end
807
+
808
+ [ 'characterID', 'name', 'race', 'bloodLine', 'gender','corporationName',
809
+ 'corporationID','balance', 'cloneName', 'cloneSkillPoints'
810
+ ].each do |field|
811
+ cs.send("#{field.downcase}=",xml.search("/eveapi/result/#{field}/").first.to_s)
812
+ end
813
+
814
+ [ 'intelligence','memory','charisma','perception','willpower' ].each do |attrib|
815
+ cs.send("#{attrib}=",xml.search("/eveapi/result/attributes/#{attrib}/").first.to_s.to_i)
816
+ end
817
+ xml.search("rowset[@name=skills]/row").each do |elem|
818
+ cs.skills << Reve::Classes::Skill.new(elem)
819
+ end
820
+
821
+ xml.search("rowset[@name=certificates]/row").each do |elem|
822
+ cs.certificate_ids << elem['certificateID'].to_i
823
+ end
824
+ [ :corporationRolesAtHQ, :corporationRoles, :corporationRolesAtBase, :corporationRolesAtOther ].each do |role_kind|
825
+ xml.search("rowset[@name=#{role_kind.to_s}]/row").each do |elem|
826
+ arry = []
827
+ role = Reve::Classes::CorporateRole.new(elem)
828
+ arry << role
829
+ cs.send("#{role_kind}=".to_sym,arry)
830
+ end
831
+ end
832
+
833
+ xml.search("rowset[@name=corporationTitles]/row").each do |elem|
834
+ cs.corporate_titles << Reve::Classes::CorporateTitle.new(elem)
835
+ end
836
+
837
+ cs
838
+ end
839
+
840
+
841
+ protected
842
+ # Sets up the post fields for Net::HTTP::Get hash for process_query method.
843
+ # See also format_url_request
844
+ # TODO: Consider moving this whole thing into process_query to avoid
845
+ # calling this in every method!
846
+ def postfields(opts = {})
847
+ ret = { "userid" => @userid, "apikey" => @key, "characterid" => @charid }.merge(opts.stringify_keys)
848
+ ret.inject({}) do |n, (k,v)|
849
+ n[k.downcase] = v.to_s if v
850
+ n
851
+ end
852
+ end
853
+
854
+ # Creates a hash for some hash of postfields. For each API method pass
855
+ # :just_hash => to something to return a hash that can be matched to
856
+ # the last_hash instance method created in process_query.
857
+ # This method is called in each API method before process_query and if
858
+ # :just_hash was passed in args then a String will be returned, otherwise
859
+ # nil will be returned
860
+ # TODO: Consider moving this whole thing into process_query before the URI parsing
861
+ def compute_hash(args = {})
862
+ args.stringify_keys!
863
+ return nil unless args.include?('just_hash')
864
+ args.delete('just_hash')
865
+ url = args['url'].kind_of?(URI) ? args['url'].path : args['url']
866
+ args.delete('url')
867
+ spl = url.split '/'
868
+ ret = (spl[-2] + '/' + spl[-1]) + ':'
869
+ args.delete_if { |k,v| (v || "").to_s.length == 0 } # Delete keys if the value is nil
870
+ h = args.stringify_keys
871
+ ret += h.sort.flatten.collect{ |e| e.to_s }.join(':')
872
+ ret.gsub(/:$/,'')
873
+ end
874
+
875
+ # Processes a URL and for simple <rowset><row /><row /></rowset> results
876
+ # create an array of objects of type klass. Or just return the XML if
877
+ # just_xml is set true. args is from postfields
878
+ # This method will call check_exception to see if an Exception came from
879
+ # CCP.
880
+ # Expects:
881
+ # * klass ( Class ) - The class container for parsing. An array of these is returned in default behaviour.
882
+ # * url ( String ) - API URL
883
+ # * just_xml ( Boolean ) - Return only the XML and not attempt to parse //rowset/row. Useful if the XML is not in that form.
884
+ # * args ( Hash ) - Hash of arguments for the request. See postfields method.
885
+ def process_query(klass, url, just_xml = false, opts = {})
886
+
887
+ #args = postfields(opts)
888
+ #h = compute_hash(args.merge(:url => url))
889
+ #return h if h
890
+
891
+ @last_hash = compute_hash(opts.merge({:url => url, :just_hash => true })) # compute hash
892
+
893
+ xml = check_exception(get_xml(url,opts))
894
+ save_xml(xml) if @save_path
895
+
896
+ return xml if just_xml
897
+ return [] if xml.nil? # No XML document returned. We should panic.
898
+
899
+ # Create the array of klass objects to return, assume we start with an empty set from the XML search for rows
900
+ # and build from there.
901
+ xml.search("//rowset/row").inject([]) { |ret,elem| ret << klass.new(elem) }
902
+ end
903
+
904
+ # Turns a hash into ?var=baz&bam=boo
905
+ def format_url_request(opts)
906
+ req = "?"
907
+
908
+ opts.stringify_keys!
909
+ opts.keys.sort.each do |key|
910
+ req += "#{CGI.escape(key.to_s)}=#{CGI.escape(opts[key].to_s)}&" if opts[key]
911
+ end
912
+ req.chop # We are lazy and append a & to each pair even if it's the last one. FIXME: Don't do this.
913
+ end
914
+
915
+
916
+ # Gets the XML from a source.
917
+ # Expects:
918
+ # * source ( String | URI ) - If the +source+ is a String Reve will attempt to load the XML file from the local filesystem by the path specified as +source+. If the +source+ is a URI or is a String starting with http (lowercase) Reve will fetch it from that URI on the web.
919
+ # * opts ( Hash ) - Hash of parameters for the request, such as userid, apikey and such.
920
+ # NOTE: To override the lowercase http -> URI rule make the HTTP part uppercase.
921
+ def get_xml(source,opts)
922
+ xml = ""
923
+
924
+ # Let people still pass Strings starting with http.
925
+ if source =~ /^http/
926
+ source = URI.parse(source)
927
+ end
928
+
929
+ if source.kind_of?(URI)
930
+ opts.merge({ :version => 2, :url => nil }) #the uri bit will now ignored in format_url_request
931
+ req_args = format_url_request(opts)
932
+ req = Net::HTTP::Get.new(source.path + req_args)
933
+ req['User-Agent'] = @http_referer_agent || "Reve"
934
+
935
+ res = nil
936
+ response = nil
937
+ 1.upto(@max_tries) do |try|
938
+ begin
939
+ # ||= to prevent making a new Net::HTTP object, the res = nil above should reset this for the next request.
940
+ # the request needs to be here to rescue exceptions from it.
941
+ res ||= Net::HTTP.new(source.host, source.port).start {|http| http.request(req) }
942
+ case res
943
+ when Net::HTTPSuccess, Net::HTTPRedirection
944
+ response = res.body
945
+ end
946
+ rescue Exception
947
+ sleep 5
948
+ next
949
+ end
950
+ break if response
951
+ end
952
+ raise Reve::Exceptions::ReveNetworkStatusException.new( (res.body rescue "No Response Body!") ) unless response
953
+
954
+ xml = response
955
+
956
+ # here ends test for URI
957
+ elsif source.kind_of?(String)
958
+ xml = File.open(source).read
959
+ else
960
+ raise Reve::Exceptions::ReveNetworkStatusException.new("Don't know how to deal with a #{source.class} XML source. I expect a URI or String")
961
+ end
962
+ xml
963
+ end
964
+
965
+ # Raises the proper exception (if there is one), otherwise it returns the
966
+ # XML response.
967
+ def check_exception(xml)
968
+ x = Hpricot::XML(xml)
969
+ begin
970
+ out = x.search("//error") # If this fails then there are some big problems with Hpricot#search ?
971
+ rescue Exception => e
972
+ $stderr.puts "Fatal error ((#{e.to_s})): Couldn't search the XML document ((#{xml})) for any potential error messages! Is your Hpricot broken?"
973
+ exit 1
974
+ end
975
+ @current_time = (x/:currentTime).inner_html.to_time rescue Time.now.utc # Shouldn't need to rescue this but one never knows
976
+ @cached_until = (x/:cachedUntil).inner_html.to_time rescue nil # Errors aren't always cached
977
+ return x if out.size < 1
978
+ code = out.first['code'].to_i
979
+ str = out.first.inner_html
980
+ Reve::Exceptions.raise_it(code,str)
981
+ end
982
+
983
+ def save_xml(xml)
984
+ path = build_save_filename
985
+ FileUtils.mkdir_p(File.dirname(path))
986
+ File.open(path,'w') { |f| f.print xml.to_original_html }
987
+ end
988
+ def build_save_filename
989
+ method = caller(3).first.match(/\`(.+)'/)[1] # Get the API method that's being called. This is called from save_xml -> process_query -> :real_method
990
+ File.join(@save_path,@userid.to_s,method,( @cached_until || Time.now.utc).to_i.to_s + '.xml')
991
+ end
992
+
993
+ # Returns an array of +klass+
994
+ def pull_out_top_10_data(xml,klass,kind,field)
995
+ xml.search("/eveapi/result/#{kind}/rowset[@name='#{field}']/row").inject([]) do |all,row|
996
+ all << klass.new(row)
997
+ all
998
+ end
999
+ end
1000
+ end
1001
+ end