alert2muc/src/main.rs

113 lines
2.9 KiB
Rust

use std::net::SocketAddr;
use askama::Template;
use axum::{
extract::State,
routing::{get, post},
http::StatusCode,
response::{IntoResponse, Response},
Json, Router,
};
use serde::Deserialize;
mod jabber;
mod prometheus_alert;
mod apprise_notify;
enum Payload {
Prometheus(prometheus_alert::Payload),
Apprise(apprise_notify::Notification),
}
impl Payload {
fn render(&self) -> Result<String, askama::Error> {
match self {
Payload::Prometheus(payload) => payload.render(),
Payload::Apprise(notification) => notification.render(),
}
}
async fn handle_payload(&self, jabber: jabber::Handle) -> Response {
let mut error_message = None;
match self.render() {
Ok(message) => {
jabber.send_message(message).await;
}
Err(e) => {
error_message = Some(format!("{}", e));
}
}
match error_message {
None =>
StatusCode::OK.into_response(),
Some(error_message) =>
(StatusCode::INTERNAL_SERVER_ERROR,
error_message
).into_response()
}
}
}
async fn prometheus_alerts(
State(jabber): State<jabber::Handle>,
Json(payload): Json<prometheus_alert::Payload>,
) -> Response {
Payload::Prometheus(payload)
.handle_payload(jabber)
.await
}
async fn apprise_notification(
State(jabber): State<jabber::Handle>,
Json(notification): Json<apprise_notify::Notification>,
) -> Response {
Payload::Apprise(notification)
.handle_payload(jabber)
.await
}
async fn apprise_ok(
) -> Response {
([("content-type", "application/json")], "{}")
.into_response()
}
#[derive(Deserialize)]
struct Config {
listen_port: u16,
jid: String,
password: String,
muc: String,
}
#[tokio::main]
async fn main() {
// initialize tracing
tracing_subscriber::fmt::init();
let config: Config = serde_json::from_str(
&std::fs::read_to_string(
std::env::args().nth(1)
.expect("Call with config.json")
).expect("read config")
).expect("parse config");
let jabber = jabber::run(config.jid, config.password, config.muc).await;
// build our application with a route
let app = Router::new()
.route("/alert", post(prometheus_alerts))
.route("/api/v2/alerts", post(prometheus_alerts))
.route("/notify", get(apprise_ok).post(apprise_notification))
.with_state(jabber);
let addr = SocketAddr::from(([127, 0, 0, 1], config.listen_port));
tracing::debug!("listening on {}", addr);
let server = axum::Server::bind(&addr)
.serve(app.into_make_service());
systemd::daemon::notify(false, [(systemd::daemon::STATE_READY, "1")].iter())
.unwrap();
server.await
.unwrap();
}