feat: add Owncast API client for sending messages and checking status

Made-with: Cursor
This commit is contained in:
cottongin
2026-03-10 21:54:25 -04:00
parent 788634fb83
commit 3876e12ec9
2 changed files with 79 additions and 0 deletions

View File

@@ -1,6 +1,7 @@
mod config;
mod events;
mod html;
mod owncast_api;
fn main() {
println!("owncast-irc-bridge");

78
src/owncast_api.rs Normal file
View File

@@ -0,0 +1,78 @@
use reqwest::Client;
use tracing::{error, warn};
pub struct OwncastApiClient {
client: Client,
base_url: String,
access_token: String,
}
impl OwncastApiClient {
pub fn new(base_url: String, access_token: String) -> Self {
Self {
client: Client::new(),
base_url: base_url.trim_end_matches('/').to_string(),
access_token,
}
}
pub async fn send_chat_message(&self, body: &str) -> anyhow::Result<()> {
let url = format!("{}/api/integrations/chat/send", self.base_url);
let resp = self
.client
.post(&url)
.bearer_auth(&self.access_token)
.json(&serde_json::json!({ "body": body }))
.send()
.await?;
let status = resp.status();
if status.is_success() {
return Ok(());
}
let resp_body = resp.text().await.unwrap_or_default();
if status.is_client_error() {
error!(status = %status, body = %resp_body, "Owncast API client error (not retrying)");
anyhow::bail!("Owncast API returned {status}");
}
warn!(status = %status, body = %resp_body, "Owncast API server error, retrying once");
tokio::time::sleep(std::time::Duration::from_secs(1)).await;
let retry_resp = self
.client
.post(&url)
.bearer_auth(&self.access_token)
.json(&serde_json::json!({ "body": body }))
.send()
.await?;
let retry_status = retry_resp.status();
if retry_status.is_success() {
Ok(())
} else {
let retry_body = retry_resp.text().await.unwrap_or_default();
error!(status = %retry_status, body = %retry_body, "Owncast API retry failed");
anyhow::bail!("Owncast API retry returned {}", retry_status)
}
}
pub async fn get_status(&self) -> anyhow::Result<OwncastStatus> {
let url = format!("{}/api/status", self.base_url);
let resp = self.client.get(&url).send().await?;
let status: OwncastStatus = resp.json().await?;
Ok(status)
}
}
#[derive(Debug, serde::Deserialize)]
pub struct OwncastStatus {
pub online: bool,
#[serde(default)]
#[serde(rename = "streamTitle")]
pub stream_title: Option<String>,
#[serde(default)]
#[serde(rename = "viewerCount")]
pub viewer_count: Option<u64>,
}