descord 0.1.11

A minimal discord api wrapper.
Documentation
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
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
use json::object;
use nanoserde::{DeJson, SerJson};
use std::error::Error;

use super::allowed_mentions::AllowedMentions;
use super::attachment::{Attachment, AttachmentPayload};
use super::channel::Channel;
use super::components::Component;
use super::embed::Embed;
use super::guild::{Guild, Member};
use crate::prelude::User;
use crate::utils;
use crate::{consts, Client};

/// Represents a response to a message.
#[derive(DeJson, SerJson, Clone, Debug)]
pub struct MessageResponse {
    /// The message data.
    #[nserde(rename = "d")]
    pub data: Message,
}

/// Represents a message.
#[derive(DeJson, SerJson, Clone, Debug)]
pub struct Message {
    /// Whether the message is a TTS message.
    #[nserde(default)]
    pub tts: bool,
    /// The timestamp of the message.
    #[nserde(default)]
    pub timestamp: Option<String>,
    /// Whether the message is pinned.
    #[nserde(default)]
    pub pinned: bool,
    /// Whether the message mentions everyone.
    #[nserde(default)]
    pub mention_everyone: bool,
    /// The flags of the message.
    #[nserde(default)]
    pub flags: usize,
    /// The timestamp of when the message was edited.
    pub edited_timestamp: Option<String>,
    /// The content of the message.
    #[nserde(default)]
    pub content: String,
    /// The ID of the channel where the message was sent.
    pub channel_id: String,
    /// The embeds of the message.
    #[nserde(default)]
    pub embeds: Vec<Embed>,
    /// The author of the message.
    pub author: Option<User>,
    /// The message that is being replied to.
    #[nserde(default)]
    pub referenced_message: Option<Box<Message>>,
    /// The ID of the guild where the message was sent.
    pub guild_id: Option<String>,
    /// The ID of the message.
    pub id: String,
    /// The member who sent the message.
    pub member: Option<Member>,
    /// The attachments of the message.
    pub attachments: Vec<Attachment>,
    /// The components of the message.
    pub components: Vec<Component>,
    // TODO
    // mentions, mention_roles, member, etc.
}

impl Message {
    /// Reply to the message.
    ///
    /// # Arguments
    ///
    /// * `data` - The data for the reply.
    ///
    /// # Examples
    ///
    /// ```
    /// message.reply("Hello, world!").await;
    /// ```
    pub async fn reply(&self, data: impl Into<CreateMessageData>) -> Message {
        utils::send(&self.channel_id, Some(&self.id), data).await
    }

    /// Send a message in the same channel.
    ///
    /// # Arguments
    ///
    /// * `data` - The data for the message.
    ///
    /// # Examples
    ///
    /// ```
    /// message.send_in_channel("Hello, world!").await;
    /// ```
    pub async fn send_in_channel(&self, data: impl Into<CreateMessageData>) -> Message {
        utils::send(&self.channel_id, None, data).await
    }

    /// Get the current channel.
    ///
    /// # Examples
    ///
    /// ```
    /// let channel = message.get_channel().await?;
    /// ```
    pub async fn get_channel(&self) -> Result<Channel, Box<dyn std::error::Error>> {
        utils::fetch_channel(&self.channel_id).await
    }

    /// Get the message author.
    ///
    /// # Examples
    ///
    /// ```
    /// let author = message.get_author().await?;
    /// ```
    pub async fn get_author(&self) -> Result<Member, Box<dyn Error>> {
        utils::fetch_member(
            self.guild_id.as_ref().unwrap(),
            &self.author.as_ref().unwrap().id,
        )
        .await
    }

    /// Get the guild in which the message was sent.
    ///
    /// # Examples
    ///
    /// ```
    /// let guild = message.get_guild().await?;
    /// ```
    pub async fn get_guild(&self) -> Result<Guild, Box<dyn Error>> {
        utils::fetch_guild(self.guild_id.as_ref().unwrap()).await
    }

