events: Remove mixed types and conversion functions for extensible events

Mixed types have been removed from MSC1767.
This commit is contained in:
Kévin Commaille 2023-01-03 17:23:27 +01:00
parent 6cd3935280
commit 699c2daf39
No known key found for this signature in database
GPG Key ID: DD507DAE96E8245C
28 changed files with 30 additions and 2067 deletions

View File

@ -87,11 +87,6 @@ impl AudioContent {
Self::default()
}
/// Creates a new `AudioContent` with the given duration.
pub(crate) fn from_room_message_content(duration: Duration) -> Self {
Self { duration: Some(duration), ..Default::default() }
}
/// Whether this `AudioContent` is empty.
pub fn is_empty(&self) -> bool {
self.duration.is_none() && self.waveform.is_none()

View File

@ -155,21 +155,6 @@ impl FileContentInfo {
pub fn new() -> Self {
Self::default()
}
/// Create a new `FileContentInfo` with the given filename, mimetype and size.
///
/// Returns `None` if the `FileContentInfo` would be empty.
pub(crate) fn from_room_message_content(
filename: Option<String>,
mimetype: Option<String>,
size: Option<UInt>,
) -> Option<Self> {
if filename.is_none() && mimetype.is_none() && size.is_none() {
None
} else {
Some(Self { name: filename, mimetype, size })
}
}
}
/// The encryption info of a file sent to a room with end-to-end encryption enabled.

View File

@ -9,7 +9,7 @@ use serde::{Deserialize, Serialize};
use super::{
file::{EncryptedContent, FileContent},
message::MessageContent,
room::{message::Relation, MediaSource, ThumbnailInfo},
room::message::Relation,
};
use crate::OwnedMxcUri;
@ -108,20 +108,6 @@ impl ImageContent {
Self { height: Some(height), width: Some(width) }
}
/// Creates a new `ImageContent` with the given optional width and height.
///
/// Returns `None` if the `ImageContent` would be empty.
pub(crate) fn from_room_message_content(
width: Option<UInt>,
height: Option<UInt>,
) -> Option<Self> {
if width.is_none() && height.is_none() {
None
} else {
Some(Self { width, height })
}
}
/// Whether this `ImageContent` is empty.
pub fn is_empty(&self) -> bool {
self.height.is_none() && self.width.is_none()
@ -146,23 +132,6 @@ impl ThumbnailContent {
pub fn new(file: ThumbnailFileContent, image: Option<Box<ImageContent>>) -> Self {
Self { file, image }
}
/// Create a `ThumbnailContent` with the given thumbnail source and info.
///
/// Returns `None` if no thumbnail was found.
pub(crate) fn from_room_message_content(
source: Option<MediaSource>,
info: Option<Box<ThumbnailInfo>>,
) -> Option<Self> {
source.map(|source| {
let ThumbnailInfo { height, width, mimetype, size } = *info.unwrap_or_default();
let file = ThumbnailFileContent::from_room_message_content(source, mimetype, size);
let image = ImageContent::from_room_message_content(width, height).map(Box::new);
Self { file, image }
})
}
}
/// Thumbnail file content.
@ -199,20 +168,6 @@ impl ThumbnailFileContent {
Self { url, info, encryption_info: Some(Box::new(encryption_info)) }
}
/// Create a `ThumbnailFileContent` with the given thumbnail source and info.
fn from_room_message_content(
source: MediaSource,
mimetype: Option<String>,
size: Option<UInt>,
) -> Self {
let info =
ThumbnailFileContentInfo::from_room_message_content(mimetype, size).map(Box::new);
match source.into_extensible_content() {
(url, None) => Self::plain(url, info),
(url, Some(encryption_info)) => Self::encrypted(url, encryption_info, info),
}
}
/// Whether the thumbnail file is encrypted.
pub fn is_encrypted(&self) -> bool {
self.encryption_info.is_some()
@ -237,15 +192,4 @@ impl ThumbnailFileContentInfo {
pub fn new() -> Self {
Self::default()
}
/// Creates a new `ThumbnailFileContentInfo` with the given optional MIME type and size.
///
/// Returns `None` if the `ThumbnailFileContentInfo` would be empty.
fn from_room_message_content(mimetype: Option<String>, size: Option<UInt>) -> Option<Self> {
if mimetype.is_none() && size.is_none() {
None
} else {
Some(Self { mimetype, size })
}
}
}

View File

@ -10,12 +10,6 @@ use std::collections::BTreeMap;
use js_int::UInt;
use serde::{de, Deserialize, Serialize};
#[cfg(feature = "unstable-msc3551")]
use super::file::{EncryptedContent, EncryptedContentInit, FileContent};
#[cfg(feature = "unstable-msc3552")]
use super::image::ThumbnailFileContent;
#[cfg(feature = "unstable-msc3551")]
use crate::MxcUri;
use crate::{
serde::{base64::UrlSafe, Base64},
OwnedMxcUri,
@ -55,19 +49,6 @@ pub enum MediaSource {
Encrypted(Box<EncryptedFile>),
}
#[cfg(feature = "unstable-msc3551")]
impl MediaSource {
pub(crate) fn into_extensible_content(self) -> (OwnedMxcUri, Option<EncryptedContent>) {
match self {
MediaSource::Plain(url) => (url, None),
MediaSource::Encrypted(encrypted_file) => {
let EncryptedFile { url, key, iv, hashes, v } = *encrypted_file;
(url, Some(EncryptedContentInit { key, iv, hashes, v }.into()))
}
}
}
}
// Custom implementation of `Deserialize`, because serde doesn't guarantee what variant will be
// deserialized for "externally tagged"¹ enums where multiple "tag" fields exist.
//
@ -92,30 +73,6 @@ impl<'de> Deserialize<'de> for MediaSource {
}
}
#[cfg(feature = "unstable-msc3551")]
impl From<&FileContent> for MediaSource {
fn from(content: &FileContent) -> Self {
let FileContent { url, encryption_info, .. } = content;
if let Some(encryption_info) = encryption_info.as_deref() {
Self::Encrypted(Box::new(EncryptedFile::from_extensible_content(url, encryption_info)))
} else {
Self::Plain(url.to_owned())
}
}
}
#[cfg(feature = "unstable-msc3552")]
impl From<&ThumbnailFileContent> for MediaSource {
fn from(content: &ThumbnailFileContent) -> Self {
let ThumbnailFileContent { url, encryption_info, .. } = content;
if let Some(encryption_info) = encryption_info.as_deref() {
Self::Encrypted(Box::new(EncryptedFile::from_extensible_content(url, encryption_info)))
} else {
Self::Plain(url.to_owned())
}
}
}
/// Metadata about an image.
#[derive(Clone, Debug, Default, Deserialize, Serialize)]
#[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)]
@ -219,15 +176,6 @@ pub struct EncryptedFile {
pub v: String,
}
#[cfg(feature = "unstable-msc3551")]
impl EncryptedFile {
/// Create an `EncryptedFile` from the given url and encryption info.
fn from_extensible_content(url: &MxcUri, encryption_info: &EncryptedContent) -> Self {
let EncryptedContent { key, iv, hashes, v } = encryption_info.to_owned();
Self { url: url.to_owned(), key, iv, hashes, v }
}
}
/// Initial set of fields of `EncryptedFile`.
///
/// This struct will not be updated even if additional fields are added to `EncryptedFile` in a new

View File

@ -3,36 +3,15 @@ use std::time::Duration;
use js_int::UInt;
use serde::{Deserialize, Serialize};
#[cfg(feature = "unstable-msc3245")]
use crate::events::voice::VoiceContent;
#[cfg(feature = "unstable-msc3246")]
use crate::events::{
audio::AudioContent,
file::{EncryptedContent, FileContent, FileContentInfo},
message::MessageContent,
};
use crate::{
events::room::{EncryptedFile, MediaSource},
OwnedMxcUri,
};
/// The payload for an audio message.
///
/// With the `unstable-msc3246` feature, this type contains the transitional format of
/// [`AudioEventContent`] and with the `unstable-msc3245` feature, this type also contains the
/// transitional format of [`VoiceEventContent`]. See the documentation of the [`message`] module
/// for more information.
///
/// [`AudioEventContent`]: crate::events::audio::AudioEventContent
/// [`VoiceEventContent`]: crate::events::voice::VoiceEventContent
/// [`message`]: crate::events::message
#[derive(Clone, Debug, Deserialize, Serialize)]
#[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)]
#[serde(tag = "msgtype", rename = "m.audio")]
#[cfg_attr(
feature = "unstable-msc3246",
serde(from = "super::content_serde::AudioMessageEventContentDeHelper")
)]
pub struct AudioMessageEventContent {
/// The textual representation of this message.
pub body: String,
@ -44,131 +23,19 @@ pub struct AudioMessageEventContent {
/// Metadata for the audio clip referred to in `source`.
#[serde(skip_serializing_if = "Option::is_none")]
pub info: Option<Box<AudioInfo>>,
/// Extensible-event text representation of the message.
///
/// If present, this should be preferred over the `body` field.
#[cfg(feature = "unstable-msc3246")]
#[serde(flatten, skip_serializing_if = "Option::is_none")]
pub message: Option<MessageContent>,
/// Extensible-event file content of the message.
///
/// If present, this should be preferred over the `source` and `info` fields.
#[cfg(feature = "unstable-msc3246")]
#[serde(rename = "org.matrix.msc1767.file", skip_serializing_if = "Option::is_none")]
pub file: Option<FileContent>,
/// Extensible-event audio info of the message.
///
/// If present, this should be preferred over the `info` field.
#[cfg(feature = "unstable-msc3246")]
#[serde(rename = "org.matrix.msc1767.audio", skip_serializing_if = "Option::is_none")]
pub audio: Option<AudioContent>,
/// Extensible-event voice flag of the message.
///
/// If present, this should be represented as a voice message.
#[cfg(feature = "unstable-msc3245")]
#[serde(rename = "org.matrix.msc3245.voice", skip_serializing_if = "Option::is_none")]
pub voice: Option<VoiceContent>,
}
impl AudioMessageEventContent {
/// Creates a new non-encrypted `AudioMessageEventContent` with the given body, url and
/// optional extra info.
pub fn plain(body: String, url: OwnedMxcUri, info: Option<Box<AudioInfo>>) -> Self {
Self {
#[cfg(feature = "unstable-msc3246")]
message: Some(MessageContent::plain(body.clone())),
#[cfg(feature = "unstable-msc3246")]
file: Some(FileContent::plain(
url.clone(),
info.as_deref().and_then(|info| {
FileContentInfo::from_room_message_content(
None,
info.mimetype.to_owned(),
info.size.to_owned(),
)
.map(Box::new)
}),
)),
#[cfg(feature = "unstable-msc3246")]
audio: Some(
info.as_deref()
.and_then(|info| info.duration)
.map(AudioContent::from_room_message_content)
.unwrap_or_default(),
),
#[cfg(feature = "unstable-msc3245")]
voice: None,
body,
source: MediaSource::Plain(url),
info,
}
Self { body, source: MediaSource::Plain(url), info }
}
/// Creates a new encrypted `AudioMessageEventContent` with the given body and encrypted
/// file.
pub fn encrypted(body: String, file: EncryptedFile) -> Self {
Self {
#[cfg(feature = "unstable-msc3246")]
message: Some(MessageContent::plain(body.clone())),
#[cfg(feature = "unstable-msc3246")]
file: Some(FileContent::encrypted(
file.url.clone(),
EncryptedContent::from(&file),
None,
)),
#[cfg(feature = "unstable-msc3246")]
audio: Some(AudioContent::default()),
#[cfg(feature = "unstable-msc3245")]
voice: None,
body,
source: MediaSource::Encrypted(Box::new(file)),
info: None,
}
}
/// Create a new `AudioMessageEventContent` with the given message, file info and audio info.
#[cfg(feature = "unstable-msc3246")]
pub(crate) fn from_extensible_content(
message: MessageContent,
file: FileContent,
audio: AudioContent,
) -> Self {
let body = if let Some(body) = message.find_plain() {
body.to_owned()
} else {
message[0].body.clone()
};
let source = (&file).into();
let info = AudioInfo::from_extensible_content(file.info.as_deref(), &audio).map(Box::new);
Self {
message: Some(message),
file: Some(file),
audio: Some(audio),
#[cfg(feature = "unstable-msc3245")]
voice: None,
body,
source,
info,
}
}
/// Create a new `AudioMessageEventContent` with the given message, file info, audio info and
/// voice flag.
#[cfg(feature = "unstable-msc3245")]
pub fn from_extensible_voice_content(
message: MessageContent,
file: FileContent,
audio: AudioContent,
voice: VoiceContent,
) -> Self {
let mut content = Self::from_extensible_content(message, file, audio);
content.voice = Some(voice);
content
Self { body, source: MediaSource::Encrypted(Box::new(file)), info: None }
}
}
@ -198,27 +65,4 @@ impl AudioInfo {
pub fn new() -> Self {
Self::default()
}
/// Create an `AudioInfo` from the given file info and audio info.
///
/// Returns `None` if the `AudioInfo` would be empty.
#[cfg(feature = "unstable-msc3246")]
fn from_extensible_content(
file_info: Option<&FileContentInfo>,
audio: &AudioContent,
) -> Option<Self> {
let (mimetype, size) = file_info
.map(|info| {
let FileContentInfo { mimetype, size, .. } = info;
(mimetype.to_owned(), size.to_owned())
})
.unwrap_or_default();
let AudioContent { duration, .. } = audio;
if duration.is_none() && mimetype.is_none() && size.is_none() {
None
} else {
Some(Self { duration: duration.to_owned(), mimetype, size })
}
}
}

View File

@ -3,42 +3,8 @@
use serde::{de, Deserialize};
use serde_json::value::RawValue as RawJsonValue;
#[cfg(feature = "unstable-msc3552")]
use super::ImageMessageEventContent;
use super::{relation_serde::deserialize_relation, MessageType, RoomMessageEventContent};
#[cfg(feature = "unstable-msc3246")]
use super::{AudioInfo, AudioMessageEventContent};
#[cfg(feature = "unstable-msc3551")]
use super::{FileInfo, FileMessageEventContent};
#[cfg(feature = "unstable-msc3488")]
use super::{LocationInfo, LocationMessageEventContent};
#[cfg(feature = "unstable-msc3553")]
use super::{VideoInfo, VideoMessageEventContent};
#[cfg(feature = "unstable-msc3246")]
use crate::events::audio::AudioContent;
#[cfg(feature = "unstable-msc3551")]
use crate::events::file::FileContent;
#[cfg(feature = "unstable-msc3552")]
use crate::events::image::{ImageContent, ThumbnailContent};
#[cfg(feature = "unstable-msc3488")]
use crate::events::location::{AssetContent, LocationContent};
#[cfg(any(
feature = "unstable-msc3246",
feature = "unstable-msc3488",
feature = "unstable-msc3551"
))]
use crate::events::message::MessageContent;
#[cfg(feature = "unstable-msc3552")]
use crate::events::room::ImageInfo;
#[cfg(feature = "unstable-msc3551")]
use crate::events::room::MediaSource;
#[cfg(feature = "unstable-msc3553")]
use crate::events::video::VideoContent;
#[cfg(feature = "unstable-msc3245")]
use crate::events::voice::VoiceContent;
use crate::serde::from_raw_json_value;
#[cfg(feature = "unstable-msc3488")]
use crate::MilliSecondsSinceUnixEpoch;
impl<'de> Deserialize<'de> for RoomMessageEventContent {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
@ -83,372 +49,3 @@ impl<'de> Deserialize<'de> for MessageType {
})
}
}
/// Helper struct for deserializing `AudioMessageEventContent` with stable and unstable field names.
///
/// It's not possible to use the `alias` attribute of serde because of
/// https://github.com/serde-rs/serde/issues/1504.
#[derive(Clone, Debug, Deserialize)]
#[cfg(feature = "unstable-msc3246")]
pub struct AudioMessageEventContentDeHelper {
/// The textual representation of this message.
pub body: String,
/// The source of the audio clip.
#[serde(flatten)]
pub source: MediaSource,
/// Metadata for the audio clip referred to in `source`.
pub info: Option<Box<AudioInfo>>,
/// Extensible-event text representation of the message.
#[serde(flatten)]
pub message: Option<MessageContent>,
/// Extensible-event file content of the message, with stable name.
#[serde(rename = "m.file")]
pub file_stable: Option<FileContent>,
/// Extensible-event file content of the message, with unstable name.
#[serde(rename = "org.matrix.msc1767.file")]
pub file_unstable: Option<FileContent>,
/// Extensible-event audio info of the message, with stable name.
#[serde(rename = "m.audio")]
pub audio_stable: Option<AudioContent>,
/// Extensible-event audio info of the message, with unstable name.
#[serde(rename = "org.matrix.msc1767.audio")]
pub audio_unstable: Option<AudioContent>,
/// Extensible-event voice flag of the message, with stable name.
#[cfg(feature = "unstable-msc3245")]
#[serde(rename = "m.voice")]
pub voice_stable: Option<VoiceContent>,
/// Extensible-event voice flag of the message, with unstable name.
#[cfg(feature = "unstable-msc3245")]
#[serde(rename = "org.matrix.msc3245.voice")]
pub voice_unstable: Option<VoiceContent>,
}
#[cfg(feature = "unstable-msc3246")]
impl From<AudioMessageEventContentDeHelper> for AudioMessageEventContent {
fn from(helper: AudioMessageEventContentDeHelper) -> Self {
let AudioMessageEventContentDeHelper {
body,
source,
info,
message,
file_stable,
file_unstable,
audio_stable,
audio_unstable,
#[cfg(feature = "unstable-msc3245")]
voice_stable,
#[cfg(feature = "unstable-msc3245")]
voice_unstable,
} = helper;
let file = file_stable.or(file_unstable);
let audio = audio_stable.or(audio_unstable);
#[cfg(feature = "unstable-msc3245")]
let voice = voice_stable.or(voice_unstable);
Self {
body,
source,
info,
message,
file,
audio,
#[cfg(feature = "unstable-msc3245")]
voice,
}
}
}
/// Helper struct for deserializing `FileMessageEventContent` with stable and unstable field names.
///
/// It's not possible to use the `alias` attribute of serde because of
/// https://github.com/serde-rs/serde/issues/1504.
#[derive(Clone, Debug, Deserialize)]
#[cfg(feature = "unstable-msc3551")]
pub struct FileMessageEventContentDeHelper {
/// A human-readable description of the file.
pub body: String,
/// The original filename of the uploaded file.
pub filename: Option<String>,
/// The source of the file.
#[serde(flatten)]
pub source: MediaSource,
/// Metadata about the file referred to in `source`.
pub info: Option<Box<FileInfo>>,
/// Extensible-event text representation of the message.
#[serde(flatten)]
pub message: Option<MessageContent>,
/// Extensible-event file content of the message, with stable name.
#[serde(rename = "m.file")]
pub file_stable: Option<FileContent>,
/// Extensible-event file content of the message, with unstable name.
#[serde(rename = "org.matrix.msc1767.file")]
pub file_unstable: Option<FileContent>,
}
#[cfg(feature = "unstable-msc3551")]
impl From<FileMessageEventContentDeHelper> for FileMessageEventContent {
fn from(helper: FileMessageEventContentDeHelper) -> Self {
let FileMessageEventContentDeHelper {
body,
filename,
source,
info,
message,
file_stable,
file_unstable,
} = helper;
let file = file_stable.or(file_unstable);
Self { body, filename, source, info, message, file }
}
}
/// Helper struct for deserializing `ImageMessageEventContent` with stable and unstable field names.
///
/// It's not possible to use the `alias` attribute of serde because of
/// https://github.com/serde-rs/serde/issues/1504.
#[derive(Clone, Debug, Deserialize)]
#[cfg(feature = "unstable-msc3552")]
pub struct ImageMessageEventContentDeHelper {
/// A textual representation of the image.
pub body: String,
/// The source of the image.
#[serde(flatten)]
pub source: MediaSource,
/// Metadata about the image referred to in `source`.
pub info: Option<Box<ImageInfo>>,
/// Extensible-event text representation of the message.
#[serde(flatten)]
pub message: Option<MessageContent>,
/// Extensible-event file content of the message, with unstable name.
#[serde(rename = "m.file")]
pub file_stable: Option<FileContent>,
/// Extensible-event file content of the message, with unstable name.
#[serde(rename = "org.matrix.msc1767.file")]
pub file_unstable: Option<FileContent>,
/// Extensible-event image info of the message, with stable name.
#[serde(rename = "m.image")]
pub image_stable: Option<Box<ImageContent>>,
/// Extensible-event image info of the message, with unstable name.
#[serde(rename = "org.matrix.msc1767.image")]
pub image_unstable: Option<Box<ImageContent>>,
/// Extensible-event thumbnails of the message, with stable name.
#[serde(rename = "m.thumbnail")]
pub thumbnail_stable: Option<Vec<ThumbnailContent>>,
/// Extensible-event thumbnails of the message, with unstable name.
#[serde(rename = "org.matrix.msc1767.thumbnail")]
pub thumbnail_unstable: Option<Vec<ThumbnailContent>>,
/// Extensible-event captions of the message, with stable name.
#[serde(rename = "m.caption")]
pub caption_stable: Option<MessageContent>,
/// Extensible-event captions of the message, with unstable name.
#[serde(rename = "org.matrix.msc1767.caption")]
pub caption_unstable: Option<MessageContent>,
}
#[cfg(feature = "unstable-msc3552")]
impl From<ImageMessageEventContentDeHelper> for ImageMessageEventContent {
fn from(helper: ImageMessageEventContentDeHelper) -> Self {
let ImageMessageEventContentDeHelper {
body,
source,
info,
message,
file_stable,
file_unstable,
image_stable,
image_unstable,
thumbnail_stable,
thumbnail_unstable,
caption_stable,
caption_unstable,
} = helper;
let file = file_stable.or(file_unstable);
let image = image_stable.or(image_unstable);
let thumbnail = thumbnail_stable.or(thumbnail_unstable);
let caption = caption_stable.or(caption_unstable);
Self { body, source, info, message, file, image, thumbnail, caption }
}
}
/// Helper struct for deserializing `LocationMessageEventContent` with stable and unstable field
/// names.
///
/// It's not possible to use the `alias` attribute of serde because of
/// https://github.com/serde-rs/serde/issues/1504.
#[derive(Clone, Debug, Deserialize)]
#[cfg(feature = "unstable-msc3488")]
pub struct LocationMessageEventContentDeHelper {
/// A description of the location.
pub body: String,
/// A geo URI representing the location.
pub geo_uri: String,
/// Info about the location being represented.
#[serde(skip_serializing_if = "Option::is_none")]
pub info: Option<Box<LocationInfo>>,
/// Extensible-event text representation of the message.
#[serde(flatten)]
pub message: Option<MessageContent>,
/// Extensible-event location info of the message, with stable name.
#[serde(rename = "m.location")]
pub location_stable: Option<LocationContent>,
/// Extensible-event location info of the message, with unstable name.
#[serde(rename = "org.matrix.msc3488.location")]
pub location_unstable: Option<LocationContent>,
/// Extensible-event asset this message refers to, with stable name.
#[serde(rename = "m.asset")]
pub asset_stable: Option<AssetContent>,
/// Extensible-event asset this message refers to, with unstable name.
#[serde(rename = "org.matrix.msc3488.asset")]
pub asset_unstable: Option<AssetContent>,
/// Extensible-event timestamp this message refers to, with stable name.
#[serde(rename = "m.ts")]
pub ts_stable: Option<MilliSecondsSinceUnixEpoch>,
/// Extensible-event timestamp this message refers to, with unstable name.
#[serde(rename = "org.matrix.msc3488.ts")]
pub ts_unstable: Option<MilliSecondsSinceUnixEpoch>,
}
#[cfg(feature = "unstable-msc3488")]
impl From<LocationMessageEventContentDeHelper> for LocationMessageEventContent {
fn from(helper: LocationMessageEventContentDeHelper) -> Self {
let LocationMessageEventContentDeHelper {
body,
geo_uri,
info,
message,
location_stable,
location_unstable,
asset_stable,
asset_unstable,
ts_stable,
ts_unstable,
} = helper;
let location = location_stable.or(location_unstable);
let asset = asset_stable.or(asset_unstable);
let ts = ts_stable.or(ts_unstable);
Self { body, geo_uri, info, message, location, asset, ts }
}
}
/// Helper struct for deserializing `VideoMessageEventContent` with stable and unstable field names.
///
/// It's not possible to use the `alias` attribute of serde because of
/// https://github.com/serde-rs/serde/issues/1504.
#[derive(Clone, Debug, Deserialize)]
#[cfg(feature = "unstable-msc3553")]
pub struct VideoMessageEventContentDeHelper {
/// A description of the video.
pub body: String,
/// The source of the video clip.
#[serde(flatten)]
pub source: MediaSource,
/// Metadata about the video clip referred to in `source`.
pub info: Option<Box<VideoInfo>>,
/// Extensible-event text representation of the message.
#[serde(flatten)]
pub message: Option<MessageContent>,
/// Extensible-event file content of the message, with stable name.
#[serde(rename = "m.file")]
pub file_stable: Option<FileContent>,
/// Extensible-event file content of the message, with unstable name.
#[serde(rename = "org.matrix.msc1767.file")]
pub file_unstable: Option<FileContent>,
/// Extensible-event video info of the message, with stable name.
#[serde(rename = "m.video")]
pub video_stable: Option<Box<VideoContent>>,
/// Extensible-event video info of the message, with unstable name.
#[serde(rename = "org.matrix.msc1767.video")]
pub video_unstable: Option<Box<VideoContent>>,
/// Extensible-event thumbnails of the message, with stable name.
#[serde(rename = "m.thumbnail")]
pub thumbnail_stable: Option<Vec<ThumbnailContent>>,
/// Extensible-event thumbnails of the message, with unstable name.
#[serde(rename = "org.matrix.msc1767.thumbnail")]
pub thumbnail_unstable: Option<Vec<ThumbnailContent>>,
/// Extensible-event captions of the message, with stable name.
#[serde(rename = "m.caption")]
pub caption_stable: Option<MessageContent>,
/// Extensible-event captions of the message, with unstable name.
#[serde(rename = "org.matrix.msc1767.caption")]
pub caption_unstable: Option<MessageContent>,
}
#[cfg(feature = "unstable-msc3553")]
impl From<VideoMessageEventContentDeHelper> for VideoMessageEventContent {
fn from(helper: VideoMessageEventContentDeHelper) -> Self {
let VideoMessageEventContentDeHelper {
body,
source,
info,
message,
file_stable,
file_unstable,
video_stable,
video_unstable,
thumbnail_stable,
thumbnail_unstable,
caption_stable,
caption_unstable,
} = helper;
let file = file_stable.or(file_unstable);
let video = video_stable.or(video_unstable);
let thumbnail = thumbnail_stable.or(thumbnail_unstable);
let caption = caption_stable.or(caption_unstable);
Self { body, source, info, message, file, video, thumbnail, caption }
}
}

