wowget 0.2.3 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/lib/wowget/item.rb CHANGED
@@ -187,52 +187,80 @@ module Wowget
187
187
  28 => 'Relic'
188
188
  }
189
189
 
190
- def initialize(query)
190
+ def self.find(query)
191
+ item_ids = []
192
+ items = []
191
193
 
192
194
  if query.class == Fixnum
193
195
  # easy — e.g. 12345
194
- item_id = query
196
+ item_ids << query
195
197
  elsif query.class == String
196
198
  # try parsing a number, e.g. "12345"
197
199
  item_id = id_from_string(query)
198
200
 
199
- # try searching for this item by name
200
- unless item_id
201
+ unless item_id.nil?
202
+ item_ids << item_id
203
+ else
204
+ # try searching for this item by name
201
205
  item_redirect = Net::HTTP.get_response(URI.parse("http://www.wowhead.com/search?q=#{uri_escape(query)}"))["Location"]
202
206
  if item_redirect
203
- item_id = item_redirect.match(/^\/item=([1-9][0-9]*)$/)[1].to_i
207
+ item_ids << item_redirect.match(/^\/item=([1-9][0-9]*)$/)[1].to_i
208
+ else
209
+ # try retrieving a list of items that match the supplied query
210
+ begin
211
+ # horrendously messy. fuck you very much, wowhead.
212
+ item_json = JSON Nokogiri::XML(open("http://www.wowhead.com/search?q=#{uri_escape(query)}")).inner_text.match(/new Listview\(\{template: 'item'.*, data: (\[.*\])\}\);$/)[1]
213
+ rescue
214
+ no_results = true
215
+ end
216
+
217
+ if no_results || item_json.length == 0
218
+ self.error = {:error => "no items found"}
219
+ else
220
+ item_json.each do |item|
221
+ item_ids << item["id"].to_i
222
+ end
223
+ end
204
224
  end
205
225
  end
226
+ elsif query.class == NilClass
227
+ item_ids << nil
206
228
  end
207
229
 
208
- if item_id
209
- item_xml = Nokogiri::XML(open("http://www.wowhead.com/item=#{item_id}&xml"))
210
- if item_xml.css('wowhead error').length == 1
211
- self.error = {:error => "not found"}
212
- else
213
- item_json = JSON "{#{item_xml.css('wowhead item json').inner_text.strip.to_s}}"
214
- item_equip_json = JSON "{#{item_xml.css('wowhead item jsonEquip').inner_text.strip.to_s}}"
215
- self.id = item_id.to_i
216
- self.name = item_xml.css('wowhead item name').inner_text.strip.to_s
217
- self.level = item_xml.css('wowhead item level').inner_text.strip.to_i
218
- self.quality_id = item_xml.css('wowhead item quality').attribute('id').content.to_i
219
- self.category_id = item_xml.css('wowhead item class').attribute('id').content.to_i
220
- self.subcategory_id = item_xml.css('wowhead item subclass').attribute('id').content.to_i
221
- self.icon_id = item_xml.css('wowhead item icon').attribute('displayId').content.to_i
222
- self.icon_name = item_xml.css('wowhead item icon').inner_text.strip.to_s
223
- self.required_level = item_json['reqlevel']
224
- self.inventory_slot_id = item_xml.css('wowhead item inventorySlot').attribute('id').content.to_i
225
- self.buy_price = item_equip_json['buyprice'].to_i
226
- self.sell_price = item_equip_json['sellprice'].to_i
227
-
228
- if item_xml.css('wowhead item createdBy').length == 1
229
- self.recipe_id = item_xml.css('wowhead item createdBy spell').attribute('id').content.to_i
230
- end
230
+ if item_ids.length > 0
231
+ item_ids.each do |item_id|
232
+ items << Wowget::Item.new(item_id)
231
233
  end
232
- elsif query.class == NilClass
234
+ end
235
+
236
+ items.length == 1 ? items[0] : items
237
+ end
238
+
239
+ def initialize(item_id)
240
+ item_xml = Nokogiri::XML(open("http://www.wowhead.com/item=#{item_id}&xml"))
241
+ if item_id.nil?
233
242
  self.error = {:error => "no item ID supplied"}
243
+ elsif item_xml.css('wowhead error').length == 1
244
+ self.error = {:error => "not found"}
234
245
  else
