diff --git a/twilight-http/src/client/mod.rs b/twilight-http/src/client/mod.rs index 79c5f563ebe..1df82ab6376 100644 --- a/twilight-http/src/client/mod.rs +++ b/twilight-http/src/client/mod.rs @@ -1380,12 +1380,20 @@ impl Client { /// and upper limits. This method will not delete messages older than two /// weeks. See [Discord Docs/Bulk Delete Messages]. /// + /// # Errors + /// + /// Returns an error of type + /// [`ChannelValidationErrorType::BulkDeleteMessagesInvalid`] when the number of + /// messages to delete in bulk is invalid. + /// is not between 1 and 120 characters in length. + /// /// [Discord Docs/Bulk Delete Messages]: https://discord.com/developers/docs/resources/channel#bulk-delete-messages - pub const fn delete_messages<'a>( + /// [`ChannelValidationErrorType::BulkDeleteMessagesInvalid`]: twilight_validate::channel::ChannelValidationErrorType::BulkDeleteMessagesInvalid + pub fn delete_messages<'a>( &'a self, channel_id: Id, message_ids: &'a [Id], - ) -> DeleteMessages<'a> { + ) -> Result, ChannelValidationError> { DeleteMessages::new(self, channel_id, message_ids) } diff --git a/twilight-http/src/request/channel/message/delete_messages.rs b/twilight-http/src/request/channel/message/delete_messages.rs index 4615da141ff..7abe2e86d09 100644 --- a/twilight-http/src/request/channel/message/delete_messages.rs +++ b/twilight-http/src/request/channel/message/delete_messages.rs @@ -11,7 +11,10 @@ use twilight_model::id::{ marker::{ChannelMarker, MessageMarker}, Id, }; -use twilight_validate::request::{audit_reason as validate_audit_reason, ValidationError}; +use twilight_validate::{ + channel::{bulk_delete_messages as validate_bulk_delete_messages, ChannelValidationError}, + request::{audit_reason as validate_audit_reason, ValidationError}, +}; #[derive(Serialize)] struct DeleteMessagesFields<'a> { @@ -35,17 +38,19 @@ pub struct DeleteMessages<'a> { } impl<'a> DeleteMessages<'a> { - pub(crate) const fn new( + pub(crate) fn new( http: &'a Client, channel_id: Id, messages: &'a [Id], - ) -> Self { - Self { + ) -> Result { + validate_bulk_delete_messages(messages.len())?; + + Ok(Self { channel_id, fields: DeleteMessagesFields { messages }, http, reason: None, - } + }) } /// Execute the request, returning a future resolving to a [`Response`]. diff --git a/twilight-validate/src/channel.rs b/twilight-validate/src/channel.rs index 06cfaedf51e..467144b0c04 100644 --- a/twilight-validate/src/channel.rs +++ b/twilight-validate/src/channel.rs @@ -9,6 +9,12 @@ use twilight_model::channel::ChannelType; /// Minimum bitrate of a voice channel. pub const CHANNEL_BITRATE_MIN: u32 = 8000; +/// Maximum number of bulk messages that can be deleted. +pub const CHANNEL_BULK_DELETE_MESSAGES_MAX: usize = 100; + +/// Minimum number of bulk messages that can be deleted. +pub const CHANNEL_BULK_DELETE_MESSAGES_MIN: usize = 2; + /// Maximum length of a forum channel's topic. pub const CHANNEL_FORUM_TOPIC_LENGTH_MAX: usize = 4096; @@ -67,6 +73,13 @@ impl Display for ChannelValidationError { f.write_str("bitrate is less than ")?; Display::fmt(&CHANNEL_BITRATE_MIN, f) } + ChannelValidationErrorType::BulkDeleteMessagesInvalid => { + f.write_str("number of messages deleted in bulk is less than ")?; + Display::fmt(&CHANNEL_BULK_DELETE_MESSAGES_MIN, f)?; + f.write_str(" or greater than ")?; + + Display::fmt(&CHANNEL_BULK_DELETE_MESSAGES_MAX, f) + } ChannelValidationErrorType::ForumTopicInvalid => { f.write_str("the forum topic is invalid") } @@ -99,6 +112,8 @@ impl Error for ChannelValidationError {} pub enum ChannelValidationErrorType { /// The bitrate is less than 8000. BitrateInvalid, + /// Number of messages being deleted in bulk is invalid. + BulkDeleteMessagesInvalid, /// The length of the topic is more than 4096 UTF-16 characters. ForumTopicInvalid, /// The length of the name is either fewer than 1 UTF-16 characters or @@ -139,6 +154,26 @@ pub const fn bitrate(value: u32) -> Result<(), ChannelValidationError> { } } +/// Ensure the number of messages to delete in bulk is correct. +/// +/// # Errors +/// +/// Returns an error of type [`BulkDeleteMessagesInvalid`] if the number of +/// messages to delete in bulk is invalid. +/// +/// [`BulkDeleteMessagesInvalid`]: ChannelValidationErrorType::BulkDeleteMessagesInvalid +pub const fn bulk_delete_messages(message_count: usize) -> Result<(), ChannelValidationError> { + if message_count >= CHANNEL_BULK_DELETE_MESSAGES_MIN + && message_count <= CHANNEL_BULK_DELETE_MESSAGES_MAX + { + Ok(()) + } else { + Err(ChannelValidationError { + kind: ChannelValidationErrorType::BulkDeleteMessagesInvalid, + }) + } +} + /// Ensure a channel is a thread. /// /// # Errors @@ -269,6 +304,23 @@ pub const fn user_limit(value: u16) -> Result<(), ChannelValidationError> { mod tests { use super::*; + #[test] + fn bulk_delete_messages() { + assert!(matches!( + super::bulk_delete_messages(0).unwrap_err().kind(), + ChannelValidationErrorType::BulkDeleteMessagesInvalid, + )); + assert!(matches!( + super::bulk_delete_messages(1).unwrap_err().kind(), + ChannelValidationErrorType::BulkDeleteMessagesInvalid, + )); + assert!(super::bulk_delete_messages(100).is_ok()); + assert!(matches!( + super::bulk_delete_messages(101).unwrap_err().kind(), + ChannelValidationErrorType::BulkDeleteMessagesInvalid, + )); + } + #[test] fn channel_bitrate() { assert!(bitrate(8000).is_ok());