View File

@ -1,16 +1,8 @@
use serde::{Deserialize, Serialize};
use super::FormattedBody;
#[cfg(feature = "unstable-msc1767")]
use crate::events::message::MessageContent;
/// The payload for an emote message.
///
/// With the `unstable-msc1767` feature, this type contains the transitional format of
/// [`EmoteEventContent`]. See the documentation of the [`message`] module for more information.
///
/// [`EmoteEventContent`]: crate::events::emote::EmoteEventContent
/// [`message`]: crate::events::message
#[derive(Clone, Debug, Deserialize, Serialize)]
#[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)]
#[serde(tag = "msgtype", rename = "m.emote")]
@ -21,37 +13,19 @@ pub struct EmoteMessageEventContent {
/// Formatted form of the message `body`.
#[serde(flatten)]
pub formatted: Option<FormattedBody>,
/// Extensible-event representation of the message.
///
/// If present, this should be preferred over the other fields.
#[cfg(feature = "unstable-msc1767")]
#[serde(flatten, skip_serializing_if = "Option::is_none")]
pub message: Option<MessageContent>,
}
impl EmoteMessageEventContent {
/// A convenience constructor to create a plain-text emote.
pub fn plain(body: impl Into<String>) -> Self {
let body = body.into();
Self {
#[cfg(feature = "unstable-msc1767")]
message: Some(MessageContent::plain(body.clone())),
body,
formatted: None,
}
Self { body, formatted: None }
}
/// A convenience constructor to create an html emote message.
pub fn html(body: impl Into<String>, html_body: impl Into<String>) -> Self {
let body = body.into();
let html_body = html_body.into();
Self {
#[cfg(feature = "unstable-msc1767")]
message: Some(MessageContent::html(body.clone(), html_body.clone())),
body,
formatted: Some(FormattedBody::html(html_body)),
}
Self { body, formatted: Some(FormattedBody::html(html_body)) }
}
/// A convenience constructor to create a markdown emote.
@ -67,13 +41,3 @@ impl EmoteMessageEventContent {
}
}
}
#[cfg(feature = "unstable-msc1767")]
impl From<MessageContent> for EmoteMessageEventContent {
fn from(message: MessageContent) -> Self {
let body = if let Some(body) = message.find_plain() { body } else { &message[0].body };
let formatted = message.find_html().map(FormattedBody::html);
Self { body: body.to_owned(), formatted, message: Some(message) }
}
}

