docs: update docs for Mumble integration

Add Mumble sections to USAGE.md, CHEATSHEET.md, API.md, README.md.
Mark Mumble done in ROADMAP.md and TODO.md. Update TASKS.md sprint.
This commit is contained in:
user
2026-02-21 21:02:46 +01:00
parent 37c858f4d7
commit ca46042c41
7 changed files with 262 additions and 1 deletions

View File

@@ -357,6 +357,87 @@ Same stable attributes and methods as `Bot`:
---
## `derp.mumble` -- Mumble Adapter
Alternative bot adapter for Mumble via TCP/TLS protobuf control channel
(text chat only). All TCP routed through SOCKS5 proxy. Uses a minimal
built-in protobuf encoder/decoder (no external dependency). Exposes the
same plugin API as `derp.bot.Bot`.
### `MumbleMessage` dataclass
Duck-typed compatible with IRC `Message`:
| Field | Type | Description |
|-------|------|-------------|
| `raw` | `dict` | Decoded protobuf fields |
| `nick` | `str \| None` | Sender username (from session lookup) |
| `prefix` | `str \| None` | Sender username (for ACL) |
| `text` | `str \| None` | Message body (HTML stripped) |
| `target` | `str \| None` | channel_id as string (or `"dm"`) |
| `is_channel` | `bool` | `True` for channel msgs, `False` for DMs |
| `command` | `str` | Always `"PRIVMSG"` (compat shim) |
| `params` | `list[str]` | `[target, text]` |
| `tags` | `dict[str, str]` | Empty dict (no IRCv3 tags) |
### `MumbleBot`
Same stable attributes and methods as `Bot`:
| Attribute | Type | Description |
|-----------|------|-------------|
| `name` | `str` | Always `"mumble"` |
| `config` | `dict` | Merged TOML configuration |
| `nick` | `str` | Bot username (from config) |
| `prefix` | `str` | Command prefix (from `[mumble]` or `[bot]`) |
| `state` | `StateStore` | Persistent key-value storage |
| `registry` | `PluginRegistry` | Shared command and event registry |
**Sending messages** -- same signatures, Mumble protobuf transport:
| Method | Behaviour |
|--------|-----------|
| `send(target, text)` | TextMessage to channel (HTML-escaped) |
| `reply(msg, text)` | `send(msg.target, text)` |
| `long_reply(msg, lines, *, label="")` | Paste overflow, same logic as IRC |
| `action(target, text)` | Italic HTML text (`<i>...</i>`) |
| `shorten_url(url)` | Same FlaskPaste integration |
**IRC no-ops** (debug log, no error):
`join`, `part`, `kick`, `mode`, `set_topic`
**Plugin management** -- delegates to shared registry:
`load_plugins`, `load_plugin`, `reload_plugin`, `unload_plugin`
**Permission tiers** -- same model, exact username string matching:
`_get_tier(msg)`, `_is_admin(msg)`
### Protobuf Codec (internal)
Minimal protobuf wire format helpers -- not part of the stable API:
| Function | Description |
|----------|-------------|
| `_encode_varint(value)` | Encode unsigned int as protobuf varint |
| `_decode_varint(data, offset)` | Decode varint, returns `(value, offset)` |
| `_encode_field(num, wire_type, value)` | Encode a single protobuf field |
| `_decode_fields(data)` | Decode payload into `{field_num: [values]}` |
| `_pack_msg(msg_type, payload)` | Wrap payload in 6-byte Mumble header |
| `_unpack_header(data)` | Unpack header into `(msg_type, length)` |
### Helper Functions
| Function | Signature | Description |
|----------|-----------|-------------|
| `_strip_html` | `(text: str) -> str` | Strip HTML tags and unescape entities |
| `_escape_html` | `(text: str) -> str` | Escape text for Mumble HTML messages |
| `_build_mumble_message` | `(fields, users, our_session) -> MumbleMessage \| None` | Build message from decoded TextMessage fields |
---
## Handler Signatures
All command and event handlers are async functions receiving `bot` and

