events: Remove conversions between extensible types and room messages

They are more difficult to implement and use with
generic replacements, for little gain.
This commit is contained in:
Kévin Commaille 2022-10-12 18:57:43 +02:00 committed by Kévin Commaille
parent ec853e968a
commit 7c802c89ca
14 changed files with 14 additions and 681 deletions

View File

@ -13,27 +13,15 @@ mod waveform_serde;
use waveform_serde::WaveformSerDeHelper; use waveform_serde::WaveformSerDeHelper;
use super::{ use super::{file::FileContent, message::MessageContent, room::message::Relation};
file::FileContent,
message::MessageContent,
room::message::{
AudioInfo, AudioMessageEventContent, MessageType, Relation, RoomMessageEventContent,
},
};
/// The payload for an extensible audio message. /// The payload for an extensible audio message.
/// ///
/// This is the new primary type introduced in [MSC3246] and should not be sent before the end of /// This is the new primary type introduced in [MSC3246] and should not be sent before the end of
/// the transition period. See the documentation of the [`message`] module for more information. /// the transition period. See the documentation of the [`message`] module for more information.
/// ///
/// `AudioEventContent` can be converted to a [`RoomMessageEventContent`] with a
/// [`MessageType::Audio`]. You can convert it back with
/// [`AudioEventContent::from_audio_room_message()`].
///
/// [MSC3246]: https://github.com/matrix-org/matrix-spec-proposals/pull/3246 /// [MSC3246]: https://github.com/matrix-org/matrix-spec-proposals/pull/3246
/// [`message`]: super::message /// [`message`]: super::message
/// [`RoomMessageEventContent`]: super::room::message::RoomMessageEventContent
/// [`MessageType::Audio`]: super::room::message::MessageType::Audio
#[derive(Clone, Debug, Serialize, Deserialize, EventContent)] #[derive(Clone, Debug, Serialize, Deserialize, EventContent)]
#[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)] #[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)]
#[ruma_event(type = "m.audio", kind = MessageLike, without_relation)] #[ruma_event(type = "m.audio", kind = MessageLike, without_relation)]
@ -70,52 +58,6 @@ impl AudioEventContent {
pub fn with_message(message: MessageContent, file: FileContent) -> Self { pub fn with_message(message: MessageContent, file: FileContent) -> Self {
Self { message, file, audio: Default::default(), relates_to: None } Self { message, file, audio: Default::default(), relates_to: None }
} }
/// Create a new `AudioEventContent` from the given `AudioMessageEventContent` and optional
/// relation.
pub fn from_audio_room_message(
content: AudioMessageEventContent,
relates_to: Option<Relation>,
) -> Self {
// Otherwise the `voice` field has an extra indentation
#[rustfmt::skip]
let AudioMessageEventContent {
body,
source,
info,
message,
file,
audio,
#[cfg(feature = "unstable-msc3245")]
voice: _,
} = content;
let AudioInfo { duration, mimetype, size } = info.map(|info| *info).unwrap_or_default();
let message = message.unwrap_or_else(|| MessageContent::plain(body));
let file = file.unwrap_or_else(|| {
FileContent::from_room_message_content(source, None, mimetype, size)
});
let audio = audio.unwrap_or_else(|| {
let mut content = AudioContent::new();
content.duration = duration;
content
});
Self { message, file, audio, relates_to }
}
}
impl From<AudioEventContent> for RoomMessageEventContent {
fn from(content: AudioEventContent) -> Self {
let AudioEventContent { message, file, audio, relates_to } = content;
Self {
msgtype: MessageType::Audio(AudioMessageEventContent::from_extensible_content(
message, file, audio,
)),
relates_to,
}
}
} }
/// Audio content. /// Audio content.

View File

@ -5,24 +5,15 @@
use ruma_macros::EventContent; use ruma_macros::EventContent;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use super::{ use super::{message::MessageContent, room::message::Relation};
message::MessageContent,
room::message::{EmoteMessageEventContent, MessageType, Relation, RoomMessageEventContent},
};
/// The payload for an extensible emote message. /// The payload for an extensible emote message.
/// ///
/// This is the new primary type introduced in [MSC1767] and should not be sent before the end of /// This is the new primary type introduced in [MSC1767] and should not be sent before the end of
/// the transition period. See the documentation of the [`message`] module for more information. /// the transition period. See the documentation of the [`message`] module for more information.
/// ///
/// `EmoteEventContent` can be converted to a [`RoomMessageEventContent`] with a
/// [`MessageType::Emote`]. You can convert it back with
/// [`EmoteEventContent::from_emote_room_message()`].
///
/// [MSC1767]: https://github.com/matrix-org/matrix-spec-proposals/pull/1767 /// [MSC1767]: https://github.com/matrix-org/matrix-spec-proposals/pull/1767
/// [`message`]: super::message /// [`message`]: super::message
/// [`RoomMessageEventContent`]: super::room::message::RoomMessageEventContent
/// [`MessageType::Emote`]: super::room::message::MessageType::Emote
#[derive(Clone, Debug, Serialize, Deserialize, EventContent)] #[derive(Clone, Debug, Serialize, Deserialize, EventContent)]
#[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)] #[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)]
#[ruma_event(type = "m.emote", kind = MessageLike, without_relation)] #[ruma_event(type = "m.emote", kind = MessageLike, without_relation)]
@ -55,26 +46,4 @@ impl EmoteEventContent {
pub fn markdown(body: impl AsRef<str> + Into<String>) -> Self { pub fn markdown(body: impl AsRef<str> + Into<String>) -> Self {
Self { message: MessageContent::markdown(body), relates_to: None } Self { message: MessageContent::markdown(body), relates_to: None }
} }
/// Create a new `EmoteEventContent` from the given `EmoteMessageEventContent` and optional
/// relation.
pub fn from_emote_room_message(
content: EmoteMessageEventContent,
relates_to: Option<Relation>,
) -> Self {
let EmoteMessageEventContent { body, formatted, message, .. } = content;
if let Some(message) = message {
Self { message, relates_to }
} else {
Self { message: MessageContent::from_room_message_content(body, formatted), relates_to }
}
}
}
impl From<EmoteEventContent> for RoomMessageEventContent {
fn from(content: EmoteEventContent) -> Self {
let EmoteEventContent { message, relates_to, .. } = content;
Self { msgtype: MessageType::Emote(message.into()), relates_to }
}
} }

