From 144193e3bbdefaa2ca9de66eb6bb23afd0552186 Mon Sep 17 00:00:00 2001 From: user Date: Sat, 21 Feb 2026 19:04:23 +0100 Subject: [PATCH] docs: update docs for multi-server support Co-Authored-By: Claude Opus 4.6 --- ROADMAP.md | 2 +- TASKS.md | 15 +++++++++++- TODO.md | 2 +- docs/CHEATSHEET.md | 29 +++++++++++++++++++++++ docs/USAGE.md | 57 +++++++++++++++++++++++++++++++++++++++++++--- 5 files changed, 99 insertions(+), 6 deletions(-) diff --git a/ROADMAP.md b/ROADMAP.md index 90388ef..ec6a11e 100644 --- a/ROADMAP.md +++ b/ROADMAP.md @@ -110,7 +110,7 @@ ## v2.0.0 -- Multi-Server + Integrations -- [ ] Multi-server support (per-server config, shared plugins) +- [x] Multi-server support (per-server config, shared plugins) - [ ] Stable plugin API (versioned, breaking change policy) - [x] Paste overflow (auto-paste long output to FlaskPaste, return link) - [x] URL shortener integration (shorten URLs in subscription announcements) diff --git a/TASKS.md b/TASKS.md index 916572e..259dd7c 100644 --- a/TASKS.md +++ b/TASKS.md @@ -1,6 +1,19 @@ # derp - Tasks -## Current Sprint -- v2.0.0 ACL + Webhook (2026-02-21) +## Current Sprint -- v2.0.0 Multi-Server (2026-02-21) + +| Pri | Status | Task | +|-----|--------|------| +| P0 | [x] | `build_server_configs()` in `src/derp/config.py` (legacy + multi layout) | +| P0 | [x] | `Bot.__init__` signature: `name`, `_pstate`, per-server state DB path | +| P0 | [x] | `cli.py` multi-bot loop: concurrent `asyncio.gather`, shared registry | +| P0 | [x] | 9 stateful plugins migrated to `_ps(bot)` pattern (rss, yt, twitch, alert, cron, pastemoni, remind, webhook, urltitle) | +| P0 | [x] | `core.py` -- `!version` shows `bot.name` | +| P1 | [x] | All affected tests updated (Bot signature, FakeBot._pstate, state access) | +| P1 | [x] | New tests: `TestServerName` (6), `TestBuildServerConfigs` (10) | +| P2 | [x] | Documentation update (USAGE.md, CHEATSHEET.md, ROADMAP.md, TODO.md) | + +## Previous Sprint -- v2.0.0 ACL + Webhook (2026-02-21) | Pri | Status | Task | |-----|--------|------| diff --git a/TODO.md b/TODO.md index 5d5d8da..377a15c 100644 --- a/TODO.md +++ b/TODO.md @@ -2,7 +2,7 @@ ## Core -- [ ] Multi-server support (per-server config, shared plugins) +- [x] Multi-server support (per-server config, shared plugins) - [ ] Stable plugin API (versioned, breaking change policy) - [x] Paste overflow (auto-paste long output to FlaskPaste) - [x] URL shortener integration (shorten URLs in subscription announcements) diff --git a/docs/CHEATSHEET.md b/docs/CHEATSHEET.md index e1b0549..3470c07 100644 --- a/docs/CHEATSHEET.md +++ b/docs/CHEATSHEET.md @@ -510,6 +510,35 @@ msg.params # All params list msg.tags # IRCv3 tags dict ``` +## Multi-Server + +```toml +# config/derp.toml +[bot] +prefix = "!" # Shared defaults +plugins_dir = "plugins" + +[servers.libera] +host = "irc.libera.chat" +port = 6697 +nick = "derp" +channels = ["#test"] + +[servers.oftc] +host = "irc.oftc.net" +port = 6697 +nick = "derpbot" +channels = ["#derp"] +admins = ["*!~admin@oftc.host"] # Per-server override +``` + +Per-server blocks accept both server keys (host, port, nick, tls, ...) +and bot overrides (prefix, channels, admins, ...). Unset keys inherit +from `[bot]`/`[server]` defaults. Legacy `[server]` config still works. + +State isolated per server: `data/state-libera.db`, `data/state-oftc.db`. +Plugins loaded once, shared across all servers. + ## Config Locations ``` diff --git a/docs/USAGE.md b/docs/USAGE.md index 725e72f..897e265 100644 --- a/docs/USAGE.md +++ b/docs/USAGE.md @@ -23,7 +23,9 @@ derp --config /path/to/derp.toml --verbose ## Configuration -All settings in `config/derp.toml`: +All settings in `config/derp.toml`. + +### Single-Server (Legacy) ```toml [server] @@ -67,6 +69,55 @@ port = 8080 # Bind port secret = "" # HMAC-SHA256 shared secret (empty = no auth) ``` +### Multi-Server + +Connect to multiple IRC servers from a single config. Plugins are loaded +once and shared; state is isolated per server (`data/state-.db`). + +```toml +[bot] +prefix = "!" # Shared defaults for all servers +plugins_dir = "plugins" +admins = ["*!~root@*.ops.net"] + +[servers.libera] +host = "irc.libera.chat" +port = 6697 +tls = true +nick = "derp" +channels = ["#test", "#ops"] + +[servers.oftc] +host = "irc.oftc.net" +port = 6697 +tls = true +nick = "derpbot" +channels = ["#derp"] +admins = ["*!~admin@oftc.host"] # Override shared admins + +[logging] +level = "info" +format = "json" + +[webhook] +enabled = true +port = 8080 +secret = "shared-secret" +``` + +Each `[servers.]` block may contain both server-level keys (host, +port, tls, nick, etc.) and bot-level overrides (prefix, channels, admins, +operators, trusted, rate_limit, rate_burst, paste_threshold). Unset keys +inherit from the shared `[bot]` and `[server]` defaults. + +The server name (e.g. `libera`, `oftc`) is used for: +- Log prefixes and `!version` output +- State DB path (`data/state-libera.db`) +- Plugin runtime state isolation + +Existing single-server configs (`[server]` section) continue to work +unchanged. The server name is derived from the hostname automatically. + ## Built-in Commands | Command | Description | @@ -358,8 +409,8 @@ keys = bot.state.keys("myplugin") bot.state.clear("myplugin") ``` -Data is stored in `data/state.db` (SQLite). Each plugin gets its own -namespace so keys never collide. +Data is stored in `data/state-.db` (SQLite, one per server). Each +plugin gets its own namespace so keys never collide. ### Inspection Commands (admin)