sparkle_impostor/
reference.rs

1//! Handling the message having a reference
2
3use twilight_model::channel::{
4    message::{embed::EmbedAuthor, Embed},
5    Message,
6};
7
8use crate::{avatar, error::Error, MessageSource};
9
10/// Info about the message's reference
11#[derive(Debug, Clone, Copy, PartialEq)]
12pub enum Info<'a> {
13    /// Message does not have a reference or it hasn't been checked
14    None,
15    /// Message has a reference, but it's been deleted or is unknown due to a
16    /// Discord error
17    UnknownOrDeleted,
18    /// Message has a known reference
19    Reference(&'a Message),
20}
21
22impl MessageSource<'_> {
23    /// Handle the message having a reference
24    ///
25    /// This adds an embed with the reference message's info to the message
26    ///
27    /// # Warnings
28    ///
29    /// Must be called before [`MessageSource::create`]
30    ///
31    /// # Errors
32    ///
33    /// Returns [`Error::MessageValidation`] if the message already has
34    /// [`EMBED_COUNT_LIMIT`] embeds
35    ///
36    /// [`EMBED_COUNT_LIMIT`]: twilight_validate::message::EMBED_COUNT_LIMIT
37    #[allow(clippy::missing_panics_doc)]
38    pub fn handle_reference(mut self) -> Result<Self, Error> {
39        if Info::None == self.reference_info {
40            return Ok(self);
41        }
42
43        let base_embed = Embed {
44            title: Some("Reply to:".to_owned()),
45            author: None,
46            color: None,
47            description: None,
48            fields: vec![],
49            footer: None,
50            image: None,
51            kind: String::new(),
52            provider: None,
53            thumbnail: None,
54            timestamp: None,
55            url: None,
56            video: None,
57        };
58
59        // can't create the error manually
60        self.embeds.push(base_embed);
61        let mut embed = if let Err(err) = twilight_validate::message::embeds(&self.embeds) {
62            self.embeds.pop();
63            return Err(err.into());
64        } else {
65            self.embeds.pop().unwrap()
66        };
67
68        embed.description = Some(match self.reference_info {
69            Info::UnknownOrDeleted => "Unknown or deleted message".to_owned(),
70            Info::Reference(message) => message
71                .content
72                .chars()
73                .take(97)
74                .chain(['.'; 3])
75                .collect::<String>(),
76            Info::None => unreachable!(),
77        });
78
79        if let Info::Reference(message) = self.reference_info {
80            let mut avatar_info = avatar::Info {
81                url: None,
82                user_id: message.author.id,
83                guild_id: self.guild_id,
84                user_discriminator: message.author.discriminator,
85                user_avatar: message.author.avatar,
86                member_avatar: message.member.as_ref().and_then(|member| member.avatar),
87            };
88            avatar_info.set_url();
89
90            embed.author = Some(EmbedAuthor {
91                icon_url: avatar_info.url,
92                name: message
93                    .member
94                    .as_ref()
95                    .and_then(|member| member.nick.as_ref())
96                    .unwrap_or(&message.author.name)
97                    .clone(),
98                proxy_icon_url: None,
99                url: None,
100            });
101
102            embed.url = Some(format!(
103                "https://discord.com/channels/{}/{}/{}",
104                self.guild_id, message.channel_id, message.id
105            ));
106        }
107
108        self.embeds.push(embed);
109
110        Ok(self)
111    }
112}