View File

@ -10,12 +10,7 @@ use serde::{Deserialize, Serialize};
use super::{ use super::{
message::MessageContent, message::MessageContent,
room::{ room::{message::Relation, EncryptedFile, JsonWebKey},
message::{
FileInfo, FileMessageEventContent, MessageType, Relation, RoomMessageEventContent,
},
EncryptedFile, JsonWebKey, MediaSource,
},
}; };
use crate::{serde::Base64, OwnedMxcUri}; use crate::{serde::Base64, OwnedMxcUri};
@ -24,14 +19,8 @@ use crate::{serde::Base64, OwnedMxcUri};
/// This is the new primary type introduced in [MSC3551] and should not be sent before the end of /// This is the new primary type introduced in [MSC3551] and should not be sent before the end of
/// the transition period. See the documentation of the [`message`] module for more information. /// the transition period. See the documentation of the [`message`] module for more information.
/// ///
/// `FileEventContent` can be converted to a [`RoomMessageEventContent`] with a
/// [`MessageType::File`]. You can convert it back with
/// [`FileEventContent::from_file_room_message()`].
///
/// [MSC3551]: https://github.com/matrix-org/matrix-spec-proposals/pull/3551 /// [MSC3551]: https://github.com/matrix-org/matrix-spec-proposals/pull/3551
/// [`message`]: super::message /// [`message`]: super::message
/// [`RoomMessageEventContent`]: super::room::message::RoomMessageEventContent
/// [`MessageType::File`]: super::room::message::MessageType::File
#[derive(Clone, Debug, Serialize, Deserialize, EventContent)] #[derive(Clone, Debug, Serialize, Deserialize, EventContent)]
#[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)] #[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)]
#[ruma_event(type = "m.file", kind = MessageLike, without_relation)] #[ruma_event(type = "m.file", kind = MessageLike, without_relation)]
@ -99,36 +88,6 @@ impl FileEventContent {
) -> Self { ) -> Self {
Self { message, file: FileContent::encrypted(url, encryption_info, info), relates_to: None } Self { message, file: FileContent::encrypted(url, encryption_info, info), relates_to: None }
} }
/// Create a new `FileEventContent` from the given `FileMessageEventContent` and optional
/// relation.
pub fn from_file_room_message(
content: FileMessageEventContent,
relates_to: Option<Relation>,
) -> Self {
let FileMessageEventContent { body, filename, source, info, message, file } = content;
let FileInfo { mimetype, size, .. } = info.map(|info| *info).unwrap_or_default();
let message = message.unwrap_or_else(|| MessageContent::plain(body));
let file = file.unwrap_or_else(|| {
FileContent::from_room_message_content(source, filename, mimetype, size)
});
Self { message, file, relates_to }
}
}
impl From<FileEventContent> for RoomMessageEventContent {
fn from(content: FileEventContent) -> Self {
let FileEventContent { message, file, relates_to } = content;
Self {
msgtype: MessageType::File(FileMessageEventContent::from_extensible_content(
message, file,
)),
relates_to,
}
}
} }
/// File content. /// File content.
@ -164,20 +123,6 @@ impl FileContent {
Self { url, info, encryption_info: Some(Box::new(encryption_info)) } Self { url, info, encryption_info: Some(Box::new(encryption_info)) }
} }
/// Create a new `FileContent` with the given media source, file info and filename.
pub(crate) fn from_room_message_content(
source: MediaSource,
filename: Option<String>,
mimetype: Option<String>,
size: Option<UInt>,
) -> Self {
let (url, encryption_info) = source.into_extensible_content();
let info =
FileContentInfo::from_room_message_content(filename, mimetype, size).map(Box::new);
Self { url, encryption_info: encryption_info.map(Box::new), info }
}
/// Whether the file is encrypted. /// Whether the file is encrypted.
pub fn is_encrypted(&self) -> bool { pub fn is_encrypted(&self) -> bool {
self.encryption_info.is_some() self.encryption_info.is_some()

View File

@ -9,10 +9,7 @@ use serde::{Deserialize, Serialize};
use super::{ use super::{
file::{EncryptedContent, FileContent}, file::{EncryptedContent, FileContent},
message::MessageContent, message::MessageContent,
room::{ room::{message::Relation, MediaSource, ThumbnailInfo},
message::{ImageMessageEventContent, MessageType, Relation, RoomMessageEventContent},
ImageInfo, MediaSource, ThumbnailInfo,
},
}; };
use crate::OwnedMxcUri; use crate::OwnedMxcUri;
@ -21,14 +18,8 @@ use crate::OwnedMxcUri;
/// This is the new primary type introduced in [MSC3552] and should not be sent before the end of /// This is the new primary type introduced in [MSC3552] and should not be sent before the end of
/// the transition period. See the documentation of the [`message`] module for more information. /// the transition period. See the documentation of the [`message`] module for more information.
/// ///
/// `ImageEventContent` can be converted to a [`RoomMessageEventContent`] with a
/// [`MessageType::Image`]. You can convert it back with
/// [`ImageEventContent::from_image_room_message()`].
///
/// [MSC3552]: https://github.com/matrix-org/matrix-spec-proposals/pull/3552 /// [MSC3552]: https://github.com/matrix-org/matrix-spec-proposals/pull/3552
/// [`message`]: super::message /// [`message`]: super::message
/// [`RoomMessageEventContent`]: super::room::message::RoomMessageEventContent
/// [`MessageType::Image`]: super::room::message::MessageType::Image
#[derive(Clone, Debug, Serialize, Deserialize, EventContent)] #[derive(Clone, Debug, Serialize, Deserialize, EventContent)]
#[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)] #[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)]
#[ruma_event(type = "m.image", kind = MessageLike, without_relation)] #[ruma_event(type = "m.image", kind = MessageLike, without_relation)]
@ -87,54 +78,6 @@ impl ImageEventContent {
relates_to: None, relates_to: None,
} }
} }
/// Create a new `ImageEventContent` from the given `ImageMessageEventContent` and optional
/// relation.
pub fn from_image_room_message(
content: ImageMessageEventContent,
relates_to: Option<Relation>,
) -> Self {
let ImageMessageEventContent {
body,
source,
info,
message,
file,
image,
thumbnail,
caption,
} = content;
let ImageInfo { height, width, mimetype, size, thumbnail_info, thumbnail_source, .. } =
info.map(|info| *info).unwrap_or_default();
let message = message.unwrap_or_else(|| MessageContent::plain(body));
let file = file.unwrap_or_else(|| {
FileContent::from_room_message_content(source, None, mimetype, size)
});
let image = image
.or_else(|| ImageContent::from_room_message_content(width, height).map(Box::new))
.unwrap_or_default();
let thumbnail = thumbnail.unwrap_or_else(|| {
ThumbnailContent::from_room_message_content(thumbnail_source, thumbnail_info)
.into_iter()
.collect()
});
Self { message, file, image, thumbnail, caption, relates_to }
}
}
impl From<ImageEventContent> for RoomMessageEventContent {
fn from(content: ImageEventContent) -> Self {
let ImageEventContent { message, file, image, thumbnail, caption, relates_to } = content;
Self {
msgtype: MessageType::Image(ImageMessageEventContent::from_extensible_content(
message, file, image, thumbnail, caption,
)),
relates_to,
}
}
} }
/// Image content. /// Image content.

