From 08aa2ca04c86ff7d345f063ecf4a68f11928b413 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Commaille?= Date: Thu, 5 Jan 2023 12:46:30 +0100 Subject: [PATCH] events: Update types according to changes in MSC3245 --- crates/ruma-common/src/events/enums.rs | 5 +- crates/ruma-common/src/events/voice.rs | 83 ++++++++++++++++-------- crates/ruma-common/tests/events/voice.rs | 26 +++++--- 3 files changed, 75 insertions(+), 39 deletions(-) diff --git a/crates/ruma-common/src/events/enums.rs b/crates/ruma-common/src/events/enums.rs index 27cecb2d..7a6961de 100644 --- a/crates/ruma-common/src/events/enums.rs +++ b/crates/ruma-common/src/events/enums.rs @@ -89,7 +89,8 @@ event_enum! { #[ruma_enum(alias = "m.video")] "org.matrix.msc1767.video" => super::video, #[cfg(feature = "unstable-msc3245")] - "m.voice" => super::voice, + #[ruma_enum(alias = "m.voice")] + "org.matrix.msc3245.voice.v2" => super::voice, } /// Any state event. @@ -330,7 +331,7 @@ impl AnyMessageLikeEventContent { Self::Encrypted(ev) => ev.relates_to.clone(), #[cfg(feature = "unstable-msc3245")] Self::Voice(ev) => ev.relates_to.clone().map(Into::into), - #[cfg(feature = "unstable-msc3246")] + #[cfg(feature = "unstable-msc3927")] Self::Audio(ev) => ev.relates_to.clone().map(Into::into), #[cfg(feature = "unstable-msc3488")] Self::Location(ev) => ev.relates_to.clone().map(Into::into), diff --git a/crates/ruma-common/src/events/voice.rs b/crates/ruma-common/src/events/voice.rs index 195123b4..7fa9b1e1 100644 --- a/crates/ruma-common/src/events/voice.rs +++ b/crates/ruma-common/src/events/voice.rs @@ -2,12 +2,13 @@ //! //! [MSC3245]: https://github.com/matrix-org/matrix-spec-proposals/pull/3245 +use std::time::Duration; + use ruma_macros::EventContent; use serde::{Deserialize, Serialize}; use super::{ - audio::AudioDetailsContentBlock, file::FileContentBlock, message::TextContentBlock, - room::message::Relation, + audio::Amplitude, file::FileContentBlock, message::TextContentBlock, room::message::Relation, }; /// The payload for an extensible voice message. @@ -20,7 +21,7 @@ use super::{ /// [`message`]: super::message #[derive(Clone, Debug, Serialize, Deserialize, EventContent)] #[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)] -#[ruma_event(type = "m.voice", kind = MessageLike, without_relation)] +#[ruma_event(type = "org.matrix.msc3245.voice.v2", kind = MessageLike, without_relation)] pub struct VoiceEventContent { /// The text representation of the message. #[serde(rename = "org.matrix.msc1767.text")] @@ -31,12 +32,17 @@ pub struct VoiceEventContent { pub file: FileContentBlock, /// The audio content of the message. - #[serde(rename = "org.matrix.msc1767.audio_details", skip_serializing_if = "Option::is_none")] - pub audio_details: Option, + #[serde(rename = "org.matrix.msc1767.audio_details")] + pub audio_details: VoiceAudioDetailsContentBlock, - /// The voice content of the message. - #[serde(rename = "m.voice")] - pub voice: VoiceContent, + /// Whether this message is automated. + #[cfg(feature = "unstable-msc3955")] + #[serde( + default, + skip_serializing_if = "crate::serde::is_default", + rename = "org.matrix.msc1767.automated" + )] + pub automated: bool, /// Information about related messages. #[serde( @@ -48,35 +54,58 @@ pub struct VoiceEventContent { } impl VoiceEventContent { - /// Creates a new `VoiceEventContent` with the given fallback representation and file. - pub fn new(text: TextContentBlock, file: FileContentBlock) -> Self { - Self { text, file, audio_details: None, voice: Default::default(), relates_to: None } + /// Creates a new `VoiceEventContent` with the given fallback representation, file and audio + /// details. + pub fn new( + text: TextContentBlock, + file: FileContentBlock, + audio_details: VoiceAudioDetailsContentBlock, + ) -> Self { + Self { + text, + file, + audio_details, + #[cfg(feature = "unstable-msc3955")] + automated: false, + relates_to: None, + } } - /// Creates a new `VoiceEventContent` with the given plain text fallback representation and - /// file. - pub fn plain(text: impl Into, file: FileContentBlock) -> Self { + /// Creates a new `VoiceEventContent` with the given plain text fallback representation, file + /// and audio details. + pub fn with_plain_text( + plain_text: impl Into, + file: FileContentBlock, + audio_details: VoiceAudioDetailsContentBlock, + ) -> Self { Self { - text: TextContentBlock::plain(text), + text: TextContentBlock::plain(plain_text), file, - audio_details: None, - voice: Default::default(), + audio_details, + #[cfg(feature = "unstable-msc3955")] + automated: false, relates_to: None, } } } -/// Voice content. -/// -/// This is currently empty and used as a flag to mark an audio event that should be displayed as a -/// voice message. -#[derive(Clone, Debug, Default, Serialize, Deserialize)] +/// A block for details of voice audio content. +#[derive(Clone, Debug, Serialize, Deserialize)] #[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)] -pub struct VoiceContent {} +pub struct VoiceAudioDetailsContentBlock { + /// The duration of the audio in seconds. + #[serde(with = "ruma_common::serde::duration::secs")] + pub duration: Duration, -impl VoiceContent { - /// Creates a new empty `VoiceContent`. - pub fn new() -> Self { - Self::default() + /// The waveform representation of the content. + #[serde(rename = "org.matrix.msc3246.waveform")] + pub waveform: Vec, +} + +impl VoiceAudioDetailsContentBlock { + /// Creates a new `AudioDetailsContentBlock` with the given duration and waveform + /// representation. + pub fn new(duration: Duration, waveform: Vec) -> Self { + Self { duration, waveform } } } diff --git a/crates/ruma-common/tests/events/voice.rs b/crates/ruma-common/tests/events/voice.rs index 16a8b3de..f085acd6 100644 --- a/crates/ruma-common/tests/events/voice.rs +++ b/crates/ruma-common/tests/events/voice.rs @@ -7,8 +7,12 @@ use js_int::uint; use ruma_common::{ event_id, events::{ - audio::AudioDetailsContentBlock, file::FileContentBlock, relation::InReplyTo, - room::message::Relation, voice::VoiceEventContent, AnyMessageLikeEvent, MessageLikeEvent, + audio::Amplitude, + file::FileContentBlock, + relation::InReplyTo, + room::message::Relation, + voice::{VoiceAudioDetailsContentBlock, VoiceEventContent}, + AnyMessageLikeEvent, MessageLikeEvent, }, mxc_uri, serde::CanBeEmpty, @@ -18,17 +22,20 @@ use serde_json::{from_value as from_json_value, json, to_value as to_json_value} #[test] fn event_serialization() { - let mut content = VoiceEventContent::plain( + let mut content = VoiceEventContent::with_plain_text( "Voice message", FileContentBlock::plain( mxc_uri!("mxc://notareal.hs/abcdef").to_owned(), "voice_message.ogg".to_owned(), ), + VoiceAudioDetailsContentBlock::new( + Duration::from_secs(23), + vec![Amplitude::from(255), Amplitude::from(0)], + ), ); content.file.mimetype = Some("audio/opus".to_owned()); content.file.size = Some(uint!(897_774)); - content.audio_details = Some(AudioDetailsContentBlock::new(Duration::from_secs(23))); content.relates_to = Some(Relation::Reply { in_reply_to: InReplyTo::new(event_id!("$replyevent:example.com").to_owned()), }); @@ -47,8 +54,8 @@ fn event_serialization() { }, "org.matrix.msc1767.audio_details": { "duration": 23, + "org.matrix.msc3246.waveform": [255, 0], }, - "m.voice": {}, "m.relates_to": { "m.in_reply_to": { "event_id": "$replyevent:example.com" @@ -73,14 +80,14 @@ fn message_event_deserialization() { }, "org.matrix.msc1767.audio_details": { "duration": 53, + "org.matrix.msc3246.waveform": [255, 0], }, - "m.voice": {}, }, "event_id": "$event:notareal.hs", "origin_server_ts": 134_829_848, "room_id": "!roomid:notareal.hs", "sender": "@user:notareal.hs", - "type": "m.voice", + "type": "org.matrix.msc3245.voice.v2", }); let ev = assert_matches!( @@ -100,7 +107,6 @@ fn message_event_deserialization() { assert_eq!(content.file.name, "voice_message.ogg"); assert_eq!(content.file.mimetype.as_deref(), Some("audio/opus")); assert_eq!(content.file.size, Some(uint!(123_774))); - let audio_details = content.audio_details.unwrap(); - assert_eq!(audio_details.duration, Duration::from_secs(53)); - assert!(audio_details.waveform.is_empty()); + assert_eq!(content.audio_details.duration, Duration::from_secs(53)); + assert_eq!(content.audio_details.waveform.len(), 2); }