use reqwest::Client;
use crate::notifier::{ErrorEvent, ErrorNotifier, NotifyFuture};
#[derive(Debug, Clone)]
pub struct SlackConfig {
pub webhook_url: String,
pub mention: Option<String>,
}
impl SlackConfig {
pub fn new(webhook_url: impl Into<String>) -> Self {
Self {
webhook_url: webhook_url.into(),
mention: None,
}
}
pub fn with_mention(mut self, mention: impl Into<String>) -> Self {
self.mention = Some(mention.into());
self
}
}
pub struct SlackProvider {
config: SlackConfig,
}
impl SlackProvider {
pub fn new(config: SlackConfig) -> Self {
Self { config }
}
}
impl ErrorNotifier for SlackProvider {
fn notify<'a>(&'a self, client: &'a Client, event: &'a ErrorEvent) -> NotifyFuture<'a> {
Box::pin(async move {
let mut blocks = vec![
serde_json::json!({
"type": "section",
"text": {
"type": "mrkdwn",
"text": format!(":red_circle: *{:?}* — `{}`", event.error_code, event.app_name)
}
}),
serde_json::json!({
"type": "section",
"text": {
"type": "mrkdwn",
"text": format!("```[{}] {}```", event.location, event.message)
}
}),
];
if let Some(ref mention) = self.config.mention {
blocks.push(serde_json::json!({
"type": "context",
"elements": [
{
"type": "mrkdwn",
"text": mention
}
]
}));
}
let payload = serde_json::json!({ "blocks": blocks });
client
.post(&self.config.webhook_url)
.json(&payload)
.send()
.await?
.error_for_status()?;
Ok(())
})
}
fn name(&self) -> &'static str {
"slack"
}
}