feat: add Matrix transport (Element X, Element Web, FluffyChat)#3
Open
jchidley wants to merge 9 commits intotintinweb:masterfrom
Open
feat: add Matrix transport (Element X, Element Web, FluffyChat)#3jchidley wants to merge 9 commits intotintinweb:masterfrom
jchidley wants to merge 9 commits intotintinweb:masterfrom
Conversation
Add MatrixProvider implementing ITransportProvider using matrix-bot-sdk. - Auto-joins rooms on invite - Challenge-based auth (same OTP flow as other transports) - Rich HTML formatting for code blocks, bold, italic, links - Typing indicators - Group chat support with bot mention detection - Configure via /msg-bridge command or env vars (PI_MATRIX_HOMESERVER, PI_MATRIX_ACCESS_TOKEN) - Persistent sync state in ~/.pi/msg-bridge-matrix-store.json Setup: create a bot account on any Matrix homeserver, get an access token, then: /msg-bridge configure matrix <homeserver-url> <access-token>
Initial sync replays events from all rooms including ones the bot previously left. The handleMessage handler would then call getJoinedRoomMembers and checkAuthorization on rooms where the bot has no access, causing M_FORBIDDEN errors. Guard early by checking getJoinedRooms() before processing.
- Cache botUserId at connect time (was API call per message) - Cache joinedRooms as Set, updated via room.join/room.leave events (was getJoinedRooms() API call per message) - Skip events with origin_server_ts before connectedAt (prevents processing stale messages replayed during initial sync) - Simplify sendMessage to single call with conditional spread - Clean up state on disconnect Analysis artifacts in analysis/
- Constructor takes config object instead of raw args (matches Discord/Slack) - Add console.log/console.error logging (matches Discord pattern) - Input validation in connect() (matches Discord pattern) - Move escapeHtml to private method (matches Discord splitMessage pattern) - Add 'mx' abbreviation to status widget
Add persistent E2EE encryption using matrix-bot-sdk's built-in RustSdkCryptoStorageProvider backed by @matrix-org/matrix-sdk-crypto-nodejs (native Rust, SQLite on disk). - Crypto state persists at ~/.pi/msg-bridge-matrix-crypto/ (SQLite) - Same device and keys across restarts (no device proliferation) - Encrypted rooms are decrypted automatically - Device must be verified once from another Matrix client - encryption config option (defaults to enabled) - Falls back gracefully if crypto module not available
…failure - Cache per-room member count to eliminate getJoinedRoomMembers() API call on every incoming message. Seeded at connect, refreshed on join/leave, lazy-fetched on cache miss. - Add cleanup in connect() catch block: if client.start() throws, reset client, botUserId, joinedRooms, roomMemberCount so connect() can be retried cleanly. - Fresh code-overhaul analysis (v0.3.0) in analysis/.
Extract formatForMatrix, escapeHtml, shouldSkipEvent, extractUsername, wasBotMentioned, stripBotMention from MatrixProvider class into matrix-utils.ts for testability without mocks. Tests cover: HTML escaping, markdown→HTML conversion, code block protection, event filter chain (own/stale/non-text/edit/left-room), username extraction, mention detection, mention stripping. Boundary tests: connectedAt exact boundary, missing timestamps, homeservers with ports, empty strings.
Property tests: - formatForMatrix: body always preserves original input - formatForMatrix: no formattedBody when no markdown chars - stripBotMention: result never contains the bot MXID - escapeHtml: output never contains raw <, >, &, or " 47 tests total (43 EBTs + 4 property tests). All mutation gates passed (10/10 caught, 1 equivalent mutant).
e7ceb51 to
692aae5
Compare
matrix-bot-sdk replays historical events during initial sync and tries to decrypt them. For E2EE rooms this produces known errors that our connectedAt filter already handles. Instead of blanket log suppression, use a filtering logger that drops only: 1. MatrixClientLite 'Decryption error' — old messages without keys 2. MatrixHttpClient 'M_NOT_FOUND' — stale sync token references All other errors pass through normally. Filters are removed after initial sync completes — real errors during operation are never hidden. Note: Node.js DEP0060 (util._extend from upstream htmlencode dep) fires at import time before any runtime code executes. Cannot be suppressed without dynamic imports or patching the dependency.
692aae5 to
d7cd0ea
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Adds Matrix as a transport alongside Telegram, WhatsApp, Slack, and Discord.
New MatrixProvider using matrix-bot-sdk. Auto-joins rooms, OTP auth, rich HTML formatting, typing indicators, group chat support with mention detection.
Configure via command or env vars. Works with Element X, Element Web, FluffyChat, any Matrix client.