Daily Bluesky bot for AT Mot. Invites players and congratulates yesterday's solvers.
0

Configure Feed

Select the types of activity you want to include in your feed.

at trunk 62 lines 2.1 kB View raw View rendered
1# atmot-bot 2 3Daily Bluesky bot for [AT Mot](https://atmot.herve.bzh). Posts once per language 4each day just after the UTC puzzle rollover: invites players to today's puzzle and 5congratulates yesterday's solvers (by count only). 6 7Runs as a stateless Cloudflare Worker with two Cron Triggers (EN 00:10 UTC, FR 800:11 UTC). Counts are read from the public Constellation backlink index; there is 9no database. The bot duplicates a small set of the app's frozen constants 10(`src/config.ts`) rather than importing the app. 11 12## Develop 13 14```sh 15npm install 16npm test # vitest — composer + facets + puzzle math 17npm run typecheck 18npm run dev # wrangler dev --test-scheduled (see Dry run below) 19``` 20 21## Dry run (no real post) 22 23Create a gitignored `.dev.vars`: 24 25``` 26DRY_RUN = "1" 27ATMOT_BOT_IDENTIFIER = "atmot.herve.bzh" 28ATMOT_BOT_APP_PASSWORD = "dry-run-unused" 29``` 30 31Then `npm run dev` and, in another shell: 32 33```sh 34curl "http://localhost:8787/__scheduled?cron=10+0+*+*+*" # EN 35curl "http://localhost:8787/__scheduled?cron=11+0+*+*+*" # FR 36``` 37 38The composed post is logged instead of published. 39 40## Deploy 41 42The bot posts as **@atmot.herve.bzh** using a Bluesky **app password** (Settings → 43Privacy and security → App passwords — not the account password). 44 45```sh 46npx wrangler login 47npx wrangler secret put ATMOT_BOT_IDENTIFIER # e.g. atmot.herve.bzh 48npx wrangler secret put ATMOT_BOT_APP_PASSWORD # the app password 49npm run deploy 50``` 51 52The free Workers plan is sufficient: each language runs in its own scheduled 53invocation, so each gets the full 50-subrequest budget. Solver counting samples up 54to `SOLVER_SAMPLE_CAP` (20) records per language; beyond that the count is hedged 55(e.g. "20+"). 56 57Each sampled record costs ~2 subrequests (DID-document resolution + the record 58read), so the default cap of 20 already uses most of the per-invocation budget on 59the free plan — keep headroom for the count, session, idempotency check, and 60publish (~6 more). On the paid plan you can raise `SOLVER_SAMPLE_CAP` in 61`src/config.ts`, but size it against the subrequest cost (~2 per record), not just 62the desired sample size.