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 +60 -32
- data/lib/wowget/spell.rb +68 -46
- data/lib/wowget.rb +5 -1
- data/spec/item_spec.rb +18 -10
- data/spec/spell_spec.rb +8 -0
- metadata +2 -2
data/lib/wowget/item.rb
CHANGED
@@ -187,52 +187,80 @@ module Wowget
|
|
187
187
|
28 => 'Relic'
|
188
188
|
}
|
189
189
|
|
190
|
-
def
|
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
|
-
|
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
|
-
|
200
|
-
|
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
|
-
|
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
|
209
|
-
|
210
|
-
|
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
|
-
|
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
|
-
|
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
|
-
#
|
30
|
-
|
31
|
-
|
32
|
-
|
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
|
39
|
-
|
40
|
-
self.
|
41
|
-
self.
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
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
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
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
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.
|
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.
|
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.
|
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.
|
91
|
-
it "should return
|
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.
|
98
|
-
it "should return
|
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.
|
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.
|
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-
|
13
|
+
date: 2011-07-12 00:00:00 +01:00
|
14
14
|
default_executable:
|
15
15
|
dependencies:
|
16
16
|
- !ruby/object:Gem::Dependency
|