View File

@ -8,10 +8,7 @@ use serde::{Deserialize, Serialize};
mod zoomlevel_serde; mod zoomlevel_serde;
use super::{ use super::{message::MessageContent, room::message::Relation};
message::MessageContent,
room::message::{LocationMessageEventContent, MessageType, Relation, RoomMessageEventContent},
};
use crate::{MilliSecondsSinceUnixEpoch, PrivOwnedStr}; use crate::{MilliSecondsSinceUnixEpoch, PrivOwnedStr};
/// The payload for an extensible location message. /// The payload for an extensible location message.
@ -19,14 +16,8 @@ use crate::{MilliSecondsSinceUnixEpoch, PrivOwnedStr};
/// This is the new primary type introduced in [MSC3488] and should not be sent before the end of /// This is the new primary type introduced in [MSC3488] and should not be sent before the end of
/// the transition period. See the documentation of the [`message`] module for more information. /// the transition period. See the documentation of the [`message`] module for more information.
/// ///
/// `LocationEventContent` can be converted to a [`RoomMessageEventContent`] with a
/// [`MessageType::Location`]. You can convert it back with
/// [`LocationEventContent::from_location_room_message()`].
///
/// [MSC3488]: https://github.com/matrix-org/matrix-spec-proposals/pull/3488 /// [MSC3488]: https://github.com/matrix-org/matrix-spec-proposals/pull/3488
/// [`message`]: super::message /// [`message`]: super::message
/// [`RoomMessageEventContent`]: super::room::message::RoomMessageEventContent
/// [`MessageType::Location`]: super::room::message::MessageType::Location
#[derive(Clone, Debug, Serialize, Deserialize, EventContent)] #[derive(Clone, Debug, Serialize, Deserialize, EventContent)]
#[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)] #[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)]
#[ruma_event(type = "m.location", kind = MessageLike, without_relation)] #[ruma_event(type = "m.location", kind = MessageLike, without_relation)]
@ -68,35 +59,6 @@ impl LocationEventContent {
pub fn with_message(message: MessageContent, location: LocationContent) -> Self { pub fn with_message(message: MessageContent, location: LocationContent) -> Self {
Self { message, location, asset: Default::default(), ts: None, relates_to: None } Self { message, location, asset: Default::default(), ts: None, relates_to: None }
} }
/// Create a new `LocationEventContent` from the given `LocationMessageEventContent` and
/// optional relation.
pub fn from_location_room_message(
content: LocationMessageEventContent,
relates_to: Option<Relation>,
) -> Self {
let LocationMessageEventContent { body, geo_uri, message, location, asset, ts, .. } =
content;
let message = message.unwrap_or_else(|| MessageContent::plain(body));
let location = location.unwrap_or_else(|| LocationContent::new(geo_uri));
let asset = asset.unwrap_or_default();
Self { message, location, asset, ts, relates_to }
}
}
impl From<LocationEventContent> for RoomMessageEventContent {
fn from(content: LocationEventContent) -> Self {
let LocationEventContent { message, location, asset, ts, relates_to } = content;
Self {
msgtype: MessageType::Location(LocationMessageEventContent::from_extensible_content(
message, location, asset, ts,
)),
relates_to,
}
}
} }
/// Location content. /// Location content.

