Skip to content

Instantly share code, notes, and snippets.

@jbodah
Created December 1, 2022 04:37
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jbodah/731a4079dcac3c0b5cd08e5b9a68f9a2 to your computer and use it in GitHub Desktop.
Save jbodah/731a4079dcac3c0b5cd08e5b9a68f9a2 to your computer and use it in GitHub Desktop.
#! /usr/bin/env ruby
require 'nokogiri'
require 'set'
class Object
def as_node
Node.new(self)
end
end
class Node
def initialize(doc)
@doc = doc
end
def find(name)
Node.new(@doc.children.find { |c| c.name == name })
end
def select(name)
@doc.children.select { |c| c.name == name }.map { |doc| Node.new(doc) }
end
def [](name)
@doc.attributes[name].value
end
def attributes
@doc.attributes
end
def as_doc
@doc
end
def children
@doc.children.map { |doc| Node.new(doc) }
end
end
base = "https://boardgamegeek.com"
items_by_id = {}
page = 1
done = false
until done == true
io = `curl '#{base}/xmlapi2/plays?username=hiimjosh&mindate=2022-11-01&page=#{page}' 2> /dev/null`
root = Nokogiri::XML(io)
root = Node.new(root.children[0])
plays = root.select("play")
done = true if plays.size != 100
page += 1
plays.each do |play|
item = play.find("item")
players = play.find("players").select("player")
my_play = players.find { |p| p["username"] == "hiimjosh" }
id = item["objectid"]
items_by_id[id] ||= {plays: 0, new: 0, id: id, name: item["name"]}
items_by_id[id][:plays] += 1
if my_play["new"] == "1"
items_by_id[id][:new] = 1
end
end
end
items = items_by_id.values
new_items = items.select { |i| i[:new] == 1 }
collection = {}
styles_by_value = {}
page = 1
done = false
seen = Set.new
until done == true
io = `curl '#{base}/collection/user/hiimjosh?played=1&subtype=boardgame&page=#{page}' 2> /dev/null`
page += 1
root = Nokogiri::HTML(io)
el_size = root.css('.collection_objectname').size
done = true if el_size != 300
rows = root.css('tr').to_a.select { |x| x.attributes["id"] && x.attributes["id"].value =~ /row_/ }.map { |x| x.children.select { |x| x.name == "td" }}
rows.each do |tds|
nodes = tds.map(&:as_node)
name = nodes.find { |c| c["class"].rstrip == "collection_objectname" }
rating = nodes.find { |c| c["class"].rstrip == "collection_rating" }
comment = nodes.find { |c| c["class"].rstrip == "collection_comment" }
relurl = name.as_doc.css('.primary')[0].attr('href')
id = relurl.split('/')[2]
next unless items_by_id.key?(id)
item = items_by_id[id]
item[:rating_value] = rating.as_doc.css('.ratingtext')[0]&.inner_html || ""
# TODO: @jbodah 2022-11-30:
if item[:rating_value] != ""
style = rating.as_doc.css('.rating')[0].attr('style').split(':')[1][0..-2]
styles_by_value[item[:rating_value]] = style
end
item[:comment] = comment.as_doc.css('div').find { |x| x.attr('id').start_with? 'results_comment' }.inner_html.strip.gsub('<br>', "\n")
item[:url] = base + relurl
end
end
unrated_items, rated_items = new_items.partition { |i| i[:rating_value] == "" }
rated_items.each do |item|
begin
io = `curl '#{base}/xmlapi2/thing?id=#{item[:id]}' 2> /dev/null`
image_id = File.basename(Nokogiri::HTML(io).css('thumbnail')[0].inner_html, ".*").sub('pic', '')
item[:image_id] = image_id
sleep 0.5
rescue => e
puts [item[:name], e].inspect
end
end
rated_items.sort_by { |i| -i[:rating_value].to_i }.each do |item|
puts <<~EOF
[size=12][b][thing=#{item[:id]}]#{item[:name]}[/thing] - [COLOR=#00CC00]#{item[:plays]} plays[/COLOR] - [BGCOLOR=#{styles_by_value[item[:rating_value]]}] #{item[:rating_value]} [/BGCOLOR][/b][/size]
[imageID=#{item[:image_id]} square inline]
#{item[:comment]}
EOF
end
if unrated_items.any?
puts "Unrated Items:"
unrated_items.sort_by { |i| i[:name] }.each { |i| puts "* #{i[:name]} (#{i[:url]})" }
end
nocomment_items.select { |x| x[:comment].empty? }
if nocomment_items.any?
puts "Nocomment Items:"
nocomment_items.sort_by { |i| i[:name] }.each { |i| puts "* #{i[:name]} (#{i[:url]})" }
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment