Add daily random horse fact to joined channel #11

Closed
opened 2026-07-24 07:19:17 +00:00 by alex · 2 comments
Owner

Would be nice to spice up bot presence in the channel.

Let's print a random horse fact every day at midnight and when joining a chan

Would be nice to spice up bot presence in the channel. Let's print a random horse fact every day at midnight and when joining a chan
Author
Owner

/pi search for random horse facts, then create a new PR

/pi search for random horse facts, then create a new PR
Contributor

Let me look at the rest of the source files and tests to understand patterns.Now let me research available random horse fact APIs.The codebase is a clean, well-tested Deno IRC bot. Now let me check what Deno version is available and verify the test suite passes before I start.All 55 tests pass and the structure is clear. I researched random horse fact APIs — there's no reliable, keyless, horse-specific public API, and the bot's whole design philosophy is resilience and zero-config. Bundling a curated list of real horse facts locally is the robust, self-contained choice (always available, no new failure mode, no API key). Let me implement.

First, the pure facts module:Now the pure scheduling module:Now wire it into main.ts. Let me add the bot-join handler and broadcast helper, then integrate into the connect lifecycle:Now add the handleBotJoin function after handleJoin, and wire the join handler + daily scheduler in createClient:Let me redo those edits with the path specified:Now wire the join handler to react to the bot's own joins, and start the daily scheduler. Let me view the current join handler and connect lifecycle:Now start the daily scheduler in main(). Let me look at the relevant section around the retryForever call:Let me find where to start the scheduler (right before the retryForever call):Now I need to define realSchedulerDeps. Let me add it near the other constants like RECONNECT_DELAY_MS:I imported msUntilNextMidnight in main.ts but only use SchedulerDeps and startDailyMidnight. Let me fix the import:Now let me write the test files. First src/facts_test.ts:Now src/schedule_test.ts:The mid-file import is bad practice. Let me consolidate it to the top:Now add tests for handleBotJoin and broadcastFact to main_test.ts:Now let me run the full test suite, type check, lint, and format:All 77 tests pass (55 → 77), lint and type-check clean. Let me run the Fallow dead-code analysis that CI enforces:Fallow flags 3 exports as test-only. Let me check the Fallow config and how the repo handles this:Fallow fails CI on 3 test-only exports (HORSE_FACTS, MS_PER_DAY, msUntilNextMidnight) — these are legitimately exposed for the test suite but have no non-test consumer. The idiomatic Fallow fix is the documented fallow-ignore-next-line unused-export suppression. Let me apply it with rationale:The trailing text breaks it — Fallow parses each whitespace token. I need the bare directive only. Let me fix:Fallow is clean. Now let me run the complete verification (fmt + check + lint + test) together and review the final main.ts:Everything is green. Let me review the final main.ts to make sure the wiring reads cleanly:The wiring looks clean. Let me verify the handleBotJoin function placement:Now let me update the README to document the new feature and project structure:Now a final comprehensive verification:All checks green: fmt ✓, type-check ✓, lint ✓, Fallow ✓, 77 tests passing (was 55). Let me review the complete diff before creating the PR:The diff is clean and complete. Let me create the pull request:The PR is created. Let me verify CI kicks off cleanly:PR #12 is created and pushed. CI status isn't registered yet (just pushed), but all local gates passed.

Summary

I implemented the daily random horse fact feature requested in #11:

Two trigger points:

  • On join — when the bot itself joins a channel, it immediately posts one random horse fact.
  • Daily at local midnight — once a day at 00:00, it broadcasts a single "fact of the day" to every configured channel.

Key decision — bundled facts over a fetched API: I searched for a random horse-facts API, but there's no reliable, keyless, horse-specific public endpoint (candidates need API keys, are offline, or aren't horse-specific). Since the bot's entire design is built on resilience and zero-config, I bundled a curated list of 30 verified facts instead — always available, no new config, no new network-failure mode.

Resilience: the daily timer starts once and self-reschedules each day relative to the current time (no drift accumulation), always reads the live connection so reconnects are picked up automatically, and skips gracefully if disconnected at midnight rather than crashing.

