1use serde::{Deserialize, Serialize};
2
3type Snowflake = String;
4
5#[derive(Deserialize, Debug)]
6pub struct Webhook {
7 pub id: Snowflake,
8 #[serde(rename = "type")]
9 pub webhook_type: i8,
10 pub guild_id: Snowflake,
11 pub channel_id: Snowflake,
12 pub name: Option<String>,
13 pub avatar: Option<String>,
14 pub token: String,
15 pub application_id: Option<Snowflake>,
16}
17
18#[derive(Serialize, Debug)]
19pub struct Message {
20 pub content: Option<String>,
21 pub username: Option<String>,
22 pub avatar_url: Option<String>,
23 pub tts: bool,
24 pub embeds: Vec<Embed>,
25 pub allow_mentions: Option<AllowedMentions>,
26}
27
28impl Message {
29 pub fn new() -> Self {
30 Self {
31 content: None,
32 username: None,
33 avatar_url: None,
34 tts: false,
35 embeds: vec![],
36 allow_mentions: None,
37 }
38 }
39
40 pub fn content(&mut self, content: &str) -> &mut Self {
41 self.content = Some(content.to_owned());
42 self
43 }
44
45 pub fn username(&mut self, username: &str) -> &mut Self {
46 self.username = Some(username.to_owned());
47 self
48 }
49
50 pub fn avatar_url(&mut self, avatar_url: &str) -> &mut Self {
51 self.avatar_url = Some(avatar_url.to_owned());
52 self
53 }
54
55 pub fn tts(&mut self, tts: bool) -> &mut Self {
56 self.tts = tts;
57 self
58 }
59
60 pub fn embed<Func>(&mut self, func: Func) -> &mut Self
61 where
62 Func: Fn(&mut Embed) -> &mut Embed,
63 {
64 let mut embed = Embed::new();
65 func(&mut embed);
66 self.embeds.push(embed);
67
68 self
69 }
70
71 pub fn allow_mentions(
72 &mut self,
73 parse: Option<Vec<AllowedMention>>,
74 roles: Option<Vec<Snowflake>>,
75 users: Option<Vec<Snowflake>>,
76 replied_user: bool,
77 ) -> &mut Self {
78 self.allow_mentions = Some(AllowedMentions::new(parse, roles, users, replied_user));
79 self
80 }
81}
82
83#[derive(Serialize, Debug)]
84pub struct Embed {
85 pub title: Option<String>,
86 #[serde(rename = "type")]
87 embed_type: String,
88 pub description: Option<String>,
89 pub url: Option<String>,
90 pub timestamp: Option<String>, pub color: Option<String>,
92 pub footer: Option<EmbedFooter>,
93 pub image: Option<EmbedImage>,
94 pub video: Option<EmbedVideo>,
95 pub thumbnail: Option<EmbedThumbnail>,
96 pub provider: Option<EmbedProvider>,
97 pub author: Option<EmbedAuthor>,
98 pub fields: Vec<EmbedField>,
99}
100
101impl Embed {
102 pub fn new() -> Self {
103 Self {
104 title: None,
105 embed_type: String::from("rich"),
106 description: None,
107 url: None,
108 timestamp: None,
109 color: None,
110 footer: None,
111 image: None,
112 video: None,
113 thumbnail: None,
114 provider: None,
115 author: None,
116 fields: vec![],
117 }
118 }
119
120 pub fn title(&mut self, title: &str) -> &mut Self {
121 self.title = Some(title.to_owned());
122 self
123 }
124
125 pub fn description(&mut self, description: &str) -> &mut Self {
126 self.description = Some(description.to_owned());
127 self
128 }
129
130 pub fn url(&mut self, url: &str) -> &mut Self {
131 self.url = Some(url.to_owned());
132 self
133 }
134
135 pub fn timestamp(&mut self, timestamp: &str) -> &mut Self {
136 self.timestamp = Some(timestamp.to_owned());
137 self
138 }
139
140 pub fn color(&mut self, color: &str) -> &mut Self {
141 self.color = Some(color.to_owned());
142 self
143 }
144
145 pub fn footer(&mut self, text: &str, icon_url: Option<String>) -> &mut Self {
146 self.footer = Some(EmbedFooter::new(text, icon_url));
147 self
148 }
149
150 pub fn image(&mut self, url: &str) -> &mut Self {
151 self.image = Some(EmbedImage::new(url));
152 self
153 }
154
155 pub fn video(&mut self, url: &str) -> &mut Self {
156 self.video = Some(EmbedVideo::new(url));
157 self
158 }
159
160 pub fn thumbnail(&mut self, url: &str) -> &mut Self {
161 self.thumbnail = Some(EmbedThumbnail::new(url));
162 self
163 }
164
165 pub fn provider(&mut self, name: &str, url: &str) -> &mut Self {
166 self.provider = Some(EmbedProvider::new(name, url));
167 self
168 }
169
170 pub fn author(
171 &mut self,
172 name: &str,
173 url: Option<String>,
174 icon_url: Option<String>,
175 ) -> &mut Self {
176 self.author = Some(EmbedAuthor::new(name, url, icon_url));
177 self
178 }
179
180 pub fn field(&mut self, name: &str, value: &str, inline: bool) -> &mut Self {
181 if self.fields.len() == 10 {
182 panic!("You can't have more than")
183 }
184
185 self.fields.push(EmbedField::new(name, value, inline));
186 self
187 }
188}
189
190#[derive(Serialize, Debug)]
191pub struct EmbedField {
192 pub name: String,
193 pub value: String,
194 pub inline: bool,
195}
196
197impl EmbedField {
198 pub fn new(name: &str, value: &str, inline: bool) -> Self {
199 Self {
200 name: name.to_owned(),
201 value: value.to_owned(),
202 inline,
203 }
204 }
205}
206
207#[derive(Serialize, Debug)]
208pub struct EmbedFooter {
209 pub text: String,
210 pub icon_url: Option<String>,
211}
212
213impl EmbedFooter {
214 pub fn new(text: &str, icon_url: Option<String>) -> Self {
215 Self {
216 text: text.to_owned(),
217 icon_url,
218 }
219 }
220}
221
222pub type EmbedImage = EmbedUrlSource;
223pub type EmbedThumbnail = EmbedUrlSource;
224pub type EmbedVideo = EmbedUrlSource;
225
226#[derive(Serialize, Debug)]
227pub struct EmbedUrlSource {
228 pub url: String,
229}
230
231impl EmbedUrlSource {
232 pub fn new(url: &str) -> Self {
233 Self {
234 url: url.to_owned(),
235 }
236 }
237}
238
239#[derive(Serialize, Debug)]
240pub struct EmbedProvider {
241 pub name: String,
242 pub url: String,
243}
244
245impl EmbedProvider {
246 pub fn new(name: &str, url: &str) -> Self {
247 Self {
248 name: name.to_owned(),
249 url: url.to_owned(),
250 }
251 }
252}
253
254#[derive(Serialize, Debug)]
255pub struct EmbedAuthor {
256 pub name: String,
257 pub url: Option<String>,
258 pub icon_url: Option<String>,
259}
260
261impl EmbedAuthor {
262 pub fn new(name: &str, url: Option<String>, icon_url: Option<String>) -> Self {
263 Self {
264 name: name.to_owned(),
265 url,
266 icon_url,
267 }
268 }
269}
270
271pub enum AllowedMention {
272 RoleMention,
273 UserMention,
274 EveryoneMention,
275}
276
277fn resolve_allowed_mention_name(allowed_mention: AllowedMention) -> String {
278 match allowed_mention {
279 AllowedMention::RoleMention => "roles".to_string(),
280 AllowedMention::UserMention => "users".to_string(),
281 AllowedMention::EveryoneMention => "everyone".to_string(),
282 }
283}
284
285#[derive(Serialize, Debug)]
286pub struct AllowedMentions {
287 pub parse: Option<Vec<String>>,
288 pub roles: Option<Vec<Snowflake>>,
289 pub users: Option<Vec<Snowflake>>,
290 pub replied_user: bool,
291}
292
293impl AllowedMentions {
294 pub fn new(
295 parse: Option<Vec<AllowedMention>>,
296 roles: Option<Vec<Snowflake>>,
297 users: Option<Vec<Snowflake>>,
298 replied_user: bool,
299 ) -> Self {
300 let mut parse_strings: Vec<String> = vec![];
301 if parse.is_some() {
302 parse
303 .unwrap()
304 .into_iter()
305 .for_each(|x| parse_strings.push(resolve_allowed_mention_name(x)))
306 }
307
308 Self {
309 parse: Some(parse_strings),
310 roles,
311 users,
312 replied_user,
313 }
314 }
315}