2025-11-01 21:00:16 -04:00
2025-10-31 16:17:04 -04:00
2025-11-01 10:40:53 -04:00
2025-10-31 16:17:04 -04:00
2025-10-31 16:17:04 -04:00
2025-10-31 16:17:04 -04:00
2025-10-31 16:17:04 -04:00
2025-10-31 16:17:04 -04:00
2025-11-01 21:00:16 -04:00
2025-11-01 21:00:16 -04:00
2025-11-01 21:00:16 -04:00
2025-10-31 16:17:04 -04:00
2025-11-01 21:00:16 -04:00
2025-11-01 21:00:16 -04:00
2025-11-01 10:40:53 -04:00
2025-10-31 23:56:16 -04:00
2025-11-01 21:00:16 -04:00
2025-10-31 16:17:04 -04:00
2025-10-31 16:17:04 -04:00
2025-11-01 21:00:16 -04:00
2025-10-31 16:17:04 -04:00
2025-10-31 16:17:04 -04:00
2025-10-31 16:17:04 -04:00
2025-11-01 10:40:53 -04:00
2025-10-31 21:41:27 -04:00
2025-10-31 16:17:04 -04:00
2025-11-01 21:00:16 -04:00
2025-11-01 21:00:16 -04:00
2025-11-01 21:00:16 -04:00
2025-10-31 16:17:04 -04:00
2025-10-31 16:17:04 -04:00
2025-10-31 16:17:04 -04:00
2025-11-01 10:40:53 -04:00
2025-11-01 10:40:53 -04:00
2025-11-01 10:40:53 -04:00
2025-10-31 16:17:04 -04:00
2025-11-01 10:40:53 -04:00
2025-11-01 21:00:16 -04:00
2025-11-01 21:00:16 -04:00
2025-11-01 10:40:53 -04:00
2025-11-01 10:40:53 -04:00
2025-10-31 23:56:16 -04:00
2025-10-31 16:17:04 -04:00
2025-10-31 16:17:04 -04:00
2025-10-31 16:17:04 -04:00
2025-11-01 21:00:16 -04:00
2025-10-31 16:17:04 -04:00
2025-10-31 16:17:04 -04:00
2025-11-01 10:40:53 -04:00
2025-11-01 10:40:53 -04:00
2025-11-01 10:40:53 -04:00
2025-11-01 10:40:53 -04:00
2025-11-01 10:40:53 -04:00
2025-10-31 16:17:04 -04:00
2025-11-01 10:40:53 -04:00
2025-11-01 10:40:53 -04:00
2025-11-01 10:40:53 -04:00
2025-11-01 10:40:53 -04:00
2025-11-01 10:40:53 -04:00
2025-10-31 16:17:04 -04:00
2025-11-01 10:40:53 -04:00
2025-10-31 16:17:04 -04:00
2025-10-31 16:17:04 -04:00
2025-11-01 21:00:16 -04:00
2025-10-31 16:17:04 -04:00
2025-11-01 21:00:16 -04:00
2025-10-31 16:17:04 -04:00
2025-11-01 10:40:53 -04:00

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

The easiest way to run the bridge:

# 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

# 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:

# 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 for full IRC configuration options.

Usage

# 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):

subscription {
  newMessage(roomId: "roomId") {
    body
    time
    user {
      displayName
      username
    }
  }
}

Mutation (sending messages):

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:

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 by 42wim
  • Kosmi API reverse engineering from chrome extension analysis

License

Same as Matterbridge (Apache 2.0)

Description
No description provided
Readme 56 MiB
Languages
Go 99.8%
Dockerfile 0.2%