reve 0.1.0 → 0.1.3

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.
@@ -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
@@ -1,6 +1,6 @@
1
1
  require 'rake'
2
2
  require 'rake/testtask'
3
- require 'rake/rdoctask'
3
+ require 'rdoc/task'
4
4
 
5
5
  task :default => :redoc
6
6
 
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.1.0
1
+ 0.1.3
@@ -11,7 +11,7 @@ rescue LoadError
11
11
  require 'rubygems'
12
12
  require 'hpricot'
13
13
  end
14
- require 'net/http'
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 = 'http://api.eve-online.com/eve/AllianceList.xml.aspx'
50
- @@sovereignty_url = 'http://api.eve-online.com/map/Sovereignty.xml.aspx'
51
- @@reftypes_url = 'http://api.eve-online.com/eve/RefTypes.xml.aspx'
52
- @@skill_tree_url = 'http://api.eve-online.com/eve/SkillTree.xml.aspx'
53
- @@member_tracking_url = 'http://api.eve-online.com/corp/MemberTracking.xml.aspx'
54
- @@corporate_wallet_balance_url = 'http://api.eve-online.com/corp/AccountBalance.xml.aspx'
55
- @@personal_wallet_balance_url = 'http://api.eve-online.com/char/AccountBalance.xml.aspx'
56
- @@corporate_wallet_trans_url = 'http://api.eve-online.com/corp/WalletTransactions.xml.aspx'
57
- @@personal_wallet_trans_url = 'http://api.eve-online.com/char/WalletTransactions.xml.aspx'
58
- @@corporate_wallet_journal_url = 'http://api.eve-online.com/corp/WalletJournal.xml.aspx'
59
- @@personal_wallet_journal_url = 'http://api.eve-online.com/char/WalletJournal.xml.aspx'
60
- @@characters_url = 'http://api.eve-online.com/account/Characters.xml.aspx'
61
- @@training_skill_url = 'http://api.eve-online.com/char/SkillInTraining.xml.aspx'
62
- @@skill_queue_url = 'http://api.eve-online.com/char/SkillQueue.xml.aspx'
63
- @@character_sheet_url = 'http://api.eve-online.com/char/CharacterSheet.xml.aspx'
64
- @@starbases_url = 'http://api.eve-online.com/corp/StarbaseList.xml.aspx'
65
- @@starbasedetail_url = 'http://api.eve-online.com/corp/StarbaseDetail.xml.aspx'
66
- @@conqurable_outposts_url = 'http://api.eve-online.com/eve/ConquerableStationList.xml.aspx'
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
- def character_name(opts = {})
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
- compute_hash( opts.merge(:url => @@character_name_url) ) ||
204
- process_query(Reve::Classes::Character,opts[:url] || @@character_name_url,false,opts)
205
- end
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
- # Helper method to handle nested assets
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