View File

@ -27,17 +27,9 @@
//! the `unstable-mscXXXX` features (where `XXXX` is the number of the MSC). //! the `unstable-mscXXXX` features (where `XXXX` is the number of the MSC).
//! //!
//! The recommended way to send transitional extensible events while they are unstable and during //! The recommended way to send transitional extensible events while they are unstable and during
//! the transition period is to build one of the new primary types and then to convert it to a //! the transition period is to use the constructors and helper methods of
//! [`RoomMessageEventContent`] by using `.into()` or `RoomMessageEventContent::from()`. The //! [`RoomMessageEventContent`]. The data will be duplicated in both the legacy and extensible
//! provided constructors will copy the relevant data in the legacy fields. //! events fields as needed.
//!
//! For incoming events, a `RoomMessageEventContent` can be converted to an extensible event with
//! the relevant `from_*_room_message` method on the primary type. This conversion will work even
//! with legacy `m.room.message` events that don't have extensible events content.
//!
//! It is also possible to enable extensible events support and continue using
//! `RoomMessageEventContent`'s constructors. The data will be duplicated in both the legacy and
//! extensible events fields.
//! //!
//! [MSC1767]: https://github.com/matrix-org/matrix-spec-proposals/pull/1767 //! [MSC1767]: https://github.com/matrix-org/matrix-spec-proposals/pull/1767
//! [1767]: https://github.com/matrix-org/matrix-spec-proposals/pull/1767 //! [1767]: https://github.com/matrix-org/matrix-spec-proposals/pull/1767
@ -48,6 +40,7 @@
//! [3488]: https://github.com/matrix-org/matrix-spec-proposals/pull/3488 //! [3488]: https://github.com/matrix-org/matrix-spec-proposals/pull/3488
//! [MSC3245]: https://github.com/matrix-org/matrix-spec-proposals/pull/3245 //! [MSC3245]: https://github.com/matrix-org/matrix-spec-proposals/pull/3245
//! [MSC3381]: https://github.com/matrix-org/matrix-spec-proposals/pull/3381 //! [MSC3381]: https://github.com/matrix-org/matrix-spec-proposals/pull/3381
//! [`RoomMessageEventContent`]: super::room::message::RoomMessageEventContent
use std::ops::Deref; use std::ops::Deref;
use ruma_macros::EventContent; use ruma_macros::EventContent;
@ -58,10 +51,7 @@ pub(crate) mod content_serde;
use content_serde::MessageContentSerDeHelper; use content_serde::MessageContentSerDeHelper;
use super::room::message::{ use super::room::message::Relation;
FormattedBody, MessageFormat, MessageType, Relation, RoomMessageEventContent,
TextMessageEventContent,
};
/// The payload for an extensible text message. /// The payload for an extensible text message.
/// ///
@ -71,14 +61,8 @@ use super::room::message::{
/// To construct a `MessageEventContent` with a custom [`MessageContent`], convert it with /// To construct a `MessageEventContent` with a custom [`MessageContent`], convert it with
/// `MessageEventContent::from()` / `.into()`. /// `MessageEventContent::from()` / `.into()`.
/// ///
/// `MessageEventContent` can be converted to a [`RoomMessageEventContent`] with a
/// [`MessageType::Text`]. You can convert it back with
/// [`MessageEventContent::from_text_room_message()`].
///
/// [MSC1767]: https://github.com/matrix-org/matrix-spec-proposals/pull/1767 /// [MSC1767]: https://github.com/matrix-org/matrix-spec-proposals/pull/1767
/// [`message`]: super::message /// [`message`]: super::message
/// [`RoomMessageEventContent`]: super::room::message::RoomMessageEventContent
/// [`MessageType::Text`]: super::room::message::MessageType::Text
#[derive(Clone, Debug, Serialize, Deserialize, EventContent)] #[derive(Clone, Debug, Serialize, Deserialize, EventContent)]
#[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)] #[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)]
#[ruma_event(type = "m.message", kind = MessageLike, without_relation)] #[ruma_event(type = "m.message", kind = MessageLike, without_relation)]
@ -111,20 +95,6 @@ impl MessageEventContent {
pub fn markdown(body: impl AsRef<str> + Into<String>) -> Self { pub fn markdown(body: impl AsRef<str> + Into<String>) -> Self {
Self { message: MessageContent::markdown(body), relates_to: None } Self { message: MessageContent::markdown(body), relates_to: None }
} }
/// Create a new `MessageEventContent` from the given `TextMessageEventContent` and optional
/// relation.
pub fn from_text_room_message(
content: TextMessageEventContent,
relates_to: Option<Relation>,
) -> Self {
let TextMessageEventContent { body, formatted, message, .. } = content;
if let Some(message) = message {
Self { message, relates_to }
} else {
Self { message: MessageContent::from_room_message_content(body, formatted), relates_to }
}
}
} }
impl From<MessageContent> for MessageEventContent { impl From<MessageContent> for MessageEventContent {
@ -133,14 +103,6 @@ impl From<MessageContent> for MessageEventContent {
} }
} }
impl From<MessageEventContent> for RoomMessageEventContent {
fn from(content: MessageEventContent) -> Self {
let MessageEventContent { message, relates_to, .. } = content;
Self { msgtype: MessageType::Text(message.into()), relates_to }
}
}
/// Text message content. /// Text message content.
/// ///
/// A `MessageContent` must contain at least one message to be used as a fallback text /// A `MessageContent` must contain at least one message to be used as a fallback text
@ -188,20 +150,6 @@ impl MessageContent {
Self(message) Self(message)
} }
/// Create a new `MessageContent` from the given body and optional formatted body.
pub(crate) fn from_room_message_content(
body: String,
formatted: Option<FormattedBody>,
) -> Self {
if let Some(FormattedBody { body: html_body, .. }) =
formatted.filter(|formatted| formatted.format == MessageFormat::Html)
{
Self::html(body, html_body)
} else {
Self::plain(body)
}
}
/// Get the plain text representation of this message. /// Get the plain text representation of this message.
pub fn find_plain(&self) -> Option<&str> { pub fn find_plain(&self) -> Option<&str> {
self.iter() self.iter()

View File

@ -5,24 +5,15 @@
use ruma_macros::EventContent; use ruma_macros::EventContent;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use super::{ use super::{message::MessageContent, room::message::Relation};
message::MessageContent,
room::message::{MessageType, NoticeMessageEventContent, Relation, RoomMessageEventContent},
};
/// The payload for an extensible notice message. /// The payload for an extensible notice message.
/// ///
/// This is the new primary type introduced in [MSC1767] and should not be sent before the end of /// This is the new primary type introduced in [MSC1767] and should not be sent before the end of
/// the transition period. See the documentation of the [`message`] module for more information. /// the transition period. See the documentation of the [`message`] module for more information.
/// ///
/// `NoticeEventContent` can be converted to a [`RoomMessageEventContent`] with a
/// [`MessageType::Notice`]. You can convert it back with
/// [`NoticeEventContent::from_notice_room_message()`].
///
/// [MSC1767]: https://github.com/matrix-org/matrix-spec-proposals/pull/1767 /// [MSC1767]: https://github.com/matrix-org/matrix-spec-proposals/pull/1767
/// [`message`]: super::message /// [`message`]: super::message
/// [`RoomMessageEventContent`]: super::room::message::RoomMessageEventContent
/// [`MessageType::Notice`]: super::room::message::MessageType::Notice
#[derive(Clone, Debug, Serialize, Deserialize, EventContent)] #[derive(Clone, Debug, Serialize, Deserialize, EventContent)]
#[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)] #[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)]
#[ruma_event(type = "m.notice", kind = MessageLike, without_relation)] #[ruma_event(type = "m.notice", kind = MessageLike, without_relation)]
@ -55,26 +46,4 @@ impl NoticeEventContent {
pub fn markdown(body: impl AsRef<str> + Into<String>) -> Self { pub fn markdown(body: impl AsRef<str> + Into<String>) -> Self {
Self { message: MessageContent::markdown(body), relates_to: None } Self { message: MessageContent::markdown(body), relates_to: None }
} }
/// Create a new `NoticeEventContent` from the given `NoticeMessageEventContent` and optional
/// relation.
pub fn from_notice_room_message(
content: NoticeMessageEventContent,
relates_to: Option<Relation>,
) -> Self {
let NoticeMessageEventContent { body, formatted, message, .. } = content;
if let Some(message) = message {
Self { message, relates_to }
} else {
Self { message: MessageContent::from_room_message_content(body, formatted), relates_to }
}
}
}
impl From<NoticeEventContent> for RoomMessageEventContent {
fn from(content: NoticeEventContent) -> Self {
let NoticeEventContent { message, relates_to, .. } = content;
Self { msgtype: MessageType::Notice(message.into()), relates_to }
}
} }

View File

@ -13,10 +13,7 @@ use serde::{de, Deserialize, Serialize};
#[cfg(feature = "unstable-msc3551")] #[cfg(feature = "unstable-msc3551")]
use super::file::{EncryptedContent, EncryptedContentInit, FileContent}; use super::file::{EncryptedContent, EncryptedContentInit, FileContent};
#[cfg(feature = "unstable-msc3552")] #[cfg(feature = "unstable-msc3552")]
use super::{ use super::image::ThumbnailFileContent;
file::FileContentInfo,
image::{ImageContent, ThumbnailContent, ThumbnailFileContent, ThumbnailFileContentInfo},
};
#[cfg(feature = "unstable-msc3551")] #[cfg(feature = "unstable-msc3551")]
use crate::MxcUri; use crate::MxcUri;
use crate::{ use crate::{
@ -165,48 +162,6 @@ impl ImageInfo {
pub fn new() -> Self { pub fn new() -> Self {
Self::default() Self::default()
} }
/// Create an `ImageInfo` from the given file info, image info and thumbnail.
///
/// Returns `None` if the `ImageInfo` would be empty.
#[cfg(feature = "unstable-msc3552")]
fn from_extensible_content(
file_info: Option<&FileContentInfo>,
image: &ImageContent,
thumbnail: &[ThumbnailContent],
) -> Option<Self> {
if file_info.is_none() && image.is_empty() && thumbnail.is_empty() {
None
} else {
let (mimetype, size) = file_info
.map(|info| (info.mimetype.to_owned(), info.size.to_owned()))
.unwrap_or_default();
let ImageContent { height, width } = image.to_owned();
let (thumbnail_source, thumbnail_info) = thumbnail
.get(0)
.map(|thumbnail| {
let source = (&thumbnail.file).into();
let info = ThumbnailInfo::from_extensible_content(
thumbnail.file.info.as_deref(),
thumbnail.image.as_deref(),
)
.map(Box::new);
(Some(source), info)
})
.unwrap_or_default();
Some(Self {
height,
width,
mimetype,
size,
thumbnail_source,
thumbnail_info,
#[cfg(feature = "unstable-msc2448")]
blurhash: None,
})
}
}
} }
/// Metadata about a thumbnail. /// Metadata about a thumbnail.
@ -235,24 +190,6 @@ impl ThumbnailInfo {
pub fn new() -> Self { pub fn new() -> Self {
Self::default() Self::default()
} }
/// Create a `ThumbnailInfo` with the given file info and image info.
///
/// Returns `None` if the `ThumbnailInfo` would be empty.
#[cfg(feature = "unstable-msc3552")]
fn from_extensible_content(
file_info: Option<&ThumbnailFileContentInfo>,
image: Option<&ImageContent>,
) -> Option<Self> {
if file_info.is_none() && image.is_none() {
None
} else {
let ThumbnailFileContentInfo { mimetype, size } =
file_info.map(ToOwned::to_owned).unwrap_or_default();
let ImageContent { height, width } = image.map(ToOwned::to_owned).unwrap_or_default();
Some(Self { height, width, mimetype, size })
}
}
} }
/// A file sent to a room with end-to-end encryption enabled. /// A file sent to a room with end-to-end encryption enabled.

View File

@ -98,24 +98,6 @@ impl FileMessageEventContent {
info: None, info: None,
} }
} }
/// Create a new `FileMessageEventContent` with the given message and file info.
#[cfg(feature = "unstable-msc3551")]
pub(crate) fn from_extensible_content(message: MessageContent, file: FileContent) -> Self {
let body = if let Some(body) = message.find_plain() {
body.to_owned()
} else {
message[0].body.clone()
};
let filename = file.info.as_deref().and_then(|info| info.name.clone());
let info = file.info.as_deref().and_then(|info| {
FileInfo::from_extensible_content(info.mimetype.to_owned(), info.size.to_owned())
.map(Box::new)
});
let source = (&file).into();
Self { message: Some(message), file: Some(file), body, filename, source, info }
}
} }
/// Metadata about a file. /// Metadata about a file.
@ -148,16 +130,4 @@ impl FileInfo {
pub fn new() -> Self { pub fn new() -> Self {
Self::default() Self::default()
} }
/// Creates a `FileInfo` with the given optional mimetype and size.
///
/// Returns `None` if the `FileInfo` would be empty.
#[cfg(feature = "unstable-msc3551")]
fn from_extensible_content(mimetype: Option<String>, size: Option<UInt>) -> Option<Self> {
if mimetype.is_none() && size.is_none() {
None
} else {
Some(Self { mimetype, size, ..Default::default() })
}
}
} }

