4b3864bb77ae53a46f4493097e8dfedefd80d2a6
Both services now send notifications to the hookshot webhook endpoint:
- Bazarr: switched from broken Apprise Matrix URL to JSON notifier
with jsons://matrix.lotusguild.org/webhook/<uuid>
- Huntarr: fixed apprise_url from raw https:// to jsons:// scheme
Both hookshot transforms updated to parse Apprise JSON payload:
{version, title, message, type, attachments}
Huntarr avatar set from selfhst icons CDN.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
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
PostgreSQL migrationTURN serverRoom structure + space setupMatrix bot (core + commands)LiveKit / Element CallSSO / OIDC (Authelia)Webhook integrations (hookshot)- Discord bridge (lets people transition gradually)
- Custom Element Web (chat.lotusguild.org with branding)
- Custom emoji packs
- Moderation bot
- 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 |
| 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.
Each service gets its own virtual user (@hookshot_<service>) with a unique avatar.
Webhook URL format: https://matrix.lotusguild.org/webhook/<uuid>
| 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 (Apprise JSON notifier) |
| Huntarr | 78af735b-7802-4e6c-987b-db22f8636ceb |
Hunt/search events (Apprise jsons://) |
| 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_datafor@hookshot - JS transformation functions use hookshot v2 API: set
result = { version: "v2", plain, html, msgtype } - The
resultvariable must be assigned withoutvar/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_tokenin hookshot-registration.yaml) impersonating each user
Server Checklist
Quality of Life
- Migrate from SQLite to PostgreSQL
- TURN/STUN server (coturn) for reliable voice/video
- URL previews
- Upload size limit 200MB
- Full-text message search (PostgreSQL backend)
- Media retention policy (remote: 1yr, local: 3yr)
- Sliding sync (native Synapse)
- LiveKit for Element Call video rooms
- Default room version v12, all rooms upgraded
- Landing page with client recommendations (Cinny, Commet, Element, Element X mobile)
- Push notifications gateway (Sygnal) for mobile clients
Auth & SSO
- Token-based registration
- SSO/OIDC via Authelia
allow_existing_users: truefor linking accounts to SSO- Password auth alongside SSO
Webhooks & Integrations
- matrix-hookshot 7.3.2 installed and running
- Generic webhook bridge for 13 services (incl. Bazarr + Huntarr via Apprise jsons://)
- Per-service JS transformation functions (formatted messages with emoji)
- Per-service virtual user avatars
- NPM reverse proxy for
/webhookpath - Tinker Tickets custom code
Bridging
- mautrix-discord bridge
- Bridge key channels (general, gaming, memes)
- Puppet bridging
Room Structure
- The Lotus Guild space
- All core rooms with correct power levels and join rules
- Spam and Stuff room for service notifications (hookshot)
- Custom room avatars
- Read-only announcements room
Hardening
- Rate limiting
- E2EE on all rooms (except Spam and Stuff — intentional for hookshot)
- Federation allow/deny lists
- Regular Synapse updates
- Automated database + media backups
Admin
- Synapse admin API dashboard (synapse-admin at http://10.10.10.29:8080)
- Power levels per room
- Mjolnir/Draupnir moderation bot
Bot Checklist
Core
- matrix-nio async client with E2EE
- Device trust (auto-trust all devices)
- Graceful shutdown (SIGTERM/SIGINT)
- Initial sync token (ignores old messages on startup)
- Auto-accept room invites
- Deployed as systemd service (
matrixbot.service) on LXC 151
Commands
!help— list commands!ping— latency check!8ball <question>— magic 8-ball!fortune— fortune cookie!flip— coin flip!roll <NdS>— dice roller!random <min> <max>— random number!rps <choice>— rock paper scissors!poll <question>— poll with reactions!trivia— trivia game (reactions, 30s reveal)!champion [lane]— random LoL champion!agent [role]— random Valorant agent!wordle— full Wordle game (daily, hard mode, stats, share)!minecraft <username>— RCON whitelist add!ask <question>— Ollama LLM (lotusllm, 2min cooldown)!health— bot uptime + service status
Welcome System
- Watches Space joins and DMs new members automatically
- React-to-join: react with ✅ in DM → bot invites to General, Commands, Memes
- Welcome event ID persisted to
welcome_state.json
Wordle
- Daily puzzles with two-pass letter evaluation
- Hard mode with constraint validation
- Stats persistence (
wordle_stats.json) - Cinny-compatible rendering (inline
<span>tiles) - DM-based gameplay,
!wordle shareposts result to public room - 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
Description
Languages
HTML
61.3%
JavaScript
25.2%
Shell
13.5%