View File

@ -1,30 +1,15 @@
use js_int::UInt;
use serde::{Deserialize, Serialize};
#[cfg(feature = "unstable-msc3551")]
use crate::events::{
file::{FileContent, FileContentInfo},
message::MessageContent,
};
use crate::{
events::room::{EncryptedFile, MediaSource, ThumbnailInfo},
OwnedMxcUri,
};
/// The payload for a file message.
///
/// With the `unstable-msc3551` feature, this type contains the transitional format of
/// [`FileEventContent`]. See the documentation of the [`message`] module for more information.
///
/// [`FileEventContent`]: crate::events::file::FileEventContent
/// [`message`]: crate::events::message
#[derive(Clone, Debug, Deserialize, Serialize)]
#[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)]
#[serde(tag = "msgtype", rename = "m.file")]
#[cfg_attr(
feature = "unstable-msc3551",
serde(from = "super::content_serde::FileMessageEventContentDeHelper")
)]
pub struct FileMessageEventContent {
/// A human-readable description of the file.
///
@ -42,61 +27,19 @@ pub struct FileMessageEventContent {
/// Metadata about the file referred to in `source`.
#[serde(skip_serializing_if = "Option::is_none")]
pub info: Option<Box<FileInfo>>,
/// Extensible-event text representation of the message.
///
/// If present, this should be preferred over the `body` field.
#[cfg(feature = "unstable-msc3551")]
#[serde(flatten, skip_serializing_if = "Option::is_none")]
pub message: Option<MessageContent>,
/// Extensible-event file content of the message.
///
/// If present, this should be preferred over the `source` and `info` fields.
#[cfg(feature = "unstable-msc3551")]
#[serde(rename = "org.matrix.msc1767.file", skip_serializing_if = "Option::is_none")]
pub file: Option<FileContent>,
}
impl FileMessageEventContent {
/// Creates a new non-encrypted `FileMessageEventContent` with the given body, url and
/// optional extra info.
pub fn plain(body: String, url: OwnedMxcUri, info: Option<Box<FileInfo>>) -> Self {
Self {
#[cfg(feature = "unstable-msc3551")]
message: Some(MessageContent::plain(body.clone())),
#[cfg(feature = "unstable-msc3551")]
file: Some(FileContent::plain(
url.clone(),
info.as_deref().and_then(|info| {
FileContentInfo::from_room_message_content(
None,
info.mimetype.to_owned(),
info.size.to_owned(),
)
.map(Box::new)
}),
)),
body,
filename: None,
source: MediaSource::Plain(url),
info,
}
Self { body, filename: None, source: MediaSource::Plain(url), info }
}
/// Creates a new encrypted `FileMessageEventContent` with the given body and encrypted
/// file.
pub fn encrypted(body: String, file: EncryptedFile) -> Self {
Self {
#[cfg(feature = "unstable-msc3551")]
message: Some(MessageContent::plain(body.clone())),
#[cfg(feature = "unstable-msc3551")]
file: Some(FileContent::encrypted(file.url.clone(), (&file).into(), None)),
body,
filename: None,
source: MediaSource::Encrypted(Box::new(file)),
info: None,
}
Self { body, filename: None, source: MediaSource::Encrypted(Box::new(file)), info: None }
}
}

View File

@ -1,30 +1,14 @@
use serde::{Deserialize, Serialize};
#[cfg(feature = "unstable-msc3552")]
use crate::events::{
file::{FileContent, FileContentInfo},
image::{ImageContent, ThumbnailContent},
message::MessageContent,
};
use crate::{
events::room::{EncryptedFile, ImageInfo, MediaSource},
OwnedMxcUri,
};
/// The payload for an image message.
///
/// With the `unstable-msc3552` feature, this type contains the transitional format of
/// [`ImageEventContent`]. See the documentation of the [`message`] module for more information.
///
/// [`ImageEventContent`]: crate::events::image::ImageEventContent
/// [`message`]: crate::events::message
#[derive(Clone, Debug, Deserialize, Serialize)]
#[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)]
#[serde(tag = "msgtype", rename = "m.image")]
#[cfg_attr(
feature = "unstable-msc3552",
serde(from = "super::content_serde::ImageMessageEventContentDeHelper")
)]
pub struct ImageMessageEventContent {
/// A textual representation of the image.
///
@ -39,108 +23,18 @@ pub struct ImageMessageEventContent {
/// Metadata about the image referred to in `source`.
#[serde(skip_serializing_if = "Option::is_none")]
pub info: Option<Box<ImageInfo>>,
/// 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<MessageContent>,
/// Extensible-event file content of the message.
///
/// If present, this should be preferred over the `source` and `info` fields.
#[cfg(feature = "unstable-msc3552")]
#[serde(rename = "org.matrix.msc1767.file", skip_serializing_if = "Option::is_none")]
pub file: Option<FileContent>,
/// 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", skip_serializing_if = "Option::is_none")]
pub image: Option<Box<ImageContent>>,
/// 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", skip_serializing_if = "Option::is_none")]
pub thumbnail: Option<Vec<ThumbnailContent>>,
/// Extensible-event captions of the message.
#[cfg(feature = "unstable-msc3552")]
#[serde(
rename = "org.matrix.msc1767.caption",
with = "crate::events::message::content_serde::as_vec",
default,
skip_serializing_if = "Option::is_none"
)]
pub caption: Option<MessageContent>,
}
impl ImageMessageEventContent {
/// Creates a new non-encrypted `ImageMessageEventContent` with the given body, url and
/// optional extra info.
pub fn plain(body: String, url: OwnedMxcUri, info: Option<Box<ImageInfo>>) -> Self {
Self {
#[cfg(feature = "unstable-msc3552")]
message: Some(MessageContent::plain(body.clone())),
#[cfg(feature = "unstable-msc3552")]
file: Some(FileContent::plain(
url.clone(),
info.as_deref().and_then(|info| {
FileContentInfo::from_room_message_content(
None,
info.mimetype.to_owned(),
info.size,
)
.map(Box::new)
}),
)),
#[cfg(feature = "unstable-msc3552")]
image: Some(Box::new(
info.as_deref()
.and_then(|info| {
ImageContent::from_room_message_content(info.width, info.height)
})
.unwrap_or_default(),
)),
#[cfg(feature = "unstable-msc3552")]
thumbnail: info
.as_deref()
.and_then(|info| {
ThumbnailContent::from_room_message_content(
info.thumbnail_source.to_owned(),
info.thumbnail_info.to_owned(),
)
})
.map(|thumbnail| vec![thumbnail]),
#[cfg(feature = "unstable-msc3552")]
caption: None,
body,
source: MediaSource::Plain(url),
info,
}
Self { body, source: MediaSource::Plain(url), info }
}
/// Creates a new encrypted `ImageMessageEventContent` with the given body and encrypted
/// file.
pub fn encrypted(body: String, file: EncryptedFile) -> Self {
Self {
#[cfg(feature = "unstable-msc3552")]
message: Some(MessageContent::plain(body.clone())),
#[cfg(feature = "unstable-msc3552")]
file: Some(FileContent::encrypted(file.url.clone(), (&file).into(), None)),
#[cfg(feature = "unstable-msc3552")]
image: Some(Box::default()),
#[cfg(feature = "unstable-msc3552")]
thumbnail: None,
#[cfg(feature = "unstable-msc3552")]
caption: None,
body,
source: MediaSource::Encrypted(Box::new(file)),
info: None,
}
Self { body, source: MediaSource::Encrypted(Box::new(file)), info: None }
}
}

