mirror of
https://github.com/profullstack/agentbbs.git
synced 2026-08-13 14:27:27 +00:00
feat(messaging): group & broadcast messages + email-all
Members can now message a group or everyone, and the operator can announce to
the whole membership by email.
Inbox channel (any member):
- msg@ recipient spec accepts a comma list (alice,bob,carol) or all/*/everyone
to broadcast: `ssh msg@host alice,bob hi`, `ssh msg@host all hi`.
- Members hub TUI gains multi-select: space toggles, `a` selects all, `m`
messages the selected group (header names the audience); selection clears
after send.
- store.SendMessageMulti delivers one body to many inboxes in a single
transaction (dedupes, skips empties); resolveRecipients validates names,
excludes the sender, and skips banned members on broadcast.
Email channel (operator, explicit):
- new `agentbbs broadcast` subcommand sends an announcement to ALL members via
inbox + email. Preview by default (like notify-creds); --send delivers;
--no-inbox/--no-email pick a channel; --subject/--from/--user refine it.
Email reaches only verified addresses and refuses --send without SMTP.
Tests: SendMessageMulti (dedupe/empty), resolveRecipients (list/unknown/all
tokens, banned + sender exclusion), TUI selection (toggle/select-all/group
compose). Docs: docs/messaging.md. build/vet/gofmt/`go test ./...` green.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
parent
54da317f4e
commit
103ddeb7c9
8 changed files with 658 additions and 32 deletions
83
docs/messaging.md
Normal file
83
docs/messaging.md
Normal file
|
|
@ -0,0 +1,83 @@
|
|||
# Member messaging — direct, group & broadcast
|
||||
|
||||
AgentBBS members leave each other store-and-forward notes (the `messages` table).
|
||||
Recipients read them in the hub's **Members ▸ inbox**; an unread badge shows on
|
||||
login. There are two delivery channels:
|
||||
|
||||
- **BBS inbox** — in-BBS, members-only. Any member can message one member, a
|
||||
hand-picked group, or everyone. This is the default.
|
||||
- **Email** — reaches members in their actual mailbox. This is a separate,
|
||||
explicit operator action (`agentbbs broadcast`), so an ordinary group message
|
||||
never fans out to email.
|
||||
|
||||
## Inbox messaging — the `msg@` route
|
||||
|
||||
```bash
|
||||
ssh msg@bbs.profullstack.com bob hi there # one member
|
||||
ssh msg@bbs.profullstack.com alice,bob,carol hi # a group (comma-separated, no spaces)
|
||||
ssh msg@bbs.profullstack.com all heads up, all # broadcast to every member
|
||||
echo "long note" | ssh msg@bbs.profullstack.com all # body from stdin
|
||||
```
|
||||
|
||||
The first argument is the **recipient spec**; the rest is the message (or stdin
|
||||
when omitted). The spec is either a comma-separated list of member names, or one
|
||||
of `all` / `*` / `everyone` / `@all` to reach everyone. The sender, unknown
|
||||
names, duplicates, and banned accounts are handled for you: you can't message
|
||||
yourself, an unknown name aborts the send with a hint, and a broadcast skips
|
||||
banned members. Requires your registered SSH key (members only).
|
||||
|
||||
## Inbox messaging — the hub TUI
|
||||
|
||||
In **Members** (the in-hub directory):
|
||||
|
||||
| Key | Action |
|
||||
|---|---|
|
||||
| `↑/↓` | move the cursor |
|
||||
| `space` | select / deselect the member under the cursor |
|
||||
| `a` | select all (press again to clear) |
|
||||
| `m` | message — the selected group if any, else the member under the cursor |
|
||||
| `enter` | finger (view) the member |
|
||||
| `i` | open your inbox |
|
||||
| `q` | back |
|
||||
|
||||
Selected rows show `[x]`; a "`N selected`" line appears once a group is started.
|
||||
`m` opens a one-line composer whose header names the audience (e.g. `3 members`);
|
||||
`enter` sends to everyone in the group at once, `esc` cancels. The selection
|
||||
clears after a successful send.
|
||||
|
||||
All inbox writes for a group/broadcast happen in **one transaction**
|
||||
(`store.SendMessageMulti`), so a partial failure never leaves some inboxes
|
||||
written and others not.
|
||||
|
||||
## Email broadcast — `agentbbs broadcast` (operator)
|
||||
|
||||
Reaching every member by **email** (e.g. a maintenance notice) is an operator
|
||||
command run on the host where the DB and SMTP env live. Like `notify-creds` it is
|
||||
a **preview by default** and only delivers under `--send`.
|
||||
|
||||
```bash
|
||||
agentbbs broadcast "We're upgrading the box at 0200 UTC." # PREVIEW (sends nothing)
|
||||
agentbbs broadcast --send "Heads up: brief downtime tonight." # inbox + email to all
|
||||
echo "long notice" | agentbbs broadcast --send # body on stdin
|
||||
agentbbs broadcast --send --no-email "BBS-only notice" # inbox channel only
|
||||
agentbbs broadcast --send --no-inbox --subject "Outage" "..." # email channel only
|
||||
agentbbs broadcast --send --user alice,bob "targeted note" # only these members
|
||||
```
|
||||
|
||||
| Flag | Effect |
|
||||
|---|---|
|
||||
| *(none)* | **Preview** — prints intended deliveries, sends nothing. |
|
||||
| `--send` | Actually deliver. |
|
||||
| `--no-inbox` | Skip the BBS inbox channel. |
|
||||
| `--no-email` | Skip the email channel (inbox-only broadcast). |
|
||||
| `--from NAME` | Inbox sender name (default `sysop`, or `AGENTBBS_BROADCAST_FROM`). |
|
||||
| `--subject S` | Email subject (default `Announcement from <host>`). |
|
||||
| `--user a,b` | Restrict to a comma-separated allow-list (default: all members). |
|
||||
|
||||
The **inbox** channel reaches every non-banned member in scope; the **email**
|
||||
channel reaches only members with a **verified** address (others are skipped).
|
||||
`--send` refuses the email channel when SMTP is unconfigured
|
||||
(`AGENTBBS_SMTP_HOST`/`_FROM`) — use `--no-email` for an inbox-only blast. It
|
||||
prints a per-channel delivered/failed summary and exits non-zero on any email
|
||||
failure. The email footer tells members how to reply in-BBS
|
||||
(`ssh msg@<host> sysop <reply>`).
|
||||
Loading…
Add table
Add a link
Reference in a new issue