    /// Get the message that is being replied to.
    ///
    /// # Examples
    ///
    /// ```
    /// let referenced_message = message.get_message_reference().await;
    /// ```
    pub async fn get_message_reference(&self) -> Option<Message> {
        if let Some(ref message) = self.referenced_message {
            Some(*message.clone())
        } else {
            None
        }
    }

    /// Delete this message.
    ///
    /// # Examples
    ///
    /// ```
    /// message.delete().await;
    /// ```
    pub async fn delete(&self) -> bool {
        utils::delete_message(&self.channel_id, &self.id).await
    }

    /// Delete this message after a certain amount of time.
    ///
    /// # Arguments
    ///
    /// * `time` - The duration to wait before deleting the message.
    ///
    /// # Examples
    ///
    /// ```
    /// message.delete_after(tokio::time::Duration::from_secs(10)).await;
    /// ```
    pub async fn delete_after(&self, time: tokio::time::Duration) {
        tokio::time::sleep(time);
        self.delete().await;
    }

    /// Edit the message.
    ///
    /// # Arguments
    ///
    /// * `data` - The new data for the message.
    ///
    /// # Examples
    ///
    /// ```
    /// message.edit("Edited message").await;
    /// ```
    pub async fn edit(&self, data: impl Into<CreateMessageData>) {
        utils::edit_message(&self.channel_id, &self.id, data).await;
    }

    /// React to the message with an emoji.
    ///
    /// # Arguments
    ///
    /// * `emoji` - The emoji to react with.
    ///
    /// # Examples
    ///
    /// ```
    /// message.react("👍").await;
    /// ```
    pub async fn react(&self, emoji: &str) {
        utils::react(&self.channel_id, &self.id, emoji).await;
    }
}

/// Data for creating a message.
#[derive(Default, Debug, DeJson, SerJson, Clone)]
pub struct CreateMessageData {
    /// The content of the message.
    pub content: String,
    /// Whether the message is a TTS message.
    pub tts: bool,
    /// The embeds of the message.
    pub embeds: Vec<Embed>,
    /// The allowed mentions in the message.
    pub allowed_mentions: Option<AllowedMentions>,
    /// The flags of the message.
    pub flags: Option<u32>,
    /// The components of the message.
    pub components: Vec<Component>,
    /// The attachments of the message.
    #[nserde(transparent)]
    pub attachments: Vec<AttachmentPayload>,
}

impl CreateMessageData {
    /// Converts the message data to JSON.
    ///
    /// # Examples
    ///
    /// ```
    /// let json = message_data.to_json();
    /// ```
    pub fn to_json(&self) -> String {
        let mut json = json::parse(&self.serialize_json()).unwrap();

        json.remove("attachments");

        let components = self
            .components
            .iter()
            .map(|column| {
                let components = json::parse(&column.serialize_json()).unwrap();
                json::object! {
                    type: 1,
                    components: components,
                }
            })
            .collect::<Vec<_>>();

        json::stringify(json)
    }

    /// Adds components to the message data.
    ///
    /// # Arguments
    ///
    /// * `components` - The components to add.
    ///
    /// # Examples
    ///
    /// ```
    /// message_data.add_components(vec![vec![component1, component2]]);
    /// ```
    pub fn add_components(mut self, components: Vec<Vec<Component>>) -> Self {
        let new: CreateMessageData = components.into();

        CreateMessageData {
            components: new.components,
            ..self
        }
    }
}

impl From<String> for CreateMessageData {
    /// Converts a string to `CreateMessageData`.
    ///
    /// # Arguments
    ///
    /// * `value` - The string value.
    ///
    /// # Examples
    ///
    /// ```
    /// let message_data: CreateMessageData = "Hello, world!".into();
    /// ```
    fn from(value: String) -> Self {
        Self {
            content: value,
            ..Default::default()
        }
    }
}

impl From<&String> for CreateMessageData {
    /// Converts a string reference to `CreateMessageData`.
    ///
    /// # Arguments
    ///
    /// * `value` - The string reference.
    ///
    /// # Examples
    ///
    /// ```
    /// let message_data: CreateMessageData = (&"Hello, world!".to_string()).into();
    /// ```
    fn from(value: &String) -> Self {
        Self {
            content: value.clone(),
            ..Default::default()
        }
    }
}

