From 4c8193f6eb0d602a73d4791643c4935f94356b94 Mon Sep 17 00:00:00 2001 From: Timo K Date: Wed, 22 Nov 2023 21:28:00 +0100 Subject: [PATCH] Add CallNotify event as described by MSC4075 See: [MSC4075]( https://github.com/matrix-org/matrix-spec-proposals/pull/4075) Signed-off-by: Timo K --- crates/ruma-events/Cargo.toml | 1 + crates/ruma-events/src/call.rs | 2 + crates/ruma-events/src/call/notify.rs | 72 +++++++++++++++++++++++ crates/ruma-events/src/enums.rs | 5 ++ crates/ruma-events/tests/it/call.rs | 83 +++++++++++++++++++++++++++ crates/ruma/Cargo.toml | 2 + 6 files changed, 165 insertions(+) create mode 100644 crates/ruma-events/src/call/notify.rs diff --git a/crates/ruma-events/Cargo.toml b/crates/ruma-events/Cargo.toml index 6be1c332c7..e7d64ac49d 100644 --- a/crates/ruma-events/Cargo.toml +++ b/crates/ruma-events/Cargo.toml @@ -40,6 +40,7 @@ unstable-msc3927 = ["unstable-msc3551"] unstable-msc3954 = ["unstable-msc1767"] unstable-msc3955 = ["unstable-msc1767"] unstable-msc3956 = ["unstable-msc1767"] +unstable-msc4075 = [] unstable-pdu = [] # Allow some mandatory fields to be missing, defaulting them to an empty string diff --git a/crates/ruma-events/src/call.rs b/crates/ruma-events/src/call.rs index b657ebccc0..9985e4b675 100644 --- a/crates/ruma-events/src/call.rs +++ b/crates/ruma-events/src/call.rs @@ -9,6 +9,8 @@ pub mod invite; #[cfg(feature = "unstable-msc3401")] pub mod member; pub mod negotiate; +#[cfg(feature = "unstable-msc4075")] +pub mod notify; pub mod reject; pub mod select_answer; diff --git a/crates/ruma-events/src/call/notify.rs b/crates/ruma-events/src/call/notify.rs new file mode 100644 index 0000000000..d91233bcdc --- /dev/null +++ b/crates/ruma-events/src/call/notify.rs @@ -0,0 +1,72 @@ +//! Type for the matrixRTC notify event ([MSC4075]). +//! +//! [MSC4075]: https://github.com/matrix-org/matrix-spec-proposals/pull/4075 + +use ruma_macros::EventContent; +use serde::{Deserialize, Serialize}; + +use super::member::Application; +use crate::Mentions; + +/// The content of an `m.call.notify` event. +#[derive(Clone, Debug, Deserialize, Serialize, EventContent)] +#[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)] +#[ruma_event(type = "m.call.notify", kind = MessageLike)] +pub struct CallNotifyEventContent { + /// A unique identifier for the call. + pub call_id: String, + /// The application this notify event applies to. + pub application: ApplicationType, + /// How this notify event should notify the receiver. + pub notify_type: NotifyType, + /// The users that are notified by this event (See [MSC3952](https://github.com/matrix-org/matrix-spec-proposals/pull/3952)(Intentional Mentions)). + #[serde(rename = "m.mentions")] + pub mentions: Mentions, +} + +impl CallNotifyEventContent { + /// Creates a new `CallNotifyEventContent` with the given configuration. + pub fn new( + call_id: String, + application: ApplicationType, + notify_type: NotifyType, + mentions: Mentions, + ) -> Self { + Self { call_id, application, notify_type, mentions } + } +} + +/// How this notify event should notify the receiver. +#[derive(Clone, Debug, Deserialize, Serialize)] +#[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)] +pub enum NotifyType { + /// The receiving client should ring with an audible sound. + #[serde(rename = "ring")] + Ring, + /// The receiving client should display a visual notification. + #[serde(rename = "notify")] + Notify, +} + +/// The type of matrix RTC application. +/// +/// This is different to [`Application`] because application contains all the information from the +/// call.member event. +/// +/// An `Application` can be converted into an `ApplicationType` using `.into()`. + +#[derive(Clone, Debug, Deserialize, Serialize)] +#[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)] +pub enum ApplicationType { + /// A VoIP call. + #[serde(rename = "m.call")] + Call, +} + +impl From for ApplicationType { + fn from(val: Application) -> Self { + match val { + Application::Call(_) => ApplicationType::Call, + } + } +} diff --git a/crates/ruma-events/src/enums.rs b/crates/ruma-events/src/enums.rs index 7c70aeec2e..2a920e88ee 100644 --- a/crates/ruma-events/src/enums.rs +++ b/crates/ruma-events/src/enums.rs @@ -93,6 +93,9 @@ event_enum! { #[cfg(feature = "unstable-msc3245")] #[ruma_enum(alias = "m.voice")] "org.matrix.msc3245.voice.v2" => super::voice, + #[cfg(feature = "unstable-msc4075")] + #[ruma_enum(alias = "m.call.notify")] + "org.matrix.msc4075.call.notify" => super::call::notify, } /// Any state event. @@ -352,6 +355,8 @@ impl AnyMessageLikeEventContent { } #[cfg(feature = "unstable-msc3381")] Self::PollStart(_) | Self::UnstablePollStart(_) => None, + #[cfg(feature = "unstable-msc4075")] + Self::CallNotify(_) => None, Self::CallNegotiate(_) | Self::CallReject(_) | Self::CallSelectAnswer(_) diff --git a/crates/ruma-events/tests/it/call.rs b/crates/ruma-events/tests/it/call.rs index af9aae404e..5358df4469 100644 --- a/crates/ruma-events/tests/it/call.rs +++ b/crates/ruma-events/tests/it/call.rs @@ -1,10 +1,20 @@ +#[cfg(feature = "unstable-msc4075")] +use std::collections::BTreeSet; + use assert_matches2::assert_matches; #[cfg(feature = "unstable-msc2747")] use assign::assign; use js_int::uint; +#[cfg(feature = "unstable-msc4075")] +use ruma_common::UserId; use ruma_common::{room_id, serde::CanBeEmpty, MilliSecondsSinceUnixEpoch, VoipVersionId}; #[cfg(feature = "unstable-msc2747")] use ruma_events::call::CallCapabilities; +#[cfg(feature = "unstable-msc4075")] +use ruma_events::{ + call::notify::{ApplicationType, CallNotifyEventContent, NotifyType}, + Mentions, +}; use ruma_events::{ call::{ answer::CallAnswerEventContent, @@ -598,3 +608,76 @@ fn select_v1_answer_event_deserialization() { assert_eq!(content.selected_party_id, "6336"); assert_eq!(content.version, VoipVersionId::V1); } +#[cfg(feature = "unstable-msc4075")] +#[test] +fn notify_event_serialization() { + let content_user_mention = CallNotifyEventContent::new( + "abcdef".into(), + ApplicationType::Call, + NotifyType::Ring, + Mentions::with_user_ids(vec![ + <&UserId>::try_from("@user:example.com").unwrap().into(), + <&UserId>::try_from("@user2:example.com").unwrap().into(), + ]), + ); + + let content_room_mention = CallNotifyEventContent::new( + "abcdef".into(), + ApplicationType::Call, + NotifyType::Ring, + Mentions::with_room_mention(), + ); + + assert_eq!( + to_json_value(&content_user_mention).unwrap(), + json!({ + "call_id": "abcdef", + "application": "m.call", + "m.mentions": {"user_ids": ["@user2:example.com","@user:example.com"]}, + "notify_type": "ring", + }) + ); + assert_eq!( + to_json_value(&content_room_mention).unwrap(), + json!({ + "call_id": "abcdef", + "application": "m.call", + "m.mentions": {"room": true}, + "notify_type": "ring", + }) + ); +} + +#[cfg(feature = "unstable-msc4075")] +#[test] +fn notify_event_deserialization() { + let json_data = json!({ + "content": { + "call_id": "abcdef", + "application": "m.call", + "m.mentions": {"room": false, "user_ids": ["@user:example.com", "@user2:example.com"]}, + "notify_type": "ring", + }, + "event_id": "$event:notareal.hs", + "origin_server_ts": 134_829_848, + "room_id": "!roomid:notareal.hs", + "sender": "@user:notareal.hs", + "type": "m.call.notify", + }); + + let event = from_json_value::(json_data).unwrap(); + assert_matches!( + event, + AnyMessageLikeEvent::CallNotify(MessageLikeEvent::Original(message_event)) + ); + let content = message_event.content; + assert_eq!(content.call_id, "abcdef"); + assert!(!content.mentions.room); + assert_eq!( + content.mentions.user_ids, + BTreeSet::from([ + <&UserId>::try_from("@user:example.com").unwrap().to_owned(), + <&UserId>::try_from("@user2:example.com").unwrap().to_owned(), + ]) + ); +} diff --git a/crates/ruma/Cargo.toml b/crates/ruma/Cargo.toml index d08ff9e60d..178f65df83 100644 --- a/crates/ruma/Cargo.toml +++ b/crates/ruma/Cargo.toml @@ -214,6 +214,7 @@ unstable-msc3955 = ["ruma-events?/unstable-msc3955"] unstable-msc3956 = ["ruma-events?/unstable-msc3956"] unstable-msc3958 = ["ruma-common/unstable-msc3958"] unstable-msc3983 = ["ruma-client-api?/unstable-msc3983"] +unstable-msc4075 = ["ruma-events?/unstable-msc4075"] unstable-pdu = ["ruma-events?/unstable-pdu"] unstable-unspecified = [ "ruma-common/unstable-unspecified", @@ -259,6 +260,7 @@ __ci = [ "unstable-msc3956", "unstable-msc3958", "unstable-msc3983", + "unstable-msc4075", ] [dependencies]