use reqwest::Client;
use crate::notifier::{ErrorEvent, ErrorNotifier, NotifyFuture};
#[derive(Debug, Clone)]
pub struct DiscordConfig {
pub webhook_url: String,
pub mention: Option<String>,
}
impl DiscordConfig {
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 DiscordProvider {
config: DiscordConfig,
}
impl DiscordProvider {
pub fn new(config: DiscordConfig) -> Self {
Self { config }
}
}
impl ErrorNotifier for DiscordProvider {
fn notify<'a>(&'a self, client: &'a Client, event: &'a ErrorEvent) -> NotifyFuture<'a> {
Box::pin(async move {
let formatted_message = format!("[{}] {}", event.location, event.message);
let mut fields = vec![serde_json::json!({
"name": "Details",
"value": format!("```{}```", formatted_message),
"inline": false
})];
if let Some(ref mention) = self.config.mention {
fields.push(serde_json::json!({
"name": "\u{200B}",
"value": mention,
"inline": false
}));
}
let embeds = serde_json::json!([
{
"title": format!(":red_circle: {:?} — {}", event.error_code, event.app_name),
"color": 16711680, "fields": fields
}
]);
let payload = serde_json::json!({ "embeds": embeds });
client
.post(&self.config.webhook_url)
.json(&payload)
.send()
.await?
.error_for_status()?;
Ok(())
})
}
fn name(&self) -> &'static str {
"discord"
}
}