View File

@ -1,29 +1,11 @@
use serde::{Deserialize, Serialize};
use crate::events::room::{MediaSource, ThumbnailInfo};
#[cfg(feature = "unstable-msc3488")]
use crate::{
events::{
location::{AssetContent, LocationContent},
message::MessageContent,
},
MilliSecondsSinceUnixEpoch,
};
/// The payload for a location message.
///
/// With the `unstable-msc3488` feature, this type contains the transitional format of
/// [`LocationEventContent`]. See the documentation of the [`message`] module for more information.
///
/// [`LocationEventContent`]: crate::events::location::LocationEventContent
/// [`message`]: crate::events::message
#[derive(Clone, Debug, Deserialize, Serialize)]
#[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)]
#[serde(tag = "msgtype", rename = "m.location")]
#[cfg_attr(
feature = "unstable-msc3488",
serde(from = "super::content_serde::LocationMessageEventContentDeHelper")
)]
pub struct LocationMessageEventContent {
/// A description of the location e.g. "Big Ben, London, UK", or some kind of content
/// description for accessibility, e.g. "location attachment".
@ -35,48 +17,12 @@ pub struct LocationMessageEventContent {
/// Info about the location being represented.
#[serde(skip_serializing_if = "Option::is_none")]
pub info: Option<Box<LocationInfo>>,
/// Extensible-event text representation of the message.
///
/// If present, this should be preferred over the `body` field.
#[cfg(feature = "unstable-msc3488")]
#[serde(flatten, skip_serializing_if = "Option::is_none")]
pub message: Option<MessageContent>,
/// Extensible-event location info of the message.
///
/// If present, this should be preferred over the `geo_uri` field.
#[cfg(feature = "unstable-msc3488")]
#[serde(rename = "org.matrix.msc3488.location", skip_serializing_if = "Option::is_none")]
pub location: Option<LocationContent>,
/// Extensible-event asset this message refers to.
#[cfg(feature = "unstable-msc3488")]
#[serde(rename = "org.matrix.msc3488.asset", skip_serializing_if = "Option::is_none")]
pub asset: Option<AssetContent>,
/// Extensible-event timestamp this message refers to.
#[cfg(feature = "unstable-msc3488")]
#[serde(rename = "org.matrix.msc3488.ts", skip_serializing_if = "Option::is_none")]
pub ts: Option<MilliSecondsSinceUnixEpoch>,
}
impl LocationMessageEventContent {
/// Creates a new `LocationMessageEventContent` with the given body and geo URI.
pub fn new(body: String, geo_uri: String) -> Self {
Self {
#[cfg(feature = "unstable-msc3488")]
message: Some(MessageContent::plain(body.clone())),
#[cfg(feature = "unstable-msc3488")]
location: Some(LocationContent::new(geo_uri.clone())),
#[cfg(feature = "unstable-msc3488")]
asset: None,
#[cfg(feature = "unstable-msc3488")]
ts: None,
body,
geo_uri,
info: None,
}
Self { body, geo_uri, info: None }
}
}

View File

@ -1,17 +1,8 @@
use serde::{Deserialize, Serialize};
#[cfg(feature = "unstable-msc1767")]
use crate::events::message::MessageContent;
use super::FormattedBody;
/// The payload for a notice message.
///
/// With the `unstable-msc1767` feature, this type contains the transitional format of
/// [`NoticeEventContent`]. See the documentation of the [`message`] module for more information.
///
/// [`NoticeEventContent`]: crate::events::notice::NoticeEventContent
/// [`message`]: crate::events::message
#[derive(Clone, Debug, Deserialize, Serialize)]
#[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)]
#[serde(tag = "msgtype", rename = "m.notice")]
@ -22,37 +13,19 @@ pub struct NoticeMessageEventContent {
/// Formatted form of the message `body`.
#[serde(flatten)]
pub formatted: Option<FormattedBody>,
/// Extensible-event representation of the message.
///
/// If present, this should be preferred over the other fields.
#[cfg(feature = "unstable-msc1767")]
#[serde(flatten, skip_serializing_if = "Option::is_none")]
pub message: Option<MessageContent>,
}
impl NoticeMessageEventContent {
/// A convenience constructor to create a plain text notice.
pub fn plain(body: impl Into<String>) -> Self {
let body = body.into();
Self {
#[cfg(feature = "unstable-msc1767")]
message: Some(MessageContent::plain(body.clone())),
body,
formatted: None,
}
Self { body, formatted: None }
}
/// A convenience constructor to create an html notice.
pub fn html(body: impl Into<String>, html_body: impl Into<String>) -> Self {
let body = body.into();
let html_body = html_body.into();
Self {
#[cfg(feature = "unstable-msc1767")]
message: Some(MessageContent::html(body.clone(), html_body.clone())),
body,
formatted: Some(FormattedBody::html(html_body)),
}
Self { body, formatted: Some(FormattedBody::html(html_body)) }
}
/// A convenience constructor to create a markdown notice.
@ -68,13 +41,3 @@ impl NoticeMessageEventContent {
}
}
}
#[cfg(feature = "unstable-msc1767")]
impl From<MessageContent> for NoticeMessageEventContent {
fn from(message: MessageContent) -> Self {
let body = if let Some(body) = message.find_plain() { body } else { &message[0].body };
let formatted = message.find_html().map(FormattedBody::html);
Self { body: body.to_owned(), formatted, message: Some(message) }
}
}

View File

@ -1,17 +1,8 @@
use serde::{Deserialize, Serialize};
#[cfg(feature = "unstable-msc1767")]
use crate::events::message::MessageContent;
use super::FormattedBody;
/// The payload for a text message.
///
/// With the `unstable-msc1767` feature, this type contains the transitional format of
/// [`MessageEventContent`]. See the documentation of the [`message`] module for more information.
///
/// [`MessageEventContent`]: crate::events::message::MessageEventContent
/// [`message`]: crate::events::message
#[derive(Clone, Debug, Deserialize, Serialize)]
#[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)]
#[serde(tag = "msgtype", rename = "m.text")]
@ -22,37 +13,19 @@ pub struct TextMessageEventContent {
/// Formatted form of the message `body`.
#[serde(flatten)]
pub formatted: Option<FormattedBody>,
/// Extensible-event representation of the message.
///
/// If present, this should be preferred over the other fields.
#[cfg(feature = "unstable-msc1767")]
#[serde(flatten, skip_serializing_if = "Option::is_none")]
pub message: Option<MessageContent>,
}
impl TextMessageEventContent {
/// A convenience constructor to create a plain text message.
pub fn plain(body: impl Into<String>) -> Self {
let body = body.into();
Self {
#[cfg(feature = "unstable-msc1767")]
message: Some(MessageContent::plain(body.clone())),
body,
formatted: None,
}
Self { body, formatted: None }
}
/// A convenience constructor to create an HTML message.
pub fn html(body: impl Into<String>, html_body: impl Into<String>) -> Self {
let body = body.into();
let html_body = html_body.into();
Self {
#[cfg(feature = "unstable-msc1767")]
message: Some(MessageContent::html(body.clone(), html_body.clone())),
body,
formatted: Some(FormattedBody::html(html_body)),
}
Self { body, formatted: Some(FormattedBody::html(html_body)) }
}
/// A convenience constructor to create a Markdown message.
@ -68,13 +41,3 @@ impl TextMessageEventContent {
}
}
}
#[cfg(feature = "unstable-msc1767")]
impl From<MessageContent> for TextMessageEventContent {
fn from(message: MessageContent) -> Self {
let body = if let Some(body) = message.find_plain() { body } else { &message[0].body };
let formatted = message.find_html().map(FormattedBody::html);
Self { body: body.to_owned(), formatted, message: Some(message) }
}
}

View File

