feat(images): repair reported covers and achievement icons at night
Build, Test & Push Core Service / quality-check (push) Successful in 56s
Build, Test & Push Core Service / docker (push) Successful in 1m24s

This commit is contained in:
lobo committed 2026-09-26 12:07:07 +02:00
1 parent a389bdd0c7
commit 246e255058
30 files changed
+1138 -28

No files matched your search

+11 -1
View File
@@ -32,6 +32,11 @@ To Be Played is split into three repositories:
- **Playtime history**: one row per game and day, for the activity view and the "most played in the last two weeks"
dashboard banner.
- **Wishlist**: synced from Steam with store price and discount.
- **Broken image repair**: the frontend reports a Steam cover or achievement icon that does not load. At 01:30
(Europe/Berlin) a job checks up to 200 reports. A cover that loads again is left alone; else the store's hashed
header picture (`IStoreBrowseService/GetItems` with assets) goes to `steam_game.image_url`. When a few achievement
icons do not load, the schema comes fresh from Steam; an empty answer keeps the stored one. A report that cannot be repaired is tried again on the next report, at most 3 times,
then after 30 days.
- **Time to beat**: story, extras and completionist hours from the IGDB API. Optional: without credentials the
feature is off and the rest works.
- **Public profile data**: totals, status counts, games in progress and finished games with rating, perfect games
@@ -57,6 +62,7 @@ accepted only by `GET /api/public/profiles/library` in the `X-Profile-Ticket` he
| `PUT` | `/api/library/games/{appid}/backlog` | JWT |
| `PUT` | `/api/library/games/{appid}/status` (status only, keeps rating, notes, priority) | JWT |
| `POST` | `/api/library/sync` | JWT |
| `POST` | `/api/library/broken-images` (`{appid, kind}`, kind `COVER` or `ACHIEVEMENT_ICONS`; `204`) | JWT |
| `GET` | `/api/library/picker?maxMinutes=&mood=&count=&exclude=` | JWT |
| `GET` | `/api/library/achievements/summary` | JWT |
| `GET` | `/api/library/sync-status`, `/summary`, `/activity`, `/wishlist`, `/steam-profile`, `/games-count` | JWT |
@@ -97,6 +103,7 @@ flowchart LR
Browser -->|"tbp_access cookie"| Security
Security -->|"JWKS by kid"| Auth["ToBePlayed-Auth"]
Steam --> SteamApi["Steam Web API"]
Steam -->|"HEAD"| SteamCdn["Steam CDN"]
Igdb --> IgdbApi["IGDB API"]
Igdb -->|"OAuth token"| Twitch["Twitch"]
Speedrun --> SpeedrunApi["speedrun.com API"]
@@ -108,7 +115,7 @@ flowchart LR
|---|---|
| `library` | Sync, backlog, manual games, playtime history, wishlist, achievements, public profile data |
| `stats` | Public numbers for the landing page |
| `steam_adapter` | Steam Web API client |
| `steam_adapter` | Steam Web API client, availability check of Steam CDN pictures |
| `igdb_adapter` | IGDB client (Twitch OAuth): time to beat, game tags for moods, release years, game search |
| `speedrun_adapter` | speedrun.com client: game search by name, verified runs |
@@ -142,6 +149,9 @@ Inside a module: `api` (controllers, DTOs), `service` (business logic), `domain`
The frontend polls `GET /api/library/sync-status` until the run ends.
At 01:30 `ImageRepairService` repairs the pictures reported through `POST /api/library/broken-images` (table
`broken_image`, one row per game and kind). Reports only count for Steam games the user owns.
### Manual games next to Steam games
A game the user adds by hand comes from IGDB (`ManualGameService`). Steam games and manual games share