wowget 0.2.3 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
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