Skip to content

Instantly share code, notes, and snippets.

@jmickelin
Created January 19, 2020 16:16
Show Gist options
  • Save jmickelin/e7e39827af031e8dc63d62d38db9a00b to your computer and use it in GitHub Desktop.
Save jmickelin/e7e39827af031e8dc63d62d38db9a00b to your computer and use it in GitHub Desktop.
Boardgamegeek expansion checker tool
#!/usr/bin/env python3
#
# checkexpansions.py - Simple BGG expansion checker
#
# Usage: checkexpansions.py <username>
#
# This is a script that crossreferences the owned and preordered games
# in a Boardgamegeek user's collection with their expansions. All
# expansions that are not in the user's collection are printed to the
# command line.
#
# Conventions: To prevent an expansion that you do not care about from
# being printed, you can simply add it to your collection *without*
# selecting any of the statuses (e.g. "Owned", "Want to play").
# Another option is to add it to your wishlist and selecting "Do not
# want" as priority.
#
# Requirements:
# - Python 3
# - requests.py
from lxml import etree
import requests
import time
import sys
API_ENDPOINT = "http://boardgamegeek.com/xmlapi2"
user = sys.argv[1]
def request_queued(url):
r = requests.get(url)
while r.status_code == 202:
time.sleep(1)
r = requests.get(url)
return r
def game_data(game):
return { "name": game.xpath("name/text()")[0],
"own": game.xpath("status/@own")[0] == "1",
"prevowned": game.xpath("status/@prevowned")[0] == "1",
"fortrade": game.xpath("status/@fortrade")[0] == "1",
"want": game.xpath("status/@want")[0] == "1",
"wanttoplay": game.xpath("status/@wanttoplay")[0] == "1",
"wanttobuy": game.xpath("status/@wanttobuy")[0] == "1",
"wishlist": game.xpath("status/@wishlist")[0] == "1",
"preordered": game.xpath("status/@preordered")[0] == "1",
"numplays": game.xpath("numplays/text()")[0] == "1"
}
def do_not_want(game):
return not(any([game["own"],
game["prevowned"],
game["fortrade"],
game["want"],
game["wanttoplay"],
game["wanttobuy"],
game["preordered"]
]))
r = request_queued(f"{API_ENDPOINT}/collection?username={user}")
t = etree.fromstring(r.content)
owned = t.xpath("/items/item[@subtype='boardgame']")
ownedgames = { game.get("objectid"): game_data(game) for game in owned }
for game in [game for game in ownedgames if ownedgames[game]["own"] or ownedgames[game]["preordered"]]:
time.sleep(1)
r = r = request_queued(f"{API_ENDPOINT}/thing?id={game}")
t = etree.fromstring(r.content)
expansions = t.xpath("/items/item/link[@type='boardgameexpansion']")
for expansion in expansions:
if expansion.get("id") not in ownedgames:
print(f"New expansion: {expansion.get('value')} (https://boardgamegeek.com/boardgame/{expansion.get('id')}/)")
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment