69 lines
2.3 KiB
Rust
69 lines
2.3 KiB
Rust
use crate::{App, db};
|
|
use serde_json::json;
|
|
use std::sync::Arc;
|
|
use std::time::Duration;
|
|
|
|
/// Fire-and-forget notification to the configured webhook (if any).
|
|
pub fn notify(app: Arc<App>, title: String, body: String, good: bool) {
|
|
tokio::spawn(async move {
|
|
let configured = {
|
|
let c = app.db.lock().unwrap();
|
|
!db::setting_get(&c, "webhook_url").is_empty()
|
|
};
|
|
if configured {
|
|
if let Err(e) = send(&app, &title, &body, good).await {
|
|
eprintln!("webhook failed: {e}");
|
|
}
|
|
}
|
|
});
|
|
}
|
|
|
|
pub async fn send(app: &App, title: &str, body: &str, good: bool) -> Result<(), String> {
|
|
let (url, kind) = {
|
|
let c = app.db.lock().unwrap();
|
|
(db::setting_get(&c, "webhook_url"), db::setting_get(&c, "webhook_kind"))
|
|
};
|
|
if url.is_empty() {
|
|
return Err("no webhook URL configured".into());
|
|
}
|
|
let client = &app.http_strict;
|
|
let req = match kind.as_str() {
|
|
"discord" => client
|
|
.post(&url)
|
|
.json(&json!({ "content": format!("{} **{}**\n{}", if good { "🟢" } else { "🔴" }, title, body) })),
|
|
"slack" => client
|
|
.post(&url)
|
|
.json(&json!({ "text": format!("{} *{}*\n{}", if good { ":large_green_circle:" } else { ":red_circle:" }, title, body) })),
|
|
"ntfy" => {
|
|
let mut r = client
|
|
.post(&url)
|
|
.header("Tags", if good { "white_check_mark" } else { "rotating_light" })
|
|
.header("Priority", if good { "default" } else { "high" })
|
|
.body(body.to_string());
|
|
if title.is_ascii() && !title.chars().any(|c| c.is_control()) {
|
|
r = r.header("Title", title);
|
|
} else {
|
|
r = r.body(format!("{title}\n{body}"));
|
|
}
|
|
r
|
|
}
|
|
_ => client.post(&url).json(&json!({
|
|
"title": title,
|
|
"message": body,
|
|
"status": if good { "up" } else { "down" },
|
|
"time": db::now(),
|
|
"source": "labdeck",
|
|
})),
|
|
};
|
|
let resp = req
|
|
.timeout(Duration::from_secs(10))
|
|
.send()
|
|
.await
|
|
.map_err(|e| e.to_string())?;
|
|
if resp.status().is_success() {
|
|
Ok(())
|
|
} else {
|
|
Err(format!("webhook answered HTTP {}", resp.status().as_u16()))
|
|
}
|
|
}
|