2026-05-12 22:01:25 -04:00
> [!IMPORTANT]
2026-04-05 05:58:34 -04:00
> 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.
2025-10-31 16:17:04 -04:00
# Kosmi-IRC Relay via Matterbridge
2026-05-12 22:01:25 -04:00
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.
2025-10-31 16:17:04 -04:00
## Features
2026-05-12 22:01:25 -04:00
- 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
2025-10-31 16:17:04 -04:00
## Architecture
2026-05-12 22:01:25 -04:00
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.
2025-10-31 16:17:04 -04:00
2026-05-12 22:01:25 -04:00
### How It Works
2025-10-31 16:17:04 -04:00
2026-05-12 22:01:25 -04:00
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.
2025-10-31 16:17:04 -04:00
2026-05-12 22:01:25 -04:00
### Message Flow
2025-10-31 16:17:04 -04:00
2026-05-12 22:01:25 -04:00
```
IRC User --> IRC Server --> Matterbridge Gateway --> Kosmi GraphQL WS --> Kosmi Room
Kosmi User --> Kosmi Room --> GraphQL subscription --> Matterbridge Gateway --> IRC Channel
```
2025-10-31 16:17:04 -04:00
2026-05-12 22:01:25 -04:00
### 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
2025-10-31 16:17:04 -04:00
2026-05-12 22:01:25 -04:00
### Option 1: Docker (Recommended)
2025-10-31 16:17:04 -04:00
```bash
2026-05-12 22:01:25 -04:00
# 1. Copy and edit configuration
cp matterbridge.toml.example matterbridge.toml
2025-10-31 16:17:04 -04:00
nano matterbridge.toml
# 2. Build and run
docker-compose up -d
# 3. View logs
docker-compose logs -f
```
2026-05-12 22:01:25 -04:00
See [DOCKER_QUICKSTART.md ](docs/setup/DOCKER_QUICKSTART.md ) for a 5-minute setup guide.
2025-10-31 16:17:04 -04:00
### Option 2: Build from Source
#### Prerequisites
2026-05-12 22:01:25 -04:00
- Go 1.23 or higher
- Chrome/Chromium (only required if using email/password authentication)
2025-10-31 16:17:04 -04:00
- Access to an IRC server
- A Kosmi room URL
#### Building
```bash
git clone <repository-url>
cd irc-kosmi-relay
go mod download
2026-05-12 22:01:25 -04:00
go build -o matterbridge .
2025-10-31 16:17:04 -04:00
```
## Configuration
2026-05-12 22:01:25 -04:00
Copy `matterbridge.toml.example` to `matterbridge.toml` and edit it. The key sections:
2025-10-31 16:17:04 -04:00
```toml
# Kosmi configuration
[kosmi.hyperspaceout]
2026-05-12 22:01:25 -04:00
RoomURL="https://app.kosmi.io/room/@yourroom "
# Optional: Email/password for authenticated access
# Requires Chrome/Chromium for browser automation
Email=""
Password=""
RemoteNickFormat="[{PROTOCOL}] <{NICK}> "
2025-10-31 16:17:04 -04:00
# IRC configuration
2026-05-12 22:01:25 -04:00
[irc.zeronode]
Server="irc.libera.chat:6697"
2025-10-31 16:17:04 -04:00
Nick="kosmi-relay"
2026-05-12 22:01:25 -04:00
UseTLS=true
RemoteNickFormat="[{PROTOCOL}] <{NICK}> "
2025-10-31 16:17:04 -04:00
# Gateway to connect Kosmi and IRC
[[gateway]]
name="kosmi-irc-gateway"
enable=true
[[gateway.inout]]
account="kosmi.hyperspaceout"
channel="main"
[[gateway.inout]]
2026-05-12 22:01:25 -04:00
account="irc.zeronode"
2025-10-31 16:17:04 -04:00
channel="#your -channel"
2026-05-12 22:01:25 -04:00
# Jackbox integration (optional)
[jackbox]
Enabled=false
APIURL="https://your-jackbox-api.example.com"
AdminPassword=""
UseWebSocket=true
EnableRoomCodeImage=true
RoomCodeImageDelay=28
RoomCodePlaintextDelay=22
2025-10-31 16:17:04 -04:00
```
2026-05-12 22:01:25 -04:00
### Configuration Reference
2025-10-31 16:17:04 -04:00
#### Kosmi Settings
2026-05-12 22:01:25 -04:00
| 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 |
2025-10-31 16:17:04 -04:00
#### IRC Settings
2026-05-12 22:01:25 -04:00
| 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 |
2025-10-31 16:17:04 -04:00
## Usage
```bash
# Run the bridge
./matterbridge -conf matterbridge.toml
# Run with debug logging
./matterbridge -conf matterbridge.toml -debug
2026-05-12 22:01:25 -04:00
# Start with Jackbox announcements muted
./matterbridge -conf matterbridge.toml -muted
```
2025-10-31 16:17:04 -04:00
2026-05-12 22:01:25 -04:00
### CLI Flags
2025-10-31 16:17:04 -04:00
2026-05-12 22:01:25 -04:00
| 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 |
2025-10-31 16:17:04 -04:00
2026-05-12 22:01:25 -04:00
### IRC Commands
2025-10-31 16:17:04 -04:00
2026-05-12 22:01:25 -04:00
Users can issue commands in IRC chat. See [docs/IRC.md ](docs/IRC.md ) for full details.
2025-10-31 16:17:04 -04:00
2026-05-12 22:01:25 -04:00
| 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 |
2025-10-31 16:17:04 -04:00
2026-05-12 22:01:25 -04:00
### Mute Toggle
2025-10-31 16:17:04 -04:00
2026-05-12 22:01:25 -04:00
Jackbox announcements can be toggled at runtime without restarting:
2025-10-31 16:17:04 -04:00
2026-05-12 22:01:25 -04:00
```bash
# Local process
kill -SIGUSR1 $(pgrep matterbridge)
2025-10-31 16:17:04 -04:00
2026-05-12 22:01:25 -04:00
# Docker
docker kill -s SIGUSR1 kosmi-irc-relay
2025-10-31 16:17:04 -04:00
```
2026-05-12 22:01:25 -04:00
See [MUTE_CONTROL.md ](docs/setup/MUTE_CONTROL.md ) for details.
2025-10-31 16:17:04 -04:00
2026-05-12 22:01:25 -04:00
## Environment Variables
2025-10-31 16:17:04 -04:00
2026-05-12 22:01:25 -04:00
| 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) |
2025-10-31 16:17:04 -04:00
2026-05-12 22:01:25 -04:00
## File Structure
2025-10-31 16:17:04 -04:00
2026-05-12 22:01:25 -04:00
```
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
2025-10-31 16:17:04 -04:00
```
## Troubleshooting
2026-05-12 22:01:25 -04:00
### Kosmi Connection Issues
2025-10-31 16:17:04 -04:00
2026-05-12 22:01:25 -04:00
**Bridge fails to connect to Kosmi**
2025-10-31 16:17:04 -04:00
2026-05-12 22:01:25 -04:00
- 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
2025-10-31 16:17:04 -04:00
2026-05-12 22:01:25 -04:00
**Authentication fails (email/password)**
2025-10-31 16:17:04 -04:00
2026-05-12 22:01:25 -04:00
- 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 )
2025-10-31 16:17:04 -04:00
2026-05-12 22:01:25 -04:00
### IRC Connection Issues
2025-10-31 16:17:04 -04:00
2026-05-12 22:01:25 -04:00
- 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
2025-10-31 16:17:04 -04:00
2026-05-12 22:01:25 -04:00
### Messages Not Relaying
2025-10-31 16:17:04 -04:00
2026-05-12 22:01:25 -04:00
- 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
2025-10-31 16:17:04 -04:00
2026-05-12 22:01:25 -04:00
### Jackbox Integration Issues
2025-10-31 16:17:04 -04:00
2026-05-12 22:01:25 -04:00
- 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 )
2025-10-31 16:17:04 -04:00
2026-05-12 22:01:25 -04:00
## Documentation
2025-10-31 16:17:04 -04:00
2026-05-12 22:01:25 -04:00
| 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 |
2025-10-31 16:17:04 -04:00
## Credits
- Based on [Matterbridge ](https://github.com/42wim/matterbridge ) by 42wim
2026-05-12 22:01:25 -04:00
- Kosmi API integration via reverse-engineered GraphQL protocol
2025-10-31 16:17:04 -04:00
## License
Same as Matterbridge (Apache 2.0)