feat: add daily random horse fact on join and at midnight #12

Merged
alex merged 1 commit from pi/issue11-1784878459998 into master 2026-07-24 07:36:50 +00:00
Contributor

Closes #11.

Adds a random horse fact to spice up the bot's presence in two situations, as requested:

  • On join — whenever the bot itself joins a channel, it immediately posts one random horse fact (🐴 …) to that channel.
  • Daily at local midnight — once a day at 00:00 (server local time), it broadcasts a single randomly-chosen "fact of the day" to every configured channel.

Design notes

Bundled facts, not a fetched API. I searched for a random horse-facts API, but there is no reliable, keyless, horse-specific public endpoint (the candidates either require an API key, are offline, or aren't horse-specific). More importantly, the bot's whole design philosophy is resilience and zero-config. So the facts are a curated, bundled list of 30 verified facts. This keeps the feature always available with no new config vars, no API key, and no new network-failure mode — consistent with how the rest of the bot behaves.

Resilient scheduling. The daily timer is started exactly once at startup and self-reschedules every day, always re-arming relative to the current time (so clock drift / slow callbacks never accumulate). It reads the live currentClient at fire time, so a reconnect — which replaces that reference — is picked up automatically without ever spawning a second timer. If the bot happens to be disconnected at midnight the fact is simply skipped and never crashes the process.

On-join vs greeting kept separate. The bot's own join is a distinct event from greeting newcomers, so it has its own handleBotJoin handler. Newcomer greeting behaviour is unchanged.

Implementation

Following the existing module conventions (pure logic + I/O separated, dependencies injected for testability):

File Purpose
src/facts.ts Curated HORSE_FACTS, pickRandomFact(randomFn), formatFact (pure, no I/O).
src/schedule.ts Pure msUntilNextMidnight(now) + injectable self-rescheduling startDailyMidnight.
src/main.ts handleBotJoin glue (on join), broadcastFact glue (daily), wired into main/createClient.
src/*_test.ts 22 new tests covering selection, formatting, midnight math, re-arming, and the join/broadcast handlers.

No new configuration is required and no extra runtime permissions are needed (no network, just setTimeout + local data).

Verification

  • deno fmt --check
  • deno task check
  • deno lint
  • deno task fallow ✓ (the 3 test-only exports use the documented fallow-ignore-next-line unused-export suppression)
  • deno task test ✓ — 77 passed (55 → 77)
Closes #11. Adds a random horse fact to spice up the bot's presence in two situations, as requested: - **On join** — whenever the bot itself joins a channel, it immediately posts one random horse fact (`🐴 …`) to that channel. - **Daily at local midnight** — once a day at 00:00 (server local time), it broadcasts a single randomly-chosen "fact of the day" to every configured channel. ### Design notes **Bundled facts, not a fetched API.** I searched for a random horse-facts API, but there is no reliable, keyless, horse-specific public endpoint (the candidates either require an API key, are offline, or aren't horse-specific). More importantly, the bot's whole design philosophy is resilience and zero-config. So the facts are a [curated, bundled list](src/facts.ts) of 30 verified facts. This keeps the feature always available with no new config vars, no API key, and no new network-failure mode — consistent with how the rest of the bot behaves. **Resilient scheduling.** The daily timer is started exactly once at startup and self-reschedules every day, always re-arming relative to the *current* time (so clock drift / slow callbacks never accumulate). It reads the live `currentClient` at fire time, so a reconnect — which replaces that reference — is picked up automatically without ever spawning a second timer. If the bot happens to be disconnected at midnight the fact is simply skipped and never crashes the process. **On-join vs greeting kept separate.** The bot's own join is a distinct event from greeting newcomers, so it has its own `handleBotJoin` handler. Newcomer greeting behaviour is unchanged. ### Implementation Following the existing module conventions (pure logic + I/O separated, dependencies injected for testability): | File | Purpose | | --- | --- | | `src/facts.ts` | Curated `HORSE_FACTS`, `pickRandomFact(randomFn)`, `formatFact` (pure, no I/O). | | `src/schedule.ts` | Pure `msUntilNextMidnight(now)` + injectable self-rescheduling `startDailyMidnight`. | | `src/main.ts` | `handleBotJoin` glue (on join), `broadcastFact` glue (daily), wired into `main`/`createClient`. | | `src/*_test.ts` | 22 new tests covering selection, formatting, midnight math, re-arming, and the join/broadcast handlers. | No new configuration is required and no extra runtime permissions are needed (no network, just `setTimeout` + local data). ### Verification - `deno fmt --check` ✓ - `deno task check` ✓ - `deno lint` ✓ - `deno task fallow` ✓ (the 3 test-only exports use the documented `fallow-ignore-next-line unused-export` suppression) - `deno task test` ✓ — **77 passed** (55 → 77)
feat: add daily random horse fact on join and at midnight
All checks were successful
PR / deno (pull_request) Successful in 34s
PR / fallow (pull_request) Successful in 29s
Build and Push Container Image / build-and-push-1 (push) Successful in 1m4s
Build and Push Container Image / build-and-push (push) Successful in 0s
Build and Push Container Image / deploy-1 (push) Successful in 4s
Build and Push Container Image / deploy (push) Successful in 0s
f9f3c73dcf
Co-authored-by: alex <alex@forge.l3x.in>
alex merged commit f9f3c73dcf into master 2026-07-24 07:36:50 +00:00
alex deleted branch pi/issue11-1784878459998 2026-07-24 07:36:50 +00:00
Sign in to join this conversation.
No reviewers
No labels
dependencies
No milestone
No assignees
1 participant
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!12
No description provided.