diff --git a/crates/ruma-common/src/events/room/redaction.rs b/crates/ruma-common/src/events/room/redaction.rs index 7e49d833..7c1d230d 100644 --- a/crates/ruma-common/src/events/room/redaction.rs +++ b/crates/ruma-common/src/events/room/redaction.rs @@ -2,17 +2,19 @@ //! //! [`m.room.redaction`]: https://spec.matrix.org/latest/client-server-api/#mroomredaction +use js_int::Int; use ruma_macros::{Event, EventContent}; use serde::{Deserialize, Deserializer, Serialize}; use serde_json::value::RawValue as RawJsonValue; use crate::{ events::{ - EventContent, MessageLikeEventType, MessageLikeUnsigned, RedactedUnsigned, + BundledMessageLikeRelations, EventContent, MessageLikeEventType, RedactedUnsigned, RedactionDeHelper, }, - serde::from_raw_json_value, - EventId, MilliSecondsSinceUnixEpoch, OwnedEventId, OwnedRoomId, OwnedUserId, RoomId, UserId, + serde::{from_raw_json_value, CanBeEmpty}, + EventId, MilliSecondsSinceUnixEpoch, OwnedEventId, OwnedRoomId, OwnedTransactionId, + OwnedUserId, RoomId, UserId, }; /// A possibly-redacted redaction event. @@ -60,7 +62,7 @@ pub struct OriginalRoomRedactionEvent { pub room_id: OwnedRoomId, /// Additional key-value pairs not signed by the homeserver. - pub unsigned: MessageLikeUnsigned, + pub unsigned: RoomRedactionUnsigned, } /// Redacted redaction event. @@ -106,7 +108,7 @@ pub struct OriginalSyncRoomRedactionEvent { pub origin_server_ts: MilliSecondsSinceUnixEpoch, /// Additional key-value pairs not signed by the homeserver. - pub unsigned: MessageLikeUnsigned, + pub unsigned: RoomRedactionUnsigned, } /// Redacted redaction event without a `room_id`. @@ -291,3 +293,49 @@ impl<'de> Deserialize<'de> for SyncRoomRedactionEvent { } } } + +/// Extra information about a redaction that is not incorporated into the event's hash. +#[derive(Clone, Debug, Deserialize)] +#[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)] +pub struct RoomRedactionUnsigned { + /// The time in milliseconds that has elapsed since the event was sent. + /// + /// This field is generated by the local homeserver, and may be incorrect if the local time on + /// at least one of the two servers is out of sync, which can cause the age to either be + /// negative or greater than it actually is. + pub age: Option, + + /// The client-supplied transaction ID, if the client being given the event is the same one + /// which sent it. + pub transaction_id: Option, + + /// [Bundled aggregations] of related child events. + /// + /// [Bundled aggregations]: https://spec.matrix.org/latest/client-server-api/#aggregations + #[serde(rename = "m.relations", default)] + pub relations: BundledMessageLikeRelations, +} + +impl RoomRedactionUnsigned { + /// Create a new `Unsigned` with fields set to `None`. + pub fn new() -> Self { + Self { age: None, transaction_id: None, relations: BundledMessageLikeRelations::default() } + } +} + +impl Default for RoomRedactionUnsigned { + fn default() -> Self { + Self::new() + } +} + +impl CanBeEmpty for RoomRedactionUnsigned { + /// Whether this unsigned data is empty (all fields are `None`). + /// + /// This method is used to determine whether to skip serializing the `unsigned` field in room + /// events. Do not use it to determine whether an incoming `unsigned` field was present - it + /// could still have been present but contained none of the known fields. + fn is_empty(&self) -> bool { + self.age.is_none() && self.transaction_id.is_none() && self.relations.is_empty() + } +}