impl From<&str> for CreateMessageData {
    /// Converts a string slice to `CreateMessageData`.
    ///
    /// # Arguments
    ///
    /// * `value` - The string slice.
    ///
    /// # Examples
    ///
    /// ```
    /// let message_data: CreateMessageData = "Hello, world!".into();
    /// ```
    fn from(value: &str) -> Self {
        Self {
            content: value.to_owned(),
            ..Default::default()
        }
    }
}

impl From<Vec<Embed>> for CreateMessageData {
    /// Converts a vector of embeds to `CreateMessageData`.
    ///
    /// # Arguments
    ///
    /// * `value` - The vector of embeds.
    ///
    /// # Examples
    ///
    /// ```
    /// let message_data: CreateMessageData = vec![embed1, embed2].into();
    /// ```
    fn from(value: Vec<Embed>) -> Self {
        assert!(
            value.len() <= 10,
            "A message can only contain up to 10 rich embeds"
        );

        CreateMessageData {
            embeds: value,
            ..Default::default()
        }
    }
}

impl From<Embed> for CreateMessageData {
    /// Converts an embed to `CreateMessageData`.
    ///
    /// # Arguments
    ///
    /// * `value` - The embed.
    ///
    /// # Examples
    ///
    /// ```
    /// let message_data: CreateMessageData = embed.into();
    /// ```
    fn from(value: Embed) -> Self {
        CreateMessageData {
            embeds: vec![value],
            ..Default::default()
        }
    }
}

impl From<AllowedMentions> for CreateMessageData {
    /// Converts allowed mentions to `CreateMessageData`.
    ///
    /// # Arguments
    ///
    /// * `value` - The allowed mentions.
    ///
    /// # Examples
    ///
    /// ```
    /// let message_data: CreateMessageData = allowed_mentions.into();
    /// ```
    fn from(value: AllowedMentions) -> Self {
        CreateMessageData {
            allowed_mentions: Some(value),
            ..Default::default()
        }
    }
}

impl From<Vec<Vec<Component>>> for CreateMessageData {
    /// Converts a vector of component vectors to `CreateMessageData`.
    ///
    /// # Arguments
    ///
    /// * `value` - The vector of component vectors.
    ///
    /// # Examples
    ///
    /// ```
    /// let message_data: CreateMessageData = vec![vec![component1, component2]].into();
    /// ```
    fn from(value: Vec<Vec<Component>>) -> Self {
        let components = value
            .iter()
            .map(|column| -> Component {
                let components = json::parse(&column.serialize_json()).unwrap();

                // TODO: improve this logic cause its kinda slow
                Component::deserialize_json(
                    &json::object! {
                        type: 1,
                        components: components,
                    }
                    .pretty(1),
                )
                .unwrap()
            })
            .collect::<Vec<_>>();

        CreateMessageData {
            components,
            ..Default::default()
        }
    }
}

impl From<AttachmentPayload> for CreateMessageData {
    /// Converts an attachment payload to `CreateMessageData`.
    ///
    /// # Arguments
    ///
    /// * `value` - The attachment payload.
    ///
    /// # Examples
    ///
    /// ```
    /// let message_data: CreateMessageData = attachment_payload.into();
    /// ```
    fn from(value: AttachmentPayload) -> Self {
        CreateMessageData {
            attachments: vec![value],
            ..Default::default()
        }
    }
}

impl From<Vec<AttachmentPayload>> for CreateMessageData {
    /// Converts a vector of attachment payloads to `CreateMessageData`.
    ///
    /// # Arguments
    ///
    /// * `value` - The vector of attachment payloads.
    ///
    /// # Examples
    ///
    /// ```
    /// let message_data: CreateMessageData = vec![attachment_payload1, attachment_payload2].into();
    /// ```
    fn from(value: Vec<AttachmentPayload>) -> Self {
        CreateMessageData {
            attachments: value,
            ..Default::default()
        }
    }
}