@ -3,32 +3,15 @@ use std::time::Duration;
use js_int::UInt;
use serde::{Deserialize, Serialize};
#[cfg(feature = "unstable-msc3553")]
use crate::events::{
file::{FileContent, FileContentInfo},
image::ThumbnailContent,
message::MessageContent,
video::VideoContent,
};
use crate::{
events::room::{EncryptedFile, MediaSource, ThumbnailInfo},
OwnedMxcUri,
};
/// The payload for a video message.
///
/// With the `unstable-msc3553` feature, this type contains the transitional format of
/// [`VideoEventContent`]. See the documentation of the [`message`] module for more information.
///
/// [`VideoEventContent`]: crate::events::video::VideoEventContent
/// [`message`]: crate::events::message
#[derive(Clone, Debug, Deserialize, Serialize)]
#[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)]
#[serde(tag = "msgtype", rename = "m.video")]
#[cfg_attr(
feature = "unstable-msc3553",
serde(from = "super::content_serde::VideoMessageEventContentDeHelper")
)]
pub struct VideoMessageEventContent {
/// A description of the video, e.g. "Gangnam Style", or some kind of content description for
/// accessibility, e.g. "video attachment".
@ -41,113 +24,19 @@ pub struct VideoMessageEventContent {
/// Metadata about the video clip referred to in `source`.
#[serde(skip_serializing_if = "Option::is_none")]
pub info: Option<Box<VideoInfo>>,
/// Extensible-event text representation of the message.
///
/// If present, this should be preferred over the `body` field.
#[cfg(feature = "unstable-msc3553")]
#[serde(flatten, skip_serializing_if = "Option::is_none")]
pub message: Option<MessageContent>,
/// Extensible-event file content of the message.
///
/// If present, this should be preferred over the `source` and `info` fields.
#[cfg(feature = "unstable-msc3553")]
#[serde(rename = "org.matrix.msc1767.file", skip_serializing_if = "Option::is_none")]
pub file: Option<FileContent>,
/// Extensible-event video info of the message.
///
/// If present, this should be preferred over the `info` field.
#[cfg(feature = "unstable-msc3553")]
#[serde(rename = "org.matrix.msc1767.video", skip_serializing_if = "Option::is_none")]
pub video: Option<Box<VideoContent>>,
/// Extensible-event thumbnails of the message.
///
/// If present, this should be preferred over the `info` field.
#[cfg(feature = "unstable-msc3553")]
#[serde(rename = "org.matrix.msc1767.thumbnail", skip_serializing_if = "Option::is_none")]
pub thumbnail: Option<Vec<ThumbnailContent>>,
/// Extensible-event captions of the message.
#[cfg(feature = "unstable-msc3553")]
#[serde(
rename = "org.matrix.msc1767.caption",
with = "crate::events::message::content_serde::as_vec",
default,
skip_serializing_if = "Option::is_none"
)]
pub caption: Option<MessageContent>,
}
impl VideoMessageEventContent {
/// Creates a new non-encrypted `VideoMessageEventContent` with the given body, url and
/// optional extra info.
pub fn plain(body: String, url: OwnedMxcUri, info: Option<Box<VideoInfo>>) -> Self {
Self {
#[cfg(feature = "unstable-msc3553")]
message: Some(MessageContent::plain(body.clone())),
#[cfg(feature = "unstable-msc3553")]
file: Some(FileContent::plain(
url.clone(),
info.as_deref().and_then(|info| {
FileContentInfo::from_room_message_content(
None,
info.mimetype.to_owned(),
info.size.to_owned(),
)
.map(Box::new)
}),
)),
#[cfg(feature = "unstable-msc3553")]
video: Some(Box::new(
info.as_deref()
.map(|info| {
VideoContent::from_room_message_content(
info.height,
info.width,
info.duration,
)
})
.unwrap_or_default(),
)),
#[cfg(feature = "unstable-msc3553")]
thumbnail: info
.as_deref()
.and_then(|info| {
ThumbnailContent::from_room_message_content(
info.thumbnail_source.to_owned(),
info.thumbnail_info.to_owned(),
)
})
.map(|thumbnail| vec![thumbnail]),
#[cfg(feature = "unstable-msc3553")]
caption: None,
body,
source: MediaSource::Plain(url),
info,
}
Self { body, source: MediaSource::Plain(url), info }
}
/// Creates a new encrypted `VideoMessageEventContent` with the given body and encrypted
/// file.
pub fn encrypted(body: String, file: EncryptedFile) -> Self {
Self {
#[cfg(feature = "unstable-msc3553")]
message: Some(MessageContent::plain(body.clone())),
#[cfg(feature = "unstable-msc3553")]
file: Some(FileContent::encrypted(file.url.clone(), (&file).into(), None)),
#[cfg(feature = "unstable-msc3553")]
video: Some(Box::default()),
#[cfg(feature = "unstable-msc3553")]
thumbnail: None,
#[cfg(feature = "unstable-msc3553")]
caption: None,
body,
source: MediaSource::Encrypted(Box::new(file)),
info: None,
}
Self { body, source: MediaSource::Encrypted(Box::new(file)), info: None }
}
}

View File

@ -5,22 +5,11 @@
use ruma_macros::EventContent;
use serde::{Deserialize, Serialize};
#[cfg(feature = "unstable-msc3552")]
use super::{
file::{FileContent, FileContentInfo},
image::{ImageContent, ThumbnailContent},
message::MessageContent,
};
use crate::{events::room::ImageInfo, OwnedMxcUri};
/// The content of an `m.sticker` event.
///
/// A sticker message.
///
/// With the `unstable-msc3552` feature, this type also contains the transitional extensible events
/// format. See the documentation of the [`message`] module for more information.
///
/// [`message`]: super::message
#[derive(Clone, Debug, Deserialize, Serialize, EventContent)]
#[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)]
#[ruma_event(type = "m.sticker", kind = MessageLike)]
@ -36,87 +25,11 @@ pub struct StickerEventContent {
/// The URL to the sticker image.
pub url: OwnedMxcUri,
/// 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<MessageContent>,
/// 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<FileContent>,
/// 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<Box<ImageContent>>,
/// 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<Vec<ThumbnailContent>>,
/// 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<MessageContent>,
}
impl StickerEventContent {
/// Creates a new `StickerEventContent` with the given body, image info and URL.
pub fn new(body: String, info: ImageInfo, url: OwnedMxcUri) -> Self {
Self {
#[cfg(feature = "unstable-msc3552")]
message: Some(MessageContent::plain(body.clone())),
#[cfg(feature = "unstable-msc3552")]
file: Some(FileContent::plain(
url.clone(),
FileContentInfo::from_room_message_content(None, info.mimetype.clone(), info.size)
.map(Box::new),
)),
#[cfg(feature = "unstable-msc3552")]
image: Some(Box::new(
ImageContent::from_room_message_content(info.width, info.height)
.unwrap_or_default(),
)),
#[cfg(feature = "unstable-msc3552")]
thumbnail: ThumbnailContent::from_room_message_content(
info.thumbnail_source.clone(),
info.thumbnail_info.clone(),
)
.map(|thumbnail| vec![thumbnail]),
#[cfg(feature = "unstable-msc3552")]
caption: None,
body,
info,
url,
}
Self { body, info, url }
}
}

View File

