Repository navigation
feat(games): give each game its cover from IGDB - #186
Merged
Merged
Conversation
Each game in GET /games/recent now carries its cover from IGDB when BAKHYARD_TWITCH_CLIENT_ID and the Twitch app's secret are set (decision 306). The covers package keeps each title's cover, or that IGDB has none, for a week, for the latest list's titles only. The first failure stops the asking until the next fetch, and a missing cover never fails the list.
Bakhomious
added a commit
that referenced
this pull request
Oct 30, 2026
The games service has sent each game's IGDB cover since #186 (decision 306). The Games page now shows it in a column between the day and the title, as the background of a framed blank, so a game without a cover, a cover still loading and one that fails to load all leave the same blank, and screen readers skip it (decision 308). Merged under the user's standing OK once CI's check was green.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Brief
Goal: each game that
GET /games/recentanswers carries its cover from IGDB, which games asks as the Twitch app that the settings name, and each title is matched at most once a week: the seventh ofgames-exophase's eleven steps.Scope:
services/games/internal/covers, which keeps the covers found for the latest list's titles, each for a week at most;gamesservice's wiring: the settingBAKHYARD_TWITCH_CLIENT_ID, the secrettwitch-client-secret, the Twitch and IGDB clients (decisions 304 and 305), andcoverin each game of the answer;docs/setup.mdandmise.local.example.toml;Out of scope:
homelab-games);games-page-covers).Acceptance criteria:
BAKHYARD_TWITCH_CLIENT_ID, games starts, reads no secret, asks neither Twitch nor IGDB, and its games have nocover.twitch-client-secret, and when that fails, it exits 1 withread the Twitch client secret: <why>.cover, the address of its cover on IGDB (decision 305), or nocoverwhen IGDB has none.failure. games logsfind coverswith the error, unless it's stopping. The failed title isn't kept, so the next fetch asks again.mise run checkis green.What changed
services/games/internal/covers/covers.go:Cachekeeps each title's cover, or that IGDB has none, for a week from when it asked, for the latest list's titles only.Findasks itsFinderfor the titles not kept, one after another, each once, and stops at the first error.services/games/covers.go:coverCachebuilds the cache fromBAKHYARD_TWITCH_CLIENT_ID, the secrettwitch-client-secret, and the Twitch and IGDB clients (decisions 304 and 305), or gives none without the setting;coveredgives each game its cover, and logsfind coversat the first failure.services/games/internal/api/api.go:Gameembedsexophase.Gameand addscover, left out when it's empty.services/games/main.goandexophase.go:routestakes the secrets reader and the three APIs' addresses, and the poll finds the covers once Exophase has answered.internal/covers/covers_test.go: the order, the week in synctest bubbles, the latest titles and the failure;covers_test.go: the answer with its covers, against stand-ins for Twitch and IGDB; the missing secret; the setting left out; and the log;internal/api/api_test.go: the cover in the JSON;main_test.goandexophase_test.go:routes' new parameters.docs/setup.md: the setting, and a new IGDB section on registering the Twitch app;mise.local.example.tomland the process-compose description;docs/plan.md: decision 306, the §0 row and the §8.2 bullet.QA
Tests:
-race.coversandapi, and 85.7% for the main package, whosemain.goisn't counted.Mutants: I ran 34 hand mutants, and all 34 are killed. QA added three tests first, to kill the three that had survived:
The mutants covered:
omitzeroand the field's name;pollandroutes.Live: run on port 8301 against a public reference profile, which had 43 games:
cover, and no failure.read the Twitch client secret: no Keychain item with service bakhyard and account twitch-client-secret.BAKHYARD_SECRETSfolder:cover, and no failure.find covers err="find the cover of \"…\": get a Twitch token: 400 Bad Request, invalid client".Gates:
mise run checkpassed on this branch's tree, merged withmainafter feat(games): find a game's cover on IGDB #183:coversand 85.7% for the main package;Review
exophase_test.gostill starts its two servers by hand, asserveincovers_test.gonow does for the new stand-ins.Merged under the user's standing OK once CI's
checkis green.