use crate::{Error, Message};
#[derive(Clone, Debug)]
pub struct Client {
pub webhook_url: String,
base_message: Option<Message>,
http_client: reqwest::Client,
}
impl Client {
pub async fn deliver(&self, message: Message) -> Result<(), Error> {
message.send(&self.http_client).await?;
Ok(())
}
pub async fn new_message<F>(&self, f: F) -> Option<Message>
where
F: FnOnce(&mut Message) -> Message,
{
if let Some(base_message) = &self.base_message {
let mut message = base_message.clone();
let new_message = f(&mut message);
Some(new_message)
} else {
None
}
}
}
impl PartialEq for Client {
fn eq(&self, other: &Self) -> bool {
self.webhook_url == other.webhook_url
}
}
impl Eq for Client {}
#[derive(Default)]
pub struct ClientBuilder {
webhook_url: Option<String>,
baseline_message: Option<Message>,
}
impl ClientBuilder {
pub fn new() -> ClientBuilder {
ClientBuilder::default()
}
pub fn set_webhook_url<S: Into<String>>(mut self, url: S) -> ClientBuilder {
self.webhook_url = Some(url.into());
self
}
pub fn set_baseline_message(mut self, message: Message) -> ClientBuilder {
self.baseline_message = Some(message);
self
}
pub fn build(self) -> Result<Client, Error> {
if let Some(webhook_url) = self.webhook_url {
Ok(Client {
webhook_url,
http_client: reqwest::Client::new(),
base_message: self.baseline_message,
})
} else {
Err(Error::MissingWebhookURL)
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn new_returns_default_builder() {
let builder = ClientBuilder::new();
assert!(builder.webhook_url.is_none());
}
#[test]
fn set_webhook_url_sets_url() {
let builder = ClientBuilder::new().set_webhook_url("https://hooks.slack.com/abc");
assert_eq!(
builder.webhook_url,
Some("https://hooks.slack.com/abc".to_string())
);
}
#[test]
fn build_returns_error_if_missing_webhook() {
let builder = ClientBuilder::new();
let result = builder.build();
assert!(matches!(result, Err(Error::MissingWebhookURL)));
}
#[test]
fn build_successfully_creates_client() {
let builder = ClientBuilder::new()
.set_webhook_url("https://hooks.slack.com/xyz")
.set_baseline_message(Message::Custom(serde_json::json!({
"title": "Warning: detected a tampered token detected.",
"description": "A request with a tampered token was used by IP: xxx.xx.xx.xxx",
})));
let client = builder.build().expect("Expected successful build");
let base_message = Message::Custom(serde_json::json!({
"title": "Warning: detected a tampered token detected.",
"description": "A request with a tampered token was used by IP: xxx.xx.xx.xxx",
}));
assert_eq!(
client,
Client {
webhook_url: "https://hooks.slack.com/xyz".into(),
http_client: reqwest::Client::new(),
base_message: Some(base_message)
}
);
}
}