diff --git a/crates/ruma-common/src/events/sticker.rs b/crates/ruma-common/src/events/sticker.rs index 2ff18406..a79ab4f4 100644 --- a/crates/ruma-common/src/events/sticker.rs +++ b/crates/ruma-common/src/events/sticker.rs @@ -5,6 +5,12 @@ use ruma_macros::EventContent; use serde::{Deserialize, Serialize}; +#[cfg(feature = "unstable-msc3552")] +use super::{ + file::FileContent, + image::{ImageContent, ThumbnailContent}, + message::MessageContent, +}; use crate::{events::room::ImageInfo, MxcUri}; /// The content of an `m.sticker` event. @@ -25,11 +31,80 @@ pub struct StickerEventContent { /// The URL to the sticker image. pub url: Box, + + /// Extensible-event text representation of the message. + /// + /// If present, this should be preferred over the `body` field. + #[cfg(feature = "unstable-msc3552")] + #[serde(flatten, skip_serializing_if = "Option::is_none")] + pub message: Option, + + /// Extensible-event file content of the message. + /// + /// If present, this should be preferred over the `url`, `file` and `info` fields. + #[cfg(feature = "unstable-msc3552")] + #[serde( + rename = "org.matrix.msc1767.file", + alias = "m.file", + skip_serializing_if = "Option::is_none" + )] + pub file: Option, + + /// Extensible-event image info of the message. + /// + /// If present, this should be preferred over the `info` field. + #[cfg(feature = "unstable-msc3552")] + #[serde( + rename = "org.matrix.msc1767.image", + alias = "m.image", + skip_serializing_if = "Option::is_none" + )] + pub image: Option>, + + /// Extensible-event thumbnails of the message. + /// + /// If present, this should be preferred over the `info` field. + #[cfg(feature = "unstable-msc3552")] + #[serde( + rename = "org.matrix.msc1767.thumbnail", + alias = "m.thumbnail", + skip_serializing_if = "Option::is_none" + )] + pub thumbnail: Option>, + + /// Extensible-event captions of the message. + #[cfg(feature = "unstable-msc3552")] + #[serde( + rename = "org.matrix.msc1767.caption", + alias = "m.caption", + with = "super::message::content_serde::as_vec", + default, + skip_serializing_if = "Option::is_none" + )] + pub caption: Option, } impl StickerEventContent { /// Creates a new `StickerEventContent` with the given body, image info and URL. pub fn new(body: String, info: ImageInfo, url: Box) -> Self { - Self { body, info, url } + Self { + #[cfg(feature = "unstable-msc3552")] + message: Some(MessageContent::plain(body.clone())), + #[cfg(feature = "unstable-msc3552")] + file: Some(FileContent::plain(url.clone(), Some(Box::new((&info).into())))), + #[cfg(feature = "unstable-msc3552")] + image: Some(Box::new((&info).into())), + #[cfg(feature = "unstable-msc3552")] + thumbnail: ThumbnailContent::from_room_message_content( + info.thumbnail_source.as_ref(), + info.thumbnail_info.as_deref(), + ) + .map(|thumbnail| vec![thumbnail]), + #[cfg(feature = "unstable-msc3552")] + caption: None, + body, + info, + url, + } } } diff --git a/crates/ruma-common/tests/events/message_event.rs b/crates/ruma-common/tests/events/message_event.rs index 38ef9db9..fb9348a3 100644 --- a/crates/ruma-common/tests/events/message_event.rs +++ b/crates/ruma-common/tests/events/message_event.rs @@ -44,6 +44,8 @@ fn message_serialize_sticker() { }; let actual = to_json_value(&aliases_event).unwrap(); + + #[cfg(not(feature = "unstable-msc3552"))] let expected = json!({ "content": { "body": "Hello", @@ -69,6 +71,51 @@ fn message_serialize_sticker() { "type": "m.sticker", }); + #[cfg(feature = "unstable-msc3552")] + let expected = json!({ + "content": { + "body": "Hello", + "info": { + "h": 423, + "mimetype": "image/png", + "size": 84242, + "thumbnail_info": { + "h": 334, + "mimetype": "image/png", + "size": 82595, + "w": 800 + }, + "thumbnail_url": "mxc://matrix.org/irsns989Rrsn", + "w": 1011 + }, + "url": "mxc://matrix.org/rnsldl8srs98IRrs", + "org.matrix.msc1767.text": "Hello", + "org.matrix.msc1767.file": { + "url": "mxc://matrix.org/rnsldl8srs98IRrs", + "mimetype": "image/png", + "size": 84242, + }, + "org.matrix.msc1767.image": { + "height": 423, + "width": 1011, + }, + "org.matrix.msc1767.thumbnail": [ + { + "url": "mxc://matrix.org/irsns989Rrsn", + "mimetype": "image/png", + "size": 82595, + "height": 334, + "width": 800, + } + ], + }, + "event_id": "$h29iv0s8:example.com", + "origin_server_ts": 1, + "room_id": "!roomid:room.com", + "sender": "@carl:example.com", + "type": "m.sticker", + }); + assert_eq!(actual, expected); } diff --git a/crates/ruma-common/tests/events/mod.rs b/crates/ruma-common/tests/events/mod.rs index dc500bae..c078e4aa 100644 --- a/crates/ruma-common/tests/events/mod.rs +++ b/crates/ruma-common/tests/events/mod.rs @@ -19,6 +19,7 @@ mod redaction; mod relations; mod room_message; mod state_event; +mod sticker; mod stripped; mod to_device; mod video; diff --git a/crates/ruma-common/tests/events/sticker.rs b/crates/ruma-common/tests/events/sticker.rs new file mode 100644 index 00000000..531f127c --- /dev/null +++ b/crates/ruma-common/tests/events/sticker.rs @@ -0,0 +1,78 @@ +#![cfg(feature = "unstable-msc3552")] + +use ruma_common::{ + events::{room::ImageInfo, sticker::StickerEventContent}, + mxc_uri, +}; +use serde_json::{from_value as from_json_value, json, to_value as to_json_value}; + +#[test] +fn content_serialization() { + let message_event_content = StickerEventContent::new( + "Upload: my_image.jpg".to_owned(), + ImageInfo::new(), + mxc_uri!("mxc://notareal.hs/file").to_owned(), + ); + + assert_eq!( + to_json_value(&message_event_content).unwrap(), + json!({ + "body": "Upload: my_image.jpg", + "url": "mxc://notareal.hs/file", + "info": {}, + "org.matrix.msc1767.text": "Upload: my_image.jpg", + "org.matrix.msc1767.file": { + "url": "mxc://notareal.hs/file", + }, + "org.matrix.msc1767.image": {}, + }) + ); +} + +#[test] +fn content_stable_deserialization() { + let json_data = json!({ + "body": "Upload: my_image.jpg", + "url": "mxc://notareal.hs/file", + "info": {}, + "m.text": "Upload: my_image.jpg", + "m.file": { + "url": "mxc://notareal.hs/file", + }, + "m.image": {}, + }); + + let content = from_json_value::(json_data).unwrap(); + assert_eq!(content.body, "Upload: my_image.jpg"); + assert_eq!(content.url, "mxc://notareal.hs/file"); + let message = content.message.unwrap(); + assert_eq!(message.len(), 1); + assert_eq!(message[0].body, "Upload: my_image.jpg"); + let file = content.file.unwrap(); + assert_eq!(file.url, "mxc://notareal.hs/file"); + assert!(!file.is_encrypted()); +} + +#[test] +fn content_unstable_deserialization() { + let json_data = json!({ + "body": "Upload: my_image.jpg", + "url": "mxc://notareal.hs/file", + "info": {}, + "org.matrix.msc1767.text": "Upload: my_image.jpg", + "org.matrix.msc1767.file": { + "url": "mxc://notareal.hs/file", + }, + "org.matrix.msc1767.image": {}, + }); + + let content = from_json_value::(json_data).unwrap(); + assert_eq!(content.body, "Upload: my_image.jpg"); + assert_eq!(content.url, "mxc://notareal.hs/file"); + let message = content.message.unwrap(); + assert_eq!(message.len(), 1); + assert_eq!(message[0].body, "Upload: my_image.jpg"); + let file = content.file.unwrap(); + assert_eq!(file.url, "mxc://notareal.hs/file"); + assert!(!file.is_encrypted()); +}