From 12961f66daa657865ca5489d88e5d84db436af44 Mon Sep 17 00:00:00 2001 From: reverse Date: Wed, 29 Jul 2026 20:05:38 +0000 Subject: [PATCH] Update README --- README.md | 68 +++++++++++++++++++++++++++++-------------------------- 1 file changed, 36 insertions(+), 32 deletions(-) diff --git a/README.md b/README.md index cefce9d..b32a642 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,8 @@ # rustbot -A small, modular IRC bot in Rust — **zero dependencies**, with its own IRC -protocol layer built to the [modern IRC client spec](https://modern.ircdocs.horse/). +A small, modular IRC bot in Rust — **almost dependency-free** (only `native-tls` +for the TLS transport), with a hand-rolled IRC protocol layer, HTTP client, JSON +parser, and hashes, built to the [modern IRC client spec](https://modern.ircdocs.horse/). ## Structure @@ -12,9 +13,11 @@ rustbot is a **library crate** (`src/lib.rs`) with a thin binary on top: | `src/irc/` | protocol + I/O | `message` (parse IRCv3 wire format), `connection` (TCP/TLS transport), `encoding` (base64, server-time) | | `src/bot/` | behavior | `mod` (state + loop), `caps` (IRCv3 + SASL), `commands` (routing + help), `module` (plugin trait), `modules/` (feature modules) | | `src/config.rs` | configuration | Layered `Config`; multi-network `[section]` parsing | +| `src/http.rs` | utility | Minimal HTTPS GET over `native-tls`, with retry | +| `src/json.rs` | utility | Recursive-descent JSON parser | | `src/lib.rs` | crate root | Ties the modules into the reusable `rustbot` library | | `src/main.rs` | binary | Thin per-network connect/reconnect supervisor | -| `tests/` | tests | Integration tests (`config.rs`, `protocol.rs`) against the public API | +| `tests/` | tests | Integration tests against the public API, one file per subsystem | The layers are deliberately separable: `irc` knows nothing about the bot, `bot` knows nothing about how the process is launched, and `main` only supervises. @@ -37,14 +40,14 @@ pub trait Module { At startup the bot builds a `command → module` route table and auto-generates `help` from every module's `CommandSpec`s. Each network gets its own fresh set -of modules, so stateful ones (like the dice roller's PRNG) keep per-network -state with no locking. +of modules, so stateful ones (like the dice roller's PRNG or the weather cache) +keep per-network state with no locking. **To add a module**, create `src/bot/modules/.rs` implementing `Module`, then add one line to `all()` in `src/bot/modules/mod.rs`: ```rust -pub fn all() -> Vec> { +pub fn all(network: &str) -> Vec> { vec![ Box::new(builtins::Builtins), Box::new(dice::Dice::new()), @@ -53,21 +56,31 @@ pub fn all() -> Vec> { } ``` -Shipped modules: **`builtins`** (`ping`, `echo`, `hello`), **`dice`** -(`roll [NdM]`), **`hash`** (`md5`/`sha1`/`sha256`/`hash `, hand-rolled), -**`weather`** (`add ` then `w [location]` via wttr.in; per-user -locations saved to a per-network JSON file, path from `RUSTBOT_DATA_DIR`), and -web lookups over the shared `http`/`json` helpers: **`crypto `** (Bitstamp), -**`wiki `**, **`define `**, **`urban `**, **`tinyurl `**, -**`down `**. Module tests live in `tests/` — construct a module (or call -its pure formatter with a canned API body) and assert on the result, no network -required. +Web modules fetch with the shared `http::get` and parse with `json::Json`; each +has a pure formatter unit-tested against a canned API body (no network needed). + +## Commands + +Triggered by the configured prefix (default `!`, set with `prefix`); `help` +lists them at runtime and `help ` describes one. + +| Command | Does | +|---|---| +| `ping` / `echo ` / `hello` | basics | +| `roll [NdM]` | roll dice (default `1d6`) | +| `md5` / `sha1` / `sha256` / `hash ` | hex digests | +| `add ` then `w [location]` | weather (wttr.in), per-user location | +| `crypto ` | coin price in USD (Bitstamp) | +| `wiki ` | Wikipedia summary | +| `define ` / `urban ` | dictionary / Urban Dictionary | +| `tinyurl ` | shorten a URL | +| `down ` | is a site reachable? | ## Build & run ```sh cargo build # or: cargo build --release -cargo test # integration tests in tests/ (config + protocol) +cargo test # integration tests in tests/ cargo run ``` @@ -89,9 +102,11 @@ RUSTBOT_CONFIG=/etc/rustbot.conf cargo run ``` Config file keys: `server`, `port`, `tls`, `nick`, `user`, `realname`, -`channels` (comma/space-separated), `prefix`, `password`, `sasl_user`, -`sasl_pass`, and `name` (a network's log label). Whole-line `#`/`;` comments -only — inline comments would clash with channel `#`s. +`channels` (comma/space-separated), `prefix`, `verbose` (wire logging, default +on), `password`, `sasl_user`, `sasl_pass`, and `name` (a network's log label). +Whole-line `#`/`;` comments only — inline comments would clash with channel `#`s. + +Web modules write per-network state under `RUSTBOT_DATA_DIR` (default `.`). ### Multiple networks @@ -122,7 +137,7 @@ With more than one network, each network's log lines are tagged with its section name (`[libera] << …`) so the interleaved output stays readable. Environment overrides: `IRC_SERVER`, `IRC_PORT`, `IRC_TLS`, `IRC_NICK`, -`IRC_REALNAME`, `IRC_CHANNELS`, `IRC_PREFIX`, `IRC_PASSWORD`, +`IRC_REALNAME`, `IRC_CHANNELS`, `IRC_PREFIX`, `IRC_VERBOSE`, `IRC_PASSWORD`, `IRC_SASL_USER`, `IRC_SASL_PASS`. ```sh @@ -132,17 +147,6 @@ IRC_NICK=mybot IRC_CHANNELS='#test' cargo run # override the file for one run > If you put a real `password` in `rustbot.conf`, add it to `.gitignore` so the > secret isn't committed. -## Built-in commands - -With the default `!` prefix: - -- `!ping` → `pong` -- `!echo ` → echoes text back -- `!hello` → greets the sender -- `!help` → lists commands - -Add your own in `Bot::handle_command` in `src/bot.rs`. - ## Deployment (systemd) Runs as a system service (`User=debian`), auto-restarts on crash, and starts on @@ -155,7 +159,7 @@ sudo systemctl daemon-reload sudo systemctl enable --now rustbot # start now + on boot systemctl status rustbot # health -journalctl -u rustbot -f # live logs (<< in, >> out) +journalctl -u rustbot -f # live logs (<< in, >> out; verbose=false to quiet) sudo systemctl restart rustbot # after a rebuild ```