# dms-irc (Dank Chat) A [Dank Material Shell](https://github.com/AvengeMedia/DankMaterialShell) plugin that brings a unified chat frontend to the shell: IRC, Discord, and Sneedchat (SockChat, the Tor-only XenForo chat feature) today, with XMPP/Matrix/Slack support landing protocol by protocol without frontend changes. The architecture is deliberately service-agnostic - the QML side only ever sees a unified account/buffer/message model, never a protocol-specific concept. ## Why two parts Quickshell's QML runtime only exposes Unix-domain sockets, not raw TCP/TLS, so the actual protocol work can't live in QML. Instead: - **`chatd`** (`chatd-rs/`, Rust) speaks each protocol directly and translates it into a small unified JSON model (accounts, buffers, messages) over a Unix socket. It never exposes protocol-specific concepts to the plugin; it speaks the unified model, and each backend module happens to be how that model gets populated for a given service. - **The QML plugin** (top-level `*.qml`, `plugin.json`) spawns/supervises `chatd` and renders whatever it reports: a DankBar status pill, a slideout for quick access, and a floating window for a full chat session. ``` chatd-rs/ chatd - the Rust daemon, one crate per concern: chatd/src/backend/ one module per protocol (irc, discord, sockchat, ...) chatd/src/rpc/ the Unix-socket JSON-RPC server chatd/src/store.rs SQLite-backed scrollback persistence chatd/src/runtime.rs protocol-agnostic connection/buffer/message state *.qml the DMS plugin surfaces plugin.json points at directly: daemon supervisor, bar widget, startup check, settings entry views/ main chat UI: slideout/popout window, accounts, buffers, messages settings/ per-protocol settings panels loaded by views/ChatSettings.qml forms/ per-protocol account-connect forms loaded by views/AccountsPanel.qml plugin.json DMS plugin manifest ``` ## Building chatd ```bash cd chatd-rs cargo build --release ``` Enable the plugin in DMS (Settings → Plugins, or `dms ipc call plugins enable dankChat`). `StartupCheck.qml` verifies the built binary exists at `chatd-rs/target/release/chatd` before allowing activation. ## Opening the chat UI Besides the DankBar pill (`ChatBarWidget.qml`), `ChatDaemon.qml` registers an `IpcHandler` under the `dankChat` target for scripting/keybinds: ```bash dms ipc call dankChat toggle # open/close the slideout (or the floating window, if that's what's open) dms ipc call dankChat popout # open (or bring forward) the floating window directly ``` ## Protocol backends - **IRC** - TLS with SASL PLAIN, NickServ auto-identify, autojoin. - **Discord** - official cross-device QR login (the same one discord.com/app offers), a real-time gateway client, message edit/delete/reactions/replies sync. - **Sneedchat (SockChat)** - the Tor-only chat built into Kiwi Farms. Runs over an embedded Tor client (or an external SOCKS5 proxy), solves the site's own proof-of-work anti-bot gate, and connects to every configured room simultaneously (one persistent websocket per room, sharing a single login). Supports message edit/delete and avatars (fetched through the same Tor session and cached locally, since the frontend has no route to a `.onion` host on its own). - **XMPP/Matrix/Slack** - not implemented yet; see the project plan for the milestone list. ## Wire protocol Newline-delimited JSON over a Unix socket at `$XDG_RUNTIME_DIR/dms-chat/chatd.sock`: ``` request: {"id": 1, "method": "sendMessage", "params": {...}} response: {"id": 1, "result": {...}} or {"id": 1, "error": "..."} push: {"event": "message", "data": {...}} ``` Core methods: `listAccounts`, `listBuffers`, `listProtocols`, `addAccount`, `removeAccount`, `setAccountConnected`, `joinBuffer`, `partBuffer`, `sendMessage`, `editMessage`, `deleteMessage`, `subscribe`/`unsubscribe`, `getBacklog` (SQLite-backed, persists across `chatd` restarts). Each protocol also has its own account-creation method (`addAccount` for IRC, `addDiscordAccount`, `addSockChatAccount`, ...). Push events: `message`, `messageUpdated`, `messageDeleted`, `reactionsChanged`, `presenceChange`, `bufferListChange`, `connectionState`, `notification`, plus per-protocol login-flow events (`discordLoginQr`/`discordLoginScanned`/ `discordLoginResult`, `sockChatLoginStatus`/`sockChatLoginResult`). `message` and `presenceChange` are only delivered to clients that called `subscribe` for that buffer. ## Status Core loop is verified end to end through the actual DMS-spawned plugin: connect to real IRC networks over TLS with SASL PLAIN auth, log into Discord via QR and Sneedchat via username/password (+ optional TOTP 2FA), list/add accounts, join channels, send/ receive messages through a slideout or floating window, mentions flagged as highlights and pushed as notification events, and scrollback that survives a `chatd` restart. Not yet built: tab-complete, multi-account grouping in the buffer list, and XMPP/ Matrix/Slack backends. See the project plan for the full milestone list.