IRCv3 Bot
  • Crystal 99.5%
  • Just 0.3%
  • Dockerfile 0.2%
Find a file
Repository files (latest commit first)
Filename Latest commit message Latest commit date
Alexander Fortin ed9dd3c953
All checks were successful
Build and Push Container Image, redeploy service / get-tag (push) Successful in 7s
Build and Push Container Image, redeploy service / deploy-1 (push) Successful in 3s
Build and Push Container Image, redeploy service / deploy (push) Successful in 0s
Build and Push Container Image, redeploy service / build-and-push (push) Successful in 2m2s
chore: update base image to crystal:1-alpine
2026-10-17 21:52:52 +07:00
.forgejo/workflows fix(ci): add version tags to images 2026-10-17 13:44:34 +07:00
scripts feat: first draft 2026-10-17 08:10:46 +07:00
spec refactor: restructure folders and imports, cleanup Containerfile 2026-10-17 21:10:11 +07:00
src refactor: restructure folders and imports, cleanup Containerfile 2026-10-17 21:10:11 +07:00
.env.example feat: first draft 2026-10-17 08:10:46 +07:00
.gitignore chore: udpate README, cleanup gitignore 2026-10-17 13:25:51 +07:00
avatar.jpg chore: add avatar pic 2026-10-17 09:09:34 +07:00
Containerfile chore: update base image to crystal:1-alpine 2026-10-17 21:52:52 +07:00
justfile feat: first draft 2026-10-17 08:10:46 +07:00
lefthook.yml feat: first draft 2026-10-17 08:10:46 +07:00
LICENSE feat: first draft 2026-10-17 08:10:46 +07:00
README.md chore: udpate README, cleanup gitignore 2026-10-17 13:25:51 +07:00
renovate.json feat: first draft 2026-10-17 08:10:46 +07:00
shard.lock feat: first draft 2026-10-17 08:10:46 +07:00
shard.yml chore: cleanup shard.yml 2026-10-17 19:56:10 +07:00

Botium

IRC greeter/notifier bot written in Crystal.

Connects over TCP (plain/TLS) or WebSocket, negotiates IRCv3 caps, authenticates via SASL PLAIN (phase-1 auth; will swap to IRCv3 bearer + JWT when the bespoke auth server lands), joins the configured channels, answers PINGs with PONG-liveness tracking, and reconnects forever with capped exponential backoff.

Features

Core IRCv3

  • Multi-transport connectivity: plain TCP, TLS (ircs://), and WebSocket (ws:// / wss://)
  • IRCv3 capability negotiation, SASL PLAIN authentication, and draft/metadata-2 avatar advertisement
  • PING/PONG liveness tracking with periodic latency statistics
  • Automatic rejoin of channels after reconnection and reconnect-forever with capped exponential backoff
  • Multiline message handling

Greeting

  • Greets newcomers in a configurable channel (with WHOIS re-verification and a configurable delay)
  • Greeting template with {nick} placeholder; greeted nicks are persisted so repeat visitors aren't re-greeted

Scheduled posts

  • Daily random XKCD comic post at a configurable local time
  • Daily random programming quote/joke post, offset from the XKCD post so they don't overlap

Announcements

  • RSS/Atom feed polling with per-feed channel routing, dedup checkpoints (ETag/Last-Modified aware), and configurable announcement template
  • Forgejo repository-activity announcements (releases, pushes, issues, ...) supporting multiple Forgejo instances, per-repo channel routing, and per-repo ignore lists

Interactive commands

  • Central !command registry with help output (!help), plus !xkcd and !joke on demand
  • Channels only accept !-prefixed commands; private messages accept bare verbs too

HTTP webhook

  • Bearer-token-authenticated POST /v1/send endpoint for pushing messages to joined channels
  • Public GET /v1/health for uptime monitoring and telemetry

Operations

  • Configuration via environment variables or a .env file
  • Persistent JSON state files (greeted nicks, shown comics/quotes, feed checkpoints)
  • Structured logging with configurable level; health-check endpoint
  • E2E test suite against a real Ergo server in a podman container

Install

Either via Crystal build:

just build   # compiles the binary under `./bin/botium`

or run the container directly, e.g.:

podman run --rm --env-file .env forge.l3x.in/alex/botium:latest

Development

Requires:

  • Crystal 1.22+
  • just (task runner)
  • Podman (for e2e only)

Run just to list all available targets:

just  # available targets

End-to-end validation

spec/e2e_spec.cr runs the IRC client against a real Ergo server in a podman testcontainer (anonymous registration + cap negotiation, SASL PLAIN, channel PRIVMSG round trip, WebSocket transport):

E2E=1 crystal spec spec/e2e_spec.cr   # requires podman + the ergo image
# or simply:
just e2e

Configuration is via environment variables or a .env file (see .env.example).

Running dev

cp .env.example .env    # edit
just run