235
- self.error = {:error => "unsupported initialiser"}
246
+ item_json = JSON "{#{item_xml.css('wowhead item json').inner_text.strip.to_s}}"
247
+ item_equip_json = JSON "{#{item_xml.css('wowhead item jsonEquip').inner_text.strip.to_s}}"
248
+ self.id = item_id.to_i
249
+ self.name = item_xml.css('wowhead item name').inner_text.strip.to_s
250
+ self.level = item_xml.css('wowhead item level').inner_text.strip.to_i
251
+ self.quality_id = item_xml.css('wowhead item quality').attribute('id').content.to_i
252
+ self.category_id = item_xml.css('wowhead item class').attribute('id').content.to_i
253
+ self.subcategory_id = item_xml.css('wowhead item subclass').attribute('id').content.to_i
254
+ self.icon_id = item_xml.css('wowhead item icon').attribute('displayId').content.to_i
255
+ self.icon_name = item_xml.css('wowhead item icon').inner_text.strip.to_s
256
+ self.required_level = item_json['reqlevel']
257
+ self.inventory_slot_id = item_xml.css('wowhead item inventorySlot').attribute('id').content.to_i
258
+ self.buy_price = item_equip_json['buyprice'].to_i
259
+ self.sell_price = item_equip_json['sellprice'].to_i
260
+
261
+ if item_xml.css('wowhead item createdBy').length == 1
262
+ self.recipe_id = item_xml.css('wowhead item createdBy spell').attribute('id').content.to_i
263
+ end
236
264
  end
237
265
  end
238
266
 
@@ -268,11 +296,11 @@ module Wowget
268
296
 
269
297
  private
270
298
 
271
- def id_from_string(string)
299
+ def self.id_from_string(string)
272
300
  string.to_i if string.match /^[1-9][0-9]*$/
273
301
  end
274
302
 
275
- def uri_escape(string)
303
+ def self.uri_escape(string)
276
304
  URI.escape(string, Regexp.new("[^#{URI::PATTERN::UNRESERVED}]"))
277
305
  end
278
306
 
data/lib/wowget/spell.rb CHANGED
@@ -1,15 +1,20 @@
1
1
  require 'open-uri'
2
2
  require 'nokogiri'
3
+ require 'json'
3
4
 
4
5
  module Wowget
5
6
  class Spell
6
7
  attr_accessor :id
7
8
  attr_accessor :name
8
9
  attr_accessor :item_id
10
+ attr_accessor :item_quantity_min
11
+ attr_accessor :item_quantity_max
9
12
  attr_accessor :reagents
10
13
  attr_accessor :profession
11
14
  attr_accessor :profession_id
12
15
  attr_accessor :skill
16
+ attr_accessor :skillup
17
+ attr_accessor :source_id
13
18
  attr_accessor :error
14
19
 
15
20
  def initialize(spell_id)
@@ -26,59 +31,76 @@ module Wowget
26
31
  else
27
32
  self.name = spell_xml.css('div.text h1').inner_text.strip.to_s
28
33
 
29
- # does this spell produce an item? if so, what item_id?
30
- if spell_xml.css('table#spelldetails th#icontab-icon1 + td span a').length == 1
31
- self.item_id = spell_xml.css('table#spelldetails th#icontab-icon1 + td span a').attribute('href').content.match(/\/item=([0-9]+)/)[1].to_i
32
- end
33
-
34
- # profession
35
- unless self.item_id.nil?
36
- prof_markup = spell_xml.xpath("//script[contains(., 'Markup')]")
34
+ # retrieve recipe data
35
+ recipe = spell_xml.inner_text.match(/^new Listview\(\{template: 'spell', id: 'recipes', .*, data: (\[\{.*\}\])\}\);$/)
36
+ unless recipe.nil?
37
+ recipe_json = (JSON recipe[1])[0]
37
38
 
