1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
use reqwest::{Body, Client, Method, StatusCode};

use crate::models::{Message};

pub type WebhookResult<Type> = std::result::Result<Type, Box<dyn std::error::Error + Send + Sync>>;

/// A Client that sends webhooks for discord.
pub struct WebhookClient {
    client: Client,
    url: String,
}

impl WebhookClient {
    pub fn new(url: &str) -> Self {
        let client = Client::new();
        Self {
            client,
            url: url.to_owned(),
        }
    }

    /// Example
    /// ```rust
    /// let client = WebhookClient::new("URL");
    /// client.send(|message| message
    ///     .content("content")
    ///     .username("username")).await?;
    /// ```
    pub async fn send<Func>(&self, function: Func) -> WebhookResult<bool>
    where
        Func: Fn(&mut Message) -> &mut Message,
    {
        let mut message = Message::new();
        function(&mut message);
        let result = self.send_message(&message).await?;

        Ok(result)
    }

    pub async fn send_message(&self, message: &Message) -> WebhookResult<bool> {
        let body = serde_json::to_string(message)?;

        let mut req = self.client.request(Method::POST, &self.url);

        req = req
            .header("content-type", "application/json")
            .body(Body::from(body));

        let req = req.build()?;

        let response = self.client.execute(req).await?;

        Ok(response.status() == StatusCode::OK)
    }
}