events: Add support for extensible notice and emote events
As defined in MSC1767
This commit is contained in:
parent
f78d3480a5
commit
99cd70b430
@ -6,7 +6,7 @@ Breaking changes:
|
||||
|
||||
Improvements:
|
||||
|
||||
* Add unstable support for extensible text message events ([MSC1767](https://github.com/matrix-org/matrix-spec-proposals/pull/1767))
|
||||
* Add unstable support for extensible text, notice and emote message events ([MSC1767](https://github.com/matrix-org/matrix-spec-proposals/pull/1767))
|
||||
|
||||
# 0.26.0
|
||||
|
||||
|
54
crates/ruma-events/src/emote.rs
Normal file
54
crates/ruma-events/src/emote.rs
Normal file
@ -0,0 +1,54 @@
|
||||
//! Types for extensible emote message events ([MSC1767]).
|
||||
//!
|
||||
//! [MSC1767]: https://github.com/matrix-org/matrix-spec-proposals/pull/1767
|
||||
|
||||
use ruma_macros::EventContent;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::{
|
||||
message::{MessageContent, TextMessage},
|
||||
room::message::Relation,
|
||||
};
|
||||
|
||||
/// The payload for an extensible emote message.
|
||||
#[derive(Clone, Debug, Serialize, Deserialize, EventContent)]
|
||||
#[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)]
|
||||
#[ruma_event(type = "m.emote", kind = MessageLike)]
|
||||
pub struct EmoteEventContent {
|
||||
/// The message's text content.
|
||||
#[serde(flatten)]
|
||||
pub message: MessageContent,
|
||||
|
||||
/// Information about related messages for [rich replies].
|
||||
///
|
||||
/// [rich replies]: https://spec.matrix.org/v1.2/client-server-api/#rich-replies
|
||||
#[serde(flatten, skip_serializing_if = "Option::is_none")]
|
||||
pub relates_to: Option<Relation>,
|
||||
}
|
||||
|
||||
impl EmoteEventContent {
|
||||
/// A convenience constructor to create a plain text message.
|
||||
pub fn plain(body: impl Into<String>) -> Self {
|
||||
Self { message: MessageContent::plain(body), relates_to: None }
|
||||
}
|
||||
|
||||
/// A convenience constructor to create an HTML message.
|
||||
pub fn html(body: impl Into<String>, html_body: impl Into<String>) -> Self {
|
||||
Self { message: MessageContent::html(body, html_body), relates_to: None }
|
||||
}
|
||||
|
||||
/// A convenience constructor to create a Markdown message.
|
||||
///
|
||||
/// Returns an HTML message if some Markdown formatting was detected, otherwise returns a plain
|
||||
/// text message.
|
||||
#[cfg(feature = "markdown")]
|
||||
pub fn markdown(body: impl AsRef<str> + Into<String>) -> Self {
|
||||
Self { message: MessageContent::markdown(body), relates_to: None }
|
||||
}
|
||||
}
|
||||
|
||||
impl TextMessage for EmoteEventContent {
|
||||
fn message(&self) -> &MessageContent {
|
||||
&self.message
|
||||
}
|
||||
}
|
@ -37,6 +37,8 @@ event_enum! {
|
||||
"m.call.invite",
|
||||
"m.call.hangup",
|
||||
"m.call.candidates",
|
||||
#[cfg(feature = "unstable-msc1767")]
|
||||
"m.emote",
|
||||
"m.key.verification.ready",
|
||||
"m.key.verification.start",
|
||||
"m.key.verification.cancel",
|
||||
@ -46,6 +48,8 @@ event_enum! {
|
||||
"m.key.verification.done",
|
||||
#[cfg(feature = "unstable-msc1767")]
|
||||
"m.message",
|
||||
#[cfg(feature = "unstable-msc1767")]
|
||||
"m.notice",
|
||||
#[cfg(feature = "unstable-msc2677")]
|
||||
"m.reaction",
|
||||
"m.room.encrypted",
|
||||
@ -356,6 +360,10 @@ impl AnyMessageLikeEventContent {
|
||||
Self::RoomMessage(ev) => ev.relates_to.clone().map(Into::into),
|
||||
#[cfg(feature = "unstable-msc1767")]
|
||||
Self::Message(ev) => ev.relates_to.clone().map(Into::into),
|
||||
#[cfg(feature = "unstable-msc1767")]
|
||||
Self::Notice(ev) => ev.relates_to.clone().map(Into::into),
|
||||
#[cfg(feature = "unstable-msc1767")]
|
||||
Self::Emote(ev) => ev.relates_to.clone().map(Into::into),
|
||||
Self::CallAnswer(_)
|
||||
| Self::CallInvite(_)
|
||||
| Self::CallHangup(_)
|
||||
|
@ -172,12 +172,16 @@ pub mod macros {
|
||||
pub mod call;
|
||||
pub mod direct;
|
||||
pub mod dummy;
|
||||
#[cfg(feature = "unstable-msc1767")]
|
||||
pub mod emote;
|
||||
pub mod forwarded_room_key;
|
||||
pub mod fully_read;
|
||||
pub mod ignored_user_list;
|
||||
pub mod key;
|
||||
#[cfg(feature = "unstable-msc1767")]
|
||||
pub mod message;
|
||||
#[cfg(feature = "unstable-msc1767")]
|
||||
pub mod notice;
|
||||
#[cfg(feature = "unstable-pdu")]
|
||||
pub mod pdu;
|
||||
pub mod policy;
|
||||
|
54
crates/ruma-events/src/notice.rs
Normal file
54
crates/ruma-events/src/notice.rs
Normal file
@ -0,0 +1,54 @@
|
||||
//! Types for extensible notice message events ([MSC1767]).
|
||||
//!
|
||||
//! [MSC1767]: https://github.com/matrix-org/matrix-spec-proposals/pull/1767
|
||||
|
||||
use ruma_macros::EventContent;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::{
|
||||
message::{MessageContent, TextMessage},
|
||||
room::message::Relation,
|
||||
};
|
||||
|
||||
/// The payload for an extensible notice message.
|
||||
#[derive(Clone, Debug, Serialize, Deserialize, EventContent)]
|
||||
#[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)]
|
||||
#[ruma_event(type = "m.notice", kind = MessageLike)]
|
||||
pub struct NoticeEventContent {
|
||||
/// The message's text content.
|
||||
#[serde(flatten)]
|
||||
pub message: MessageContent,
|
||||
|
||||
/// Information about related messages for [rich replies].
|
||||
///
|
||||
/// [rich replies]: https://spec.matrix.org/v1.2/client-server-api/#rich-replies
|
||||
#[serde(flatten, skip_serializing_if = "Option::is_none")]
|
||||
pub relates_to: Option<Relation>,
|
||||
}
|
||||
|
||||
impl NoticeEventContent {
|
||||
/// A convenience constructor to create a plain text message.
|
||||
pub fn plain(body: impl Into<String>) -> Self {
|
||||
Self { message: MessageContent::plain(body), relates_to: None }
|
||||
}
|
||||
|
||||
/// A convenience constructor to create an HTML message.
|
||||
pub fn html(body: impl Into<String>, html_body: impl Into<String>) -> Self {
|
||||
Self { message: MessageContent::html(body, html_body), relates_to: None }
|
||||
}
|
||||
|
||||
/// A convenience constructor to create a Markdown message.
|
||||
///
|
||||
/// Returns an HTML message if some Markdown formatting was detected, otherwise returns a plain
|
||||
/// text message.
|
||||
#[cfg(feature = "markdown")]
|
||||
pub fn markdown(body: impl AsRef<str> + Into<String>) -> Self {
|
||||
Self { message: MessageContent::markdown(body), relates_to: None }
|
||||
}
|
||||
}
|
||||
|
||||
impl TextMessage for NoticeEventContent {
|
||||
fn message(&self) -> &MessageContent {
|
||||
&self.message
|
||||
}
|
||||
}
|
@ -5,7 +5,9 @@ use js_int::uint;
|
||||
use matches::assert_matches;
|
||||
use ruma_common::MilliSecondsSinceUnixEpoch;
|
||||
use ruma_events::{
|
||||
emote::EmoteEventContent,
|
||||
message::MessageEventContent,
|
||||
notice::NoticeEventContent,
|
||||
room::message::{InReplyTo, Relation},
|
||||
AnyMessageLikeEvent, MessageLikeEvent, Unsigned,
|
||||
};
|
||||
@ -219,3 +221,134 @@ fn message_event_deserialization() {
|
||||
&& unsigned.is_empty()
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn notice_event_serialization() {
|
||||
let event = MessageLikeEvent {
|
||||
content: NoticeEventContent::plain("Hello, I'm a robot!"),
|
||||
event_id: event_id!("$event:notareal.hs").to_owned(),
|
||||
sender: user_id!("@user:notareal.hs").to_owned(),
|
||||
origin_server_ts: MilliSecondsSinceUnixEpoch(uint!(134_829_848)),
|
||||
room_id: room_id!("!roomid:notareal.hs").to_owned(),
|
||||
unsigned: Unsigned::default(),
|
||||
};
|
||||
|
||||
assert_eq!(
|
||||
to_json_value(&event).unwrap(),
|
||||
json!({
|
||||
"content": {
|
||||
"org.matrix.msc1767.text": "Hello, I'm a robot!",
|
||||
},
|
||||
"event_id": "$event:notareal.hs",
|
||||
"origin_server_ts": 134_829_848,
|
||||
"room_id": "!roomid:notareal.hs",
|
||||
"sender": "@user:notareal.hs",
|
||||
"type": "m.notice",
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn notice_event_deserialization() {
|
||||
let json_data = json!({
|
||||
"content": {
|
||||
"org.matrix.msc1767.message": [
|
||||
{ "body": "Hello, I'm a <em>robot</em>!", "mimetype": "text/html"},
|
||||
{ "body": "Hello, I'm a robot!" },
|
||||
]
|
||||
},
|
||||
"event_id": "$event:notareal.hs",
|
||||
"origin_server_ts": 134_829_848,
|
||||
"room_id": "!roomid:notareal.hs",
|
||||
"sender": "@user:notareal.hs",
|
||||
"type": "m.notice",
|
||||
});
|
||||
|
||||
assert_matches!(
|
||||
from_json_value::<AnyMessageLikeEvent>(json_data).unwrap(),
|
||||
AnyMessageLikeEvent::Notice(MessageLikeEvent {
|
||||
content: NoticeEventContent {
|
||||
message,
|
||||
..
|
||||
},
|
||||
event_id,
|
||||
origin_server_ts,
|
||||
room_id,
|
||||
sender,
|
||||
unsigned
|
||||
}) if event_id == event_id!("$event:notareal.hs")
|
||||
&& message.find_plain().unwrap() == "Hello, I'm a robot!"
|
||||
&& message.find_html().unwrap() == "Hello, I'm a <em>robot</em>!"
|
||||
&& origin_server_ts == MilliSecondsSinceUnixEpoch(uint!(134_829_848))
|
||||
&& room_id == room_id!("!roomid:notareal.hs")
|
||||
&& sender == user_id!("@user:notareal.hs")
|
||||
&& unsigned.is_empty()
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn emote_event_serialization() {
|
||||
let event = MessageLikeEvent {
|
||||
content: EmoteEventContent::html(
|
||||
"is testing some code…",
|
||||
"is testing some <code>code</code>…",
|
||||
),
|
||||
event_id: event_id!("$event:notareal.hs").to_owned(),
|
||||
sender: user_id!("@user:notareal.hs").to_owned(),
|
||||
origin_server_ts: MilliSecondsSinceUnixEpoch(uint!(134_829_848)),
|
||||
room_id: room_id!("!roomid:notareal.hs").to_owned(),
|
||||
unsigned: Unsigned::default(),
|
||||
};
|
||||
|
||||
assert_eq!(
|
||||
to_json_value(&event).unwrap(),
|
||||
json!({
|
||||
"content": {
|
||||
"org.matrix.msc1767.message": [
|
||||
{ "body": "is testing some <code>code</code>…", "mimetype": "text/html" },
|
||||
{ "body": "is testing some code…", "mimetype": "text/plain" },
|
||||
]
|
||||
},
|
||||
"event_id": "$event:notareal.hs",
|
||||
"origin_server_ts": 134_829_848,
|
||||
"room_id": "!roomid:notareal.hs",
|
||||
"sender": "@user:notareal.hs",
|
||||
"type": "m.emote",
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn emote_event_deserialization() {
|
||||
let json_data = json!({
|
||||
"content": {
|
||||
"org.matrix.msc1767.text": "is testing some code…",
|
||||
},
|
||||
"event_id": "$event:notareal.hs",
|
||||
"origin_server_ts": 134_829_848,
|
||||
"room_id": "!roomid:notareal.hs",
|
||||
"sender": "@user:notareal.hs",
|
||||
"type": "m.emote",
|
||||
});
|
||||
|
||||
assert_matches!(
|
||||
from_json_value::<AnyMessageLikeEvent>(json_data).unwrap(),
|
||||
AnyMessageLikeEvent::Emote(MessageLikeEvent {
|
||||
content: EmoteEventContent {
|
||||
message,
|
||||
..
|
||||
},
|
||||
event_id,
|
||||
origin_server_ts,
|
||||
room_id,
|
||||
sender,
|
||||
unsigned
|
||||
}) if event_id == event_id!("$event:notareal.hs")
|
||||
&& message.find_plain().unwrap() == "is testing some code…"
|
||||
&& message.find_html().is_none()
|
||||
&& origin_server_ts == MilliSecondsSinceUnixEpoch(uint!(134_829_848))
|
||||
&& room_id == room_id!("!roomid:notareal.hs")
|
||||
&& sender == user_id!("@user:notareal.hs")
|
||||
&& unsigned.is_empty()
|
||||
);
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user