reve 0.1.0 → 0.1.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/Rakefile +1 -1
- data/VERSION +1 -1
- data/lib/reve.rb +150 -254
- data/lib/reve/classes.rb +199 -131
- data/test/test_reve.rb +98 -29
- data/test/xml/mail_messages.xml +9 -9
- metadata +162 -47
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 5f791f5b67b627b79b4791339bc3c693b28822e4
|
4
|
+
data.tar.gz: d7f8b73f32992bd46f360df441ed714491b7f112
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 053385d07e36ef01a9b16a467609def1fa136750703f066b36dc20c9b4de83c6cb1b361b9d05fa3234c88f463a3bb049e3b607d07e83f2d7d498f9a182a25794
|
7
|
+
data.tar.gz: d30853a03669ea1f8be250015fccfee75e1722593666a1eb684e1e4e2ede7cc23e2dea2f8ed6613abfb04444079f9f6801cebf974bac7ee5ce7d04c0f4189fd4
|
data/Rakefile
CHANGED
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.1.
|
1
|
+
0.1.3
|
data/lib/reve.rb
CHANGED
@@ -11,7 +11,7 @@ rescue LoadError
|
|
11
11
|
require 'rubygems'
|
12
12
|
require 'hpricot'
|
13
13
|
end
|
14
|
-
require 'net/
|
14
|
+
require 'net/https'
|
15
15
|
require 'uri'
|
16
16
|
require 'cgi'
|
17
17
|
require 'digest'
|
@@ -23,6 +23,7 @@ $:.unshift(File.dirname(__FILE__)) unless $:.include?(File.dirname(__FILE__)) ||
|
|
23
23
|
require 'reve/exceptions'
|
24
24
|
require 'reve/extensions'
|
25
25
|
require 'reve/classes'
|
26
|
+
require 'reve/processing_helpers'
|
26
27
|
|
27
28
|
|
28
29
|
module Reve
|
@@ -45,58 +46,67 @@ module Reve
|
|
45
46
|
# All API methods have the functionality to read XML from an arbitrary location. This could be another webserver, or a XML file on disk.
|
46
47
|
# 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.
|
47
48
|
class API
|
49
|
+
BASE_URL = 'https://api.eveonline.com'
|
50
|
+
|
51
|
+
@@characters_url = BASE_URL + '/account/Characters.xml.aspx'
|
52
|
+
@@account_status_url = BASE_URL + '/account/AccountStatus.xml.aspx'
|
53
|
+
|
54
|
+
@@research_url = BASE_URL + '/char/Research.xml.aspx'
|
55
|
+
@@contracts_url = BASE_URL + '/char/Contracts.xml.aspx'
|
56
|
+
@@personal_notification_url = BASE_URL + '/char/Notifications.xml.aspx'
|
57
|
+
@@personal_mailing_lists_url = BASE_URL + '/char/mailinglists.xml.aspx'
|
58
|
+
@@personal_mail_messages_url = BASE_URL + '/char/MailMessages.xml.aspx'
|
59
|
+
@@personal_mail_message_bodies_url= BASE_URL + '/char/MailBodies.xml.aspx'
|
60
|
+
@@personal_contacts_url = BASE_URL + '/char/ContactList.xml.aspx'
|
61
|
+
@@personal_wallet_balance_url = BASE_URL + '/char/AccountBalance.xml.aspx'
|
62
|
+
@@personal_wallet_trans_url = BASE_URL + '/char/WalletTransactions.xml.aspx'
|
63
|
+
@@personal_wallet_journal_url = BASE_URL + '/char/WalletJournal.xml.aspx'
|
64
|
+
@@training_skill_url = BASE_URL + '/char/SkillInTraining.xml.aspx'
|
65
|
+
@@skill_queue_url = BASE_URL + '/char/SkillQueue.xml.aspx'
|
66
|
+
@@character_sheet_url = BASE_URL + '/char/CharacterSheet.xml.aspx'
|
67
|
+
@@personal_market_orders_url = BASE_URL + '/char/MarketOrders.xml.aspx'
|
68
|
+
@@personal_industry_jobs_url = BASE_URL + '/char/IndustryJobs.xml.aspx'
|
69
|
+
@@personal_assets_url = BASE_URL + '/char/AssetList.xml.aspx'
|
70
|
+
@@personal_kills_url = BASE_URL + '/char/KillLog.xml.aspx'
|
71
|
+
@@personal_faction_war_stats_url = BASE_URL + '/char/FacWarStats.xml.aspx'
|
72
|
+
@@character_medals_url = BASE_URL + '/char/Medals.xml.aspx'
|
73
|
+
@@upcoming_calendar_events_url = BASE_URL + '/char/UpcomingCalendarEvents.xml.aspx'
|
74
|
+
|
75
|
+
@@member_tracking_url = BASE_URL + '/corp/MemberTracking.xml.aspx'
|
76
|
+
@@corporate_wallet_balance_url = BASE_URL + '/corp/AccountBalance.xml.aspx'
|
77
|
+
@@corporate_wallet_trans_url = BASE_URL + '/corp/WalletTransactions.xml.aspx'
|
78
|
+
@@corporate_wallet_journal_url = BASE_URL + '/corp/WalletJournal.xml.aspx'
|
79
|
+
@@starbases_url = BASE_URL + '/corp/StarbaseList.xml.aspx'
|
80
|
+
@@starbasedetail_url = BASE_URL + '/corp/StarbaseDetail.xml.aspx'
|
81
|
+
@@corporation_sheet_url = BASE_URL + '/corp/CorporationSheet.xml.aspx'
|
82
|
+
@@corporation_member_security_url = BASE_URL + '/corp/MemberSecurity.xml.aspx'
|
83
|
+
@@corporate_market_orders_url = BASE_URL + '/corp/MarketOrders.xml.aspx'
|
84
|
+
@@corporate_industry_jobs_url = BASE_URL + '/corp/IndustryJobs.xml.aspx'
|
85
|
+
@@corporate_assets_url = BASE_URL + '/corp/AssetList.xml.aspx'
|
86
|
+
@@corporate_kills_url = BASE_URL + '/corp/KillLog.xml.aspx'
|
87
|
+
@@corporate_faction_war_stats_url = BASE_URL + '/corp/FacWarStats.xml.aspx'
|
88
|
+
@@corporate_medals_url = BASE_URL + '/corp/Medals.xml.aspx'
|
89
|
+
@@corp_member_medals_url = BASE_URL + '/corp/MemberMedals.xml.aspx'
|
90
|
+
@@corporate_contacts_url = BASE_URL + '/corp/ContactList.xml.aspx'
|
48
91
|
|
49
|
-
@@alliances_url
|
50
|
-
@@
|
51
|
-
@@
|
52
|
-
@@
|
53
|
-
@@
|
54
|
-
@@
|
55
|
-
@@
|
56
|
-
@@
|
57
|
-
@@
|
58
|
-
@@
|
59
|
-
@@
|
60
|
-
|
61
|
-
@@
|
62
|
-
@@
|
63
|
-
@@
|
64
|
-
@@
|
65
|
-
|
66
|
-
@@
|
67
|
-
@@corporation_sheet_url = 'http://api.eve-online.com/corp/CorporationSheet.xml.aspx'
|
68
|
-
@@corporation_member_security_url = 'http://api.eve-online.com/corp/MemberSecurity.xml.aspx'
|
69
|
-
@@errors_url = 'http://api.eve-online.com/eve/ErrorList.xml.aspx'
|
70
|
-
@@map_jumps_url = 'http://api.eve-online.com/map/Jumps.xml.aspx'
|
71
|
-
@@map_kills_url = 'http://api.eve-online.com/map/Kills.xml.aspx'
|
72
|
-
@@personal_market_orders_url = 'http://api.eve-online.com/char/MarketOrders.xml.aspx'
|
73
|
-
@@corporate_market_orders_url = 'http://api.eve-online.com/corp/MarketOrders.xml.aspx'
|
74
|
-
@@personal_industry_jobs_url = 'http://api.eve-online.com/char/IndustryJobs.xml.aspx'
|
75
|
-
@@corporate_industry_jobs_url = 'http://api.eve-online.com/corp/IndustryJobs.xml.aspx'
|
76
|
-
@@personal_assets_url = 'http://api.eve-online.com/char/AssetList.xml.aspx'
|
77
|
-
@@corporate_assets_url = 'http://api.eve-online.com/corp/AssetList.xml.aspx'
|
78
|
-
@@personal_kills_url = 'http://api.eve-online.com/char/KillLog.xml.aspx'
|
79
|
-
@@corporate_kills_url = 'http://api.eve-online.com/corp/KillLog.xml.aspx'
|
80
|
-
@@character_id_url = 'http://api.eve-online.com/eve/CharacterID.xml.aspx' # ?names=CCP%20Garthagk
|
81
|
-
@@character_name_url = 'http://api.eve-online.com/eve/CharacterName.xml.aspx' # ?ids=797400947
|
82
|
-
@@personal_faction_war_stats_url= 'http://api.eve-online.com/char/FacWarStats.xml.aspx'
|
83
|
-
@@corporate_faction_war_stats_url= 'http://api.eve-online.com/corp/FacWarStats.xml.aspx'
|
84
|
-
@@general_faction_war_stats_url= 'http://api.eve-online.com/eve/FacWarStats.xml.aspx'
|
85
|
-
@@top_faction_war_stats_url = 'http://api.eve-online.com/eve/FacWarTopStats.xml.aspx'
|
86
|
-
@@faction_war_occupancy_url = 'http://api.eve-online.com/map/FacWarSystems.xml.aspx'
|
87
|
-
@@certificate_tree_url = 'http://api.eve-online.com/eve/CertificateTree.xml.aspx'
|
88
|
-
@@character_medals_url = 'http://api.eve-online.com/char/Medals.xml.aspx'
|
89
|
-
@@corporate_medals_url = 'http://api.eve-online.com/corp/Medals.xml.aspx'
|
90
|
-
@@corp_member_medals_url = 'http://api.eve-online.com/corp/MemberMedals.xml.aspx'
|
91
|
-
@@server_status_url = 'http://api.eve-online.com/Server/ServerStatus.xml.aspx'
|
92
|
-
@@research_url = 'http://api.eve-online.com/char/Research.xml.aspx'
|
93
|
-
@@personal_notification_url = 'http://api.eve-online.com/char/Notifications.xml.aspx'
|
94
|
-
@@personal_mailing_lists_url = 'http://api.eve-online.com/char/mailinglists.xml.aspx'
|
95
|
-
@@personal_mail_messages_url = 'http://api.eve-online.com/char/MailMessages.xml.aspx'
|
96
|
-
@@personal_contacts_url = 'http://api.eve-online.com/char/ContactList.xml.aspx'
|
97
|
-
@@corporate_contacts_url = 'http://api.eve-online.com/corp/ContactList.xml.aspx'
|
98
|
-
@@account_status_url = 'http://api.eve-online.com/account/AccountStatus.xml.aspx'
|
99
|
-
@@character_info_url = 'http://api.eve-online.com/eve/CharacterInfo.xml.aspx'
|
92
|
+
@@alliances_url = BASE_URL + '/eve/AllianceList.xml.aspx'
|
93
|
+
@@reftypes_url = BASE_URL + '/eve/RefTypes.xml.aspx'
|
94
|
+
@@skill_tree_url = BASE_URL + '/eve/SkillTree.xml.aspx'
|
95
|
+
@@conqurable_outposts_url = BASE_URL + '/eve/ConquerableStationList.xml.aspx'
|
96
|
+
@@errors_url = BASE_URL + '/eve/ErrorList.xml.aspx'
|
97
|
+
@@character_id_url = BASE_URL + '/eve/CharacterID.xml.aspx' # ?names=CCP%20Garthagk
|
98
|
+
@@general_faction_war_stats_url = BASE_URL + '/eve/FacWarStats.xml.aspx'
|
99
|
+
@@top_faction_war_stats_url = BASE_URL + '/eve/FacWarTopStats.xml.aspx'
|
100
|
+
@@certificate_tree_url = BASE_URL + '/eve/CertificateTree.xml.aspx'
|
101
|
+
@@character_name_url = BASE_URL + '/eve/CharacterName.xml.aspx' # ?ids=797400947
|
102
|
+
@@character_info_url = BASE_URL + '/eve/CharacterInfo.xml.aspx'
|
103
|
+
|
104
|
+
@@sovereignty_url = BASE_URL + '/map/Sovereignty.xml.aspx'
|
105
|
+
@@map_jumps_url = BASE_URL + '/map/Jumps.xml.aspx'
|
106
|
+
@@map_kills_url = BASE_URL + '/map/Kills.xml.aspx'
|
107
|
+
@@faction_war_occupancy_url = BASE_URL + '/map/FacWarSystems.xml.aspx'
|
108
|
+
|
109
|
+
@@server_status_url = BASE_URL + '/Server/ServerStatus.xml.aspx'
|
100
110
|
|
101
111
|
cattr_accessor :character_sheet_url, :training_skill_url, :characters_url, :personal_wallet_journal_url,
|
102
112
|
:corporate_wallet_journal_url, :personal_wallet_trans_url, :corporate_wallet_trans_url,
|
@@ -111,15 +121,14 @@ module Reve
|
|
111
121
|
:certificate_tree_url, :character_medals_url, :corporate_medals_url,
|
112
122
|
:corp_member_medals_url, :server_status_url, :skill_queue_url, :corporation_member_security_url,
|
113
123
|
:personal_notification_url, :personal_mailing_lists_url, :personal_mail_messages_url,
|
114
|
-
:research_url, :personal_contacts_url, :corporate_contacts_url,
|
115
|
-
:account_status_url, :character_info_url
|
116
|
-
|
124
|
+
:personal_mail_message_bodies_url, :research_url, :personal_contacts_url, :corporate_contacts_url,
|
125
|
+
:account_status_url, :character_info_url, :upcoming_calendar_events_url
|
117
126
|
|
118
127
|
attr_accessor :key, :keyid, :cak, :charid
|
119
128
|
alias :userid :keyid
|
120
129
|
alias :userid= :keyid=
|
121
130
|
attr_accessor :http_user_agent, :save_path, :timeout
|
122
|
-
attr_reader :current_time, :cached_until, :last_hash, :reve_version
|
131
|
+
attr_reader :current_time, :cached_until, :last_hash, :last_xml, :reve_version
|
123
132
|
|
124
133
|
# Create a new API instance.
|
125
134
|
# current_time and cached_until are meaningful only for the LAST call made.
|
@@ -145,6 +154,7 @@ module Reve
|
|
145
154
|
@current_time = nil
|
146
155
|
@cached_until = nil
|
147
156
|
@last_hash = nil
|
157
|
+
@last_xml = nil
|
148
158
|
@reve_version = File.read(File.join(File.dirname(__FILE__),'../','VERSION')).chomp
|
149
159
|
@http_user_agent = "Reve v#{@reve_version}; http://github.com/lisa/reve"
|
150
160
|
end
|
@@ -196,14 +206,24 @@ module Reve
|
|
196
206
|
# Expects a Hash as a parameter with these keys:
|
197
207
|
# * ids ( Array ) - An Array of Character IDs to fetch the names of.
|
198
208
|
# See Also: character_name, Reve::Classes::Character, character_sheet
|
199
|
-
|
209
|
+
|
210
|
+
def ids_to_names(opts = {})
|
200
211
|
ids = opts[:ids] || []
|
201
|
-
return [] if ids.empty?
|
212
|
+
return [] if ids.empty? #No ids where passed
|
202
213
|
opts[:ids] = ids.join(',')
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
214
|
+
args = postfields(opts)
|
215
|
+
h = compute_hash( opts.merge(:url => @@character_name_url) )
|
216
|
+
return h if h
|
217
|
+
xml = process_query(nil,opts[:url] || @@character_name_url, true,opts)
|
218
|
+
ret = []
|
219
|
+
xml.search("//rowset/row").each do |elem|
|
220
|
+
ret << Reve::Classes::Character.new(elem)
|
221
|
+
end
|
222
|
+
ret
|
223
|
+
end
|
224
|
+
|
225
|
+
alias_method :character_name, :ids_to_names
|
226
|
+
|
207
227
|
# Return a list of Alliances and member Corporations from
|
208
228
|
# http://api.eve-online.com/eve/AllianceList.xml.aspx
|
209
229
|
# Use the corporation_sheet method to get information for each member
|
@@ -394,6 +414,20 @@ module Reve
|
|
394
414
|
process_query(Reve::Classes::Research,opts[:url] || @@research_url,false,args)
|
395
415
|
end
|
396
416
|
|
417
|
+
#
|
418
|
+
#gets contracts
|
419
|
+
# http://api.eve-online/char/Contracts.xml.aspx
|
420
|
+
# * characterid ( Integer | String ) - Get stats for this Character
|
421
|
+
# See also: Reve::Classes::Contract
|
422
|
+
|
423
|
+
def contracts(opts = { :characterid => nil })
|
424
|
+
args = postfields(opts)
|
425
|
+
h = compute_hash(args.merge(:url => @@contracts_url))
|
426
|
+
return h if h
|
427
|
+
process_query(Reve::Classes::Contracts,opts[:url] || @@contracts_url,false,args)
|
428
|
+
end
|
429
|
+
|
430
|
+
|
397
431
|
# Gets one's own personal WalletBalance from
|
398
432
|
# http://api.eve-online.com/char/AccountBalance.xml.aspx
|
399
433
|
# Expects:
|
@@ -953,12 +987,63 @@ module Reve
|
|
953
987
|
# * characterid ( Integer | String ) - Get the MailMessages for this Character
|
954
988
|
# See also: Reve::Classes::MailMessage
|
955
989
|
def personal_mail_messages(opts = { :characterid => nil })
|
990
|
+
with_bodies = opts.include?(:with_bodies) ? opts.delete(:with_bodies) : false
|
956
991
|
args = postfields(opts)
|
957
992
|
h = compute_hash(args.merge(:url => @@personal_mail_messages_url))
|
958
993
|
return h if h
|
959
|
-
process_query(Reve::Classes::MailMessage, opts[:url] || @@personal_mail_messages_url,false,args)
|
994
|
+
messages = process_query(Reve::Classes::MailMessage, opts[:url] || @@personal_mail_messages_url,false,args)
|
995
|
+
if with_bodies
|
996
|
+
ids = messages.collect{|m| m.id }
|
997
|
+
bodies = personal_mail_message_bodies(:ids => ids)
|
998
|
+
messages.each do |msg|
|
999
|
+
# For now we are ignoring messages that come back saying
|
1000
|
+
# body is missing. So use fetch to assign body to message
|
1001
|
+
msg.body = bodies.fetch(msg.id.to_s, nil)
|
1002
|
+
end
|
1003
|
+
end
|
1004
|
+
messages
|
1005
|
+
end
|
1006
|
+
|
1007
|
+
# Gets the bodies for mail messages. NB this API call does not
|
1008
|
+
# return objects. It returns a hash with messageID strings as the keys -
|
1009
|
+
# suitable for merging into a Reve::Classes::MailMessage object
|
1010
|
+
#
|
1011
|
+
# Note from the Eve API docs:
|
1012
|
+
# Bodies cannot be accessed if you have not called for their headers recently.
|
1013
|
+
#
|
1014
|
+
# Expects:
|
1015
|
+
# * ids ( List of Integers ) - List of message ids for which we want bodies
|
1016
|
+
# See also: Reve::Classes::MailMessage
|
1017
|
+
def personal_mail_message_bodies(opts = { :ids => [] })
|
1018
|
+
args = postfields(opts)
|
1019
|
+
h = compute_hash(args.merge(:url => @@personal_mail_message_bodies_url))
|
1020
|
+
return h if h
|
1021
|
+
just_xml = true
|
1022
|
+
xml = process_query(Reve::Classes::MailMessage, opts[:url] || @@personal_mail_message_bodies_url,just_xml,args)
|
1023
|
+
results = {}
|
1024
|
+
xml.search("//rowset/row").each do |el|
|
1025
|
+
results[el.attributes['messageID']] = el.inner_text
|
1026
|
+
end
|
1027
|
+
results
|
1028
|
+
end
|
1029
|
+
|
1030
|
+
|
1031
|
+
|
1032
|
+
|
1033
|
+
#Gets upcoming calendar events
|
1034
|
+
#Reve::Classes::UpcomingCalendarEvents
|
1035
|
+
def upcoming_calendar_events(opts = { :characterid => nil })
|
1036
|
+
args = postfields(opts)
|
1037
|
+
h = compute_hash(args.merge(:url => @@upcoming_calendar_events_url))
|
1038
|
+
return h if h
|
1039
|
+
process_query(Reve::Classes::UpcomingCalendarEvents, opts[:url] || @@upcoming_calendar_events_url,false,args)
|
960
1040
|
end
|
961
1041
|
|
1042
|
+
|
1043
|
+
|
1044
|
+
|
1045
|
+
|
1046
|
+
|
962
1047
|
# Gets the status of the selected account. Returns
|
963
1048
|
# Reve::Classes::AccountStatus
|
964
1049
|
def account_status(opts = {})
|
@@ -979,196 +1064,7 @@ module Reve
|
|
979
1064
|
Reve::Classes::CharacterInfo.new(xml.search('//result').first)
|
980
1065
|
end
|
981
1066
|
|
982
|
-
protected
|
983
|
-
|
984
|
-
def recur_through_assets(rows)
|
985
|
-
assets = []
|
986
|
-
rows.each do |container|
|
987
|
-
unless container.empty?
|
988
|
-
asset_container = Reve::Classes::AssetContainer.new(container)
|
989
|
-
asset_container.assets = self.recur_through_assets(container.search("/rowset/row"))
|
990
|
-
assets << asset_container
|
991
|
-
else
|
992
|
-
assets << Reve::Classes::Asset.new(container)
|
993
|
-
end
|
994
|
-
end
|
995
|
-
assets
|
996
|
-
end
|
997
|
-
|
998
|
-
# Sets up the post fields for Net::HTTP::Get hash for process_query method.
|
999
|
-
# See also format_url_request
|
1000
|
-
# TODO: Consider moving this whole thing into process_query to avoid
|
1001
|
-
# calling this in every method!
|
1002
|
-
def postfields(opts = {})
|
1003
|
-
baseargs = { :characterid => @charid }
|
1004
|
-
if @cak
|
1005
|
-
baseargs[:keyid] = @keyid
|
1006
|
-
baseargs[:vcode] = @key
|
1007
|
-
else
|
1008
|
-
baseargs[:userid] = @keyid
|
1009
|
-
baseargs[:apikey] = @key
|
1010
|
-
end
|
1011
|
-
ret = opts.clone
|
1012
|
-
baseargs.each do |k,v|
|
1013
|
-
if ret[k].nil?
|
1014
|
-
ret[k] = v
|
1015
|
-
end
|
1016
|
-
end
|
1017
|
-
ret.inject({}) do |n, (k,v)|
|
1018
|
-
n[k.downcase] = v.to_s if v
|
1019
|
-
n
|
1020
|
-
end
|
1021
|
-
end
|
1022
|
-
|
1023
|
-
# Creates a hash for some hash of postfields. For each API method pass
|
1024
|
-
# :just_hash => to something to return a hash that can be matched to
|
1025
|
-
# the last_hash instance method created in process_query.
|
1026
|
-
# This method is called in each API method before process_query and if
|
1027
|
-
# :just_hash was passed in args then a String will be returned, otherwise
|
1028
|
-
# nil will be returned
|
1029
|
-
# TODO: Consider moving this whole thing into process_query before the URI parsing
|
1030
|
-
def compute_hash(args = {})
|
1031
|
-
args.stringify_keys!
|
1032
|
-
return nil unless args.include?('just_hash')
|
1033
|
-
args.delete('just_hash')
|
1034
|
-
url = args['url'].kind_of?(URI) ? args['url'].path : args['url']
|
1035
|
-
args.delete('url')
|
1036
|
-
spl = url.split '/'
|
1037
|
-
ret = (spl[-2] + '/' + spl[-1]) + ':'
|
1038
|
-
args.delete_if { |k,v| (v || "").to_s.length == 0 } # Delete keys if the value is nil
|
1039
|
-
h = args.stringify_keys
|
1040
|
-
ret += h.sort.flatten.collect{ |e| e.to_s }.join(':')
|
1041
|
-
ret.gsub(/:$/,'')
|
1042
|
-
end
|
1043
|
-
|
1044
|
-
# Processes a URL and for simple <rowset><row /><row /></rowset> results
|
1045
|
-
# create an array of objects of type klass. Or just return the XML if
|
1046
|
-
# just_xml is set true. args is from postfields
|
1047
|
-
# This method will call check_exception to see if an Exception came from
|
1048
|
-
# CCP.
|
1049
|
-
# Expects:
|
1050
|
-
# * klass ( Class ) - The class container for parsing. An array of these is returned in default behaviour.
|
1051
|
-
# * url ( String ) - API URL
|
1052
|
-
# * just_xml ( Boolean ) - Return only the XML and not attempt to parse //rowset/row. Useful if the XML is not in that form.
|
1053
|
-
# * args ( Hash ) - Hash of arguments for the request. See postfields method.
|
1054
|
-
def process_query(klass, url, just_xml = false, opts = {})
|
1055
|
-
|
1056
|
-
#args = postfields(opts)
|
1057
|
-
#h = compute_hash(args.merge(:url => url))
|
1058
|
-
#return h if h
|
1059
|
-
|
1060
|
-
@last_hash = compute_hash(opts.merge({:url => url, :just_hash => true })) # compute hash
|
1061
|
-
|
1062
|
-
|
1063
|
-
xml = check_exception(get_xml(url,opts))
|
1064
|
-
save_xml(xml) if @save_path
|
1065
|
-
|
1066
|
-
return xml if just_xml
|
1067
|
-
return [] if xml.nil? # No XML document returned. We should panic.
|
1068
|
-
|
1069
|
-
# Create the array of klass objects to return, assume we start with an empty set from the XML search for rows
|
1070
|
-
# and build from there.
|
1071
|
-
xml.search("//rowset/row").inject([]) { |ret,elem| ret << klass.new(elem) }
|
1072
|
-
end
|
1073
|
-
|
1074
|
-
# Turns a hash into ?var=baz&bam=boo
|
1075
|
-
def format_url_request(opts)
|
1076
|
-
req = "?"
|
1077
|
-
|
1078
|
-
opts.stringify_keys!
|
1079
|
-
opts.keys.sort.each do |key|
|
1080
|
-
req += "#{CGI.escape(key.to_s)}=#{CGI.escape(opts[key].to_s)}&" if opts[key]
|
1081
|
-
end
|
1082
|
-
req.chop # We are lazy and append a & to each pair even if it's the last one. FIXME: Don't do this.
|
1083
|
-
end
|
1084
|
-
|
1085
|
-
|
1086
|
-
# Gets the XML from a source.
|
1087
|
-
# Expects:
|
1088
|
-
# * 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.
|
1089
|
-
# * opts ( Hash ) - Hash of parameters for the request, such as keyid, vcode and such.
|
1090
|
-
# NOTE: To override the lowercase http -> URI rule make the HTTP part uppercase.
|
1091
|
-
def get_xml(source,opts)
|
1092
|
-
xml = ""
|
1093
|
-
|
1094
|
-
# Let people still pass Strings starting with http.
|
1095
|
-
if source =~ /^http/
|
1096
|
-
source = URI.parse(source)
|
1097
|
-
end
|
1098
|
-
|
1099
|
-
if source.kind_of?(URI)
|
1100
|
-
opts.merge({ :version => 2, :url => nil }) #the uri bit will now ignored in format_url_request
|
1101
|
-
req_args = format_url_request(opts)
|
1102
|
-
req = Net::HTTP::Get.new(source.path + req_args)
|
1103
|
-
req['User-Agent'] = @http_referer_agent || "Reve v#{@reve_version}; http://github.com/lisa/reve"
|
1104
|
-
|
1105
|
-
res = nil
|
1106
|
-
response = nil
|
1107
|
-
1.upto(@max_tries) do |try|
|
1108
|
-
begin
|
1109
|
-
# ||= to prevent making a new Net::HTTP object, the res = nil above should reset this for the next request.
|
1110
|
-
# the request needs to be here to rescue exceptions from it.
|
1111
|
-
http ||= Net::HTTP.new(source.host, source.port)
|
1112
|
-
http.open_timeout = 3
|
1113
|
-
http.read_timeout = @timeout
|
1114
|
-
res = http.start {|http| http.request(req) }
|
1115
|
-
case res
|
1116
|
-
when Net::HTTPSuccess, Net::HTTPRedirection
|
1117
|
-
response = res.body
|
1118
|
-
end
|
1119
|
-
rescue Exception
|
1120
|
-
sleep 5
|
1121
|
-
next
|
1122
|
-
end
|
1123
|
-
break if response
|
1124
|
-
end
|
1125
|
-
raise Reve::Exceptions::ReveNetworkStatusException.new( (res.body rescue "No Response Body!") ) unless response
|
1126
|
-
|
1127
|
-
xml = response
|
1128
|
-
|
1129
|
-
# here ends test for URI
|
1130
|
-
elsif source.kind_of?(String)
|
1131
|
-
xml = File.open(source).read
|
1132
|
-
else
|
1133
|
-
raise Reve::Exceptions::ReveNetworkStatusException.new("Don't know how to deal with a #{source.class} XML source. I expect a URI or String")
|
1134
|
-
end
|
1135
|
-
xml
|
1136
|
-
end
|
1137
|
-
|
1138
|
-
# Raises the proper exception (if there is one), otherwise it returns the
|
1139
|
-
# XML response.
|
1140
|
-
def check_exception(xml)
|
1141
|
-
x = Hpricot::XML(xml)
|
1142
|
-
begin
|
1143
|
-
out = x.search("//error") # If this fails then there are some big problems with Hpricot#search ?
|
1144
|
-
rescue Exception => e
|
1145
|
-
$stderr.puts "Fatal error ((#{e.to_s})): Couldn't search the XML document ((#{xml})) for any potential error messages! Is your Hpricot broken?"
|
1146
|
-
exit 1
|
1147
|
-
end
|
1148
|
-
@current_time = (x/:currentTime).inner_html.to_time rescue Time.now.utc # Shouldn't need to rescue this but one never knows
|
1149
|
-
@cached_until = (x/:cachedUntil).inner_html.to_time rescue nil # Errors aren't always cached
|
1150
|
-
return x if out.size < 1
|
1151
|
-
code = out.first['code'].to_i
|
1152
|
-
str = out.first.inner_html
|
1153
|
-
Reve::Exceptions.raise_it(code,str)
|
1154
|
-
end
|
1155
|
-
|
1156
|
-
def save_xml(xml)
|
1157
|
-
path = build_save_filename
|
1158
|
-
FileUtils.mkdir_p(File.dirname(path))
|
1159
|
-
File.open(path,'w') { |f| f.print xml.to_original_html }
|
1160
|
-
end
|
1161
|
-
def build_save_filename
|
1162
|
-
method = caller(3).first.match(/\`(.+)'/)[1] # Get the API method that's being called. This is called from save_xml -> process_query -> :real_method
|
1163
|
-
File.join(@save_path,@keyid.to_s,method,( @cached_until || Time.now.utc).to_i.to_s + '.xml')
|
1164
|
-
end
|
1165
|
-
|
1166
|
-
# Returns an array of +klass+
|
1167
|
-
def pull_out_top_10_data(xml,klass,kind,field)
|
1168
|
-
xml.search("/eveapi/result/#{kind}/rowset[@name='#{field}']/row").inject([]) do |all,row|
|
1169
|
-
all << klass.new(row)
|
1170
|
-
all
|
1171
|
-
end
|
1172
|
-
end
|
1067
|
+
#protected
|
1068
|
+
include ProcessingHelpers
|
1173
1069
|
end
|
1174
1070
|
end
|