38
- unless prof_markup.empty?
39
- matches = prof_markup.inner_text.match(/\[ul\]\[li\](.+?)\[\/li\]/)[1].match(/Requires (.+?) \(([0-9]+?)\)/)
40
- self.profession = matches[1]
41
- self.profession_id = case self.profession
42
- when "Alchemy" then 1
43
- when "Blacksmithing" then 2
44
- when "Cooking" then 3
45
- when "Enchanting" then 4
46
- when "Engineering" then 5
47
- when "First Aid" then 6
48
- when "Jewelcrafting" then 7
49
- when "Leatherworking" then 8
50
- when "Mining" then 9
51
- when "Tailoring" then 10
52
- when "Yes" then 11
53
- when "No" then 12
54
- when "Fishing" then 13
55
- when "Herbalism" then 14
56
- when "Inscription" then 15
57
- when "Archaeology" then 16
39
+ unless recipe_json["creates"].nil?
40
+ # item produced and quantity
41
+ self.item_id = recipe_json["creates"][0]
42
+ self.item_quantity_min = recipe_json["creates"][1]
43
+ self.item_quantity_max = recipe_json["creates"][2]
44
+
45
+ # profession
46
+ unless recipe_json["skill"].nil?
47
+ profession = wowhead_profession(recipe_json["skill"][0])
48
+ self.profession = profession[:name]
49
+ self.profession_id = profession[:id]
50
+ self.skill = recipe_json["learnedat"]
51
+ self.skillup = recipe_json["nskillup"]
52
+ self.source_id = recipe_json["source"][0]
58
53
  end
59
- self.skill = matches[2].to_i
60
- end
61
- end
62
-
63
- # reagents
64
- if spell_xml.css("h3:contains('Reagents')").length == 1
65
- self.reagents = []
66
- reagents = spell_xml.css("h3:contains('Reagents')+table.iconlist tr td")
67
- reagents.each do |r|
68
- item_id = r.css("span a").attribute('href').content.match(/\/item=([0-9]+)/)[1].to_i
69
- quantity_match = r.content.match(/\(([0-9]+)\)$/)
70
- if quantity_match.nil?
71
- quantity = 1
72
- else
73
- quantity = quantity_match[1].to_i
74
- quantity += 1 if self.profession.nil? # see http://www.wowhead.com/spell=49244#comments:id=448843
75
- end
76
- self.reagents.push({:item => Wowget::Item.new(item_id), :quantity => quantity})
54
+
55
+ # reagents
56
+ self.reagents = []
57
+ recipe_json["reagents"].each do |reagent|
58
+ item_id = reagent[0]
59
+ quantity = self.profession_id.nil? ? reagent[1] + 1 : reagent[1]
60
+ self.reagents.push({:item => Wowget::Item.new(item_id), :quantity => quantity})
61
+ end
77
62
  end
78
63
  end
79
64
 
80
65
  end
81
66
  end
82
67
 
68
+ def source
69
+ case self.source_id
70
+ when 1 then "Crafted"
71
+ when 2 then "Drop"
72
+ when 3 then "PvP"
73
+ when 4 then "Quest"
74
+ when 5 then "Vendor"
75
+ when 6 then "Trainer"
76
+ when 7 then "Discovery"
77
+ when 8 then "Redemption"
78
+ when 9 then "Talent"
79
+ when 10 then "Starter"
80
+ when 11 then "Event"
81
+ when 12 then "Achievement"
82
+ end
83
+ end
84
+
85
+ private
86
+
87
+ def wowhead_profession(id)
88
+ case id
89
+ when 171 then {:name => "Alchemy", :id => 1}
90
+ when 164 then {:name => "Blacksmithing", :id => 2}
91
+ when 333 then {:name => "Enchanting", :id => 4}
92
+ when 202 then {:name => "Engineering", :id => 5}
93
+ when 182 then {:name => "Herbalism", :id => 14}
94
+ when 773 then {:name => "Inscription", :id => 15}
95
+ when 755 then {:name => "Jewelcrafting", :id => 7}
96
+ when 165 then {:name => "Leatherworking", :id => 8}
97
+ when 186 then {:name => "Mining", :id => 9}
98
+ when 197 then {:name => "Tailoring", :id => 10}
99
+ when 794 then {:name => "Archaeology", :id => 16}
100
+ when 185 then {:name => "Cooking", :id => 3}
101
+ when 129 then {:name => "First Aid", :id => 6}
102
+ end
103
+ end
104
+
83
105
  end
84
106
  end
data/lib/wowget.rb CHANGED
@@ -1,2 +1,6 @@
1
1
  require 'wowget/item.rb'
2
- require 'wowget/spell.rb'
2
+ require 'wowget/spell.rb'
3
+
4
+ module Wowget
5
+ VERSION = '0.3.0'
6
+ end
data/spec/item_spec.rb CHANGED
@@ -3,7 +3,7 @@ require_relative "../lib/wowget/item.rb"
3
3
  describe Wowget::Item do
4
4
 
