fix: HTML-escape IRC username in Owncast chat, fix WebSocket auth, fix echo suppression

- Escape angle brackets around IRC username so Owncast doesn't swallow
  them as HTML tags (&lt;nick&gt; instead of <nick>)
- Register a chat user via POST /api/chat/register to obtain an
  accessToken, then pass it as a query param when connecting to /ws
  (Owncast closes the WebSocket immediately without one)
- Cache the access token across reconnections; re-register only on
  rejection
- Add ws_display_name config option (default "IRC Bridge")
- Fix echo suppression: record_sent and is_echo now both compare
  raw body instead of mismatched formatted/raw values

Made-with: Cursor
This commit is contained in:
cottongin
2026-03-12 14:06:41 -04:00
parent c24cef9d6d
commit 196997f728
7 changed files with 144 additions and 13 deletions

View File

@@ -33,6 +33,8 @@ pub struct OwncastConfig {
pub websocket_enabled: bool,
#[serde(default = "default_health_poll_interval")]
pub health_poll_interval_secs: u64,
#[serde(default = "default_ws_display_name")]
pub ws_display_name: String,
}
#[derive(Debug, Deserialize)]
@@ -70,6 +72,7 @@ fn default_webhook_port() -> u16 { 9078 }
fn default_health_poll_interval() -> u64 { 30 }
fn default_irc_prefix() -> String { "[IRC]".to_string() }
fn default_owncast_prefix() -> String { "[OC]".to_string() }
fn default_ws_display_name() -> String { "IRC Bridge".to_string() }
fn default_socket_path() -> String { "/tmp/owncast-irc-bridge.sock".to_string() }
impl Default for BridgeSettings {
@@ -104,6 +107,7 @@ impl BridgeConfig {
webhook_port: 9078,
websocket_enabled: false,
health_poll_interval_secs: 30,
ws_display_name: default_ws_display_name(),
},
bridge: BridgeSettings::default(),
control: ControlConfig::default(),