discord_webhook_rs/
discord.rs

1use super::Embed;
2
3use reqwest::blocking::{Client, Response};
4use serde_json::{Map, Value};
5
6#[derive(Debug)]
7pub enum Error {
8    Request(reqwest::Error),
9    MaxContent,
10    MaxEmbed,
11    MaxField,
12    InvalidColor,
13    InvalidEmbed,
14    MissingNameField,
15    MissingValueField,
16}
17
18pub struct Webhook {
19    url: String,
20    username: Option<String>,
21    avatar_url: Option<String>,
22    content: Option<String>,
23    embeds: Vec<Embed>,
24}
25
26impl Webhook {
27    pub fn new(url: impl Into<String>) -> Self {
28        Webhook {
29            url: url.into(),
30            username: None,
31            avatar_url: None,
32            content: None,
33            embeds: Vec::new(),
34        }
35    }
36
37    pub fn username(mut self, username: impl Into<String>) -> Self {
38        self.username = Some(username.into());
39        self
40    }
41
42    pub fn avatar_url(mut self, avatar_url: impl Into<String>) -> Self {
43        self.avatar_url = Some(avatar_url.into());
44        self
45    }
46
47    pub fn content(mut self, content: impl Into<String>) -> Self {
48        self.content = Some(content.into());
49        self
50    }
51
52    pub fn add_embed(mut self, embed: Embed) -> Self {
53        self.embeds.push(embed);
54        self
55    }
56
57    fn verify(&self) -> Result<(), Error> {
58        if let Some(content) = &self.content {
59            if content.len() > 2000 {
60                return Err(Error::MaxContent);
61            }
62        }
63
64        if self.embeds.len() > 10 {
65            return Err(Error::MaxEmbed);
66        }
67
68        Ok(())
69    }
70
71    fn build(&self) -> Result<Value, Error> {
72        self.verify()?;
73
74        let mut obj = Map::new(); // Construct Body
75
76        if let Some(content) = &self.content {
77            obj.insert("content".into(), Value::String(content.clone()));
78        } else {
79            obj.insert("content".into(), Value::String("Hello from Rust!".into()));
80        }
81
82        if let Some(username) = &self.username {
83            obj.insert("username".into(), Value::String(username.clone()));
84        }
85
86        if let Some(avatar_url) = &self.avatar_url {
87            obj.insert("avatar_url".into(), Value::String(avatar_url.clone()));
88        }
89
90        obj.insert("embeds".into(), Value::Array(vec![]));
91        for embed in &self.embeds {
92            if let Value::Array(ref mut embeds) = obj["embeds"] {
93                embeds.push(embed.build()?);
94            }
95        }
96
97        Ok(Value::Object(obj))
98    }
99
100    pub fn send(self) -> Result<Response, Error> {
101        let client = Client::new();
102        let req = client
103            .post(&self.url)
104            .header("Content-Type", "application/json")
105            .body(self.build()?.to_string());
106
107        match req.send() {
108            Ok(response) => Ok(response),
109            Err(error) => Err(Error::Request(error)),
110        }
111    }
112}