View File

@ -143,36 +143,4 @@ impl ImageMessageEventContent {
info: None, info: None,
} }
} }
/// Create a new `ImageMessageEventContent` with the given message, file info, image info,
/// thumbnails and captions.
#[cfg(feature = "unstable-msc3552")]
pub(crate) fn from_extensible_content(
message: MessageContent,
file: FileContent,
image: Box<ImageContent>,
thumbnail: Vec<ThumbnailContent>,
caption: Option<MessageContent>,
) -> Self {
let body = if let Some(body) = message.find_plain() {
body.to_owned()
} else {
message[0].body.clone()
};
let source = (&file).into();
let info = ImageInfo::from_extensible_content(file.info.as_deref(), &image, &thumbnail)
.map(Box::new);
let thumbnail = if thumbnail.is_empty() { None } else { Some(thumbnail) };
Self {
message: Some(message),
file: Some(file),
image: Some(image),
thumbnail,
caption,
body,
source,
info,
}
}
} }

View File

@ -78,33 +78,6 @@ impl LocationMessageEventContent {
info: None, info: None,
} }
} }
/// Create a new `LocationMessageEventContent` with the given message, location info, asset and
/// timestamp.
#[cfg(feature = "unstable-msc3488")]
pub(crate) fn from_extensible_content(
message: MessageContent,
location: LocationContent,
asset: AssetContent,
ts: Option<MilliSecondsSinceUnixEpoch>,
) -> Self {
let body = if let Some(body) = message.find_plain() {
body.to_owned()
} else {
message[0].body.clone()
};
let geo_uri = location.uri.clone();
Self {
message: Some(message),
location: Some(location),
asset: Some(asset),
ts,
body,
geo_uri,
info: None,
}
}
} }
/// Thumbnail info associated with a location. /// Thumbnail info associated with a location.

