sparkle_impostor/
delete.rs

1use std::time::{Duration, SystemTime};
2
3#[cfg(docs)]
4use twilight_model::guild::Permissions;
5use twilight_model::id::{marker::MessageMarker, Id};
6use twilight_util::snowflake::Snowflake;
7
8use crate::{error::Error, MessageSource};
9
10struct MessagesDelete {
11    bulk: Vec<Vec<Id<MessageMarker>>>,
12    single: Vec<Id<MessageMarker>>,
13}
14
15impl<'a> MessageSource<'a> {
16    /// Check if [`MessageSource::delete`] would use more than `n` requests
17    ///
18    /// If [`MessageSource::later_messages`] or
19    /// [`MessageSource::later_messages_batched`] wasn't called, `n` is always 1
20    ///
21    /// Each message older than 2 weeks uses 1 request, others use
22    /// `other_message_count` divided by
23    /// [`twilight_validate::channel::CHANNEL_BULK_DELETE_MESSAGES_MAX`] rounded
24    /// up requests
25    ///
26    /// # Errors
27    ///
28    /// Returns [`Error::DeleteRequestCountAboveLimit`] if
29    /// [`MessageSource::delete`] would use more than `n` requests
30    pub fn check_delete_request_count_in(&self, n: u16) -> Result<(), Error> {
31        let messages_delete = self.messages_delete();
32
33        if messages_delete
34            .single
35            .len()
36            .saturating_add(messages_delete.bulk.len())
37            > usize::from(n)
38        {
39            return Err(Error::DeleteRequestCountAboveLimit(n));
40        }
41
42        Ok(())
43    }
44
45    /// Delete the original message
46    ///
47    /// If [`MessageSource::later_messages`] or
48    /// [`MessageSource::later_messages_batched`] was called, later messages
49    /// will also be deleted
50    ///
51    /// If there is a message older than two weeks, they'll be
52    /// deleted individually since bulk delete isn't valid for these messages,
53    /// see [`MessageSource::check_delete_request_count_in`] if this is not the
54    /// expected behavior
55    ///
56    /// # Errors
57    ///
58    /// Returns [`Error::Http`] if deleting the messages fails
59    ///
60    /// # Panics
61    ///
62    /// If two weeks ago or the time a message was sent can't be represented
63    /// with [`SystemTime`] on the current platform
64    pub async fn delete(self) -> Result<MessageSource<'a>, Error> {
65        let messages_delete = self.messages_delete();
66
67        for message_ids_chunk in messages_delete.bulk {
68            self.http
69                .delete_messages(self.source_channel_id, &message_ids_chunk)
70                .unwrap()
71                .await?;
72        }
73
74        for message_id in messages_delete.single {
75            self.http
76                .delete_message(self.source_channel_id, message_id)
77                .await?;
78        }
79
80        Ok(self)
81    }
82
83    fn messages_delete(&self) -> MessagesDelete {
84        let mut message_ids = vec![self.source_id];
85
86        if self.later_messages.is_later_message_sources_created {
87            message_ids.extend(
88                self.later_messages
89                    .messages
90                    .iter()
91                    .map(|message| message.id),
92            );
93        }
94
95        let two_weeks_ago = SystemTime::now()
96            .checked_sub(Duration::from_secs(60 * 60 * 24 * 7 * 2))
97            .unwrap();
98
99        let (mut message_ids_bulk_delete, mut message_ids_delete) = message_ids
100            .into_iter()
101            .partition::<Vec<_>, _>(|message_id| {
102                SystemTime::UNIX_EPOCH
103                    .checked_add(Duration::from_millis(
104                        message_id.timestamp().try_into().unwrap(),
105                    ))
106                    .unwrap()
107                    >= two_weeks_ago
108            });
109        if message_ids_bulk_delete.len() == 1 {
110            message_ids_delete.push(message_ids_bulk_delete.pop().unwrap());
111        }
112
113        MessagesDelete {
114            bulk: message_ids_bulk_delete
115                .chunks(twilight_validate::channel::CHANNEL_BULK_DELETE_MESSAGES_MAX)
116                .map(ToOwned::to_owned)
117                .collect(),
118            single: message_ids_delete,
119        }
120    }
121}