cockatrice_feeder 0.0.2 → 0.0.7

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.
Files changed (4) hide show
  1. checksums.yaml +4 -4
  2. data/bin/gobble +0 -1
  3. data/lib/cockatrice_feeder.rb +219 -42
  4. metadata +5 -5
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 24f7024643afdea0db12839734cbed1c53ee4c6c
4
- data.tar.gz: 01bcde57c9f203c9fe6950fc494f69ff83c08e10
3
+ metadata.gz: 8e43bbd10275d5150dd9d3e45c8d5b01df882c65
4
+ data.tar.gz: 18d5eae374e7e1ebe294f46fcdb7fcf3fa0c697f
5
5
  SHA512:
6
- metadata.gz: eae340d56ba6c06d767a2a4f95755c09652fbe50eb8002605dc2fec899cdd6b0d9946f73bbac41ee28dd652063230498b98001577ac89d0305a42ada5bea865c
7
- data.tar.gz: 6b389611a8499be46c93f05731e8bd7499f9745aa9a19fc14c06dd8fa354c0006576e2214044ee1d12af03dac90e967bbf78825d7eb1b2394e669f604d553645
6
+ metadata.gz: 0d7f63f8025a330e9a62b6179cece671f0d7a91b0539fe9fa971ee3ef4e2bfee4dc4b3be0667800ce999662667825abc958d7fc5bc3165f6adf68f337f29b006
7
+ data.tar.gz: d7463259b547c30638eae233ea0174a31d7d79a64b9054ee05a50298248501399a11518f7330fa247d7df07e8c4be9f4812f986cf383af1ec355a73b6224702d
data/bin/gobble CHANGED
@@ -1,4 +1,3 @@
1
1
  #!/usr/bin/env ruby
2
-
3
2
  require 'cockatrice_feeder'
4
3
  CockatriceFeeder.gobble
@@ -1,7 +1,7 @@
1
1
  module CockatriceFeeder
2
2
  require 'httparty'
3
- require 'awesome_print'
4
3
  require 'nokogiri'
4
+ require 'fileutils'
5
5
 
6
6
  @@app_dir = Dir.pwd+"/"
7
7
  @@deck_dir = @@app_dir+"decks/"
@@ -11,6 +11,9 @@ module CockatriceFeeder
11
11
  @@app_dir = (dir + (dir[-1] != "/" ? "/" : ""))
12
12
  @@deck_dir = @@app_dir+"decks/"
13
13
  @@meta_dir = @@app_dir+"meta/"
14
+
15
+ puts "decks will go here: #{@@deck_dir}"
16
+ puts "meta data will go here: #{@@meta_dir}"
14
17
  end
15
18
 
16
19
  def self.app_dir
@@ -19,6 +22,7 @@ module CockatriceFeeder
19
22
 
20
23
  def self.set_deck_dir(dir)
21
24
  @@deck_dir = (dir + (dir[-1] != "/" ? "/" : ""))
25
+ puts "decks will go here: #{@@deck_dir}"
22
26
  end
23
27
 
24
28
  def self.deck_dir
@@ -27,27 +31,30 @@ module CockatriceFeeder
27
31
 
28
32
  def self.set_meta_dir(dir)
29
33
  @@meta_dir = (dir + (dir[-1] != "/" ? "/" : ""))
34
+ puts "meta data will go here: #{@@meta_dir}"
30
35
  end
31
36
 
32
37
  def self.meta_dir
33
38
  @@meta_dir
34
39
  end
35
40
 
36
- def self.setup
41
+ def self.setup(skip_meta = false)
37
42
  unless File.directory?(@@meta_dir)
38
43
  Dir.mkdir(@@meta_dir)
39
44
  puts "Creating a folder at '#{@@meta_dir}' for storing meta data."
40
- puts "Fetching meta data."
41
- update_commanders()
42
- update_banned()
43
- update_commander_tiers()
45
+ unless skip_meta
46
+ puts "Fetching meta data."
47
+ update_commanders()
48
+ update_banned()
49
+ update_commander_tiers()
50
+ end
44
51
  end
