diff --git a/crates/core/database/src/models/messages/model.rs b/crates/core/database/src/models/messages/model.rs index ea79c016..abb0597b 100644 --- a/crates/core/database/src/models/messages/model.rs +++ b/crates/core/database/src/models/messages/model.rs @@ -4,8 +4,8 @@ use indexmap::{IndexMap, IndexSet}; use iso8601_timestamp::Timestamp; use revolt_config::{config, FeaturesLimits}; use revolt_models::v0::{ - self, BulkMessageResponse, DataMessageSend, Embed, MessageAuthor, MessageSort, MessageWebhook, - PushNotification, ReplyIntent, SendableEmbed, Text, RE_MENTION, + self, BulkMessageResponse, DataMessageSend, Embed, MessageAuthor, MessageFlags, MessageSort, + MessageWebhook, PushNotification, ReplyIntent, SendableEmbed, Text, RE_MENTION, }; use revolt_permissions::{ChannelPermission, PermissionValue}; use revolt_result::Result; @@ -65,6 +65,10 @@ auto_derived_partial!( /// Name and / or avatar overrides for this message #[serde(skip_serializing_if = "Option::is_none")] pub masquerade: Option, + + /// Bitfield of message flags + #[serde(skip_serializing_if = "Option::is_none")] + pub flags: Option, }, "PartialMessage" ); @@ -200,6 +204,7 @@ impl Default for Message { reactions: Default::default(), interactions: Default::default(), masquerade: None, + flags: None, } } } @@ -241,6 +246,13 @@ impl Message { return Err(create_error!(EmptyMessage)); } + // Ensure flags are either not set or have permissible values + if let Some(flags) = &data.flags { + if flags != &0 && flags != &1 { + return Err(create_error!(InvalidProperty)); + } + } + // Ensure restrict_reactions is not specified without reactions list if let Some(interactions) = &data.interactions { if interactions.restrict_reactions { @@ -274,6 +286,7 @@ impl Message { .unwrap_or_default(), author: author_id, webhook: webhook.map(|w| w.into()), + flags: data.flags.map(|v| v as i32), ..Default::default() }; @@ -438,24 +451,26 @@ impl Message { ) .await?; - // Push out Web Push notifications - crate::tasks::web_push::queue( - { - match channel { - Channel::DirectMessage { recipients, .. } - | Channel::Group { recipients, .. } => recipients.clone(), - Channel::TextChannel { .. } => self.mentions.clone().unwrap_or_default(), - _ => vec![], - } - }, - PushNotification::from( - self.clone().into_model(None, None), - Some(author), - &channel.id(), + if !self.has_suppressed_notifications() { + // Push out Web Push notifications + crate::tasks::web_push::queue( + { + match channel { + Channel::DirectMessage { recipients, .. } + | Channel::Group { recipients, .. } => recipients.clone(), + Channel::TextChannel { .. } => self.mentions.clone().unwrap_or_default(), + _ => vec![], + } + }, + PushNotification::from( + self.clone().into_model(None, None), + Some(author), + &channel.id(), + ) + .await, ) - .await, - ) - .await; + .await; + } Ok(()) } @@ -487,6 +502,16 @@ impl Message { })) } + /// Whether this message has suppressed notifications + pub fn has_suppressed_notifications(&self) -> bool { + if let Some(flags) = self.flags { + flags & MessageFlags::SupressNotifications as i32 + == MessageFlags::SupressNotifications as i32 + } else { + false + } + } + /// Update message data pub async fn update(&mut self, db: &Database, partial: PartialMessage) -> Result<()> { self.apply_options(partial.clone()); diff --git a/crates/core/database/src/util/bridge/v0.rs b/crates/core/database/src/util/bridge/v0.rs index b185c9c1..747857cd 100644 --- a/crates/core/database/src/util/bridge/v0.rs +++ b/crates/core/database/src/util/bridge/v0.rs @@ -470,7 +470,7 @@ impl crate::Message { member, webhook: self.webhook, content: self.content, - system: self.system.map(|system| system.into()), + system: self.system.map(Into::into), attachments: self .attachments .map(|v| v.into_iter().map(|f| f.into()).collect()), @@ -480,7 +480,8 @@ impl crate::Message { replies: self.replies, reactions: self.reactions, interactions: self.interactions.into(), - masquerade: self.masquerade.map(|masq| masq.into()), + masquerade: self.masquerade.map(Into::into), + flags: self.flags.map(|flags| flags as u32).unwrap_or_default(), } } } @@ -496,7 +497,7 @@ impl From for PartialMessage { member: None, webhook: value.webhook, content: value.content, - system: value.system.map(|system| system.into()), + system: value.system.map(Into::into), attachments: value .attachments .map(|v| v.into_iter().map(|f| f.into()).collect()), @@ -505,8 +506,9 @@ impl From for PartialMessage { mentions: value.mentions, replies: value.replies, reactions: value.reactions, - interactions: value.interactions.map(|interactions| interactions.into()), - masquerade: value.masquerade.map(|masq| masq.into()), + interactions: value.interactions.map(Into::into), + masquerade: value.masquerade.map(Into::into), + flags: value.flags.map(|flags| flags as u32), } } } diff --git a/crates/core/models/src/v0/messages.rs b/crates/core/models/src/v0/messages.rs index ce2e3cf0..8d0d601c 100644 --- a/crates/core/models/src/v0/messages.rs +++ b/crates/core/models/src/v0/messages.rs @@ -70,6 +70,15 @@ auto_derived_partial!( /// Name and / or avatar overrides for this message #[serde(skip_serializing_if = "Option::is_none")] pub masquerade: Option, + + /// Bitfield of message flags + /// + /// https://docs.rs/revolt-models/latest/revolt_models/v0/enum.MessageFlags.html + #[cfg_attr( + feature = "serde", + serde(skip_serializing_if = "crate::if_zero_u32", default) + )] + pub flags: u32, }, "PartialMessage" ); @@ -247,6 +256,11 @@ auto_derived!( pub masquerade: Option, /// Information about how this message should be interacted with pub interactions: Option, + + /// Bitfield of message flags + /// + /// https://docs.rs/revolt-models/latest/revolt_models/v0/enum.MessageFlags.html + pub flags: Option, } /// Options for querying messages @@ -334,6 +348,13 @@ auto_derived!( /// Remove all reactions pub remove_all: Option, } + + /// Message flag bitfield + #[repr(u32)] + pub enum MessageFlags { + /// Message will not send push / desktop notifications + SupressNotifications = 1, + } ); /// Message Author Abstraction diff --git a/crates/core/models/src/v0/users.rs b/crates/core/models/src/v0/users.rs index 8d72eb18..58a7f2c4 100644 --- a/crates/core/models/src/v0/users.rs +++ b/crates/core/models/src/v0/users.rs @@ -42,6 +42,8 @@ auto_derived_partial!( pub relations: Vec, /// Bitfield of user badges + /// + /// https://docs.rs/revolt-models/latest/revolt_models/v0/enum.UserBadges.html #[cfg_attr( feature = "serde", serde(skip_serializing_if = "crate::if_zero_u32", default) @@ -52,6 +54,8 @@ auto_derived_partial!( pub status: Option, /// Enum of user flags + /// + /// https://docs.rs/revolt-models/latest/revolt_models/v0/enum.UserFlags.html #[cfg_attr( feature = "serde", serde(skip_serializing_if = "crate::if_zero_u32", default)