Files
gacha-event-tracker/snapshots
Lucas WintherandClaude Opus 5 b085087b05 feat: refresh sources on a schedule
The feed was generated from checked-in fixtures and only moved when
somebody captured a page by hand. This fetches.

bun run refresh caches each page raw under snapshots/ and rebuilds the
feed from what it cached; build-feed prefers a snapshot and falls back to
the fixture, so a clean checkout and the container build stay offline and
reproducible. The workflow runs it twice a day and commits only when a
page's bytes actually changed — a 304, an identical body or a rejected
parse all leave the tree clean — then dispatches ci.yml, which already
knows how to test, build and deploy.

Scraping conduct is enforced in code rather than left to good
intentions: one request per source per cycle, a six-hour floor checked
per source, conditional requests, a User-Agent with a contact URL, and
robots.txt honoured — failing closed, because a permission we could not
read is not a permission we have. No retries; a retry is a second
request.

A body that yields zero events is rejected and the previous snapshot
kept, so a redesigned wiki shows up as a stale timestamp rather than an
emptied calendar. One source down is a warning; all of them down fails
the run, so a cycle that learned nothing is never committed.

Tested entirely offline against an injected fetch and clock — no request
has ever been made to a live wiki from this code.

Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
2026-08-15 21:15:25 +02:00
..
2026-08-15 21:15:25 +02:00

Snapshots

Raw pages, exactly as fetched. scripts/refresh-sources.ts writes them; nothing else fetches.

<source-id>.html        the body verbatim — tracked
<source-id>.meta.json   hash, size, ETag, Last-Modified, when the bytes last changed — tracked
<source-id>.state.json  when we last checked, and failure streak — gitignored

Three reasons this is committed rather than cached:

  • Re-parsing never re-fetches. Iterating on a parser reads these files, not the wikis (CLAUDE.md § Scraping conduct).
  • A refresh is reviewable. The commit diff is the page diff, so "an event vanished" is a question you can answer from git rather than from a wiki that has since changed again.
  • The build stays offline. bun run build:feed parses whichever of these exists and falls back to fixtures/ otherwise, so a clean checkout and the container build work with no network.

The .state.json files are the exception: they change every cycle whether or not a page did, and committing them would mean a commit per run saying nothing happened. CI keeps them in the actions cache instead.

Fixtures are not the same thing. A fixture is pinned to a date and kept forever as the regression test for a page shape; a snapshot is the current page and is overwritten each time it changes.