diff --git a/ruma-events/src/lib.rs b/ruma-events/src/lib.rs index 3f450f06..b90ab8c6 100644 --- a/ruma-events/src/lib.rs +++ b/ruma-events/src/lib.rs @@ -238,6 +238,8 @@ pub mod push_rules; #[cfg(feature = "unstable-pre-spec")] pub mod reaction; pub mod receipt; +#[cfg(feature = "unstable-pre-spec")] +pub mod relation; pub mod room; pub mod room_key; pub mod room_key_request; @@ -245,6 +247,8 @@ pub mod sticker; pub mod tag; pub mod typing; +#[cfg(feature = "unstable-pre-spec")] +pub use self::relation::Relations; pub use self::{ enums::{ AnyBasicEvent, AnyBasicEventContent, AnyEphemeralRoomEvent, AnyEphemeralRoomEventContent, @@ -282,6 +286,11 @@ pub struct Unsigned { /// is the same one which sent it. #[serde(skip_serializing_if = "Option::is_none")] pub transaction_id: Option, + + /// Server-compiled information from other events relating to this event. + #[cfg(feature = "unstable-pre-spec")] + #[serde(rename = "m.relations", skip_serializing_if = "Option::is_none")] + pub relations: Option, } impl Unsigned { diff --git a/ruma-events/src/policy/rule/room.rs b/ruma-events/src/policy/rule/room.rs index cc766314..4ec2699d 100644 --- a/ruma-events/src/policy/rule/room.rs +++ b/ruma-events/src/policy/rule/room.rs @@ -36,7 +36,12 @@ mod tests { room_id: room_id!("!jEsUZKDJdhlrceRyVU:example.org"), state_key: "rule:#*:example.org".into(), prev_content: None, - unsigned: Unsigned { age: Some(1234.into()), transaction_id: None }, + unsigned: Unsigned { + age: Some(1234.into()), + transaction_id: None, + #[cfg(feature = "unstable-pre-spec")] + relations: None, + }, content: RoomEventContent(PolicyRuleEventContent { entity: "#*:example.org".into(), reason: "undesirable content".into(), diff --git a/ruma-events/src/relation.rs b/ruma-events/src/relation.rs new file mode 100644 index 00000000..f405da56 --- /dev/null +++ b/ruma-events/src/relation.rs @@ -0,0 +1,77 @@ +//! Types describing event relations after MSC 2674, 2675, 2676, 2677. + +use std::{fmt::Debug, time::SystemTime}; + +use js_int::UInt; +use serde::{Deserialize, Serialize}; + +/// Summary of all reactions with the given key to an event. +#[derive(Clone, Debug, Default, Deserialize, PartialEq, Eq, Serialize)] +#[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)] +pub struct BundledReaction { + /// The key (emoji) used for reaction. + pub key: String, + + /// Time of the bundled reaction being compiled on the server. + #[serde( + with = "ruma_serde::time::opt_ms_since_unix_epoch", + default, + skip_serializing_if = "Option::is_none" + )] + pub origin_server_ts: Option, + + /// Number of reactions. + pub count: UInt, +} + +impl BundledReaction { + /// Creates a new `BundledReaction`. + pub fn new(key: String, origin_server_ts: Option, count: UInt) -> Self { + Self { key, origin_server_ts, count } + } +} + +/// Type of bundled annotation. +#[derive(Clone, Debug, Deserialize, Serialize)] +#[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)] +#[serde(tag = "type")] +pub enum BundledAnnotation { + /// An emoji reaction and its count. + #[serde(rename = "m.reaction")] + Reaction(BundledReaction), +} + +/// The first chunk of annotations with a token for loading more. +#[derive(Clone, Debug, Default, Deserialize, Serialize)] +#[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)] +pub struct AnnotationChunk { + /// The first batch of bundled annotations. + pub chunk: Vec, + + /// Token to receive the next annotation batch. + #[serde(skip_serializing_if = "Option::is_none")] + pub next_batch: Option, +} + +impl AnnotationChunk { + /// Creates a new `AnnotationChunk`. + pub fn new(chunk: Vec, next_batch: Option) -> Self { + Self { chunk, next_batch } + } +} + +/// Precompiled list of relations to this event grouped by relation type. +#[derive(Clone, Debug, Default, Deserialize, Serialize)] +#[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)] +pub struct Relations { + /// Annotation relations. + #[serde(rename = "m.annotation")] + pub annotation: Option, +} + +impl Relations { + /// Creates a new `Relations` struct. + pub fn new(annotation: Option) -> Self { + Self { annotation } + } +}