use reqwest::Client;
use crate::notifier::{ErrorEvent, ErrorNotifier, NotifyFuture};
#[derive(Debug, Clone)]
pub struct NtfyConfig {
pub server_url: String,
pub topic: String,
pub access_token: Option<String>,
}
impl NtfyConfig {
pub fn new(topic: impl Into<String>) -> Self {
Self {
server_url: "https://ntfy.sh".into(),
topic: topic.into(),
access_token: None,
}
}
pub fn with_server(mut self, url: impl Into<String>) -> Self {
self.server_url = url.into();
self
}
pub fn with_token(mut self, token: impl Into<String>) -> Self {
self.access_token = Some(token.into());
self
}
}
pub struct NtfyProvider {
config: NtfyConfig,
}
impl NtfyProvider {
pub fn new(config: NtfyConfig) -> Self {
Self { config }
}
}
impl ErrorNotifier for NtfyProvider {
fn notify<'a>(&'a self, client: &'a Client, event: &'a ErrorEvent) -> NotifyFuture<'a> {
Box::pin(async move {
let url = format!(
"{}/{}",
self.config.server_url.trim_end_matches('/'),
self.config.topic
);
let title = format!(
"🔴 {} Error — {}",
event.severity().to_uppercase(),
event.app_name
);
let body = format!("[{}][{:?}] {}", event.location, event.error_code, event.message);
let priority = match event.severity() {
"critical" => "5",
"major" => "4",
"minor" => "3",
"warning" => "2",
_ => "3",
};
let mut request = client
.post(&url)
.header("Title", title)
.header("Priority", priority)
.header(
"Tags",
format!("error,{:?}", event.error_code).to_lowercase(),
)
.body(body);
if let Some(ref token) = self.config.access_token {
request = request.header("Authorization", format!("Bearer {}", token));
}
request.send().await?.error_for_status()?;
Ok(())
})
}
fn name(&self) -> &'static str {
"ntfy"
}
}