cottongin 65471fb9fc feat: strip IRC formatting codes from messages sent to Owncast
Add irc_format module that removes mIRC control codes (bold, color,
italic, underline, reverse, strikethrough, monospace, reset) before
forwarding to Owncast. Color codes with fg/bg digit params are
consumed correctly. Multi-byte UTF-8 (emoji, accented chars, CJK)
is preserved.

Made-with: Cursor
2026-03-12 14:07:01 -04:00
2026-03-10 22:01:52 -04:00

owncast-irc-bridge

Bidirectional chat bridge between Owncast and IRC. Messages sent in your Owncast chat appear in an IRC channel and vice versa.

Quick Start (Docker Compose)

1. Create your config file

cp config.example.toml config.toml

Edit config.toml with your IRC server/channel and Owncast URL.

2. Get an Owncast access token

In your Owncast admin panel, go to Integrations > Access Tokens and create a token with "send messages" permission.

3. Set the token

export OWNCAST_ACCESS_TOKEN="your-token-here"

Or create a .env file (git-ignored):

OWNCAST_ACCESS_TOKEN=your-token-here

4. Configure the Owncast webhook

In your Owncast admin, go to Integrations > Webhooks and add a webhook pointing to:

http://<bridge-host>:9078/webhook

Select the events: Chat Message, Stream Started, Stream Stopped.

5. Run it

docker compose up -d

Check logs:

docker compose logs -f

Running Without Docker

Requires Rust 1.75+.

cargo build --release
export OWNCAST_ACCESS_TOKEN="your-token-here"
./target/release/owncast-irc-bridge --config config.toml

Configuration

See config.example.toml for all options. The only required sections are [irc] (with server and channel) and [owncast] (with url). Everything else has defaults.

Section Key Default Description
irc server (required) IRC server hostname
irc port 6667 IRC server port
irc tls false Use TLS for IRC
irc nick owncast-bridge IRC nickname
irc channel (required) IRC channel to join
owncast url (required) Owncast instance URL
owncast webhook_port 9078 Port the webhook server listens on
owncast websocket_enabled false Also connect via WebSocket (redundant with webhook, useful as fallback)
owncast health_poll_interval_secs 30 How often to poll Owncast status
bridge irc_prefix [IRC] Prefix for IRC messages in Owncast
bridge owncast_prefix [OC] Prefix for Owncast messages in IRC
control socket_path /tmp/owncast-irc-bridge.sock Unix socket for bridge-ctl

The access token is always read from the OWNCAST_ACCESS_TOKEN environment variable (not the config file).

Runtime Control

Use bridge-ctl to interact with a running bridge:

bridge-ctl status              # Show bridge status as JSON
bridge-ctl irc reconnect       # Reconnect to IRC
bridge-ctl owncast reconnect   # Reconnect to Owncast
bridge-ctl quit                # Shut down the bridge

Inside Docker:

docker compose exec bridge bridge-ctl status

How It Works

  • Owncast → IRC: Owncast sends webhook events to the bridge. The bridge formats the message and sends it to IRC via PRIVMSG.
  • IRC → Owncast: The bridge listens for PRIVMSG in the configured channel and posts to Owncast via the integration API.
  • Deduplication: If both webhook and WebSocket are enabled, duplicate messages are detected by ID and dropped.
  • Echo suppression: Messages the bridge itself sent are recognized and not re-bridged.
  • Stream events: Stream start/stop events are announced in IRC.
  • Health polling: The bridge polls Owncast's /api/status endpoint and announces state changes in IRC.
Description
Bidirectional chat bridge between [Owncast](https://owncast.online/) and IRC. Messages sent in your Owncast chat appear in an IRC channel and vice versa.
Readme MIT 154 KiB
Languages
Rust 99.1%
Dockerfile 0.9%