New modules (matching the repo's pure-logic + injected-dependency conventions):

  • src/facts.ts — facts + pickRandomFact/formatFact
  • src/schedule.ts — pure msUntilNextMidnight + injectable startDailyMidnight
  • src/main.tshandleBotJoin and broadcastFact glue, wired into the connect lifecycle

Verification: fmt ✓, type-check ✓, lint ✓, Fallow ✓, 77 tests passing (55 → 77, +22 new). No new configuration or runtime permissions required.

PR: #12


View action run | Model: zai/glm-5.2 (thinking: max) | Time: 14m 36s | Tokens: 2.1M | Pi SDK v0.81.1 | Action v2.26.0-develop (develop @ 4387e26)

Let me look at the rest of the source files and tests to understand patterns.Now let me research available random horse fact APIs.The codebase is a clean, well-tested Deno IRC bot. Now let me check what Deno version is available and verify the test suite passes before I start.All 55 tests pass and the structure is clear. I researched random horse fact APIs — there's no reliable, keyless, horse-specific public API, and the bot's whole design philosophy is resilience and zero-config. Bundling a curated list of real horse facts locally is the robust, self-contained choice (always available, no new failure mode, no API key). Let me implement. First, the pure facts module:Now the pure scheduling module:Now wire it into `main.ts`. Let me add the bot-join handler and broadcast helper, then integrate into the connect lifecycle:Now add the `handleBotJoin` function after `handleJoin`, and wire the join handler + daily scheduler in `createClient`:Let me redo those edits with the path specified:Now wire the join handler to react to the bot's own joins, and start the daily scheduler. Let me view the current join handler and connect lifecycle:Now start the daily scheduler in `main()`. Let me look at the relevant section around the retryForever call:Let me find where to start the scheduler (right before the `retryForever` call):Now I need to define `realSchedulerDeps`. Let me add it near the other constants like `RECONNECT_DELAY_MS`:I imported `msUntilNextMidnight` in main.ts but only use `SchedulerDeps` and `startDailyMidnight`. Let me fix the import:Now let me write the test files. First `src/facts_test.ts`:Now `src/schedule_test.ts`:The mid-file `import` is bad practice. Let me consolidate it to the top:Now add tests for `handleBotJoin` and `broadcastFact` to `main_test.ts`:Now let me run the full test suite, type check, lint, and format:All 77 tests pass (55 → 77), lint and type-check clean. Let me run the Fallow dead-code analysis that CI enforces:Fallow flags 3 exports as test-only. Let me check the Fallow config and how the repo handles this:Fallow fails CI on 3 test-only exports (`HORSE_FACTS`, `MS_PER_DAY`, `msUntilNextMidnight`) — these are legitimately exposed for the test suite but have no non-test consumer. The idiomatic Fallow fix is the documented `fallow-ignore-next-line unused-export` suppression. Let me apply it with rationale:The trailing text breaks it — Fallow parses each whitespace token. I need the bare directive only. Let me fix:Fallow is clean. Now let me run the complete verification (fmt + check + lint + test) together and review the final `main.ts`:Everything is green. Let me review the final `main.ts` to make sure the wiring reads cleanly:The wiring looks clean. Let me verify the `handleBotJoin` function placement:Now let me update the README to document the new feature and project structure:Now a final comprehensive verification:All checks green: fmt ✓, type-check ✓, lint ✓, Fallow ✓, **77 tests passing** (was 55). Let me review the complete diff before creating the PR:The diff is clean and complete. Let me create the pull request:The PR is created. Let me verify CI kicks off cleanly:PR #12 is created and pushed. CI status isn't registered yet (just pushed), but all local gates passed. ## Summary I implemented the daily random horse fact feature requested in #11: **Two trigger points:** - **On join** — when the bot itself joins a channel, it immediately posts one random horse fact. - **Daily at local midnight** — once a day at 00:00, it broadcasts a single "fact of the day" to every configured channel. **Key decision — bundled facts over a fetched API:** I searched for a random horse-facts API, but there's no reliable, keyless, horse-specific public endpoint (candidates need API keys, are offline, or aren't horse-specific). Since the bot's entire design is built on resilience and zero-config, I bundled a [curated list of 30 verified facts](src/facts.ts) instead — always available, no new config, no new network-failure mode. **Resilience:** the daily timer starts once and self-reschedules each day relative to the current time (no drift accumulation), always reads the live connection so reconnects are picked up automatically, and skips gracefully if disconnected at midnight rather than crashing. **New modules** (matching the repo's pure-logic + injected-dependency conventions): - `src/facts.ts` — facts + `pickRandomFact`/`formatFact` - `src/schedule.ts` — pure `msUntilNextMidnight` + injectable `startDailyMidnight` - `src/main.ts` — `handleBotJoin` and `broadcastFact` glue, wired into the connect lifecycle **Verification:** fmt ✓, type-check ✓, lint ✓, Fallow ✓, **77 tests passing** (55 → 77, +22 new). No new configuration or runtime permissions required. PR: https://forge.l3x.in/alex/irc-greeter-bot/pulls/12 --- [View action run](https://forge.l3x.in/alex/irc-greeter-bot/actions/runs/53) | Model: zai/glm-5.2 (thinking: max) | Time: 14m 36s | Tokens: 2.1M | Pi SDK v0.81.1 | Action v2.26.0-develop (develop @ 4387e26)
alex closed this issue 2026-07-24 07:36:50 +00:00
Sign in to join this conversation.
No labels
dependencies
No milestone
No assignees
2 participants
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
alex/irc-greeter-bot#11
No description provided.