Show a game page
This guide builds the information for a game page the way the Bazoodle website does, from a game’s detail and its pictures. The first part is JavaScript for Node.js 18 or later and uses the api helper from the JavaScript guide; the picture part is Python 3 with the helper from the Python guide.
Read the game
Section titled “Read the game”const game = await api("/catalog/games/coins");
console.log(game.title);console.log(game.rating_label); // "Kid-friendly"console.log(`${game.players.min}-${game.players.max} players`);console.log(game.tags.join(", "));console.log(game.like_pct === null ? "not rated yet" : `${game.like_pct}% liked`);like_pct is null until a game has at least five votes; say “not rated yet” rather than showing zero.
The text
Section titled “The text”console.log(game.description);if (game.controls_text) console.log("How to play:\n" + game.controls_text);Both are plain text written by the creator. Paragraphs are separated by blank lines, and lines in controls_text by line breaks. Escape them before putting them in a web page.
Pictures, updates and similar games
Section titled “Pictures, updates and similar games”const pictures = [game.thumbnail_url, ...game.gallery].filter(Boolean);console.log(pictures.length, "pictures");
for (const update of game.updates) { console.log(new Date(update.at * 1000).toISOString().slice(0, 10), "version", update.version, update.notes);}
console.log(game.similar.map((g) => `${g.title} -> https://bazoodle.com/game/${g.id}`));Use picture addresses exactly as given (Media files); the list may be empty. at is in seconds, so multiply by 1000 for JavaScript dates. similar already holds up to six game cards: do not call the API again for each one.
Save pictures once
Section titled “Save pictures once”Thumbnails never change at a given address, so you can download one once and reuse it forever. This Python function uses the api helper from the Python guide:
import osimport hashlibimport urllib.request
def save_thumbnail(url, folder="thumbnails"): if not url: return None os.makedirs(folder, exist_ok=True) name = hashlib.sha256(url.encode()).hexdigest()[:16] + ".img" path = os.path.join(folder, name) if os.path.exists(path): return path # already downloaded: the file at this address never changes request = urllib.request.Request(url, headers={"User-Agent": "MyGameList/1.0 (contact: you@example.com)"}) with urllib.request.urlopen(request, timeout=20) as response: with open(path, "wb") as out: out.write(response.read()) return path
page = api("/catalog/browse", sort="new", limit=3)for game in page["games"]: print(game["title"], "->", save_thumbnail(game["thumbnail_url"]))The check os.path.exists is the whole cache: the response is marked Cache-Control: public, max-age=31536000, immutable, so the file at that address will never be different. If a creator replaces a picture, it gets a new address: your next call to Browse returns the new thumbnail_url and your code downloads it because it is a new name.
On a web page you can also point an <img> straight at the address; pictures can be shown on any website. Downloading and serving your own copy is kinder to our servers when you have many visitors. The pictures belong to their creators: use them to show and link to the game, not as general artwork.