diff --git a/crates/delta/src/routes/channels/message_edit.rs b/crates/delta/src/routes/channels/message_edit.rs index e02b5dc8..d9388c6e 100644 --- a/crates/delta/src/routes/channels/message_edit.rs +++ b/crates/delta/src/routes/channels/message_edit.rs @@ -36,6 +36,8 @@ pub async fn req( edit.validate() .map_err(|error| Error::FailedValidation { error })?; + Message::validate_sum(&edit.content, &edit.embeds)?; + let mut message = msg.as_message(db).await?; if message.channel != target { return Err(Error::NotFound); diff --git a/crates/delta/src/routes/channels/message_send.rs b/crates/delta/src/routes/channels/message_send.rs index 993c6506..0cf373d2 100644 --- a/crates/delta/src/routes/channels/message_send.rs +++ b/crates/delta/src/routes/channels/message_send.rs @@ -33,6 +33,8 @@ pub struct DataMessageSend { /// Messages to reply to replies: Option>, /// Embeds to include in message + /// + /// Text embed content contributes to the content length cap #[validate(length(min = 1, max = 10))] embeds: Option>, /// Masquerade to apply to this message @@ -61,6 +63,8 @@ pub async fn message_send( data.validate() .map_err(|error| Error::FailedValidation { error })?; + Message::validate_sum(&data.content, &data.embeds)?; + idempotency.consume_nonce(data.nonce).await?; let channel = target.as_channel(db).await?; diff --git a/crates/quark/src/impl/generic/channels/message.rs b/crates/quark/src/impl/generic/channels/message.rs index d17c0170..6eaa3e5e 100644 --- a/crates/quark/src/impl/generic/channels/message.rs +++ b/crates/quark/src/impl/generic/channels/message.rs @@ -166,6 +166,31 @@ impl Message { .await; Ok(()) } + + /// Validate the sum of content of a message is under threshold + pub fn validate_sum( + content: &Option, + embeds: &Option>, + ) -> Result<()> { + let mut running_total = 0; + if let Some(content) = content { + running_total += content.len(); + } + + if let Some(embeds) = embeds { + for embed in embeds { + if let Some(desc) = &embed.description { + running_total += desc.len(); + } + } + } + + if running_total <= 2000 { + Ok(()) + } else { + Err(Error::PayloadTooLarge) + } + } } pub trait IntoUsers { diff --git a/crates/quark/src/util/result.rs b/crates/quark/src/util/result.rs index 9e0c2a9b..54b26488 100644 --- a/crates/quark/src/util/result.rs +++ b/crates/quark/src/util/result.rs @@ -41,6 +41,7 @@ pub enum Error { TooManyAttachments, TooManyReplies, EmptyMessage, + PayloadTooLarge, CannotRemoveYourself, GroupTooLarge { max: usize, @@ -145,6 +146,7 @@ impl<'r> Responder<'r, 'static> for Error { Error::TooManyAttachments => Status::BadRequest, Error::TooManyReplies => Status::BadRequest, Error::EmptyMessage => Status::UnprocessableEntity, + Error::PayloadTooLarge => Status::UnprocessableEntity, Error::CannotRemoveYourself => Status::BadRequest, Error::GroupTooLarge { .. } => Status::Forbidden, Error::AlreadyInGroup => Status::Conflict,