wowr 0.3.0 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,31 +1,17 @@
1
- 0.3.0
2
- * It is now possible to use shorter method calls
3
- api.get_item_tooltip(29242)
4
- api.get_item_tooltip(29242, :caching => false, :lang => 'fr_fr')
1
+ 0.4.0
2
+ * Added Guild Bank functionality
3
+ Guild bank contents and transaction logs are now available.
4
+ Accessing them requires that you login, which returns a cookie string which must be used for all subsequent requests.
5
+
6
+ api = Wowr::API.new(:guild_name => 'my_guild', :realm => 'my_realm')
7
+ cookie = api.login('myuser', 'mypass')
8
+ api.get_guild_bank_contents(cookie)
9
+ api.get_guild_bank_log(cookie)
5
10
 
6
- Old method calls using hashes are still supported
7
- api.get_item_tooltip(:item_id => 29242)
11
+ It's possible to specify the guild and usual extra parameters
12
+ api.get_guild_bank_contents(cookie, "my_other_guild", :realm => 'other_realm)
8
13
 
9
- api.get_character_sheet("Smith")
10
-
11
- The same applies for searches, instead of
12
- api.search_characters(:search => "cake")
13
- it is now possible to write
14
- api.search_characters("cake")
15
-
16
- * A new request get_character has been created which gets the full character details provided by the character_sheet.xml, character_skills.xml and character_reputation.xml. It is still possible to use get_character_sheet, but this is deprecated
17
-
18
- * A new method Wowr::API.get_item has been created, which provides the details from get_item_info and get_item_tooltip returned in one object.
19
-
20
- * The API is now more strict and will throw exceptions if the correct parameters are not provided.
21
-
22
- * For consistency, the get requests now throws exceptions whenever the item or character is not found. Search requests still return empty arrays if nothing is found, but will return an exception if empty search parameters are provided.
23
-
24
- * Skill information is now in a hash my_char.skill_categories['weaponskills'].skills['maces']
25
-
26
- * Reputation information is accessible by hash: my_char.rep['alliance'].factions['darnassus']
27
-
28
- * More informative exception messages.
29
-
30
- * Caching is now on by default.
14
+ At no point are your user details stored and SSH is used for connections to the server.
15
+ Thanks to Hesperus and SheepCow of Rawr for help with this.
31
16
 
17
+ * Buy and sell prices, as well as transactions in the guild bank now use Wowr::Classes::Money
@@ -15,6 +15,7 @@ rescue LoadError
15
15
  require 'hpricot'
16
16
  end
17
17
  require 'net/http'
18
+ require 'net/https'
18
19
  require 'cgi'
19
20
  require 'fileutils'
20
21
 
@@ -28,10 +29,11 @@ require 'wowr/character.rb'
28
29
  require 'wowr/guild.rb'
29
30
  require 'wowr/item.rb'
30
31
  require 'wowr/arena_team.rb'
32
+ require 'wowr/guild_bank.rb'
31
33
 
32
34
  module Wowr
33
35
  class API
34
- VERSION = '0.3.0'
36
+ VERSION = '0.4.0'
35
37
 
36
38
  @@armory_url_base = 'wowarmory.com/'
37
39
 
@@ -49,6 +51,11 @@ module Wowr
49
51
 
50
52
  @@arena_team_url = 'team-info.xml'
51
53
 
54
+ @@guild_bank_contents_url = 'guild-bank-contents.xml'
55
+ @@guild_bank_log_url = 'guild-bank-log.xml'
56
+
57
+ @@login_url = 'login.xml'
58
+
52
59
  @@max_connection_tries = 10
53
60
 
54
61
  @@cache_directory_path = 'cache/'
@@ -192,6 +199,7 @@ module Wowr
192
199
  character_skills = get_xml(@@character_skills_url, options)
193
200
  character_reputation = get_xml(@@character_reputation_url, options)
194
201
 
202
+ # FIXME
195
203
  if true
196
204
  return Wowr::Classes::FullCharacter.new(character_sheet,
197
205
  character_skills,
@@ -417,6 +425,143 @@ module Wowr
417
425
  end
418
426
 
419
427
 
428
+ # Get the current items within the guild bank.
429
+ # Note that the bags and items the user can see is dependent on their privileges.
430
+ # Requires realm.
431
+ # * cookie (String) Cookie data returned by the login function.
432
+ # * guild_name (String) Guild name
433
+ # * options (Hash) Optional hash of arguments identical to those used in the API constructor (realm, debug, cache etc.)
434
+ def get_guild_bank_contents(cookie, guild_name = @guild_name, options = {})
435
+ if (cookie.is_a?(Hash))
436
+ options = cookie
437
+ elsif (guild_name.is_a?(Hash))
438
+ options = guild_name
439
+ options.merge!(:cookie => cookie)
440
+ options.merge!(:guild_name => @guild_name)
441
+ else
442
+ options.merge!(:cookie => cookie)
443
+ options.merge!(:guild_name => guild_name)
444
+ end
445
+ options = merge_defaults(options)
446
+
447
+ if options[:cookie].nil? || options[:cookie] == ""
448
+ raise Wowr::Exceptions::CookieNotSet.new
449
+ elsif options[:guild_name].nil? || options[:guild_name] == ""
450
+ raise Wowr::Exceptions::GuildNameNotSet.new
451
+ elsif options[:realm].nil? || options[:realm] == ""
452
+ raise Wowr::Exceptions::RealmNotSet.new
453
+ end
454
+
455
+ options.merge!(:secure => true)
456
+
457
+ xml = get_xml(@@guild_bank_contents_url, options)
458
+
459
+ if !(xml%'guildBank').children.empty?
460
+ return Wowr::Classes::GuildBankContents.new(xml, self)
461
+ else
462
+ raise Wowr::Exceptions::GuildBankNotFound.new(options[:guild_name])
463
+ end
464
+ end
465
+
466
+
467
+ # Get a particular page of the guild bank transaction log.
468
+ # Each page contains up to 1000 transactions, other pages can be specified using :group in the options hash.
469
+ # Note that data returned is specific to the logged in user's privileges.
470
+ # Requires realm.
471
+ # * cookie (String) Cookie data returned by the login function
472
+ # * guild_name (String) Guild name
473
+ # * options (Hash) Optional hash of arguments identical to those used in the API constructor (realm, debug, cache etc.)
474
+ def get_guild_bank_log(cookie, name = @guild_name, options = {})
475
+ if (cookie.is_a?(Hash))
476
+ options = cookie
477
+ elsif (name.is_a?(Hash))
478
+ options = name
479
+ options.merge!(:cookie => cookie)
480
+ options.merge!(:guild_name => @guild_name)
481
+ else
482
+ options.merge!(:cookie => cookie)
483
+ options.merge!(:guild_name => name)
484
+ end
485
+
486
+ options = merge_defaults(options)
487
+
488
+ if options[:cookie].nil? || options[:cookie] == ""
489
+ raise Wowr::Exceptions::CookieNotSet.new
490
+ elsif options[:guild_name].nil? || options[:guild_name] == ""
491
+ raise Wowr::Exceptions::GuildNameNotSet.new
492
+ elsif options[:realm].nil? || options[:realm] == ""
493
+ raise Wowr::Exceptions::RealmNotSet.new
494
+ end
495
+
496
+ options.merge!(:secure => true)
497
+
498
+ xml = get_xml(@@guild_bank_log_url, options)
499
+
500
+ if !(xml%'guildBank').children.empty?
501
+ return Wowr::Classes::GuildBankLog.new(xml, self)
502
+ else
503
+ raise Wowr::Exceptions::GuildBankNotFound.new(options[:guild_name])
504
+ end
505
+ end
506
+
507
+
508
+ # Logs the user into the armory using their main world of warcraft username and password.
509
+ # Returns a cookie string used for secure requests like get_guild_bank_contents and get_guild_bank_log.
510
+ # Uses SSH to send details to the login page.
511
+ def login(username, password)
512
+ # url = 'https://eu.wowarmory.com/guild-bank-contents.xml?n=Rawr&r=Trollbane'
513
+ url = base_url(@locale, {:secure => true}) + @@login_url
514
+
515
+ req = Net::HTTP::Post.new(url)
516
+ req["user-agent"] = "Mozilla/5.0 Gecko/20070219 Firefox/2.0.0.2" # ensure returns XML
517
+ req["cookie"] = "cookieMenu=all; cookies=true;"
518
+
519
+ uri = URI.parse(url)
520
+
521
+ http = Net::HTTP.new(uri.host, uri.port)
522
+
523
+ # Suppress "warning: peer certificate won't be verified in this SSL session"
524
+ http.verify_mode = OpenSSL::SSL::VERIFY_NONE
525
+ http.use_ssl = true
526
+
527
+ req.set_form_data({'accountName' => username, 'password' => password}, '&')
528
+
529
+
530
+ http.start do
531
+ res = http.request(req)
532
+
533
+ tries = 0
534
+ response = case res
535
+ when Net::HTTPSuccess, Net::HTTPRedirection
536
+ res.body
537
+ else
538
+ tries += 1
539
+ if tries > @@max_connection_tries
540
+ raise Wowr::Exceptions::NetworkTimeout.new('Timed out')
541
+ else
542
+ retry
543
+ end
544
+ end
545
+
546
+ doc = Hpricot.XML(response)
547
+
548
+ # error = 0 nothing provided
549
+ # error = 1 invalid credentials
550
+ # TODO: Detect different kinds of errors
551
+ if (doc%'login')
552
+ raise Wowr::Exceptions::InvalidLoginDetails
553
+ else
554
+ cookie = nil
555
+ res.header['set-cookie'].scan(/JSESSIONID=(.*?);/) {
556
+ cookie = 'JSESSIONID=' + $1 + ';'
557
+ }
558
+ return cookie
559
+ end
560
+ end
561
+ end
562
+
563
+
564
+
420
565
  # Clear the cache, optional directory name.
421
566
  # * cache_path (String) Relative path of the cache directory to be deleted
422
567
  def clear_cache(cache_path = @@cache_directory_path)
@@ -430,12 +575,22 @@ module Wowr
430
575
 
431
576
  # Return the base url for the armory, e.g. http://eu.wowarmory.com/
432
577
  # * locale (String) The locale, defaults to that specified in the API constructor
433
- def base_url(locale = @locale)
434
- if locale == 'us'
435
- 'http://www.' + @@armory_url_base
578
+ def base_url(locale = @locale, options = {})
579
+ str = ""
580
+
581
+ if (options[:secure] == true)
582
+ str += 'https://'
436
583
  else
437
- 'http://' + locale + '.' + @@armory_url_base
584
+ str += 'http://'
438
585
  end
586
+
587
+ if (locale == 'us')
588
+ str += 'www.' + @@armory_url_base
589
+ else
590
+ str += locale + '.' + @@armory_url_base
591
+ end
592
+
593
+ return str
439
594
  end
440
595
 
441
596
 
@@ -471,9 +626,11 @@ module Wowr
471
626
  :guild_name => 'n',
472
627
  :item_id => 'i',
473
628
  :team_size => 'ts',
474
- :team_name => 't'
629
+ :team_name => 't',
630
+ :group => 'group'
475
631
  }
476
632
 
633
+
477
634
  params = []
478
635
  options.each do |key, value|
479
636
  params << "#{reqs[key]}=#{u(value)}" if reqs[key]
@@ -481,7 +638,7 @@ module Wowr
481
638
 
482
639
  query = '?' + params.join('&') if params.size > 0
483
640
 
484
- base = self.base_url(options[:locale])
641
+ base = self.base_url(options[:locale], options)
485
642
  full_query = base + url + query
486
643
 
487
644
  puts full_query if options[:debug]
@@ -505,15 +662,26 @@ module Wowr
505
662
  end
506
663
  end
507
664
 
665
+
508
666
  # Perform an HTTP request and return the contents of the document
509
667
  def http_request(url, options = {})
510
668
  req = Net::HTTP::Get.new(url)
511
669
  req["user-agent"] = "Mozilla/5.0 Gecko/20070219 Firefox/2.0.0.2" # ensure returns XML
512
670
  req["cookie"] = "cookieMenu=all; cookieLangId=" + options[:lang] + "; cookies=true;"
513
671
 
672
+ req["cookie"] += options[:cookie] if options[:cookie]
673
+
514
674
  uri = URI.parse(url)
515
675
 
516
- http = Net::HTTP.new(uri.host, uri.port)
676
+ http = Net::HTTP.new(uri.host, uri.port)
677
+
678
+ if (options[:secure])
679
+ puts "Secure authentication" if options[:debug]
680
+
681
+ http.verify_mode = OpenSSL::SSL::VERIFY_NONE
682
+ http.use_ssl = true
683
+ end
684
+
517
685
 
518
686
  begin
519
687
  http.start do
@@ -39,6 +39,24 @@ module Wowr
39
39
  end
40
40
  end
41
41
 
42
+ class CookieNotSet < StandardError
43
+ def initialize
44
+ super "Cookie required for secure requests not set. Use login(username, password) to retrieve cookie."
45
+ end
46
+ end
47
+
48
+ class GuildBankNotFound < StandardError
49
+ def initialize(guild)
50
+ super "Guild bank for '#{guild}' not found, this could be due to lack of access privileges or failed login attempt."
51
+ end
52
+ end
53
+
54
+ class InvalidLoginDetails < StandardError
55
+ def initialize
56
+ super "It was not possible to login using the username and password provided."
57
+ end
58
+ end
59
+
42
60
  class InvalidArenaTeamSize < StandardError
43
61
  end
44
62
 
@@ -0,0 +1,31 @@
1
+ $:.unshift(File.dirname(__FILE__)) unless $:.include?(File.dirname(__FILE__)) || $:.include?(File.expand_path(File.dirname(__FILE__)))
2
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
3
+
4
+ module Wowr
5
+ module Classes
6
+
7
+ # TODO: Fix default to_s option
8
+ class Money
9
+ attr_reader :total
10
+ alias_method :to_i, :total
11
+ alias_method :to_s, :total
12
+
13
+ def initialize(total)
14
+ @total = total
15
+ end
16
+
17
+ def gold
18
+ return (@total / 10000)
19
+ end
20
+
21
+ def silver
22
+ return (@total % 10000) / 100
23
+ end
24
+
25
+ def bronze
26
+ return @total % 100
27
+ end
28
+ end
29
+
30
+ end
31
+ end
@@ -0,0 +1,181 @@
1
+ $:.unshift(File.dirname(__FILE__)) unless $:.include?(File.dirname(__FILE__)) || $:.include?(File.expand_path(File.dirname(__FILE__)))
2
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
3
+
4
+ require 'item.rb'
5
+ require 'general.rb'
6
+
7
+ module Wowr
8
+ module Classes
9
+
10
+ # def get_login_status
11
+ # name = xml%'loginStatus'[:username]
12
+ # return name == "" ? nil : name
13
+ # end
14
+
15
+ class GuildBank < Guild
16
+ attr_reader :motd, :info, :money, :ranks, :bags
17
+
18
+ def initialize(elem)
19
+ super(elem%'guildKey')
20
+
21
+ @motd = (elem%'guildMessages')[:motd]
22
+ @info = (elem%'guildMessages')[:info]
23
+ @info.gsub("&#10;", "\n")
24
+
25
+ @bags = []
26
+ (elem%'bags'/:bag).each do |bag|
27
+ @bags[bag[:id].to_i] = GuildBankBag.new(bag)
28
+ end
29
+
30
+ @ranks = []
31
+ (elem%'guildRanks'/:rank).each do |rank|
32
+ @ranks[rank[:id].to_i] = rank[:name]
33
+ end
34
+ end
35
+ end
36
+
37
+ # bags now contain references to the items
38
+ # Items can be accessed from items (within Wowr::Classes::GuildBankContents)
39
+ # Or by their individual bags using bag.items
40
+ class GuildBankContents < GuildBank
41
+ attr_reader :items
42
+
43
+ def initialize(elem, api = nil)
44
+ super(elem)
45
+ @money = Money.new((elem%'guildBank')[:money].to_i)
46
+
47
+ @items = []
48
+ (elem%'items'/:item).each do |item|
49
+ @items << GuildBankItem.new(item, bags, api)
50
+ end
51
+ end
52
+ end
53
+
54
+
55
+ # Consists of multiple groups, each with 1000 entries
56
+ class GuildBankLog < GuildBank
57
+ attr_reader :entries
58
+
59
+ def initialize(elem, api = nil)
60
+ super(elem)
61
+
62
+ @entries = []
63
+ (elem%'banklogs'/:banklog).each do |entry|
64
+ @entries << GuildBankLogEntry.new(entry, self, api)
65
+ end
66
+ end
67
+
68
+ end
69
+
70
+
71
+ class GuildBankBag < Item
72
+ attr_reader :viewable
73
+ attr_accessor :items
74
+
75
+ def initialize(elem, api = nil)
76
+ super(elem, api)
77
+ @viewable = (@viewable == "true")
78
+
79
+ @items = []
80
+ end
81
+ end
82
+
83
+
84
+ # Zero to 1 items
85
+ # <banklog dtab="" money="1200000" otab="" player="Quixsilver" rank="0" ts="1212595269000" type="4"/>
86
+ # <banklog dtab="" money="0" otab="0" player="Quixsilver" rank="0" ts="1212527470000" type="2">
87
+ # <item count="1" icon="inv_potion_92" id="12820" name="Winterfall Firewater" qi="1" subtype="" type="consumables"/>
88
+ # </banklog>
89
+ class GuildBankLogEntry
90
+ attr_reader :dtab, :money, :otab, :player, :rank_id, :ts, :type_id, :item
91
+
92
+ @@types = {
93
+ 1 => 'Deposit Item',
94
+ 2 => 'Withdraw Item',
95
+ 3 => 'Move Item',
96
+ 4 => 'Deposit Money',
97
+ 5 => 'Withdraw Money',
98
+ 6 => 'Repair'
99
+ }
100
+
101
+ def initialize(elem, bank = nil, api = nil)
102
+ @bank = bank
103
+
104
+ @dtab = elem[:dtab] == "" ? nil : elem[:dtab].to_i
105
+ @otab = elem[:otab] == "" ? nil : elem[:otab].to_i
106
+ @money = Money.new(elem[:money].to_i)
107
+ @player = elem[:player]
108
+ @rank_id = elem[:rank].to_i
109
+ @ts = elem[:ts].to_i # TODO: Check TS isn't overloading
110
+ @type_id = elem[:type].to_i
111
+
112
+ if (elem%'item')
113
+ @item = GuildBankLogItem.new(elem%'item', api)
114
+ end
115
+ end
116
+
117
+ def type
118
+ return @@types[@type_id]
119
+ end
120
+
121
+ def rank
122
+ @rank_id.nil? ? nil : @bank.ranks[@rank_id]
123
+ end
124
+
125
+ def origin
126
+ @otab.nil? ? nil : @bank.bags[@otab]
127
+ end
128
+
129
+ def destination
130
+ @dtab.nil? ? nil : @bank.bags[@dtab]
131
+ end
132
+
133
+ def time
134
+ return Time.at(@ts / 1000)
135
+ end
136
+ end
137
+
138
+
139
+ # Simple item that appears in Wowr::Classes::GuildBankLog entries
140
+ # <item count="1" icon="inv_potion_92" id="12820" name="Winterfall Firewater" qi="1" subtype="" type="consumables"/>
141
+ class GuildBankLogItem < Item
142
+ attr_reader :count, :qi, :subtype, :type
143
+
144
+ def initialize(elem, api = nil)
145
+ super(elem, api)
146
+ @count = elem[:count].to_i
147
+ @qi = elem[:qi].to_i
148
+ @subtype = elem[:subtype] == "" ? nil : elem[:subtype]
149
+ @type = elem[:type]
150
+ end
151
+ end
152
+
153
+
154
+ # More detailed item used in full Wowr::Classes::GuildBank
155
+ # Very close to Wowr::Classes::EquippedItem
156
+ # <item bag="0" durability="0" icon="racial_dwarf_findtreasure" id="12219" maxDurability="0" name="Unadorned Seal of Ascension" qi="1" quantity="1" randomPropertiesId="0" seed="1827537860" slot="90" subtype="" subtypeLoc="Quest" type="consumables"/>
157
+ class GuildBankItem < Item
158
+ attr_reader :bag_id, :durability, :max_durability, :qi, :quantity,
159
+ :random_properties_id, :seed, :slot, :subtype, :subtype_loc, :type
160
+
161
+ def initialize(elem, bags = nil, api = nil)
162
+ super(elem, api)
163
+
164
+ @bag_id = elem[:bag].to_i
165
+ @qi = elem[:qi].to_i
166
+ @quantity = elem[:quantity].to_i
167
+
168
+ @durability = elem[:durability].to_i
169
+ @max_durability = elem[:maxDurability].to_i
170
+ @random_properties_id = elem[:randomPropertiesId] == 0 ? nil : elem[:randomPropertiesId].to_i
171
+ @seed = elem[:seed].to_i
172
+ @slot = elem[:slot].to_i
173
+ @subtype = elem[:subtype] == "" ? nil : elem[:subtype]
174
+ @subtype_loc = elem[:subtypeLoc] == "" ? nil : elem[:subtypeLoc]
175
+ @type = elem[:type].to_i
176
+
177
+ bags[@bag_id].items << self
178
+ end
179
+ end
180
+ end
181
+ end
@@ -6,6 +6,8 @@
6
6
  $:.unshift(File.dirname(__FILE__)) unless $:.include?(File.dirname(__FILE__)) || $:.include?(File.expand_path(File.dirname(__FILE__)))
7
7
  $LOAD_PATH.unshift(File.dirname(__FILE__))
8
8
 
9
+ require 'general.rb'
10
+
9
11
  module Wowr
10
12
  module Classes
11
13
 
@@ -463,8 +465,8 @@ module Wowr
463
465
  attr_reader :buy_price, :sell_price, :tokens
464
466
 
465
467
  def initialize(elem)
466
- @buy_price = elem[:buyPrice].to_i if elem[:buyPrice]
467
- @sell_price = elem[:sellPrice].to_i if elem[:sellPrice]
468
+ @buy_price = Money.new(elem[:buyPrice].to_i) if elem[:buyPrice]
469
+ @sell_price = Money.new(elem[:sellPrice].to_i) if elem[:sellPrice]
468
470
 
469
471
  if (elem%'token')
470
472
  @tokens = []
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: wowr
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.0
4
+ version: 0.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ben Humphreys
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2008-06-05 00:00:00 +01:00
12
+ date: 2008-06-07 00:00:00 +01:00
13
13
  default_executable:
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
@@ -32,10 +32,12 @@ extra_rdoc_files:
32
32
  - changelog.txt
33
33
  files:
34
34
  - lib/wowr.rb
35
+ - lib/wowr/general.rb
35
36
  - lib/wowr/arena_team.rb
36
37
  - lib/wowr/character.rb
37
38
  - lib/wowr/guild.rb
38
39
  - lib/wowr/item.rb
40
+ - lib/wowr/guild_bank.rb
39
41
  - lib/wowr/exceptions.rb
40
42
  - lib/wowr/extensions.rb
41
43
  - README