View File

@ -149,38 +149,6 @@ impl VideoMessageEventContent {
info: None, info: None,
} }
} }
/// Create a new `VideoMessageEventContent` with the given message, file info, video info,
/// thumbnails and captions.
#[cfg(feature = "unstable-msc3553")]
pub(crate) fn from_extensible_content(
message: MessageContent,
file: FileContent,
video: Box<VideoContent>,
thumbnail: Vec<ThumbnailContent>,
caption: Option<MessageContent>,
) -> Self {
let body = if let Some(body) = message.find_plain() {
body.to_owned()
} else {
message[0].body.clone()
};
let source = (&file).into();
let info = VideoInfo::from_extensible_content(file.info.as_deref(), &video, &thumbnail)
.map(Box::new);
let thumbnail = if thumbnail.is_empty() { None } else { Some(thumbnail) };
Self {
message: Some(message),
file: Some(file),
video: Some(video),
thumbnail,
caption,
body,
source,
info,
}
}
} }
/// Metadata about a video. /// Metadata about a video.
@ -237,47 +205,4 @@ impl VideoInfo {
pub fn new() -> Self { pub fn new() -> Self {
Self::default() Self::default()
} }
/// Create a `VideoInfo` from the given file info, video info and thumbnail.
///
/// Returns `None` if the `VideoInfo` would be empty.
#[cfg(feature = "unstable-msc3553")]
fn from_extensible_content(
file_info: Option<&FileContentInfo>,
video: &VideoContent,
thumbnail: &[ThumbnailContent],
) -> Option<Self> {
if file_info.is_none() && video.is_empty() && thumbnail.is_empty() {
None
} else {
let (mimetype, size) = file_info
.map(|info| (info.mimetype.to_owned(), info.size.to_owned()))
.unwrap_or_default();
let VideoContent { duration, height, width } = video.to_owned();
let (thumbnail_source, thumbnail_info) = thumbnail
.get(0)
.map(|thumbnail| {
let source = (&thumbnail.file).into();
let info = ThumbnailInfo::from_extensible_content(
thumbnail.file.info.as_deref(),
thumbnail.image.as_deref(),
)
.map(Box::new);
(Some(source), info)
})
.unwrap_or_default();
Some(Self {
duration,
height,
width,
mimetype,
size,
thumbnail_info,
thumbnail_source,
#[cfg(feature = "unstable-msc2448")]
blurhash: None,
})
}
}
} }

