Root README orients new contributors on the build/upload/iterate loop and points at ~/dev/CLAUDE.md for maubot patterns. journal/ README covers the three commands, the SQLite schema, known quirks (edits don't re-trigger, subcommand detection scope), and documents why this plugin uses @command.passive instead of the more obvious @command.new. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
||
|---|---|---|
| .. | ||
| journal.py | ||
| maubot.yaml | ||
| README.md | ||
journal
Daily-journal Matrix bot. Each room member can record what they did, and anyone in the room can query the log.
Commands
!journal <what you did> record an entry (multi-line OK)
!journal show [@user:domain] last 10 entries, optionally filtered by user
!journal today all entries from today (UTC)
Multi-line works either inline or after a newline:
!journal Did three things today:
- planted garlic
- mucked out the goat pen
- finished the irrigation patch
!journal
- planted garlic
- mucked out the goat pen
Both record the full body verbatim.
Storage
One SQLite database per maubot instance, at
/var/lib/maubot/plugin-dbs/journal.db on the host. Schema (managed
by mautrix.util.async_db.UpgradeTable):
CREATE TABLE entries (
id INTEGER PRIMARY KEY AUTOINCREMENT,
user TEXT NOT NULL, -- @sender:domain
room TEXT NOT NULL, -- !roomid:domain
ts BIGINT NOT NULL, -- ms since epoch (from evt.timestamp)
text TEXT NOT NULL -- raw entry body
);
CREATE INDEX entries_user_ts ON entries (user, ts DESC);
CREATE INDEX entries_ts ON entries (ts DESC);
Wipe data via the maubot UI's per-instance Database tab:
DELETE FROM entries;
DELETE FROM sqlite_sequence WHERE name = 'entries';
(The second line resets the auto-increment counter; skip it if you'd rather keep IDs monotonic across resets.)
Known quirks
- Edited messages don't re-trigger the bot. Matrix sends edits as
a separate
m.replaceevent that bots don't react to. If you typed!journalthen edited the message to add content, the bot saw only the empty!journaland won't record. Send a fresh message instead of editing. !journal show <random text>runs the show query with that text as the user filter. If it doesn't match any MXID, you get "No entries." Use a fully-qualified MXID like@pat:ariege.io.- Subcommand detection only looks at the first line. Anything
starting with
showortodayon the first line dispatches to the query handlers; anything else (including prose that happens to contain "show" mid-text) records as an entry.
Architecture note
This plugin uses @command.passive with a regex matcher rather than
@command.new. The reason — and why other plugins should consider the
same pattern for prose-input commands — is documented in ~/dev/CLAUDE.md
under "Multi-line freeform parent commands". Short version:
@command.new silently drops !journal\n<content> because maubot's
parser only treats space as the command/args delimiter, leading to
invisible data loss when users naturally hit Enter after the command.