@ -110,15 +110,6 @@ impl VideoContent {
Self::default()
}
/// Creates a new `VideoContent` with the given optional height, width and duration.
pub(crate) fn from_room_message_content(
height: Option<UInt>,
width: Option<UInt>,
duration: Option<Duration>,
) -> Self {
Self { height, width, duration }
}
/// Whether this `VideoContent` is empty.
pub fn is_empty(&self) -> bool {
self.height.is_none() && self.width.is_none() && self.duration.is_none()

View File

@ -345,26 +345,16 @@ fn room_message_serialization() {
"body": "Upload: my_song.mp3",
"url": "mxc://notareal.hs/file",
"msgtype": "m.audio",
"org.matrix.msc1767.text": "Upload: my_song.mp3",
"org.matrix.msc1767.file": {
"url": "mxc://notareal.hs/file",
},
"org.matrix.msc1767.audio": {},
})
);
}
#[test]
fn room_message_stable_deserialization() {
fn room_message_deserialization() {
let json_data = json!({
"body": "Upload: my_song.mp3",
"url": "mxc://notareal.hs/file",
"msgtype": "m.audio",
"m.text": "Upload: my_song.mp3",
"m.file": {
"url": "mxc://notareal.hs/file",
},
"m.audio": {},
});
let event_content = from_json_value::<RoomMessageEventContent>(json_data).unwrap();
@ -372,36 +362,4 @@ fn room_message_stable_deserialization() {
assert_eq!(content.body, "Upload: my_song.mp3");
let url = assert_matches!(content.source, MediaSource::Plain(url) => url);
assert_eq!(url, "mxc://notareal.hs/file");
let message = content.message.unwrap();
assert_eq!(message.len(), 1);
assert_eq!(message[0].body, "Upload: my_song.mp3");
let file = content.file.unwrap();
assert_eq!(file.url, "mxc://notareal.hs/file");
assert!(!file.is_encrypted());
}
#[test]
fn room_message_unstable_deserialization() {
let json_data = json!({
"body": "Upload: my_song.mp3",
"url": "mxc://notareal.hs/file",
"msgtype": "m.audio",
"org.matrix.msc1767.text": "Upload: my_song.mp3",
"org.matrix.msc1767.file": {
"url": "mxc://notareal.hs/file",
},
"org.matrix.msc1767.audio": {},
});
let event_content = from_json_value::<RoomMessageEventContent>(json_data).unwrap();
let content = assert_matches!(event_content.msgtype, MessageType::Audio(content) => content);
assert_eq!(content.body, "Upload: my_song.mp3");
let url = assert_matches!(content.source, MediaSource::Plain(url) => url);
assert_eq!(url, "mxc://notareal.hs/file");
let message = content.message.unwrap();
assert_eq!(message.len(), 1);
assert_eq!(message[0].body, "Upload: my_song.mp3");
let file = content.file.unwrap();
assert_eq!(file.url, "mxc://notareal.hs/file");
assert!(!file.is_encrypted());
}

View File

@ -202,17 +202,10 @@ fn message_room_event_deserialization() {
fn message_event_serialization() {
let content = RoomMessageEventContent::text_plain("test");
#[cfg(not(feature = "unstable-msc1767"))]
assert_eq!(
serde_json::to_string(&content).expect("Failed to serialize message event content"),
r#"{"msgtype":"m.text","body":"test"}"#
);
#[cfg(feature = "unstable-msc1767")]
assert_eq!(
serde_json::to_string(&content).expect("Failed to serialize message event content"),
r#"{"msgtype":"m.text","body":"test","org.matrix.msc1767.text":"test"}"#
);
}
#[test]

View File

@ -233,10 +233,6 @@ fn room_message_plain_content_serialization() {
"body": "Upload: my_file.txt",
"url": "mxc://notareal.hs/file",
"msgtype": "m.file",
"org.matrix.msc1767.text": "Upload: my_file.txt",
"org.matrix.msc1767.file": {
"url": "mxc://notareal.hs/file",
},
})
);
}
@ -287,36 +283,16 @@ fn room_message_encrypted_content_serialization() {
"v": "v2",
},
"msgtype": "m.file",
"org.matrix.msc1767.text": "Upload: my_file.txt",
"org.matrix.msc1767.file": {
"url": "mxc://notareal.hs/file",
"key": {
"kty": "oct",
"key_ops": ["encrypt", "decrypt"],
"alg": "A256CTR",
"k": "TLlG_OpX807zzQuuwv4QZGJ21_u7weemFGYJFszMn9A",
"ext": true
},
"iv": "S22dq3NAX8wAAAAAAAAAAA",
"hashes": {
"sha256": "aWOHudBnDkJ9IwaR1Nd8XKoI7DOrqDTwt6xDPfVGN6Q"
},
"v": "v2",
},
})
);
}
#[test]
fn room_message_plain_content_stable_deserialization() {
fn room_message_plain_content_deserialization() {
let json_data = json!({
"body": "Upload: my_file.txt",
"url": "mxc://notareal.hs/file",
"msgtype": "m.file",
"m.text": "Upload: my_file.txt",
"m.file": {
"url": "mxc://notareal.hs/file",
},
});
let event_content = from_json_value::<RoomMessageEventContent>(json_data).unwrap();
@ -324,41 +300,10 @@ fn room_message_plain_content_stable_deserialization() {
assert_eq!(content.body, "Upload: my_file.txt");
let url = assert_matches!(content.source, MediaSource::Plain(url) => url);
assert_eq!(url, "mxc://notareal.hs/file");
let message = content.message.unwrap();
assert_eq!(message.len(), 1);
assert_eq!(message[0].body, "Upload: my_file.txt");
let file = content.file.unwrap();
assert_eq!(file.url, "mxc://notareal.hs/file");
assert!(!file.is_encrypted());
}
#[test]
fn room_message_plain_content_unstable_deserialization() {
let json_data = json!({
"body": "Upload: my_file.txt",
"url": "mxc://notareal.hs/file",
"msgtype": "m.file",
"org.matrix.msc1767.text": "Upload: my_file.txt",
"org.matrix.msc1767.file": {
"url": "mxc://notareal.hs/file",
},
});
let event_content = from_json_value::<RoomMessageEventContent>(json_data).unwrap();
let content = assert_matches!(event_content.msgtype, MessageType::File(content) => content);
assert_eq!(content.body, "Upload: my_file.txt");
let url = assert_matches!(content.source, MediaSource::Plain(url) => url);
assert_eq!(url, "mxc://notareal.hs/file");
let message = content.message.unwrap();
assert_eq!(message.len(), 1);
assert_eq!(message[0].body, "Upload: my_file.txt");
let file = content.file.unwrap();
assert_eq!(file.url, "mxc://notareal.hs/file");
assert!(!file.is_encrypted());
}
#[test]
fn room_message_encrypted_content_stable_deserialization() {
fn room_message_encrypted_content_deserialization() {
let json_data = json!({
"body": "Upload: my_file.txt",
"file": {
@ -377,22 +322,6 @@ fn room_message_encrypted_content_stable_deserialization() {
"v": "v2",
},
"msgtype": "m.file",
"m.text": "Upload: my_file.txt",
"m.file": {
"url": "mxc://notareal.hs/file",
"key": {
"kty": "oct",
"key_ops": ["encrypt", "decrypt"],
"alg": "A256CTR",
"k": "TLlG_OpX807zzQuuwv4QZGJ21_u7weemFGYJFszMn9A",
"ext": true
},
"iv": "S22dq3NAX8wAAAAAAAAAAA",
"hashes": {
"sha256": "aWOHudBnDkJ9IwaR1Nd8XKoI7DOrqDTwt6xDPfVGN6Q"
},
"v": "v2",
},
});
let event_content = from_json_value::<RoomMessageEventContent>(json_data).unwrap();
@ -400,61 +329,4 @@ fn room_message_encrypted_content_stable_deserialization() {
assert_eq!(content.body, "Upload: my_file.txt");
let encrypted_file = assert_matches!(content.source, MediaSource::Encrypted(f) => f);
assert_eq!(encrypted_file.url, "mxc://notareal.hs/file");
let message = content.message.unwrap();
assert_eq!(message.len(), 1);
assert_eq!(message[0].body, "Upload: my_file.txt");
let file = content.file.unwrap();
assert_eq!(file.url, "mxc://notareal.hs/file");
assert!(file.is_encrypted());
}
#[test]
fn room_message_encrypted_content_unstable_deserialization() {
let json_data = json!({
"body": "Upload: my_file.txt",
"file": {
"url": "mxc://notareal.hs/file",
"key": {
"kty": "oct",
"key_ops": ["encrypt", "decrypt"],
"alg": "A256CTR",
"k": "TLlG_OpX807zzQuuwv4QZGJ21_u7weemFGYJFszMn9A",
"ext": true
},
"iv": "S22dq3NAX8wAAAAAAAAAAA",
"hashes": {
"sha256": "aWOHudBnDkJ9IwaR1Nd8XKoI7DOrqDTwt6xDPfVGN6Q"
},
"v": "v2",
},
"msgtype": "m.file",
"org.matrix.msc1767.text": "Upload: my_file.txt",
"org.matrix.msc1767.file": {
"url": "mxc://notareal.hs/file",
"key": {
"kty": "oct",
"key_ops": ["encrypt", "decrypt"],
"alg": "A256CTR",
"k": "TLlG_OpX807zzQuuwv4QZGJ21_u7weemFGYJFszMn9A",
"ext": true
},
"iv": "S22dq3NAX8wAAAAAAAAAAA",
"hashes": {
"sha256": "aWOHudBnDkJ9IwaR1Nd8XKoI7DOrqDTwt6xDPfVGN6Q"
},
"v": "v2",
},
});
let event_content = from_json_value::<RoomMessageEventContent>(json_data).unwrap();
let content = assert_matches!(event_content.msgtype, MessageType::File(content) => content);
assert_eq!(content.body, "Upload: my_file.txt");
let encrypted_file = assert_matches!(content.source, MediaSource::Encrypted(f) => f);
assert_eq!(encrypted_file.url, "mxc://notareal.hs/file");
let message = content.message.unwrap();
assert_eq!(message.len(), 1);
assert_eq!(message[0].body, "Upload: my_file.txt");
let file = content.file.unwrap();
assert_eq!(file.url, "mxc://notareal.hs/file");
assert!(file.is_encrypted());
}

View File

@ -301,26 +301,16 @@ fn room_message_serialization() {
"body": "Upload: my_image.jpg",
"url": "mxc://notareal.hs/file",
"msgtype": "m.image",
"org.matrix.msc1767.text": "Upload: my_image.jpg",
"org.matrix.msc1767.file": {
"url": "mxc://notareal.hs/file",
},
"org.matrix.msc1767.image": {},
})
);
}
#[test]
fn room_message_stable_deserialization() {
fn room_message_deserialization() {
let json_data = json!({
"body": "Upload: my_image.jpg",
"url": "mxc://notareal.hs/file",
"msgtype": "m.image",
"m.text": "Upload: my_image.jpg",
"m.file": {
"url": "mxc://notareal.hs/file",
},
"m.image": {},
});
let event_content = from_json_value::<RoomMessageEventContent>(json_data).unwrap();
@ -328,36 +318,4 @@ fn room_message_stable_deserialization() {
assert_eq!(content.body, "Upload: my_image.jpg");
let url = assert_matches!(content.source, MediaSource::Plain(url) => url);
assert_eq!(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 room_message_unstable_deserialization() {
let json_data = json!({
"body": "Upload: my_image.jpg",
"url": "mxc://notareal.hs/file",
"msgtype": "m.image",
"org.matrix.msc1767.text": "Upload: my_image.jpg",
"org.matrix.msc1767.file": {
"url": "mxc://notareal.hs/file",
},
"org.matrix.msc1767.image": {},
});
let event_content = from_json_value::<RoomMessageEventContent>(json_data).unwrap();
let content = assert_matches!(event_content.msgtype, MessageType::Image(content) => content);
assert_eq!(content.body, "Upload: my_image.jpg");
let url = assert_matches!(content.source, MediaSource::Plain(url) => url);
assert_eq!(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());
}

View File

@ -193,24 +193,16 @@ fn room_message_serialization() {
"body": "Alice was at geo:51.5008,0.1247;u=35",
"geo_uri": "geo:51.5008,0.1247;u=35",
"msgtype": "m.location",
"org.matrix.msc1767.text": "Alice was at geo:51.5008,0.1247;u=35",
"org.matrix.msc3488.location": {
"uri": "geo:51.5008,0.1247;u=35",
},
})
);
}
#[test]
fn room_message_stable_deserialization() {
fn room_message_deserialization() {
let json_data = json!({
"body": "Alice was at geo:51.5008,0.1247;u=35",
"geo_uri": "geo:51.5008,0.1247;u=35",
"msgtype": "m.location",
"m.text": "Alice was at geo:51.5008,0.1247;u=35",
"m.location": {
"uri": "geo:51.5008,0.1247;u=35",
},
});
let event_content = from_json_value::<RoomMessageEventContent>(json_data).unwrap();
@ -218,31 +210,4 @@ fn room_message_stable_deserialization() {
assert_eq!(content.body, "Alice was at geo:51.5008,0.1247;u=35");
assert_eq!(content.geo_uri, "geo:51.5008,0.1247;u=35");
let message = content.message.unwrap();
assert_eq!(message.len(), 1);
assert_eq!(message[0].body, "Alice was at geo:51.5008,0.1247;u=35");
assert_eq!(content.location.unwrap().uri, "geo:51.5008,0.1247;u=35");
}
#[test]
fn room_message_unstable_deserialization() {
let json_data = json!({
"body": "Alice was at geo:51.5008,0.1247;u=35",
"geo_uri": "geo:51.5008,0.1247;u=35",
"msgtype": "m.location",
"org.matrix.msc1767.text": "Alice was at geo:51.5008,0.1247;u=35",
"org.matrix.msc3488.location": {
"uri": "geo:51.5008,0.1247;u=35",
},
});
let event_content = from_json_value::<RoomMessageEventContent>(json_data).unwrap();
let content = assert_matches!(event_content.msgtype, MessageType::Location(c) => c);
assert_eq!(content.body, "Alice was at geo:51.5008,0.1247;u=35");
assert_eq!(content.geo_uri, "geo:51.5008,0.1247;u=35");
let message = content.message.unwrap();
assert_eq!(message.len(), 1);
assert_eq!(message[0].body, "Alice was at geo:51.5008,0.1247;u=35");
assert_eq!(content.location.unwrap().uri, "geo:51.5008,0.1247;u=35");
}

View File

@ -296,11 +296,10 @@ fn message_event_deserialization() {
}
#[test]
fn room_message_plain_text_stable_deserialization() {
fn room_message_plain_text_deserialization() {
let json_data = json!({
"body": "test",
"msgtype": "m.text",
"m.text": "test",
});
let content = assert_matches!(
@ -311,41 +310,15 @@ fn room_message_plain_text_stable_deserialization() {
}) => content
);
assert_eq!(content.body, "test");
let message = content.message.unwrap();
assert_eq!(message.len(), 1);
assert_eq!(message[0].body, "test");
}
#[test]
fn room_message_plain_text_unstable_deserialization() {
let json_data = json!({
"body": "test",
"msgtype": "m.text",
"org.matrix.msc1767.text": "test",
});
let content = assert_matches!(
from_json_value::<RoomMessageEventContent>(json_data),
Ok(RoomMessageEventContent {
msgtype: MessageType::Text(content),
..
}) => content
);
assert_eq!(content.body, "test");
let message = content.message.unwrap();
assert_eq!(message.len(), 1);
assert_eq!(message[0].body, "test");
}
#[test]
fn room_message_html_and_text_stable_deserialization() {
fn room_message_html_and_text_deserialization() {
let json_data = json!({
"body": "test",
"formatted_body": "<h1>test</h1>",
"format": "org.matrix.custom.html",
"msgtype": "m.text",
"m.html": "<h1>test</h1>",
"m.text": "test",
});
let content = assert_matches!(
@ -358,95 +331,6 @@ fn room_message_html_and_text_stable_deserialization() {
assert_eq!(content.body, "test");
let formatted = content.formatted.unwrap();
assert_eq!(formatted.body, "<h1>test</h1>");
let message = content.message.unwrap();
assert_eq!(message.len(), 2);
assert_eq!(message[0].body, "<h1>test</h1>");
assert_eq!(message[1].body, "test");
}
#[test]
fn room_message_html_and_text_unstable_deserialization() {
let json_data = json!({
"body": "test",
"formatted_body": "<h1>test</h1>",
"format": "org.matrix.custom.html",
"msgtype": "m.text",
"org.matrix.msc1767.html": "<h1>test</h1>",
"org.matrix.msc1767.text": "test",
});
let content = assert_matches!(
from_json_value::<RoomMessageEventContent>(json_data),
Ok(RoomMessageEventContent {
msgtype: MessageType::Text(content),
..
}) => content
);
assert_eq!(content.body, "test");
let formatted = content.formatted.unwrap();
assert_eq!(formatted.body, "<h1>test</h1>");
let message = content.message.unwrap();
assert_eq!(message.len(), 2);
assert_eq!(message[0].body, "<h1>test</h1>");
assert_eq!(message[1].body, "test");
}
#[test]
fn room_message_message_stable_deserialization() {
let json_data = json!({
"body": "test",
"formatted_body": "<h1>test</h1>",
"format": "org.matrix.custom.html",
"msgtype": "m.text",
"m.message": [
{ "body": "<h1>test</h1>", "mimetype": "text/html" },
{ "body": "test", "mimetype": "text/plain" },
],
});
let content = assert_matches!(
from_json_value::<RoomMessageEventContent>(json_data),
Ok(RoomMessageEventContent {
msgtype: MessageType::Text(content),
..
}) => content
);
assert_eq!(content.body, "test");
let formatted = content.formatted.unwrap();
assert_eq!(formatted.body, "<h1>test</h1>");
let message = content.message.unwrap();
assert_eq!(message.len(), 2);
assert_eq!(message[0].body, "<h1>test</h1>");
assert_eq!(message[1].body, "test");
}
#[test]
fn room_message_message_unstable_deserialization() {
let json_data = json!({
"body": "test",
"formatted_body": "<h1>test</h1>",
"format": "org.matrix.custom.html",
"msgtype": "m.text",
"org.matrix.msc1767.message": [
{ "body": "<h1>test</h1>", "mimetype": "text/html" },
{ "body": "test", "mimetype": "text/plain" },
],
});
let content = assert_matches!(
from_json_value::<RoomMessageEventContent>(json_data),
Ok(RoomMessageEventContent {
msgtype: MessageType::Text(content),
..
}) => content
);
assert_eq!(content.body, "test");
let formatted = content.formatted.unwrap();
assert_eq!(formatted.body, "<h1>test</h1>");
let message = content.message.unwrap();
assert_eq!(message.len(), 2);
assert_eq!(message[0].body, "<h1>test</h1>");
assert_eq!(message[1].body, "test");
}
#[test]
@ -468,7 +352,6 @@ fn room_message_notice_serialization() {
json!({
"body": "> <@test:example.com> test\n\ntest reply",
"msgtype": "m.notice",
"org.matrix.msc1767.text": "> <@test:example.com> test\n\ntest reply",
})
);
}
@ -538,11 +421,10 @@ fn notice_event_unstable_deserialization() {
}
#[test]
fn room_message_notice_stable_deserialization() {
fn room_message_notice_deserialization() {
let json_data = json!({
"body": "test",
"msgtype": "m.notice",
"m.text": "test",
});
let content = assert_matches!(
@ -553,30 +435,6 @@ fn room_message_notice_stable_deserialization() {
}) => content
);
assert_eq!(content.body, "test");
let message = content.message.unwrap();
assert_eq!(message.len(), 1);
assert_eq!(message[0].body, "test");
}
#[test]
fn room_message_notice_unstable_deserialization() {
let json_data = json!({
"body": "test",
"msgtype": "m.notice",
"org.matrix.msc1767.text": "test",
});
let content = assert_matches!(
from_json_value::<RoomMessageEventContent>(json_data),
Ok(RoomMessageEventContent {
msgtype: MessageType::Notice(content),
..
}) => content
);
assert_eq!(content.body, "test");
let message = content.message.unwrap();
assert_eq!(message.len(), 1);
assert_eq!(message[0].body, "test");
}
#[test]
@ -604,7 +462,6 @@ fn room_message_emote_serialization() {
json!({
"body": "> <@test:example.com> test\n\ntest reply",
"msgtype": "m.emote",
"org.matrix.msc1767.text": "> <@test:example.com> test\n\ntest reply",
})
);
}
@ -668,11 +525,10 @@ fn emote_event_unstable_deserialization() {
}
#[test]
fn room_message_emote_stable_deserialization() {
fn room_message_emote_deserialization() {
let json_data = json!({
"body": "test",
"msgtype": "m.emote",
"m.text": "test",
});
let content = assert_matches!(
@ -683,30 +539,6 @@ fn room_message_emote_stable_deserialization() {
}) => content
);
assert_eq!(content.body, "test");
let message = content.message.unwrap();
assert_eq!(message.len(), 1);
assert_eq!(message[0].body, "test");
}
#[test]
fn room_message_emote_unstable_deserialization() {
let json_data = json!({
"body": "test",
"msgtype": "m.emote",
"org.matrix.msc1767.text": "test",
});
let content = assert_matches!(
from_json_value::<RoomMessageEventContent>(json_data),
Ok(RoomMessageEventContent {
msgtype: MessageType::Emote(content),
..
}) => content
);
assert_eq!(content.body, "test");
let message = content.message.unwrap();
assert_eq!(message.len(), 1);
assert_eq!(message[0].body, "test");
}
#[test]

View File

@ -36,7 +36,6 @@ fn message_serialize_sticker() {
let actual = to_json_value(&content).unwrap();
#[cfg(not(feature = "unstable-msc3552"))]
let expected = json!({
"body": "Hello",
"info": {
@ -54,45 +53,6 @@ fn message_serialize_sticker() {
},
"url": "mxc://matrix.org/rnsldl8srs98IRrs",
});
#[cfg(feature = "unstable-msc3552")]
let expected = json!({
"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,
}
],
});
assert_eq!(actual, expected);
}

View File

@ -38,7 +38,6 @@ fn reply_serialize() {
relates_to: Some(Relation::Reply { in_reply_to: InReplyTo::new(event_id!("$1598361704261elfgc").to_owned()) }),
});
#[cfg(not(feature = "unstable-msc1767"))]
assert_eq!(
to_json_value(content).unwrap(),
json!({
@ -51,21 +50,6 @@ fn reply_serialize() {
},
})
);
#[cfg(feature = "unstable-msc1767")]
assert_eq!(
to_json_value(content).unwrap(),
json!({
"msgtype": "m.text",
"body": "This is a reply",
"org.matrix.msc1767.text": "This is a reply",
"m.relates_to": {
"m.in_reply_to": {
"event_id": "$1598361704261elfgc",
},
},
})
);
}
#[test]
@ -82,7 +66,6 @@ fn replacement_serialize() {
}
);
#[cfg(not(feature = "unstable-msc1767"))]
assert_eq!(
to_json_value(content).unwrap(),
json!({
@ -98,25 +81,6 @@ fn replacement_serialize() {
},
})
);
#[cfg(feature = "unstable-msc1767")]
assert_eq!(
to_json_value(content).unwrap(),
json!({
"msgtype": "m.text",
"body": "<text msg>",
"org.matrix.msc1767.text": "<text msg>",
"m.new_content": {
"body": "This is the new content.",
"msgtype": "m.text",
"org.matrix.msc1767.text": "This is the new content.",
},
"m.relates_to": {
"rel_type": "m.replace",
"event_id": "$1598361704261elfgc",
},
})
);
}
#[test]
@ -161,7 +125,6 @@ fn thread_plain_serialize() {
}
);
#[cfg(not(feature = "unstable-msc1767"))]
assert_eq!(
to_json_value(content).unwrap(),
json!({
@ -177,24 +140,6 @@ fn thread_plain_serialize() {
},
})
);
#[cfg(feature = "unstable-msc1767")]
assert_eq!(
to_json_value(content).unwrap(),
json!({
"msgtype": "m.text",
"body": "<text msg>",
"org.matrix.msc1767.text": "<text msg>",
"m.relates_to": {
"rel_type": "m.thread",
"event_id": "$1598361704261elfgc",
"m.in_reply_to": {
"event_id": "$latesteventid",
},
"is_falling_back": true,
},
})
);
}
#[test]
@ -211,7 +156,6 @@ fn thread_reply_serialize() {
}
);
#[cfg(not(feature = "unstable-msc1767"))]
assert_eq!(
to_json_value(content).unwrap(),
json!({
@ -226,23 +170,6 @@ fn thread_reply_serialize() {
},
})
);
#[cfg(feature = "unstable-msc1767")]
assert_eq!(
to_json_value(content).unwrap(),
json!({
"msgtype": "m.text",
"body": "<text msg>",
"org.matrix.msc1767.text": "<text msg>",
"m.relates_to": {
"rel_type": "m.thread",
"event_id": "$1598361704261elfgc",
"m.in_reply_to": {
"event_id": "$repliedtoeventid",
},
},
})
);
}
#[test]