View File

@ -9,12 +9,7 @@ use ruma_macros::EventContent;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use super::{ use super::{
file::FileContent, file::FileContent, image::ThumbnailContent, message::MessageContent, room::message::Relation,
image::ThumbnailContent,
message::MessageContent,
room::message::{
MessageType, Relation, RoomMessageEventContent, VideoInfo, VideoMessageEventContent,
},
}; };
/// The payload for an extensible video message. /// The payload for an extensible video message.
@ -22,14 +17,8 @@ use super::{
/// This is the new primary type introduced in [MSC3553] and should not be sent before the end of /// This is the new primary type introduced in [MSC3553] and should not be sent before the end of
/// the transition period. See the documentation of the [`message`] module for more information. /// the transition period. See the documentation of the [`message`] module for more information.
/// ///
/// `VideoEventContent` can be converted to a [`RoomMessageEventContent`] with a
/// [`MessageType::Video`]. You can convert it back with
/// [`VideoEventContent::from_video_room_message()`].
///
/// [MSC3553]: https://github.com/matrix-org/matrix-spec-proposals/pull/3553 /// [MSC3553]: https://github.com/matrix-org/matrix-spec-proposals/pull/3553
/// [`message`]: super::message /// [`message`]: super::message
/// [`RoomMessageEventContent`]: super::room::message::RoomMessageEventContent
/// [`MessageType::Video`]: super::room::message::MessageType::Video
#[derive(Clone, Debug, Serialize, Deserialize, EventContent)] #[derive(Clone, Debug, Serialize, Deserialize, EventContent)]
#[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)] #[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)]
#[ruma_event(type = "m.video", kind = MessageLike, without_relation)] #[ruma_event(type = "m.video", kind = MessageLike, without_relation)]
@ -88,62 +77,6 @@ impl VideoEventContent {
relates_to: None, relates_to: None,
} }
} }
/// Create a new `VideoEventContent` from the given `VideoMessageEventContent` and optional
/// relation.
pub fn from_video_room_message(
content: VideoMessageEventContent,
relates_to: Option<Relation>,
) -> Self {
let VideoMessageEventContent {
body,
source,
info,
message,
file,
video,
thumbnail,
caption,
} = content;
let VideoInfo {
duration,
height,
width,
mimetype,
size,
thumbnail_info,
thumbnail_source,
..
} = info.map(|info| *info).unwrap_or_default();
let message = message.unwrap_or_else(|| MessageContent::plain(body));
let file = file.unwrap_or_else(|| {
FileContent::from_room_message_content(source, None, mimetype, size)
});
let video = video.unwrap_or_else(|| {
Box::new(VideoContent::from_room_message_content(height, width, duration))
});
let thumbnail = thumbnail.unwrap_or_else(|| {
ThumbnailContent::from_room_message_content(thumbnail_source, thumbnail_info)
.into_iter()
.collect()
});
Self { message, file, video, thumbnail, caption, relates_to }
}
}
impl From<VideoEventContent> for RoomMessageEventContent {
fn from(content: VideoEventContent) -> Self {
let VideoEventContent { message, file, video, thumbnail, caption, relates_to } = content;
Self {
msgtype: MessageType::Video(VideoMessageEventContent::from_extensible_content(
message, file, video, thumbnail, caption,
)),
relates_to,
}
}
} }
/// Video content. /// Video content.

