92 lines
2.1 KiB
Rust
92 lines
2.1 KiB
Rust
|
use std::{
|
||
|
net::SocketAddr,
|
||
|
collections::HashMap,
|
||
|
sync::{Arc, Mutex},
|
||
|
};
|
||
|
use axum::{
|
||
|
extract::State,
|
||
|
routing::post,
|
||
|
http::StatusCode,
|
||
|
response::{IntoResponse, Response},
|
||
|
Json, Router,
|
||
|
};
|
||
|
use serde::Deserialize;
|
||
|
|
||
|
mod jabber;
|
||
|
|
||
|
#[derive(Deserialize, Clone, Debug)]
|
||
|
struct Alert {
|
||
|
generatorURL: String,
|
||
|
startsAt: String,
|
||
|
annotations: AlertAnnotations,
|
||
|
labels: HashMap<String, String>,
|
||
|
}
|
||
|
|
||
|
#[derive(Deserialize, Clone, Debug)]
|
||
|
struct AlertAnnotations {
|
||
|
summary: String,
|
||
|
}
|
||
|
|
||
|
#[derive(Clone)]
|
||
|
struct AppState {
|
||
|
jabber: jabber::Handle,
|
||
|
alerts: Arc<Mutex<HashMap<String, Alert>>>,
|
||
|
}
|
||
|
|
||
|
async fn alerts(
|
||
|
State(state): State<AppState>,
|
||
|
Json(payload): Json<Vec<Alert>>,
|
||
|
) -> Response {
|
||
|
let mut message = "".to_string();
|
||
|
let mut alerts = state.alerts.lock().unwrap();
|
||
|
for alert in payload.into_iter() {
|
||
|
let is_old = if let Some(old_alert) = alerts.get(&alert.generatorURL) {
|
||
|
old_alert.startsAt == alert.startsAt
|
||
|
} else {
|
||
|
false
|
||
|
};
|
||
|
|
||
|
if ! is_old {
|
||
|
if message != "" {
|
||
|
message += "\n";
|
||
|
}
|
||
|
message += &format!("{}: {}", alert.annotations.summary, alert.generatorURL);
|
||
|
alerts.insert(alert.generatorURL.clone(), alert);
|
||
|
}
|
||
|
}
|
||
|
drop(alerts);
|
||
|
|
||
|
if message != "" {
|
||
|
let jabber = state.jabber.clone();
|
||
|
tokio::spawn(async move {
|
||
|
jabber.send_message(message).await;
|
||
|
});
|
||
|
}
|
||
|
|
||
|
StatusCode::OK.into_response()
|
||
|
}
|
||
|
|
||
|
#[tokio::main]
|
||
|
async fn main() {
|
||
|
// initialize tracing
|
||
|
tracing_subscriber::fmt::init();
|
||
|
|
||
|
let jabber = jabber::run(/*secret*/).await;
|
||
|
let state = AppState {
|
||
|
jabber,
|
||
|
alerts: Arc::new(Mutex::new(HashMap::new())),
|
||
|
};
|
||
|
|
||
|
// build our application with a route
|
||
|
let app = Router::new()
|
||
|
.route("/", post(alerts))
|
||
|
.with_state(state);
|
||
|
|
||
|
let addr = SocketAddr::from(([127, 0, 0, 1], 9022));
|
||
|
tracing::debug!("listening on {}", addr);
|
||
|
axum::Server::bind(&addr)
|
||
|
.serve(app.into_make_service())
|
||
|
.await
|
||
|
.unwrap();
|
||
|
}
|