From a76d3e24a4621313b80e07183b853102c3a56380 Mon Sep 17 00:00:00 2001 From: Akshay Date: Fri, 12 Feb 2021 14:00:27 +0100 Subject: [PATCH] events: Support `m.room.message` events with custom `msgtype`s --- ruma-events/src/room/message.rs | 18 +++++++ ruma-events/src/room/message/content_serde.rs | 2 +- ruma-events/tests/room_message.rs | 51 ++++++++++++++++++- 3 files changed, 69 insertions(+), 2 deletions(-) diff --git a/ruma-events/src/room/message.rs b/ruma-events/src/room/message.rs index 944d5cc3..44ab325d 100644 --- a/ruma-events/src/room/message.rs +++ b/ruma-events/src/room/message.rs @@ -1,5 +1,7 @@ //! Types for the *m.room.message* event. +use std::collections::BTreeMap; + use js_int::UInt; use ruma_events_macros::MessageEventContent; #[cfg(feature = "unstable-pre-spec")] @@ -64,6 +66,10 @@ pub enum MessageEventContent { /// A request to initiate a key verification. #[cfg(feature = "unstable-pre-spec")] VerificationRequest(KeyVerificationRequestEventContent), + + /// A custom message. + #[doc(hidden)] + _Custom(CustomEventContent), } /// Enum modeling the different ways relationships can be expressed in a @@ -586,3 +592,15 @@ pub struct KeyVerificationRequestEventContent { /// events that have a m.reference relationship with this event. pub to: UserId, } + +/// The payload for a custom message event. +#[doc(hidden)] +#[derive(Clone, Debug, Deserialize, Serialize)] +pub struct CustomEventContent { + /// A custom msgtype + pub msgtype: String, + + /// Remaining event content + #[serde(flatten)] + pub data: BTreeMap, +} diff --git a/ruma-events/src/room/message/content_serde.rs b/ruma-events/src/room/message/content_serde.rs index 1e8e4bf0..c618ed61 100644 --- a/ruma-events/src/room/message/content_serde.rs +++ b/ruma-events/src/room/message/content_serde.rs @@ -32,7 +32,7 @@ impl<'de> de::Deserialize<'de> for MessageEventContent { "m.video" => Self::Video(from_raw_json_value(&json)?), #[cfg(feature = "unstable-pre-spec")] "m.key.verification.request" => Self::VerificationRequest(from_raw_json_value(&json)?), - _ => return Err(de::Error::custom("unknown msgtype")), + _ => Self::_Custom(from_raw_json_value(&json)?), }) } } diff --git a/ruma-events/tests/room_message.rs b/ruma-events/tests/room_message.rs index 36b5166d..4f155972 100644 --- a/ruma-events/tests/room_message.rs +++ b/ruma-events/tests/room_message.rs @@ -1,6 +1,7 @@ use std::time::{Duration, UNIX_EPOCH}; use assign::assign; +use maplit::btreemap; use matches::assert_matches; #[cfg(feature = "unstable-pre-spec")] use ruma_events::{ @@ -9,7 +10,8 @@ use ruma_events::{ use ruma_events::{ room::{ message::{ - AudioMessageEventContent, MessageEventContent, Relation, TextMessageEventContent, + AudioMessageEventContent, CustomEventContent, MessageEventContent, Relation, + TextMessageEventContent, }, relationships::InReplyTo, }, @@ -73,6 +75,53 @@ fn content_serialization() { ); } +#[test] +fn custom_content_serialization() { + let json_data = btreemap! { + "custom_field".into() => json!("baba"), + "another_one".into() => json!("abab"), + }; + let custom_event_content = MessageEventContent::_Custom(CustomEventContent { + msgtype: "my_custom_msgtype".into(), + data: json_data, + }); + + assert_eq!( + to_json_value(&custom_event_content).unwrap(), + json!({ + "msgtype": "my_custom_msgtype", + "custom_field": "baba", + "another_one": "abab", + }) + ); +} + +#[test] +fn custom_content_deserialization() { + let json_data = json!({ + "msgtype": "my_custom_msgtype", + "custom_field": "baba", + "another_one": "abab", + }); + + let expected_json_data = btreemap! { + "custom_field".into() => json!("baba"), + "another_one".into() => json!("abab"), + }; + + assert_matches!( + from_json_value::>(json_data) + .unwrap() + .deserialize() + .unwrap(), + MessageEventContent::_Custom(CustomEventContent { + msgtype, + data + }) if msgtype == "my_custom_msgtype" + && data == expected_json_data + ); +} + #[test] fn formatted_body_serialization() { let message_event_content = MessageEventContent::Text(TextMessageEventContent::html(