277 lines
7.2 KiB
Markdown
277 lines
7.2 KiB
Markdown
# Kosmi-IRC Relay via Matterbridge
|
|
|
|
A Matterbridge plugin that bridges Kosmi chat rooms with IRC channels, enabling bidirectional message relay.
|
|
|
|
## Features
|
|
|
|
- ✅ Real-time message relay between Kosmi and IRC
|
|
- ✅ Headless Chrome automation for reliable Kosmi connection
|
|
- ✅ WebSocket interception using Chrome DevTools Protocol
|
|
- ✅ Anonymous Kosmi access (no authentication required)
|
|
- ✅ Message formatting with source indicators
|
|
- ✅ Automatic reconnection handling
|
|
- ✅ Support for any Kosmi room via URL configuration
|
|
|
|
## Architecture
|
|
|
|
This implementation extends Matterbridge with a custom Kosmi bridge that:
|
|
|
|
1. Launches a headless Chrome instance using `chromedp`
|
|
2. Navigates to the Kosmi room and injects a WebSocket interceptor **before page load**
|
|
3. Captures GraphQL WebSocket messages (`wss://engine.kosmi.io/gql-ws`) from the page
|
|
4. Relays messages bidirectionally with proper formatting:
|
|
- **Kosmi → IRC**: `[Kosmi] <username> message`
|
|
- **IRC → Kosmi**: `[IRC] <username> message`
|
|
|
|
### Why Headless Chrome?
|
|
|
|
Kosmi's WebSocket API requires browser session cookies and context that are difficult to replicate with a native WebSocket client. Using headless Chrome automation ensures:
|
|
- ✅ Automatic session management
|
|
- ✅ Proper cookie handling
|
|
- ✅ Reliable WebSocket connection
|
|
- ✅ No authentication complexity
|
|
|
|
## Installation
|
|
|
|
### Option 1: Docker (Recommended) 🐳
|
|
|
|
The easiest way to run the bridge:
|
|
|
|
```bash
|
|
# 1. Edit configuration
|
|
nano matterbridge.toml
|
|
|
|
# 2. Build and run
|
|
docker-compose up -d
|
|
|
|
# 3. View logs
|
|
docker-compose logs -f
|
|
```
|
|
|
|
**See**: `DOCKER_QUICKSTART.md` for 5-minute setup guide
|
|
|
|
### Option 2: Build from Source
|
|
|
|
#### Prerequisites
|
|
|
|
- Go 1.21 or higher
|
|
- Chrome or Chromium browser installed
|
|
- Access to an IRC server
|
|
- A Kosmi room URL
|
|
|
|
#### Building
|
|
|
|
```bash
|
|
# Clone the repository
|
|
git clone <repository-url>
|
|
cd irc-kosmi-relay
|
|
|
|
# Download dependencies
|
|
go mod download
|
|
|
|
# Build the bridge
|
|
go build -o matterbridge
|
|
```
|
|
|
|
## Configuration
|
|
|
|
Edit `matterbridge.toml` to configure your bridge:
|
|
|
|
```toml
|
|
# Kosmi configuration
|
|
[kosmi.hyperspaceout]
|
|
RoomURL="https://app.kosmi.io/room/@hyperspaceout"
|
|
|
|
# IRC configuration
|
|
[irc.libera]
|
|
Server="irc.libera.chat:6667"
|
|
Nick="kosmi-relay"
|
|
UseTLS=false
|
|
|
|
# Gateway to connect Kosmi and IRC
|
|
[[gateway]]
|
|
name="kosmi-irc-gateway"
|
|
enable=true
|
|
|
|
[[gateway.inout]]
|
|
account="kosmi.hyperspaceout"
|
|
channel="main"
|
|
|
|
[[gateway.inout]]
|
|
account="irc.libera"
|
|
channel="#your-channel"
|
|
```
|
|
|
|
### Configuration Options
|
|
|
|
#### Kosmi Settings
|
|
|
|
- `RoomURL` (required): Full URL to the Kosmi room
|
|
- Format: `https://app.kosmi.io/room/@roomname` or `https://app.kosmi.io/room/roomid`
|
|
- `Server` (optional): WebSocket endpoint (default: `wss://engine.kosmi.io/gql-ws`)
|
|
- `Debug` (optional): Enable debug logging
|
|
|
|
#### IRC Settings
|
|
|
|
See [Matterbridge IRC documentation](https://github.com/42wim/matterbridge/wiki/Section-IRC-(basic)) for full IRC configuration options.
|
|
|
|
## Usage
|
|
|
|
```bash
|
|
# Run the bridge
|
|
./matterbridge -conf matterbridge.toml
|
|
|
|
# Run with debug logging
|
|
./matterbridge -conf matterbridge.toml -debug
|
|
```
|
|
|
|
## How It Works
|
|
|
|
### Kosmi Connection
|
|
|
|
The bridge connects to Kosmi using headless Chrome automation:
|
|
|
|
1. **Launch Chrome**: Starts a headless Chrome instance via `chromedp`
|
|
2. **Inject Hook**: Uses `Page.addScriptToEvaluateOnNewDocument` to inject a WebSocket interceptor **before any page scripts run**
|
|
3. **Navigate**: Loads the Kosmi room URL
|
|
4. **Intercept**: The injected script hooks `window.WebSocket` constructor to capture all WebSocket messages
|
|
5. **Poll**: Continuously polls the message queue populated by the interceptor
|
|
6. **Process**: Extracts chat messages from GraphQL subscription data
|
|
|
|
### Critical Implementation Detail
|
|
|
|
The WebSocket hook **must** be injected before page load using `Page.addScriptToEvaluateOnNewDocument`. This ensures the hook is active when Kosmi's JavaScript creates the WebSocket connection. If injected after page load, the WebSocket will already be established and messages won't be captured.
|
|
|
|
### Message Flow
|
|
|
|
```
|
|
IRC User → IRC Server → Matterbridge → Headless Chrome → Kosmi Room
|
|
Kosmi User → Kosmi Room → WebSocket → Chrome Interceptor → Matterbridge → IRC Server → IRC Channel
|
|
```
|
|
|
|
### Message Filtering
|
|
|
|
- The bridge ignores its own messages by checking for the `[IRC]` prefix
|
|
- This prevents message loops between Kosmi and IRC
|
|
|
|
## Technical Details
|
|
|
|
### GraphQL API
|
|
|
|
The Kosmi bridge uses the following GraphQL operations:
|
|
|
|
**Subscription** (receiving messages):
|
|
```graphql
|
|
subscription {
|
|
newMessage(roomId: "roomId") {
|
|
body
|
|
time
|
|
user {
|
|
displayName
|
|
username
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
**Mutation** (sending messages):
|
|
```graphql
|
|
mutation {
|
|
sendMessage(roomId: "roomId", body: "message text") {
|
|
id
|
|
}
|
|
}
|
|
```
|
|
|
|
### File Structure
|
|
|
|
```
|
|
bridge/kosmi/
|
|
├── kosmi.go # Main bridge implementation
|
|
├── chromedp_client.go # Headless Chrome client with WebSocket interception
|
|
└── graphql.go # GraphQL message structures (deprecated native client)
|
|
|
|
gateway/bridgemap/
|
|
└── bkosmi.go # Bridge registration
|
|
|
|
cmd/test-kosmi/
|
|
└── main.go # Standalone test program
|
|
|
|
matterbridge.toml # Configuration file
|
|
go.mod # Go module dependencies
|
|
```
|
|
|
|
## Troubleshooting
|
|
|
|
### Connection Issues
|
|
|
|
**Problem**: Bridge fails to connect to Kosmi
|
|
|
|
**Solutions**:
|
|
- Verify Chrome/Chromium is installed: `which google-chrome chromium chromium-browser`
|
|
- Verify the room URL is correct
|
|
- Check network connectivity to `app.kosmi.io`
|
|
- Enable debug logging to see detailed connection logs
|
|
- Look for "✓ WebSocket hook confirmed installed" in logs
|
|
- Look for "Status: WebSocket connection intercepted" in logs
|
|
|
|
### Message Not Relaying
|
|
|
|
**Problem**: Messages aren't being relayed between Kosmi and IRC
|
|
|
|
**Solutions**:
|
|
- Verify both Kosmi and IRC connections are established
|
|
- Check the gateway configuration in `matterbridge.toml`
|
|
- Ensure channel names match in the gateway configuration
|
|
- Check logs for errors
|
|
|
|
### Authentication Errors
|
|
|
|
**Problem**: Kosmi connection fails with authentication error
|
|
|
|
**Note**: Kosmi doesn't require authentication. If you see auth errors, verify:
|
|
- The WebSocket URL is correct
|
|
- The room ID is valid
|
|
- Network isn't blocking WebSocket connections
|
|
|
|
## Development
|
|
|
|
### Adding Features
|
|
|
|
The bridge follows Matterbridge's bridge interface:
|
|
|
|
```go
|
|
type Bridger interface {
|
|
Send(msg config.Message) (string, error)
|
|
Connect() error
|
|
JoinChannel(channel config.ChannelInfo) error
|
|
Disconnect() error
|
|
}
|
|
```
|
|
|
|
### Testing
|
|
|
|
To test the bridge:
|
|
|
|
1. Start the bridge with debug logging
|
|
2. Send a message in the Kosmi room
|
|
3. Verify it appears in IRC with `[Kosmi]` prefix
|
|
4. Send a message in IRC
|
|
5. Verify it appears in Kosmi with `[IRC]` prefix
|
|
|
|
## Known Limitations
|
|
|
|
1. **Anonymous Access**: The bridge connects anonymously to Kosmi, so it will have a randomly assigned username
|
|
2. **Message Sending**: The GraphQL mutation for sending messages may need adjustment based on Kosmi's actual API
|
|
3. **Room Discovery**: The bridge connects to a specific room; it doesn't support room discovery or listing
|
|
|
|
## Credits
|
|
|
|
- Based on [Matterbridge](https://github.com/42wim/matterbridge) by 42wim
|
|
- Kosmi API reverse engineering from chrome extension analysis
|
|
|
|
## License
|
|
|
|
Same as Matterbridge (Apache 2.0)
|
|
|