45
52
 
46
53
  unless File.directory?(@@deck_dir)
47
54
  Dir.mkdir(@@deck_dir)
48
55
  puts "Creating a folder at '#{@@deck_dir}' for generated decks."
49
56
 
50
- folders = %w(edhrecavg mtgdecks tappedout deckstats)
57
+ folders = %w(edhrecavg mtgdecks tappedout deckstats archidekt)
51
58
 
52
59
  folders.each do |folder|
53
60
  unless File.directory?(@@deck_dir+folder)
@@ -61,7 +68,7 @@ module CockatriceFeeder
61
68
  end
62
69
 
63
70
  def self.update_commanders
64
- puts "Downloading a list of all commanderse from EDHREC."
71
+ puts "Downloading a list of all commanders from EDHREC."
65
72
  commander_cids = %w(
66
73
  w g r u b
67
74
  wu ub br rg gw wb ur bg rw gu
@@ -139,18 +146,38 @@ module CockatriceFeeder
139
146
  end
140
147
 
141
148
  def self.commanders
149
+ unless File.exist?(@@meta_dir+"commanders.json")
150
+ update_commanders()
151
+ end
142
152
  JSON.parse(File.read(@@meta_dir+"commanders.json"))
143
153
  end
144
154
 
145
155
  def self.banned
156
+ unless File.exist?(@@meta_dir+"banned.json")
157
+ update_banned()
158
+ end
146
159
  JSON.parse(File.read(@@meta_dir+"banned.json"))
147
160
  end
148
161
  # names = banned.map{|c| c["name"]}.uniq.sort
149
162
 
150
- def self.tiers
163
+ def self.commander_tiers
164
+ unless File.exist?(@@meta_dir+"tiers.json")
165
+ update_commander_tiers()
166
+ end
151
167
  JSON.parse(File.read(@@meta_dir+"tiers.json"))
152
168
  end
153
169
 
170
+ def self.deck_obj(link = "", name = "", commanders = [], date = nil, price = nil)
171
+ {
172
+ link: link,
173
+ name: name,
174
+ commanders: commanders,
175
+ date: date,
176
+ price: price,
177
+ cardlist: []
178
+ }
179
+ end
180
+
154
181
  def self.output_cod(deck, subfolder)
155
182
  comments = [
156
183
  deck[:name],
@@ -165,7 +192,7 @@ module CockatriceFeeder
165
192
  deck[:name],
166
193
  deck[:price],
167
194
  subfolder
168
- ].compact.reject(&:empty?).uniq.join('_')
195
+ ].compact.reject(&:empty?).uniq.join('_').gsub("/","")
169
196
 
170
197
  builder = Nokogiri::XML::Builder.new do |xml|