View File

@@ -521,6 +521,26 @@ Long-polling via `getUpdates` -- no public endpoint needed. All HTTP
through SOCKS5 proxy. Strips `@botusername` suffix in groups. Messages
split at 4096 chars. IRC-only commands are no-ops. ~90% of plugins work.
## Mumble Integration
```toml
# config/derp.toml
[mumble]
enabled = true
host = "mumble.example.com"
port = 64738
username = "derp"
password = ""
tls_verify = false # self-signed certs common
admins = ["admin_user"] # Mumble usernames
operators = []
trusted = []
```
TCP/TLS via SOCKS5 proxy. Text chat only (no voice). Minimal protobuf
codec (no external dep). HTML stripped on receive, escaped on send.
IRC-only commands are no-ops. ~90% of plugins work.
## Plugin Template
```python

View File

@@ -1474,3 +1474,83 @@ this automatically: `!help@mybot` becomes `!help`.
All HTTP traffic (API calls, long-polling) routes through the SOCKS5
proxy at `127.0.0.1:1080` via `derp.http.urlopen`. No direct outbound
connections are made.
## Mumble Integration
Connect derp to a Mumble server via TCP/TLS protobuf control channel.
Text chat only (no voice). All TCP is routed through the SOCKS5 proxy.
No protobuf library dependency -- uses a minimal built-in varint/field
encoder/decoder for the ~7 message types needed.
### How It Works
The bot connects to the Mumble server over TLS (via SOCKS5), sends
Version and Authenticate messages, then enters a read loop. It tracks
channels (ChannelState), users (UserState), and dispatches commands
from TextMessage messages through the shared plugin registry.
### Configuration
```toml
[mumble]
enabled = true
host = "mumble.example.com" # Mumble server hostname
port = 64738 # Default Mumble port
username = "derp" # Bot username
password = "" # Server password (optional)
tls_verify = false # Mumble commonly uses self-signed certs
admins = ["admin_user"] # Mumble usernames
operators = [] # Mumble usernames
trusted = [] # Mumble usernames
```
### Mumble Setup
1. **Ensure a Mumble server** (Murmur/Mumble-server) is running and
accessible through the SOCKS5 proxy
2. **Configure the bot** with the server hostname, port, and credentials
3. **Configure permissions** using Mumble registered usernames. Use
`!whoami` to discover your username as the bot sees it.
### Permission Tiers
Same 4-tier model as IRC, but matches exact Mumble usernames instead of
fnmatch hostmask patterns:
```toml
[mumble]
admins = ["admin_user"]
operators = ["oper_user"]
trusted = ["trusted_user"]
```
### Plugin Compatibility
Same compatibility as Teams/Telegram -- ~90% of plugins work without
modification.
| Feature | IRC | Mumble |
|---------|-----|--------|
| `bot.reply()` | Sends PRIVMSG | TextMessage to channel |
| `bot.send()` | Sends PRIVMSG | TextMessage to channel |
| `bot.action()` | CTCP ACTION | Italic HTML text (`<i>...</i>`) |
| `bot.long_reply()` | Paste overflow | Paste overflow (same logic) |
| `bot.state` | Per-server SQLite | Per-server SQLite |
| `bot.join/part/kick/mode` | IRC commands | No-op (logged at debug) |
| Event handlers (JOIN, etc.) | Fired on IRC events | Not triggered |
| Hostmask ACL | fnmatch patterns | Exact usernames |
### Text Encoding
Mumble uses HTML for text messages. On receive, the bot strips tags and
unescapes entities. On send, text is HTML-escaped. Action messages use
`<i>` tags for italic formatting.
### Transport
All TCP connections route through the SOCKS5 proxy at `127.0.0.1:1080`
via `derp.http.create_connection`. TLS is applied on top of the proxied
socket. Mumble commonly uses self-signed certificates, so `tls_verify`
defaults to `false`.