diff --git a/src/builder/create_allowed_mentions.rs b/src/builder/create_allowed_mentions.rs index cb44a50954c..518785f0063 100644 --- a/src/builder/create_allowed_mentions.rs +++ b/src/builder/create_allowed_mentions.rs @@ -55,7 +55,7 @@ enum ParseValue { /// ``` /// /// [Discord docs](https://discord.com/developers/docs/resources/channel#allowed-mentions-object). -#[derive(Clone, Debug, Default, Serialize)] +#[derive(Clone, Debug, Default, Serialize, PartialEq)] #[must_use] pub struct CreateAllowedMentions { parse: HashSet, diff --git a/src/builder/create_attachment.rs b/src/builder/create_attachment.rs index 5bfdb110248..ddbca56bc1f 100644 --- a/src/builder/create_attachment.rs +++ b/src/builder/create_attachment.rs @@ -18,7 +18,7 @@ use crate::model::id::AttachmentId; /// [Discord docs](https://discord.com/developers/docs/resources/channel#attachment-object-attachment-structure). /// /// [`send_files`]: crate::model::id::ChannelId::send_files -#[derive(Clone, Debug, Serialize)] +#[derive(Clone, Debug, Serialize, PartialEq)] #[non_exhaustive] #[must_use] pub struct CreateAttachment { @@ -114,12 +114,12 @@ impl CreateAttachment { } } -#[derive(Debug, Clone, serde::Serialize)] +#[derive(Debug, Clone, serde::Serialize, PartialEq)] struct ExistingAttachment { id: AttachmentId, } -#[derive(Debug, Clone, serde::Serialize)] +#[derive(Debug, Clone, serde::Serialize, PartialEq)] #[serde(untagged)] enum NewOrExisting { New(CreateAttachment), @@ -181,7 +181,7 @@ enum NewOrExisting { /// /// Internally, this type is used not just for message editing endpoints, but also for message /// creation endpoints. -#[derive(Default, Debug, Clone, serde::Serialize)] +#[derive(Default, Debug, Clone, serde::Serialize, PartialEq)] #[serde(transparent)] #[must_use] pub struct EditAttachments { diff --git a/src/builder/create_components.rs b/src/builder/create_components.rs index 0ec8af4e04f..c662c178558 100644 --- a/src/builder/create_components.rs +++ b/src/builder/create_components.rs @@ -6,7 +6,7 @@ use crate::model::prelude::*; /// A builder for creating a components action row in a message. /// /// [Discord docs](https://discord.com/developers/docs/interactions/message-components#component-object). -#[derive(Clone, Debug)] +#[derive(Clone, Debug, PartialEq)] #[must_use] pub enum CreateActionRow { Buttons(Vec), @@ -32,7 +32,7 @@ impl serde::Serialize for CreateActionRow { } /// A builder for creating a button component in a message -#[derive(Clone, Debug, Serialize)] +#[derive(Clone, Debug, Serialize, PartialEq)] #[must_use] pub struct CreateButton(Button); @@ -128,7 +128,7 @@ impl Serialize for CreateSelectMenuDefault { } /// [Discord docs](https://discord.com/developers/docs/interactions/message-components#select-menu-object-select-menu-structure). -#[derive(Clone, Debug)] +#[derive(Clone, Debug, PartialEq)] pub enum CreateSelectMenuKind { String { options: Vec }, User { default_users: Option> }, @@ -198,7 +198,7 @@ impl Serialize for CreateSelectMenuKind { /// A builder for creating a select menu component in a message /// /// [Discord docs](https://discord.com/developers/docs/interactions/message-components#select-menu-object-select-menu-structure). -#[derive(Clone, Debug, Serialize)] +#[derive(Clone, Debug, Serialize, PartialEq)] #[must_use] pub struct CreateSelectMenu { custom_id: String, @@ -264,7 +264,7 @@ impl CreateSelectMenu { /// A builder for creating an option of a select menu component in a message /// /// [Discord docs](https://discord.com/developers/docs/interactions/message-components#select-menu-object-select-option-structure) -#[derive(Clone, Debug, Serialize)] +#[derive(Clone, Debug, Serialize, PartialEq)] #[must_use] pub struct CreateSelectMenuOption { label: String, @@ -324,7 +324,7 @@ impl CreateSelectMenuOption { /// A builder for creating an input text component in a modal /// /// [Discord docs](https://discord.com/developers/docs/interactions/message-components#text-inputs-text-input-structure). -#[derive(Clone, Debug, Serialize)] +#[derive(Clone, Debug, Serialize, PartialEq)] #[must_use] pub struct CreateInputText(InputText); diff --git a/src/builder/create_embed.rs b/src/builder/create_embed.rs index d5689aad007..010cbe6c7f4 100644 --- a/src/builder/create_embed.rs +++ b/src/builder/create_embed.rs @@ -21,7 +21,7 @@ use crate::model::prelude::*; /// A builder to create an embed in a message /// /// [Discord docs](https://discord.com/developers/docs/resources/channel#embed-object) -#[derive(Clone, Debug, Serialize)] +#[derive(Clone, Debug, Serialize, PartialEq)] #[must_use] pub struct CreateEmbed(Embed); diff --git a/src/builder/edit_message.rs b/src/builder/edit_message.rs index 57518530ff5..82f88ba113d 100644 --- a/src/builder/edit_message.rs +++ b/src/builder/edit_message.rs @@ -35,7 +35,7 @@ use crate::model::prelude::*; /// ``` /// /// [Discord docs](https://discord.com/developers/docs/resources/channel#edit-message) -#[derive(Clone, Debug, Default, Serialize)] +#[derive(Clone, Debug, Default, Serialize, PartialEq)] #[must_use] pub struct EditMessage { #[serde(skip_serializing_if = "Option::is_none")] @@ -221,7 +221,7 @@ impl EditMessage { #[cfg(feature = "http")] #[async_trait::async_trait] impl Builder for EditMessage { - type Context<'ctx> = (ChannelId, MessageId); + type Context<'ctx> = (ChannelId, MessageId, Option); type Built = Message; /// Edits a message in the channel. @@ -254,6 +254,17 @@ impl Builder for EditMessage { ) -> Result { self.check_length()?; + #[cfg(feature = "cache")] + if let Some(user_id) = ctx.2 { + if let Some(cache) = cache_http.cache() { + let reference_builder = EditMessage::new().suppress_embeds(true); + + if user_id != cache.current_user().id && self != reference_builder { + return Err(Error::Model(ModelError::InvalidUser)); + } + } + } + let files = self.attachments.as_mut().map_or(Vec::new(), |a| a.take_files()); cache_http.http().edit_message(ctx.0, ctx.1, &self, files).await diff --git a/src/model/channel/channel_id.rs b/src/model/channel/channel_id.rs index 7cc1367d0d8..5cef8cf2856 100644 --- a/src/model/channel/channel_id.rs +++ b/src/model/channel/channel_id.rs @@ -351,7 +351,7 @@ impl ChannelId { message_id: impl Into, builder: EditMessage, ) -> Result { - builder.execute(cache_http, (self, message_id.into())).await + builder.execute(cache_http, (self, message_id.into(), None)).await } /// Follows the News Channel diff --git a/src/model/channel/embed.rs b/src/model/channel/embed.rs index 91304155f65..afc849436f7 100644 --- a/src/model/channel/embed.rs +++ b/src/model/channel/embed.rs @@ -12,7 +12,7 @@ use crate::model::{Colour, Timestamp}; /// /// [slack's attachments]: https://api.slack.com/docs/message-attachments #[cfg_attr(feature = "typesize", derive(typesize::derive::TypeSize))] -#[derive(Clone, Default, Debug, Deserialize, Serialize)] +#[derive(Clone, Default, Debug, Deserialize, Serialize, PartialEq)] #[non_exhaustive] pub struct Embed { /// The title of the embed. @@ -73,7 +73,7 @@ pub struct Embed { /// /// [Discord docs](https://discord.com/developers/docs/resources/channel#embed-object-embed-author-structure). #[cfg_attr(feature = "typesize", derive(typesize::derive::TypeSize))] -#[derive(Clone, Debug, Deserialize, Serialize)] +#[derive(Clone, Debug, Deserialize, Serialize, PartialEq)] #[non_exhaustive] pub struct EmbedAuthor { /// The name of the author. @@ -95,7 +95,7 @@ pub struct EmbedAuthor { /// /// [Discord docs](https://discord.com/developers/docs/resources/channel#embed-object-embed-field-structure). #[cfg_attr(feature = "typesize", derive(typesize::derive::TypeSize))] -#[derive(Clone, Debug, Deserialize, Serialize)] +#[derive(Clone, Debug, Deserialize, Serialize, PartialEq)] #[non_exhaustive] pub struct EmbedField { /// The name of the field. @@ -137,7 +137,7 @@ impl EmbedField { /// /// [Discord docs](https://discord.com/developers/docs/resources/channel#embed-object-embed-footer-structure). #[cfg_attr(feature = "typesize", derive(typesize::derive::TypeSize))] -#[derive(Clone, Debug, Deserialize, Serialize)] +#[derive(Clone, Debug, Deserialize, Serialize, PartialEq)] #[non_exhaustive] pub struct EmbedFooter { /// The associated text with the footer. @@ -156,7 +156,7 @@ pub struct EmbedFooter { /// /// [Discord docs](https://discord.com/developers/docs/resources/channel#embed-object-embed-image-structure). #[cfg_attr(feature = "typesize", derive(typesize::derive::TypeSize))] -#[derive(Clone, Debug, Deserialize, Serialize)] +#[derive(Clone, Debug, Deserialize, Serialize, PartialEq)] #[non_exhaustive] pub struct EmbedImage { /// Source URL of the image. @@ -175,7 +175,7 @@ pub struct EmbedImage { /// /// [Discord docs](https://discord.com/developers/docs/resources/channel#embed-object-embed-provider-structure). #[cfg_attr(feature = "typesize", derive(typesize::derive::TypeSize))] -#[derive(Clone, Debug, Deserialize, Serialize)] +#[derive(Clone, Debug, Deserialize, Serialize, PartialEq)] #[non_exhaustive] pub struct EmbedProvider { /// The name of the provider. @@ -188,7 +188,7 @@ pub struct EmbedProvider { /// /// [Discord docs](https://discord.com/developers/docs/resources/channel#embed-object-embed-thumbnail-structure). #[cfg_attr(feature = "typesize", derive(typesize::derive::TypeSize))] -#[derive(Clone, Debug, Deserialize, Serialize)] +#[derive(Clone, Debug, Deserialize, Serialize, PartialEq)] #[non_exhaustive] pub struct EmbedThumbnail { /// The source URL of the thumbnail. @@ -207,7 +207,7 @@ pub struct EmbedThumbnail { /// /// [Discord docs](https://discord.com/developers/docs/resources/channel#embed-object-embed-video-structure). #[cfg_attr(feature = "typesize", derive(typesize::derive::TypeSize))] -#[derive(Clone, Debug, Deserialize, Serialize)] +#[derive(Clone, Debug, Deserialize, Serialize, PartialEq)] #[non_exhaustive] pub struct EmbedVideo { /// The source URL of the video. diff --git a/src/model/channel/message.rs b/src/model/channel/message.rs index 59db430fd40..2d5036404c0 100644 --- a/src/model/channel/message.rs +++ b/src/model/channel/message.rs @@ -346,21 +346,14 @@ impl Message { /// /// [Manage Messages]: Permissions::MANAGE_MESSAGES pub async fn edit(&mut self, cache_http: impl CacheHttp, builder: EditMessage) -> Result<()> { - #[cfg(feature = "cache")] - { - if let Some(cache) = cache_http.cache() { - if self.author.id != cache.current_user().id { - return Err(Error::Model(ModelError::InvalidUser)); - } - } - } if let Some(flags) = self.flags { if flags.contains(MessageFlags::IS_VOICE_MESSAGE) { return Err(Error::Model(ModelError::CannotEditVoiceMessage)); } } - *self = builder.execute(cache_http, (self.channel_id, self.id)).await?; + *self = + builder.execute(cache_http, (self.channel_id, self.id, Some(self.author.id))).await?; Ok(()) }