5
5
  describe "With a valid ID" do
6
- item = Wowget::Item.new(4817)
6
+ item = Wowget::Item.find(4817)
7
7
 
8
8
  it "should have an item name" do
9
9
  item.name.should == "Blessed Claymore"
@@ -58,11 +58,11 @@ describe Wowget::Item do
58
58
  end
59
59
 
60
60
  it "should have a vendor sell price" do
61
- item.sell_price.should == 2462
61
+ item.sell_price.should == 2462 and item.sell_price.class.should == Fixnum
62
62
  end
63
63
 
64
64
  it "should have a vendor buy price" do
65
- item.buy_price.should == 12311
65
+ item.buy_price.should == 12311 and item.sell_price.class.should == Fixnum
66
66
  end
67
67
 
68
68
  it "should produce a colorised link" do
@@ -72,14 +72,14 @@ describe Wowget::Item do
72
72
  end
73
73
 
74
74
  describe "With an ID passed as a string" do
75
- item = Wowget::Item.new("4817")
75
+ item = Wowget::Item.find("4817")
76
76
  it "should have an item name" do
77
77
  item.name.should == "Blessed Claymore"
78
78
  end
79
79
  end
80
80
 
81
81
  describe "With a recipe" do
82
- item = Wowget::Item.new(45559)
82
+ item = Wowget::Item.find(45559)
83
83
 
84
84
  it "should have a recipe spell to create this item" do
85
85
  item.recipe_id.should == 63188
@@ -87,25 +87,33 @@ describe Wowget::Item do
87
87
  end
88
88
 
89
89
  describe "With an invalid ID" do
90
- item = Wowget::Item.new(-1000)
91
- it "should return an error" do
90
+ item = Wowget::Item.find(-1000)
91
+ it "should return the error 'not found'" do
92
92
  item.error.should == {:error => "not found"}
93
93
  end
94
94
  end
95
95
 
96
96
  describe "With no item ID supplied" do
97
- item = Wowget::Item.new(nil)
98
- it "should return an error" do
97
+ item = Wowget::Item.find(nil)
98
+ it "should return the error 'no item ID supplied'" do
99
99
  item.error.should == {:error => "no item ID supplied"}
100
100
  end
101
101
  end
102
102
 
103
103
  describe "When the name of an item is supplied" do
104
- item = Wowget::Item.new("Blessed Claymore")
104
+ item = Wowget::Item.find("Blessed Claymore")
105
105
 
106
106
  it "should find the appropriate item" do
107
107
  item.id.should == 4817
108
108
  end
109
109
  end
110
110
 
111
+ describe "When an item name with multiple matches is supplied" do
112
+ it "should return an array of items" do
113
+ items = Wowget::Item.find("Titansteel")
114
+ items.class.should == ::Array
115
+ items.length.should == 15
116
+ end
117
+ end
118
+
111
119
  end
data/spec/spell_spec.rb CHANGED
@@ -36,6 +36,10 @@ describe Wowget::Spell do
36
36
  spell.item_id.should == 45559
37
37
  end
38
38
 
39
+ it "should have a minimum and maximum number of items produced" do
40
+ spell.item_quantity_min.should == 1 and spell.item_quantity_max.should == 1
41
+ end
42
+
39
43
  it "should have a list of reagents" do
40
44
  spell.reagents.length.should == 2 and
41
45
  spell.reagents.all? {|r| r[:item].class == Wowget::Item}.should == true and
@@ -50,6 +54,10 @@ describe Wowget::Spell do
50
54
  spell.profession.should == 'Blacksmithing' and
51
55
  spell.skill.should == 450
52
56
  end
57
+
58
+ it "should have a source" do
59
+ spell.source.should == "Drop"
60
+ end
53
61
  end
54
62
 
55
63
  describe "Without a recipe" do
metadata CHANGED
@@ -2,7 +2,7 @@
2
2
  name: wowget
3
3
  version: !ruby/object:Gem::Version
4
4
  prerelease:
5
- version: 0.2.3
5
+ version: 0.3.0
6
6
  platform: ruby
7
7
  authors:
8
8
  - Ben Darlow
@@ -10,7 +10,7 @@ autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
12
 
13
- date: 2011-07-05 00:00:00 +01:00
13
+ date: 2011-07-12 00:00:00 +01:00
14
14
  default_executable:
15
15
  dependencies:
16
16
  - !ruby/object:Gem::Dependency