Files
IRC-kosmi-relay/README.md
cottongin c88b75f30d docs: comprehensive documentation overhaul
Rewrite README.md and all setup guides to reflect the current native
GraphQL WebSocket architecture (replacing stale headless Chrome/WebSocket
interception descriptions). Add new docs/IRC.md with complete IRC command
reference, vote syntax, and ticker symbol table.

Archive pre-edit docs to docs/archive/setup-backup-2026-05-10/ and move
historical development notes from docs/ root into docs/archive/.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-12 22:01:25 -04:00

335 lines
12 KiB
Markdown

> [!IMPORTANT]
> This project was developed entirely with AI coding assistance (Claude Opus 4.6 via Cursor IDE) and has not undergone rigorous review. It is provided as-is and may require adjustments for other environments.
# Kosmi-IRC Relay via Matterbridge
A Matterbridge-based bridge that relays messages bidirectionally between Kosmi chat rooms and IRC channels, with optional Jackbox Game Picker integration for live voting and game announcements.
## Features
- Real-time bidirectional message relay between Kosmi and IRC
- Native GraphQL-over-WebSocket connection to Kosmi (no browser required for basic use)
- Anonymous or authenticated Kosmi access (email/password login with token caching)
- Jackbox Game Picker integration: live vote detection, game announcements, room code images
- IRC commands: `!kreconnect`, `!jreconnect`, `!reconnect`, `!votes`
- Ticker-symbol voting for specific games (e.g. `QPL3++`, `TMP2--`)
- SIGUSR1 mute toggle for Jackbox announcements
- Automatic reconnection on connection loss
- Docker deployment with persistent token cache
## Architecture
This project is a trimmed fork of [Matterbridge](https://github.com/42wim/matterbridge) with two registered bridges: **Kosmi** and **IRC**. The Kosmi bridge connects directly to `wss://engine.kosmi.io/gql-ws` using the `graphql-transport-ws` protocol -- no headless browser is needed for the primary connection path.
### How It Works
1. **Anonymous access** (default): The bridge calls Kosmi's `anonLogin` HTTP mutation to obtain a JWT, then opens a native WebSocket connection.
2. **Authenticated access** (optional): If `Email` and `Password` are configured, headless Chrome (chromedp) performs a one-time browser login to extract a JWT. The token is cached locally and reused across restarts.
3. **Room subscription**: After connecting, the bridge subscribes to `newMessage` events via GraphQL and joins the configured room.
4. **Message relay**: Incoming Kosmi messages are forwarded to IRC (and vice versa) through the Matterbridge gateway, with configurable nick formatting.
### Message Flow
```
IRC User --> IRC Server --> Matterbridge Gateway --> Kosmi GraphQL WS --> Kosmi Room
Kosmi User --> Kosmi Room --> GraphQL subscription --> Matterbridge Gateway --> IRC Channel
```
### Jackbox Integration (Optional)
When enabled, the relay connects to a Jackbox Game Picker API via WebSocket (or webhook fallback) to:
- Detect `thisgame++`/`thisgame--` votes and ticker-symbol votes in chat
- Announce upcoming games with room codes (optionally as uploaded images)
- Respond to `!votes` queries with current vote tallies
## Installation
### Option 1: Docker (Recommended)
```bash
# 1. Copy and edit configuration
cp matterbridge.toml.example matterbridge.toml
nano matterbridge.toml
# 2. Build and run
docker-compose up -d
# 3. View logs
docker-compose logs -f
```
See [DOCKER_QUICKSTART.md](docs/setup/DOCKER_QUICKSTART.md) for a 5-minute setup guide.
### Option 2: Build from Source
#### Prerequisites
- Go 1.23 or higher
- Chrome/Chromium (only required if using email/password authentication)
- Access to an IRC server
- A Kosmi room URL
#### Building
```bash
git clone <repository-url>
cd irc-kosmi-relay
go mod download
go build -o matterbridge .
```
## Configuration
Copy `matterbridge.toml.example` to `matterbridge.toml` and edit it. The key sections:
```toml
# Kosmi configuration
[kosmi.hyperspaceout]
RoomURL="https://app.kosmi.io/room/@yourroom"
# Optional: Email/password for authenticated access
# Requires Chrome/Chromium for browser automation
Email=""
Password=""
RemoteNickFormat="[{PROTOCOL}] <{NICK}> "
# IRC configuration
[irc.zeronode]
Server="irc.libera.chat:6697"
Nick="kosmi-relay"
UseTLS=true
RemoteNickFormat="[{PROTOCOL}] <{NICK}> "
# Gateway to connect Kosmi and IRC
[[gateway]]
name="kosmi-irc-gateway"
enable=true
[[gateway.inout]]
account="kosmi.hyperspaceout"
channel="main"
[[gateway.inout]]
account="irc.zeronode"
channel="#your-channel"
# Jackbox integration (optional)
[jackbox]
Enabled=false
APIURL="https://your-jackbox-api.example.com"
AdminPassword=""
UseWebSocket=true
EnableRoomCodeImage=true
RoomCodeImageDelay=28
RoomCodePlaintextDelay=22
```
### Configuration Reference
#### Kosmi Settings
| Key | Required | Description |
|-----|----------|-------------|
| `RoomURL` | Yes | Full URL to the Kosmi room |
| `Email` | No | Email for authenticated access |
| `Password` | No | Password for authenticated access |
| `RemoteNickFormat` | No | Format for nicks from other bridges |
#### IRC Settings
| Key | Required | Description |
|-----|----------|-------------|
| `Server` | Yes | IRC server address with port |
| `Nick` | Yes | Bot's IRC nickname |
| `UseTLS` | No | Enable TLS (recommended) |
| `SkipTLSVerify` | No | Skip TLS cert verification |
| `NickServNick` | No | NickServ service nick |
| `NickServPassword` | No | NickServ password |
| `UseSASL` | No | Use SASL authentication |
| `RemoteNickFormat` | No | Format for nicks from other bridges |
| `Channels` | No | Channels to auto-join |
#### Jackbox Settings
| Key | Required | Description |
|-----|----------|-------------|
| `Enabled` | Yes | Enable/disable Jackbox integration |
| `APIURL` | Yes | Jackbox Game Picker API URL |
| `AdminPassword` | Yes | API admin password for JWT auth |
| `UseWebSocket` | No | Use WebSocket transport (default: true) |
| `WebhookPort` | No | Webhook listen port (if not using WS) |
| `WebhookSecret` | No | HMAC secret for webhook verification |
| `EnableRoomCodeImage` | No | Generate room code images |
| `RoomCodeImageDelay` | No | Seconds before sending image announcement |
| `RoomCodePlaintextDelay` | No | Seconds before sending plaintext room code |
## Usage
```bash
# Run the bridge
./matterbridge -conf matterbridge.toml
# Run with debug logging
./matterbridge -conf matterbridge.toml -debug
# Start with Jackbox announcements muted
./matterbridge -conf matterbridge.toml -muted
```
### CLI Flags
| Flag | Description |
|------|-------------|
| `-conf` | Path to config file (default: `matterbridge.toml`) |
| `-debug` | Enable debug logging |
| `-version` | Show version |
| `-muted` | Start with Jackbox announcements muted |
| `-gops` | Enable gops diagnostic agent |
### IRC Commands
Users can issue commands in IRC chat. See [docs/IRC.md](docs/IRC.md) for full details.
| Command | Description |
|---------|-------------|
| `!kreconnect` | Reconnect the Kosmi bridge |
| `!jreconnect` | Reconnect the Jackbox WebSocket |
| `!reconnect` | Reconnect all non-IRC services |
| `!votes` | Show vote tally for the current game |
| `thisgame++` / `thisgame--` | Vote on the current game |
| `SYMBOL++` / `SYMBOL--` | Vote on a game by ticker symbol |
### Mute Toggle
Jackbox announcements can be toggled at runtime without restarting:
```bash
# Local process
kill -SIGUSR1 $(pgrep matterbridge)
# Docker
docker kill -s SIGUSR1 kosmi-irc-relay
```
See [MUTE_CONTROL.md](docs/setup/MUTE_CONTROL.md) for details.
## Environment Variables
| Variable | Description |
|----------|-------------|
| `DEBUG=1` | Enable debug logging |
| `MATTERBRIDGE_DATA_DIR` | Directory for persistent data (token cache) |
| `TZ` | Timezone for container logs |
| `CHROME_BIN` | Path to Chrome binary (for auth only) |
## File Structure
```
irc-kosmi-relay/
├── matterbridge.go # Entry point: flags, logger, router, mute toggle
├── matterbridge.toml.example # Example configuration
├── Dockerfile # Docker build (Go 1.23 + Chromium for auth)
├── docker-compose.yml # Docker Compose deployment
├── bridge/
│ ├── config/
│ │ └── config.go # Message types, events, protocol config
│ ├── kosmi/
│ │ ├── kosmi.go # Kosmi bridge: Connect, Send, message handling
│ │ ├── graphql_ws_client.go # Native GraphQL-over-WebSocket client
│ │ ├── graphql.go # GraphQL message/payload structs
│ │ ├── auth.go # Anonymous login (anonLogin HTTP mutation)
│ │ ├── browser_auth.go # Chromedp browser login for email/password
│ │ ├── token_cache.go # JWT token caching (file-based)
│ │ ├── image_upload.go # Image upload to Kosmi CDN
│ │ └── errors.go # Error types
│ ├── irc/
│ │ ├── irc.go # IRC bridge: Connect, Send, NAMES handling
│ │ ├── handlers.go # PRIVMSG handler, commands, vote detection
│ │ └── formatting.go # IRC formatting helpers
│ └── jackbox/
│ ├── client.go # Jackbox API client (REST + WebSocket)
│ ├── votes.go # Vote detection (thisgame/ticker parsing)
│ ├── tickers.go # Ticker symbol -> game title lookup table
│ ├── webhook.go # Webhook transport (alternative to WS)
│ ├── image_upload.go # Room code image generation + upload
│ └── roomcode_image.go # Room code GIF rendering
├── gateway/
│ ├── gateway.go # Gateway message routing and transformation
│ ├── router.go # Router: message bus, Jackbox manager, broadcast
│ ├── handlers.go # Event handlers: reconnect, votes, files
│ └── bridgemap/
│ ├── bkosmi.go # Registers "kosmi" protocol
│ └── birc.go # Registers "irc" protocol
├── docs/
│ ├── IRC.md # IRC command reference
│ ├── setup/ # Setup and deployment guides
│ └── archive/ # Historical development notes
└── cmd/ # Standalone test/debug tools
```
## Troubleshooting
### Kosmi Connection Issues
**Bridge fails to connect to Kosmi**
- Verify `RoomURL` is correct and the room exists
- Check network connectivity to `app.kosmi.io` and `engine.kosmi.io`
- Enable debug logging (`-debug`) to see WebSocket handshake details
- Look for `"Successfully connected to Kosmi"` in logs
**Authentication fails (email/password)**
- Verify Chrome/Chromium is installed and accessible
- Check credentials are correct
- Delete `data/kosmi_token_cache.json` to force a fresh login
- See [BROWSER_AUTH_GUIDE.md](docs/setup/BROWSER_AUTH_GUIDE.md)
### IRC Connection Issues
- Verify server address and port
- Check TLS settings match the server's requirements
- Confirm the bot's nick is not already in use
- Check NickServ/SASL credentials if authentication is configured
### Messages Not Relaying
- Verify both bridges show as connected in logs
- Check gateway configuration: Kosmi channel must be `"main"`, IRC channel must include `#`
- Enable debug logging to trace message flow
- Look for `"Forwarding to Matterbridge"` and `"Sending message"` in logs
### Jackbox Integration Issues
- Verify `APIURL` is accessible and `AdminPassword` is correct
- Check that a Jackbox session is active with games being played
- Confirm `Enabled=true` in the `[jackbox]` config section
- See [JACKBOX_INTEGRATION.md](docs/setup/JACKBOX_INTEGRATION.md)
## Documentation
| Document | Description |
|----------|-------------|
| [IRC.md](docs/IRC.md) | IRC commands, voting syntax, ticker symbols |
| [DOCKER_QUICKSTART.md](docs/setup/DOCKER_QUICKSTART.md) | 5-minute Docker setup |
| [DOCKER_DEPLOYMENT.md](docs/setup/DOCKER_DEPLOYMENT.md) | Full Docker deployment guide |
| [QUICKSTART.md](docs/setup/QUICKSTART.md) | Build-from-source quickstart |
| [JACKBOX_INTEGRATION.md](docs/setup/JACKBOX_INTEGRATION.md) | Jackbox Game Picker setup |
| [BROWSER_AUTH_GUIDE.md](docs/setup/BROWSER_AUTH_GUIDE.md) | Email/password authentication |
| [TOKEN_PERSISTENCE.md](docs/setup/TOKEN_PERSISTENCE.md) | Token caching details |
| [MUTE_CONTROL.md](docs/setup/MUTE_CONTROL.md) | Mute toggle guide |
## Credits
- Based on [Matterbridge](https://github.com/42wim/matterbridge) by 42wim
- Kosmi API integration via reverse-engineered GraphQL protocol
## License
Same as Matterbridge (Apache 2.0)