View File

@ -6,12 +6,7 @@ use ruma_macros::EventContent;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use super::{ use super::{
audio::AudioContent, audio::AudioContent, file::FileContent, message::MessageContent, room::message::Relation,
file::FileContent,
message::{MessageContent, TryFromExtensibleError},
room::message::{
AudioInfo, AudioMessageEventContent, MessageType, Relation, RoomMessageEventContent,
},
}; };
/// The payload for an extensible voice message. /// The payload for an extensible voice message.
@ -19,14 +14,8 @@ use super::{
/// This is the new primary type introduced in [MSC3245] and should not be sent before the end of /// This is the new primary type introduced in [MSC3245] and should not be sent before the end of
/// the transition period. See the documentation of the [`message`] module for more information. /// the transition period. See the documentation of the [`message`] module for more information.
/// ///
/// `VoiceEventContent` can be converted to a [`RoomMessageEventContent`] with a
/// [`MessageType::Audio`] with the `m.voice` flag. You can convert it back with
/// [`VoiceEventContent::try_from_audio_room_message()`].
///
/// [MSC3245]: https://github.com/matrix-org/matrix-spec-proposals/pull/3245 /// [MSC3245]: https://github.com/matrix-org/matrix-spec-proposals/pull/3245
/// [`message`]: super::message /// [`message`]: super::message
/// [`RoomMessageEventContent`]: super::room::message::RoomMessageEventContent
/// [`MessageType::Audio`]: super::room::message::MessageType::Audio
#[derive(Clone, Debug, Serialize, Deserialize, EventContent)] #[derive(Clone, Debug, Serialize, Deserialize, EventContent)]
#[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)] #[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)]
#[ruma_event(type = "m.voice", kind = MessageLike, without_relation)] #[ruma_event(type = "m.voice", kind = MessageLike, without_relation)]
@ -74,46 +63,6 @@ impl VoiceEventContent {
relates_to: None, relates_to: None,
} }
} }
/// Create a new `VoiceEventContent` from the given `AudioMessageEventContent` and optional
/// relation.
///
/// This can fail if the `AudioMessageEventContent` is not a voice message.
pub fn try_from_audio_room_message(
content: AudioMessageEventContent,
relates_to: Option<Relation>,
) -> Result<Self, TryFromExtensibleError> {
let AudioMessageEventContent { body, source, info, message, file, audio, voice } = content;
let AudioInfo { duration, mimetype, size } = info.map(|info| *info).unwrap_or_default();
let message = message.unwrap_or_else(|| MessageContent::plain(body));
let file = file.unwrap_or_else(|| {
FileContent::from_room_message_content(source, None, mimetype, size)
});
let audio = audio
.or_else(|| duration.map(AudioContent::from_room_message_content))
.unwrap_or_default();
let voice = if let Some(voice) = voice {
voice
} else {
return Err(TryFromExtensibleError::MissingField("m.voice".to_owned()));
};
Ok(Self { message, file, audio, voice, relates_to })
}
}
impl From<VoiceEventContent> for RoomMessageEventContent {
fn from(content: VoiceEventContent) -> Self {
let VoiceEventContent { message, file, audio, voice, relates_to } = content;
Self {
msgtype: MessageType::Audio(AudioMessageEventContent::from_extensible_voice_content(
message, file, audio, voice,
)),
relates_to,
}
}
} }
/// Voice content. /// Voice content.