# Lotus Matrix Bot & Server Roadmap Matrix bot and server infrastructure for the Lotus Guild homeserver (`matrix.lotusguild.org`). **Repo**: https://code.lotusguild.org/LotusGuild/matrixBot ## Status: Phase 4 — Webhooks & Integrations --- ## Priority Order 1. ~~PostgreSQL migration~~ 2. ~~TURN server~~ 3. ~~Room structure + space setup~~ 4. ~~Matrix bot (core + commands)~~ 5. ~~LiveKit / Element Call~~ 6. ~~SSO / OIDC (Authelia)~~ 7. ~~Webhook integrations (hookshot)~~ 8. Discord bridge (lets people transition gradually) 9. Custom Element Web (chat.lotusguild.org with branding) 10. Custom emoji packs 11. Moderation bot 12. Everything else --- ## Infrastructure | Service | Host | IP | LXC | Notes | |---------|------|----|-----|-------| | Synapse | large1 | 10.10.10.29 | 151 | Homeserver + coturn + LiveKit + hookshot | | PostgreSQL 17 | large1 | 10.10.10.2 | 109 | Synapse database backend | | NPM | compute-storage-01 | 10.10.10.27 | 139 | Reverse proxy + landing page | | Authelia | compute-storage-01 | 10.10.10.36 | 167 | SSO/OIDC provider | | LLDAP | large1 | 10.10.10.39 | 147 | LDAP user directory | **Key paths on Synapse LXC:** - Synapse config: `/etc/matrix-synapse/homeserver.yaml` - coturn config: `/etc/turnserver.conf` - LiveKit config: `/etc/livekit/config.yaml` - LiveKit service: `livekit-server.service` - Hookshot: `/opt/hookshot/`, service: `matrix-hookshot.service` - Hookshot config: `/opt/hookshot/config.yml` - Hookshot registration: `/etc/matrix-synapse/hookshot-registration.yaml` - Landing page: `/var/www/matrix-landing/index.html` (on NPM LXC 139) - Bot: `/opt/matrixbot/`, service: `matrixbot.service` **Port forwarding (router → 10.10.10.29):** - TCP+UDP 3478 (TURN/STUN signaling) - TCP+UDP 5349 (TURNS/TLS) - TCP 7881 (LiveKit ICE TCP fallback) - TCP+UDP 49152-65535 (TURN relay + LiveKit WebRTC media) --- ## Rooms (all v12) | Room | Room ID | Join Rule | |------|---------|-----------| | The Lotus Guild (Space) | `!-1ZBnAH-JiCOV8MGSKN77zDGTuI3pgSdy8Unu_DrDyc` | public | | General | `!wfokQ1-pE896scu_AOcCBA2s3L4qFo-PTBAFTd0WMI0` | public | | Commands | `!ou56mVZQ8ZB7AhDYPmBV5_BR28WMZ4x5zwZkPCqjq1s` | restricted (Space members) | | Memes | `!GK6v5cLEEnowIooQJv5jECfISUjADjt8aKhWv9VbG5U` | public | | Management | `!mEvR5fe3jMmzwd-FwNygD72OY_yu8H3UP_N-57oK7MI` | invite | | Cool Kids | `!R7DT3QZHG9P8QQvX6zsZYxjkKgmUucxDz_n31qNrC94` | invite | | Welcome | `!Y-wvNosuytqBOWampH9k-ta7bYXW7okqwBQ7PuRVBWE` | public | | Spam and Stuff | `!GttT4QYd1wlGlkHU3qTmq_P3gbyYKKeSSN6R7TPcJHg` | invite, **no E2EE** (hookshot) | **Power level roles (Cinny tags):** - 100: Owner (jared) - 50: The Nerdy Council (enhuynh, lonely) - 48: Panel of Geeks - 35: Cool Kids - 0: Member --- ## Webhook Integrations (matrix-hookshot 7.3.2) Generic webhooks bridged into **Spam and Stuff** via [matrix-hookshot](https://github.com/matrix-org/matrix-hookshot). Each service gets its own virtual user (`@hookshot_`) with a unique avatar. Webhook URL format: `https://matrix.lotusguild.org/webhook/` | Service | Webhook UUID | Notes | |---------|-------------|-------| | Grafana | `df4a1302-2d62-4a01-b858-fb56f4d3781a` | Unified alerting contact point | | Proxmox | `9b3eafe5-7689-4011-addd-c466e524661d` | Notification system (8.1+) | | Sonarr | `aeffc311-0686-42cb-9eeb-6757140c072e` | All event types | | Radarr | `34913454-c1ac-4cda-82ea-924d4a9e60eb` | All event types | | Readarr | `e57ab4f3-56e6-4dc4-8b30-2f4fd4bbeb0b` | All event types | | Lidarr | `66ac6fdd-69f6-4f47-bb00-b7f6d84d7c1c` | All event types | | Uptime Kuma | `1a02e890-bb25-42f1-99fe-bba6a19f1811` | Status change notifications | | Seerr | `555185af-90a1-42ff-aed5-c344e11955cf` | Request/approval events | | Owncast | `9993e911-c68b-4271-a178-c2d65ca88499` | STREAM_STARTED / STREAM_STOPPED | | Bazarr | `470fb267-3436-4dd3-a70c-e6e8db1721be` | Subtitle events | | Huntarr | `78af735b-7802-4e6c-987b-db22f8636ceb` | Hunt/search events | | Tinker-Tickets | `6e306faf-8eea-4ba5-83ef-bf8f421f929e` | Custom code needed | **Hookshot notes:** - Spam and Stuff is intentionally **unencrypted** — hookshot bridges cannot join E2EE rooms - Webhook tokens stored in Synapse PostgreSQL `room_account_data` for `@hookshot` - JS transformation functions use hookshot v2 API: set `result = { version: "v2", plain, html, msgtype }` - The `result` variable must be assigned without `var`/`let`/`const` (needs implicit global scope in the QuickJS IIFE sandbox) - NPM proxies `https://matrix.lotusguild.org/webhook/*` → `http://10.10.10.29:9003` - Virtual user avatars: set via appservice token (`as_token` in hookshot-registration.yaml) impersonating each user --- ## Server Checklist ### Quality of Life - [x] Migrate from SQLite to PostgreSQL - [x] TURN/STUN server (coturn) for reliable voice/video - [x] URL previews - [x] Upload size limit 200MB - [x] Full-text message search (PostgreSQL backend) - [x] Media retention policy (remote: 1yr, local: 3yr) - [x] Sliding sync (native Synapse) - [x] LiveKit for Element Call video rooms - [x] Default room version v12, all rooms upgraded - [x] Landing page with client recommendations (Cinny, Commet, Element, Element X mobile) - [ ] Push notifications gateway (Sygnal) for mobile clients ### Auth & SSO - [x] Token-based registration - [x] SSO/OIDC via Authelia - [x] `allow_existing_users: true` for linking accounts to SSO - [x] Password auth alongside SSO ### Webhooks & Integrations - [x] matrix-hookshot 7.3.2 installed and running - [x] Generic webhook bridge for 12 services - [x] Per-service JS transformation functions (formatted messages with emoji) - [x] Per-service virtual user avatars - [x] NPM reverse proxy for `/webhook` path - [ ] Bazarr native Matrix integration (hookshot connection exists as fallback) - [ ] Huntarr webhook format investigation - [ ] Tinker Tickets custom code ### Bridging - [ ] mautrix-discord bridge - [ ] Bridge key channels (general, gaming, memes) - [ ] Puppet bridging ### Room Structure - [x] The Lotus Guild space - [x] All core rooms with correct power levels and join rules - [x] Welcome room with react-to-join onboarding - [x] Spam and Stuff room for service notifications (hookshot) - [x] Custom room avatars - [ ] Read-only announcements room ### Hardening - [x] Rate limiting - [x] E2EE on all rooms (except Spam and Stuff — intentional for hookshot) - [ ] Federation allow/deny lists - [ ] Regular Synapse updates - [ ] Automated database + media backups ### Admin - [x] Synapse admin API dashboard (synapse-admin at http://10.10.10.29:8080) - [x] Power levels per room - [ ] Mjolnir/Draupnir moderation bot --- ## Bot Checklist ### Core - [x] matrix-nio async client with E2EE - [x] Device trust (auto-trust all devices) - [x] Graceful shutdown (SIGTERM/SIGINT) - [x] Initial sync token (ignores old messages on startup) - [x] Auto-accept room invites - [x] Deployed as systemd service (`matrixbot.service`) on LXC 151 ### Commands - [x] `!help` — list commands - [x] `!ping` — latency check - [x] `!8ball ` — magic 8-ball - [x] `!fortune` — fortune cookie - [x] `!flip` — coin flip - [x] `!roll ` — dice roller - [x] `!random ` — random number - [x] `!rps ` — rock paper scissors - [x] `!poll ` — poll with reactions - [x] `!trivia` — trivia game (reactions, 30s reveal) - [x] `!champion [lane]` — random LoL champion - [x] `!agent [role]` — random Valorant agent - [x] `!wordle` — full Wordle game (daily, hard mode, stats, share) - [x] `!minecraft ` — RCON whitelist add - [x] `!ask ` — Ollama LLM (lotusllm, 2min cooldown) - [x] `!health` — bot uptime + service status ### Welcome System - [x] Auto-post welcome message in Welcome room on startup - [x] React-to-join: react with ✅ → bot invites to General, Commands, Memes - [x] Welcome event ID persisted to `welcome_state.json` - [x] Watches Space joins and DMs new members ### Wordle - [x] Daily puzzles with two-pass letter evaluation - [x] Hard mode with constraint validation - [x] Stats persistence (`wordle_stats.json`) - [x] Cinny-compatible rendering (inline `` tiles) - [x] DM-based gameplay, `!wordle share` posts result to public room - [x] Virtual keyboard display --- ## Tech Stack | Component | Technology | |-----------|-----------| | Bot language | Python 3 | | Bot library | matrix-nio (E2EE) | | Homeserver | Synapse 1.147+ | | Database | PostgreSQL 17 | | TURN | coturn | | Video calls | LiveKit + lk-jwt-service | | SSO | Authelia (OIDC) + LLDAP | | Webhook bridge | matrix-hookshot 7.3.2 | | Reverse proxy | Nginx Proxy Manager | | Bot dependencies | matrix-nio[e2ee], aiohttp, python-dotenv, mcrcon | ## Bot Files ``` matrixBot/ ├── bot.py # Entry point, client setup, event loop ├── callbacks.py # Message + reaction event handlers ├── commands.py # All command implementations ├── config.py # Environment config + validation ├── utils.py # send_text, send_html, send_reaction, get_or_create_dm ├── welcome.py # Welcome message + react-to-join logic ├── wordle.py # Full Wordle game engine ├── wordlist_answers.py # Wordle answer word list ├── wordlist_valid.py # Wordle valid guess word list ├── .env.example # Environment variable template └── requirements.txt # Python dependencies ```