View File

@ -41,7 +41,6 @@ fn serialization() {
None,
)));
#[cfg(not(feature = "unstable-msc3246"))]
assert_eq!(
to_json_value(content).unwrap(),
json!({
@ -50,21 +49,6 @@ fn serialization() {
"url": "mxc://example.org/ffed755USFFxlgbQYZGtryd",
})
);
#[cfg(feature = "unstable-msc3246")]
assert_eq!(
to_json_value(content).unwrap(),
json!({
"body": "test",
"msgtype": "m.audio",
"url": "mxc://example.org/ffed755USFFxlgbQYZGtryd",
"org.matrix.msc1767.text": "test",
"org.matrix.msc1767.file": {
"url": "mxc://example.org/ffed755USFFxlgbQYZGtryd",
},
"org.matrix.msc1767.audio": {},
})
);
}
#[test]
@ -76,7 +60,6 @@ fn content_serialization() {
None,
)));
#[cfg(not(feature = "unstable-msc3246"))]
assert_eq!(
to_json_value(&message_event_content).unwrap(),
json!({
@ -85,21 +68,6 @@ fn content_serialization() {
"url": "mxc://example.org/ffed755USFFxlgbQYZGtryd"
})
);
#[cfg(feature = "unstable-msc3246")]
assert_eq!(
to_json_value(&message_event_content).unwrap(),
json!({
"body": "test",
"msgtype": "m.audio",
"url": "mxc://example.org/ffed755USFFxlgbQYZGtryd",
"org.matrix.msc1767.text": "test",
"org.matrix.msc1767.file": {
"url": "mxc://example.org/ffed755USFFxlgbQYZGtryd",
},
"org.matrix.msc1767.audio": {},
})
);
}
#[test]
@ -148,7 +116,6 @@ fn formatted_body_serialization() {
let message_event_content =
RoomMessageEventContent::text_html("Hello, World!", "Hello, <em>World</em>!");
#[cfg(not(feature = "unstable-msc1767"))]
assert_eq!(
to_json_value(&message_event_content).unwrap(),
json!({
@ -158,19 +125,6 @@ fn formatted_body_serialization() {
"formatted_body": "Hello, <em>World</em>!",
})
);
#[cfg(feature = "unstable-msc1767")]
assert_eq!(
to_json_value(&message_event_content).unwrap(),
json!({
"body": "Hello, World!",
"msgtype": "m.text",
"format": "org.matrix.custom.html",
"formatted_body": "Hello, <em>World</em>!",
"org.matrix.msc1767.html": "Hello, <em>World</em>!",
"org.matrix.msc1767.text": "Hello, World!",
})
);
}
#[test]
@ -178,7 +132,6 @@ fn plain_text_content_serialization() {
let message_event_content =
RoomMessageEventContent::text_plain("> <@test:example.com> test\n\ntest reply");
#[cfg(not(feature = "unstable-msc1767"))]
assert_eq!(
to_json_value(&message_event_content).unwrap(),
json!({
@ -186,16 +139,6 @@ fn plain_text_content_serialization() {
"msgtype": "m.text"
})
);
#[cfg(feature = "unstable-msc1767")]
assert_eq!(
to_json_value(&message_event_content).unwrap(),
json!({
"body": "> <@test:example.com> test\n\ntest reply",
"msgtype": "m.text",
"org.matrix.msc1767.text": "> <@test:example.com> test\n\ntest reply",
})
);
}
#[test]
@ -206,8 +149,6 @@ fn markdown_content_serialization() {
let formatted_message = RoomMessageEventContent::new(MessageType::Text(
TextMessageEventContent::markdown("Testing **bold** and _italic_!"),
));
#[cfg(not(feature = "unstable-msc1767"))]
assert_eq!(
to_json_value(&formatted_message).unwrap(),
json!({
@ -218,24 +159,9 @@ fn markdown_content_serialization() {
})
);
#[cfg(feature = "unstable-msc1767")]
assert_eq!(
to_json_value(&formatted_message).unwrap(),
json!({
"body": "Testing **bold** and _italic_!",
"formatted_body": "<p>Testing <strong>bold</strong> and <em>italic</em>!</p>\n",
"format": "org.matrix.custom.html",
"msgtype": "m.text",
"org.matrix.msc1767.html": "<p>Testing <strong>bold</strong> and <em>italic</em>!</p>\n",
"org.matrix.msc1767.text": "Testing **bold** and _italic_!",
})
);
let plain_message_simple = RoomMessageEventContent::new(MessageType::Text(
TextMessageEventContent::markdown("Testing a simple phrase…"),
));
#[cfg(not(feature = "unstable-msc1767"))]
assert_eq!(
to_json_value(&plain_message_simple).unwrap(),
json!({
@ -244,21 +170,9 @@ fn markdown_content_serialization() {
})
);
#[cfg(feature = "unstable-msc1767")]
assert_eq!(
to_json_value(&plain_message_simple).unwrap(),
json!({
"body": "Testing a simple phrase…",
"msgtype": "m.text",
"org.matrix.msc1767.text": "Testing a simple phrase…",
})
);
let plain_message_paragraphs = RoomMessageEventContent::new(MessageType::Text(
TextMessageEventContent::markdown("Testing\n\nSeveral\n\nParagraphs."),
));
#[cfg(not(feature = "unstable-msc1767"))]
assert_eq!(
to_json_value(&plain_message_paragraphs).unwrap(),
json!({
@ -268,19 +182,6 @@ fn markdown_content_serialization() {
"msgtype": "m.text"
})
);
#[cfg(feature = "unstable-msc1767")]
assert_eq!(
to_json_value(&plain_message_paragraphs).unwrap(),
json!({
"body": "Testing\n\nSeveral\n\nParagraphs.",
"formatted_body": "<p>Testing</p>\n<p>Several</p>\n<p>Paragraphs.</p>\n",
"format": "org.matrix.custom.html",
"msgtype": "m.text",
"org.matrix.msc1767.html": "<p>Testing</p>\n<p>Several</p>\n<p>Paragraphs.</p>\n",
"org.matrix.msc1767.text": "Testing\n\nSeveral\n\nParagraphs.",
})
);
}
#[test]

View File

@ -1,5 +1,3 @@
#![cfg(feature = "unstable-msc3552")]
use ruma_common::{
events::{room::ImageInfo, sticker::StickerEventContent},
mxc_uri,
@ -20,59 +18,19 @@ fn content_serialization() {
"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() {
fn content_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::<StickerEventContent>(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::<StickerEventContent>(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());
}

View File

@ -314,26 +314,16 @@ fn room_message_serialization() {
"body": "Upload: my_video.mp4",
"url": "mxc://notareal.hs/file",
"msgtype": "m.video",
"org.matrix.msc1767.text": "Upload: my_video.mp4",
"org.matrix.msc1767.file": {
"url": "mxc://notareal.hs/file",
},
"org.matrix.msc1767.video": {},
})
);
}
#[test]
fn room_message_stable_deserialization() {
fn room_message_deserialization() {
let json_data = json!({
"body": "Upload: my_video.mp4",
"url": "mxc://notareal.hs/file",
"msgtype": "m.video",
"m.text": "Upload: my_video.mp4",
"m.file": {
"url": "mxc://notareal.hs/file",
},
"m.video": {},
});
let event_content = from_json_value::<RoomMessageEventContent>(json_data).unwrap();
@ -341,36 +331,4 @@ fn room_message_stable_deserialization() {
assert_eq!(content.body, "Upload: my_video.mp4");
let url = assert_matches!(content.source, MediaSource::Plain(url) => url);
assert_eq!(url, "mxc://notareal.hs/file");
let message = content.message.unwrap();
assert_eq!(message.len(), 1);
assert_eq!(message[0].body, "Upload: my_video.mp4");
let file = content.file.unwrap();
assert_eq!(file.url, "mxc://notareal.hs/file");
assert!(!file.is_encrypted());
}
#[test]
fn room_message_unstable_deserialization() {
let json_data = json!({
"body": "Upload: my_video.mp4",
"url": "mxc://notareal.hs/file",
"msgtype": "m.video",
"org.matrix.msc1767.text": "Upload: my_video.mp4",
"org.matrix.msc1767.file": {
"url": "mxc://notareal.hs/file",
},
"org.matrix.msc1767.video": {},
});
let event_content = from_json_value::<RoomMessageEventContent>(json_data).unwrap();
let content = assert_matches!(event_content.msgtype, MessageType::Video(content) => content);
assert_eq!(content.body, "Upload: my_video.mp4");
let url = assert_matches!(content.source, MediaSource::Plain(url) => url);
assert_eq!(url, "mxc://notareal.hs/file");
let message = content.message.unwrap();
assert_eq!(message.len(), 1);
assert_eq!(message[0].body, "Upload: my_video.mp4");
let file = content.file.unwrap();
assert_eq!(file.url, "mxc://notareal.hs/file");
assert!(!file.is_encrypted());
}

View File

@ -11,11 +11,8 @@ use ruma_common::{
audio::AudioContent,
file::{FileContent, FileContentInfo},
relation::InReplyTo,
room::{
message::{AudioMessageEventContent, MessageType, Relation, RoomMessageEventContent},
MediaSource,
},
voice::{VoiceContent, VoiceEventContent},
room::message::Relation,
voice::VoiceEventContent,
AnyMessageLikeEvent, MessageLikeEvent,
},
mxc_uri,
@ -122,87 +119,3 @@ fn message_event_deserialization() {
assert_eq!(info.mimetype.as_deref(), Some("audio/opus"));
assert_eq!(info.size, Some(uint!(123_774)));
}
#[test]
fn room_message_serialization() {
let message_event_content = RoomMessageEventContent::new(MessageType::Audio(assign!(
AudioMessageEventContent::plain(
"Upload: voice_message.ogg".to_owned(),
mxc_uri!("mxc://notareal.hs/file").to_owned(),
None,
), {
voice: Some(VoiceContent::new()),
}
)));
assert_eq!(
to_json_value(&message_event_content).unwrap(),
json!({
"body": "Upload: voice_message.ogg",
"url": "mxc://notareal.hs/file",
"msgtype": "m.audio",
"org.matrix.msc1767.text": "Upload: voice_message.ogg",
"org.matrix.msc1767.file": {
"url": "mxc://notareal.hs/file",
},
"org.matrix.msc1767.audio": {},
"org.matrix.msc3245.voice": {},
})
);
}
#[test]
fn room_message_stable_deserialization() {
let json_data = json!({
"body": "Upload: voice_message.ogg",
"url": "mxc://notareal.hs/file",
"msgtype": "m.audio",
"m.text": "Upload: voice_message.ogg",
"m.file": {
"url": "mxc://notareal.hs/file",
},
"m.audio": {},
"m.voice": {},
});
let event_content = from_json_value::<RoomMessageEventContent>(json_data).unwrap();
let content = assert_matches!(event_content.msgtype, MessageType::Audio(content) => content);
assert_eq!(content.body, "Upload: voice_message.ogg");
let url = assert_matches!(content.source, MediaSource::Plain(url) => url);
assert_eq!(url, "mxc://notareal.hs/file");
let message = content.message.unwrap();
assert_eq!(message.len(), 1);
assert_eq!(message[0].body, "Upload: voice_message.ogg");
let file = content.file.unwrap();
assert_eq!(file.url, "mxc://notareal.hs/file");
assert!(!file.is_encrypted());
assert!(content.voice.is_some());
}
#[test]
fn room_message_unstable_deserialization() {
let json_data = json!({
"body": "Upload: voice_message.ogg",
"url": "mxc://notareal.hs/file",
"msgtype": "m.audio",
"org.matrix.msc1767.text": "Upload: voice_message.ogg",
"org.matrix.msc1767.file": {
"url": "mxc://notareal.hs/file",
},
"org.matrix.msc1767.audio": {},
"org.matrix.msc3245.voice": {},
});
let event_content = from_json_value::<RoomMessageEventContent>(json_data).unwrap();
let content = assert_matches!(event_content.msgtype, MessageType::Audio(content) => content);
assert_eq!(content.body, "Upload: voice_message.ogg");
let url = assert_matches!(content.source, MediaSource::Plain(url) => url);
assert_eq!(url, "mxc://notareal.hs/file");
let message = content.message.unwrap();
assert_eq!(message.len(), 1);
assert_eq!(message[0].body, "Upload: voice_message.ogg");
let file = content.file.unwrap();
assert_eq!(file.url, "mxc://notareal.hs/file");
assert!(!file.is_encrypted());
assert!(content.voice.is_some());
}

View File

@ -15,7 +15,6 @@ fn serialize_room_message_content_without_relation() {
Some(Relation::Reply { in_reply_to: InReplyTo::new(event_id!("$eventId").to_owned()) });
let without_relation = MessageType::from(content);
#[cfg(not(feature = "unstable-msc3246"))]
assert_eq!(
to_json_value(&without_relation).unwrap(),
json!({
@ -23,16 +22,6 @@ fn serialize_room_message_content_without_relation() {
"msgtype": "m.text",
})
);
#[cfg(feature = "unstable-msc3246")]
assert_eq!(
to_json_value(&without_relation).unwrap(),
json!({
"body": "Hello, world!",
"msgtype": "m.text",
"org.matrix.msc1767.text": "Hello, world!",
})
);
}
#[test]