171
198
  xml.cockatrice_deck(:version => "1"){
@@ -210,14 +237,7 @@ module CockatriceFeeder
210
237
  doc.css(".deck-wide-header a").each do |a|
211
238
  link = a.attribute("href").value
212
239
  if link.include?("/mtg-decks/")
213
- decks << {
214
- name: link.split("/").last,
215
- commanders: [],
216
- link: "https://tappedout.net"+link,
217
- date: nil,
218
- price: nil,
219
- cardlist: []
220
- }
240
+ decks << deck_obj("https://tappedout.net"+link, link.split("/").last)
221
241
  end
222
242
  end
223
243
  end
@@ -262,14 +282,7 @@ module CockatriceFeeder
262
282
 
263
283
  def self.edhrecavg_decklist
264
284
  commanders.map{|c| c["link"]}.map do |c|
265
- {
266
- name: c,
267
- commanders: [c],
268
- link: "https://edhrec-json.s3.amazonaws.com/en/decks/#{c}.json",
269
- price: nil,
270
- date: nil,
271
- cardlist: []
272
- }
285
+ deck_obj("https://edhrec-json.s3.amazonaws.com/en/decks/#{c}.json", c, [c])
273
286
  end
274
287
  end
275
288
 
@@ -280,12 +293,142 @@ module CockatriceFeeder
280
293
  output_cod(deck,"edhrecavg")
281
294
  end
282
295
 
283
- def self.deckstats_decklist
284
296
 
297
+ #order ["views,desc", "price,desc", "likes,desc", "updated,desc"]
298
+ #commander should be a name attribute from the commanders array of objects
299
+ def self.deckstats_decklist(commander = "", pages = (1..1), order_by = "likes,desc", price_min = "", price_max = "")
300
+ decklist = []
301
+ pages.each do |page|
302
+ url = [
303
+ "https://deckstats.net/decks/search/?lng=en",
304
+ "&search_title=",
305
+ "&search_format=10",
306
+ "&search_season=0",
307
+ "&search_cards_commander%5B%5D=#{URI.encode_www_form_component(commander)}",
308
+ "&search_cards_commander%5B%5D=",
309
+ "&search_price_min=#{price_min}",
310
+ "&search_price_max=#{price_max}",
311
+ "&search_colors%5B%5D=",
312
+ "&search_number_cards_main=100",
313
+ "&search_number_cards_sideboard=",
314
+ "&search_cards%5B%5D=",
315
+ "&search_tags=",
316
+ "&search_order=#{URI.encode_www_form_component(order_by)}",
317
+ "&utf8=%E2%9C%94",
318
+ "&page=#{page}"
319
+ ].join("")
320
+
321
+ doc = Nokogiri::HTML(HTTParty.get(url).body)
322
+
323
+ doc.css(".deck_row").each do |dr|
324
+ link = dr.css("td")[1].css("a").first.attribute("href").value
325
+ decklist << deck_obj(link,link.split("/")[-2],[commander].reject(&:empty?))
326
+ end
327
+ end
328
+
329
+ decklist
330
+ end
331
+
332
+ def self.deckstats_deck(deck)
333
+ docstring = HTTParty.get(deck[:link]).body
334
+
335
+ doc = Nokogiri::HTML(docstring)
336
+
337
+ legal = (doc.css(".fa-exclamation-triangle").count == 0)
338
+
339
+ if legal
340
+ deck_data = JSON.parse(docstring.split("init_deck_data(").last.split(");deck_display();").first)
341
+ deck[:date] = DateTime.strptime(deck_data["updated"].to_s,'%s')
342
+ unless deck_data["highlight_cards"].nil?
343
+ deck[:commanders] = deck_data["highlight_cards"]
344
+ end
345
+ deck[:cardlist] = deck_data["sections"].map do |sec|
346
+ sec["cards"].map{|c| "#{c["amount"]} #{c["name"]}"}
347
+ end.flatten
348
+
349
+ deck[:price] = (
350
+ !doc.css(".deck_overview_price").first.nil? ?
351
+ doc.css(".deck_overview_price").first.content.gsub("$","").strip.split(".").first
352
+ : nil
353
+ )
354
+
355
+ output_cod(deck,'deckstats')
356
+ end
285
357
  end
286
358
 
287
- def self.deckstats_deck
359
+ #colors = "White,Blue,Black,Red,Green,Colorless"
360
+ #orderBy = "-updatedAt", "-createdAt", "-points", "-viewCount"
361
+ def self.archidekt_decklist(
362
+ andcolors = nil, colors = nil, commander = nil, owner = nil, formats = 3, orderBy = "-createdAt", size: 100, pageSize: 50
363
+ )
364
+
365
+ url = [
366
+ "https://www.archidekt.com/api/decks/cards/?",
367
+ [
368
+ (andcolors.nil? ? nil : "true"),
369
+ (colors.nil? ? nil : "colors=#{URI.encode_www_form_component(colors)}"),
370
+ (commander.nil? ? nil : "commanders=#{URI.encode_www_form_component(commander)}"),
371
+ (owner.nil? ? nil : "owner=#{URI.encode_www_form_component(owner)}"),
372
+ "formats=#{formats}",
373
+ "orderBy=#{orderBy}",
374
+ "size=#{size}",
375
+ "pageSize=#{pageSize}"
376
+ ].compact.join("&")
377
+ ].join("")
378
+
379
+ puts url
380
+
381
+ decklist = []
382
+ data = JSON.parse(HTTParty.get(url).body)
383
+
384
+ data["results"].each do |r|
385
+ decklist << deck_obj("https://www.archidekt.com/decks/#{r["id"]}", r["name"])
386
+ end
288
387
 
388
+ decklist
389
+ end
390
+
391
+ # deck = CockatriceFeeder.deck_obj("https://www.archidekt.com/decks/992684#Rocking_that_equipment_Bro")
392
+ # CockatriceFeeder.archidekt_deck(deck)
393
+ def self.archidekt_deck(deck)
394
+ deck_id = deck[:link].split("/").last.split("#").first
395
+
396
+ api_url = "https://www.archidekt.com/api/decks/#{deck_id}/"
397
+
398
+ deck_data = JSON.parse(HTTParty.get(api_url).body)
399
+
400
+ included_categories = deck_data["categories"].select{|c| c["includedInDeck"]}.map{|c| c["name"] }
401
+ commander_categories = deck_data["categories"].select{|c| c["isPremier"]}.map{|c| c["name"] }
402
+ cardlist = []
403
+ tcg_price = 0.0
404
+ ck_price = 0.0
405
+ deck_data["cards"].each do |card|
406
+ cname = card["card"]["oracleCard"]["name"]
407
+
408
+ if card["card"]["oracleCard"]["layout"] != "split"
409
+ cname = cname.split(" // ").first
410
+ end
411
+
412
+ if (included_categories & card["categories"]).length > 0
413
+ cardlist << "#{card["quantity"]} #{cname}"
414
+
415
+ tcg_price += (card["card"]["prices"]["tcg"] * card["quantity"].to_f)
416
+ ck_price += (card["card"]["prices"]["ck"] * card["quantity"].to_f)
417
+ end
418
+
419
+ if (commander_categories & card["categories"]).length > 0
420
+ deck[:commanders] << cname
421
+ end
422
+ end
423
+
424
+ deck[:cardlist] = cardlist
425
+ deck[:price] = tcg_price.to_i.to_s
426
+
427
+ deck[:name] = deck_data["name"]
428
+
429
+ deck[:date] = deck_data["updatedAt"]
430
+
431
+ output_cod(deck,"archidekt")
289
432
  end
290
433
 
291
434
  def self.mtgdecks_decklist(pages = (1..1))
@@ -295,16 +438,14 @@ module CockatriceFeeder
295
438
  doc = Nokogiri::HTML(HTTParty.get("https://mtgdecks.net/Commander/decklists/page:#{page}").body)
296
439
  doc.css(".decks tr.previewable").each do |r|
297
440
  if r.css("td")[0].css(".label-danger").length == 0
298
- decks << {
299
- name: "", # r.css("td")[1].css("a")[0].content,
300
- link: "https://mtgdecks.net"+r.css("td")[1].css("a")[0].attribute("href").value,
301
- date: r.css("td")[6].css("strong")[0].content.
302
- gsub("<span class=\"hidden-xs\">","").
303
- gsub("</span>","").gsub(/\s+/, ""),
304
- price: r.css("td")[7].css("span.paper")[0].content.gsub("$","").gsub(/\s+/, ""),
305
- commanders: [],
306
- cardlist: []
307
- }
441
+ link = "https://mtgdecks.net"+r.css("td")[1].css("a")[0].attribute("href").value
442
+ name = link.split("/").last
443
+ date = r.css("td")[6].css("strong")[0].content.
444
+ gsub("<span class=\"hidden-xs\">","").
445
+ gsub("</span>","").gsub(/\s+/, "")
446
+ price = r.css("td")[7].css("span.paper")[0].content.gsub("$","").gsub(/\s+/, "")
447
+
448
+ decks << deck_obj(link,name,nil,date,price)
308
449
  end
309
450
  end
310
451
  end
@@ -313,7 +454,6 @@ module CockatriceFeeder
313
454
  end
314
455
 
315
456
  def self.mtgdecks_deck(deck)
316
- puts deck[:link]
317
457
  doc = Nokogiri::HTML(HTTParty.get(deck[:link]).body)
318
458
 
319
459
  cardlist = []
@@ -334,8 +474,30 @@ module CockatriceFeeder
334
474
  output_cod(deck,"mtgdecks")
335
475
  end
336
476
 
477
+ def self.mtggoldfish_pricer(deck)
478
+ doc = Nokogiri::HTML(HTTParty.get("https://www.mtggoldfish.com/tools/deck_pricer#paper"))
479
+ csrf_token = nil
480
+ doc.css("meta").each do |m|
481
+ if !m.attribute("name").nil? && m.attribute("name").value == "csrf-token"
482
+ csrf_token = m.attribute("content").value
483
+ end
484
+ end
485
+
486
+ doc2 = Nokogiri::HTML(HTTParty.post("https://www.mtggoldfish.com/tools/deck_pricer#paper", {
487
+ body: {
488
+ utf8: "✓",
489
+ authenticity_token: csrf_token,
490
+ deck: deck[:cardlist].join("\n")
491
+ }
492
+ }))
493
+
494
+ deck[:price] = doc2.css(".deck-price-v2.paper").first.
495
+ content.strip.split(" ").last.split(".").first.gsub(",","")
496
+ end
497
+
337
498
  def self.gobble
338
- setup()
499
+ setup(skip_meta = true)
500
+ update_commanders()
339
501
 
340
502
  total_decks = 0
341
503
 
@@ -360,10 +522,25 @@ module CockatriceFeeder
360
522
  puts "#{decks.length} decks found."
361
523
  decks.each {|d|
362
524
  CockatriceFeeder.mtgdecks_deck(d)
363
- total_decks += 1
525
+ if d[:cardlist].length > 0
526
+ total_decks += 1
527
+ end
528
+ }
529
+
530
+ puts "Fetching the first 5 pages of edh decks from deckstats ordered by likes"
531
+ decks = CockatriceFeeder.deckstats_decklist("", (1..5))
532
+ puts "#{decks.length} decks found."
533
+ decks.each {|d|
534
+ CockatriceFeeder.deckstats_deck(d)
535
+ if d[:cardlist].length > 0
536
+ total_decks += 1
537
+ end
364
538
  }
365
539
 
366
- puts "#{total_decks} decks created."
540
+ puts "#{total_decks} decks created at #{@@deck_dir}."
541
+
542
+ puts "cleaning up"
543
+ FileUtils.remove_dir(@@meta_dir)
367
544
  puts "Scraw!"
368
545
  end
369
546
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: cockatrice_feeder
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.2
4
+ version: 0.0.7
5
5
  platform: ruby
6
6
  authors:
7
7
  - Matthew Steinwachs
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-11-10 00:00:00.000000000 Z
11
+ date: 2020-12-13 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: nokogiri
@@ -38,8 +38,8 @@ dependencies:
38
38
  - - "~>"
39
39
  - !ruby/object:Gem::Version
40
40
  version: '0.18'
41
- description: A tool to scrape MTG decks from the internet along with some meta information
42
- and create Cockatrice compatible deck files.
41
+ description: A tool to scrape MTG EDH decks from the internet along with some meta
42
+ information and create Cockatrice compatible deck files.
43
43
  email: matt.steinwachs@gmail.com
44
44
  executables:
45
45
  - gobble
@@ -71,5 +71,5 @@ rubyforge_project:
71
71
  rubygems_version: 2.6.14
72
72
  signing_key:
73
73
  specification_version: 4
74
- summary: Scrape and generate decks for cockatrice
74
+ summary: Scrape and generate MTG EDH decks for cockatrice
75
75
  test_files: []