events: Update types according to MSC3927 and changes in MSC3246
This commit is contained in:
parent
60f754322e
commit
41be6ac18b
@ -35,13 +35,14 @@ unstable-msc2677 = []
|
||||
unstable-msc2746 = []
|
||||
unstable-msc2870 = []
|
||||
unstable-msc3245 = ["unstable-msc3246"]
|
||||
unstable-msc3246 = ["unstable-msc3551"]
|
||||
unstable-msc3246 = ["unstable-msc3927"]
|
||||
unstable-msc3381 = ["unstable-msc1767"]
|
||||
unstable-msc3488 = ["unstable-msc1767"]
|
||||
unstable-msc3551 = ["unstable-msc3956"]
|
||||
unstable-msc3552 = ["unstable-msc3551"]
|
||||
unstable-msc3553 = ["unstable-msc3552"]
|
||||
unstable-msc3554 = ["unstable-msc1767"]
|
||||
unstable-msc3927 = ["unstable-msc3551"]
|
||||
unstable-msc3931 = []
|
||||
unstable-msc3932 = ["unstable-msc3931"]
|
||||
unstable-msc3954 = ["unstable-msc1767"]
|
||||
|
@ -120,7 +120,7 @@ pub mod macros {
|
||||
pub use ruma_macros::{Event, EventContent};
|
||||
}
|
||||
|
||||
#[cfg(feature = "unstable-msc3246")]
|
||||
#[cfg(feature = "unstable-msc3927")]
|
||||
pub mod audio;
|
||||
pub mod call;
|
||||
pub mod direct;
|
||||
|
@ -1,6 +1,6 @@
|
||||
//! Types for extensible audio message events ([MSC3246]).
|
||||
//! Types for extensible audio message events ([MSC3927]).
|
||||
//!
|
||||
//! [MSC3246]: https://github.com/matrix-org/matrix-spec-proposals/pull/3246
|
||||
//! [MSC3927]: https://github.com/matrix-org/matrix-spec-proposals/pull/3927
|
||||
|
||||
use std::time::Duration;
|
||||
|
||||
@ -8,23 +8,25 @@ use js_int::UInt;
|
||||
use ruma_macros::EventContent;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[cfg(feature = "unstable-msc3246")]
|
||||
mod amplitude_serde;
|
||||
mod waveform_serde;
|
||||
|
||||
use waveform_serde::WaveformSerDeHelper;
|
||||
|
||||
use super::{file::FileContentBlock, message::TextContentBlock, room::message::Relation};
|
||||
use super::{
|
||||
file::{CaptionContentBlock, FileContentBlock},
|
||||
message::TextContentBlock,
|
||||
room::message::Relation,
|
||||
};
|
||||
|
||||
/// The payload for an extensible audio message.
|
||||
///
|
||||
/// This is the new primary type introduced in [MSC3246] and should only be sent in rooms with a
|
||||
/// This is the new primary type introduced in [MSC3927] and should only be sent in rooms with a
|
||||
/// version that supports it. See the documentation of the [`message`] module for more information.
|
||||
///
|
||||
/// [MSC3246]: https://github.com/matrix-org/matrix-spec-proposals/pull/3246
|
||||
/// [MSC3927]: https://github.com/matrix-org/matrix-spec-proposals/pull/3927
|
||||
/// [`message`]: super::message
|
||||
#[derive(Clone, Debug, Serialize, Deserialize, EventContent)]
|
||||
#[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)]
|
||||
#[ruma_event(type = "m.audio", kind = MessageLike, without_relation)]
|
||||
#[ruma_event(type = "org.matrix.msc1767.audio", kind = MessageLike, without_relation)]
|
||||
pub struct AudioEventContent {
|
||||
/// The text representations of the message.
|
||||
#[serde(rename = "org.matrix.msc1767.text")]
|
||||
@ -34,9 +36,22 @@ pub struct AudioEventContent {
|
||||
#[serde(rename = "org.matrix.msc1767.file")]
|
||||
pub file: FileContentBlock,
|
||||
|
||||
/// The audio content of the message.
|
||||
#[serde(rename = "m.audio")]
|
||||
pub audio: AudioContent,
|
||||
/// The audio details of the message, if any.
|
||||
#[serde(rename = "org.matrix.msc1767.audio_details", skip_serializing_if = "Option::is_none")]
|
||||
pub audio_details: Option<AudioDetailsContentBlock>,
|
||||
|
||||
/// The caption of the message, if any.
|
||||
#[serde(rename = "org.matrix.msc1767.caption", skip_serializing_if = "Option::is_none")]
|
||||
pub caption: Option<CaptionContentBlock>,
|
||||
|
||||
/// 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(
|
||||
@ -50,118 +65,77 @@ pub struct AudioEventContent {
|
||||
impl AudioEventContent {
|
||||
/// Creates a new `AudioEventContent` with the given text fallback and file.
|
||||
pub fn new(text: TextContentBlock, file: FileContentBlock) -> Self {
|
||||
Self { text, file, audio: Default::default(), relates_to: None }
|
||||
Self {
|
||||
text,
|
||||
file,
|
||||
audio_details: None,
|
||||
caption: None,
|
||||
#[cfg(feature = "unstable-msc3955")]
|
||||
automated: false,
|
||||
relates_to: None,
|
||||
}
|
||||
}
|
||||
|
||||
/// Creates a new `AudioEventContent` with the given plain text fallback representation and
|
||||
/// file.
|
||||
pub fn plain(text_fallback: impl Into<String>, file: FileContentBlock) -> Self {
|
||||
pub fn with_plain_text(plain_text: impl Into<String>, file: FileContentBlock) -> Self {
|
||||
Self {
|
||||
text: TextContentBlock::plain(text_fallback),
|
||||
text: TextContentBlock::plain(plain_text),
|
||||
file,
|
||||
audio: Default::default(),
|
||||
audio_details: None,
|
||||
caption: None,
|
||||
#[cfg(feature = "unstable-msc3955")]
|
||||
automated: false,
|
||||
relates_to: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Audio content.
|
||||
#[derive(Clone, Debug, Default, Serialize, Deserialize)]
|
||||
/// A block for details of audio content.
|
||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||
#[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)]
|
||||
pub struct AudioContent {
|
||||
/// The duration of the video in milliseconds.
|
||||
pub struct AudioDetailsContentBlock {
|
||||
/// The duration of the audio in seconds.
|
||||
#[serde(with = "ruma_common::serde::duration::secs")]
|
||||
pub duration: Duration,
|
||||
|
||||
/// The waveform representation of the audio content, if any.
|
||||
///
|
||||
/// This is optional and defaults to an empty array.
|
||||
#[cfg(feature = "unstable-msc3246")]
|
||||
#[serde(
|
||||
with = "ruma_common::serde::duration::opt_ms",
|
||||
rename = "org.matrix.msc3246.waveform",
|
||||
default,
|
||||
skip_serializing_if = "Option::is_none"
|
||||
skip_serializing_if = "Vec::is_empty"
|
||||
)]
|
||||
pub duration: Option<Duration>,
|
||||
|
||||
/// The waveform representation of the audio content.
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
pub waveform: Option<Waveform>,
|
||||
pub waveform: Vec<Amplitude>,
|
||||
}
|
||||
|
||||
impl AudioContent {
|
||||
/// Creates a new empty `AudioContent`.
|
||||
pub fn new() -> Self {
|
||||
Self::default()
|
||||
}
|
||||
|
||||
/// Whether this `AudioContent` is empty.
|
||||
pub fn is_empty(&self) -> bool {
|
||||
self.duration.is_none() && self.waveform.is_none()
|
||||
}
|
||||
}
|
||||
|
||||
/// The waveform representation of audio content.
|
||||
///
|
||||
/// Must include between 30 and 120 `Amplitude`s.
|
||||
///
|
||||
/// To build this, use the `TryFrom` implementations.
|
||||
#[derive(Clone, Debug, Deserialize, Serialize)]
|
||||
#[serde(try_from = "WaveformSerDeHelper")]
|
||||
pub struct Waveform(Vec<Amplitude>);
|
||||
|
||||
impl Waveform {
|
||||
/// The smallest number of values contained in a `Waveform`.
|
||||
pub const MIN_LENGTH: usize = 30;
|
||||
|
||||
/// The largest number of values contained in a `Waveform`.
|
||||
pub const MAX_LENGTH: usize = 120;
|
||||
|
||||
/// The amplitudes of this `Waveform`.
|
||||
pub fn amplitudes(&self) -> &[Amplitude] {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
/// An error encountered when trying to convert to a `Waveform`.
|
||||
#[derive(Copy, Clone, Debug, Eq, Hash, PartialEq, thiserror::Error)]
|
||||
#[non_exhaustive]
|
||||
pub enum WaveformError {
|
||||
/// There are more than [`Waveform::MAX_LENGTH`] values.
|
||||
#[error("too many values")]
|
||||
TooManyValues,
|
||||
/// There are less that [`Waveform::MIN_LENGTH`] values.
|
||||
#[error("not enough values")]
|
||||
NotEnoughValues,
|
||||
}
|
||||
|
||||
impl TryFrom<Vec<Amplitude>> for Waveform {
|
||||
type Error = WaveformError;
|
||||
|
||||
fn try_from(value: Vec<Amplitude>) -> Result<Self, Self::Error> {
|
||||
if value.len() < Self::MIN_LENGTH {
|
||||
Err(WaveformError::NotEnoughValues)
|
||||
} else if value.len() > Self::MAX_LENGTH {
|
||||
Err(WaveformError::TooManyValues)
|
||||
} else {
|
||||
Ok(Self(value))
|
||||
impl AudioDetailsContentBlock {
|
||||
/// Creates a new `AudioDetailsContentBlock` with the given duration.
|
||||
pub fn new(duration: Duration) -> Self {
|
||||
Self {
|
||||
duration,
|
||||
#[cfg(feature = "unstable-msc3246")]
|
||||
waveform: Default::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<&[Amplitude]> for Waveform {
|
||||
type Error = WaveformError;
|
||||
|
||||
fn try_from(value: &[Amplitude]) -> Result<Self, Self::Error> {
|
||||
Self::try_from(value.to_owned())
|
||||
}
|
||||
}
|
||||
|
||||
/// The amplitude of a waveform sample.
|
||||
///
|
||||
/// Must be an integer between 0 and 1024.
|
||||
/// Must be an integer between 0 and 256.
|
||||
#[cfg(feature = "unstable-msc3246")]
|
||||
#[derive(Clone, Copy, Debug, Default, Hash, PartialEq, Eq, PartialOrd, Ord, Serialize)]
|
||||
pub struct Amplitude(UInt);
|
||||
|
||||
#[cfg(feature = "unstable-msc3246")]
|
||||
impl Amplitude {
|
||||
/// The smallest value that can be represented by this type, 0.
|
||||
pub const MIN: u16 = 0;
|
||||
|
||||
/// The largest value that can be represented by this type, 1024.
|
||||
pub const MAX: u16 = 1024;
|
||||
/// The largest value that can be represented by this type, 256.
|
||||
pub const MAX: u16 = 256;
|
||||
|
||||
/// Creates a new `Amplitude` with the given value.
|
||||
///
|
||||
@ -176,6 +150,7 @@ impl Amplitude {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "unstable-msc3246")]
|
||||
impl From<u16> for Amplitude {
|
||||
fn from(value: u16) -> Self {
|
||||
Self::new(value)
|
||||
|
@ -1,16 +0,0 @@
|
||||
//! `Serialize` and `Deserialize` implementations for extensible events (MSC1767).
|
||||
|
||||
use serde::Deserialize;
|
||||
|
||||
use super::{Amplitude, Waveform, WaveformError};
|
||||
|
||||
#[derive(Debug, Default, Deserialize)]
|
||||
pub(crate) struct WaveformSerDeHelper(Vec<Amplitude>);
|
||||
|
||||
impl TryFrom<WaveformSerDeHelper> for Waveform {
|
||||
type Error = WaveformError;
|
||||
|
||||
fn try_from(helper: WaveformSerDeHelper) -> Result<Self, Self::Error> {
|
||||
Waveform::try_from(helper.0)
|
||||
}
|
||||
}
|
@ -33,8 +33,9 @@ event_enum! {
|
||||
|
||||
/// Any message-like event.
|
||||
enum MessageLike {
|
||||
#[cfg(feature = "unstable-msc3246")]
|
||||
"m.audio" => super::audio,
|
||||
#[cfg(feature = "unstable-msc3927")]
|
||||
#[ruma_enum(alias = "m.audio")]
|
||||
"org.matrix.msc1767.audio" => super::audio,
|
||||
"m.call.answer" => super::call::answer,
|
||||
"m.call.invite" => super::call::invite,
|
||||
"m.call.hangup" => super::call::hangup,
|
||||
|
@ -6,7 +6,8 @@ use ruma_macros::EventContent;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use super::{
|
||||
audio::AudioContent, file::FileContentBlock, message::TextContentBlock, room::message::Relation,
|
||||
audio::AudioDetailsContentBlock, file::FileContentBlock, message::TextContentBlock,
|
||||
room::message::Relation,
|
||||
};
|
||||
|
||||
/// The payload for an extensible voice message.
|
||||
@ -30,8 +31,8 @@ pub struct VoiceEventContent {
|
||||
pub file: FileContentBlock,
|
||||
|
||||
/// The audio content of the message.
|
||||
#[serde(rename = "m.audio")]
|
||||
pub audio: AudioContent,
|
||||
#[serde(rename = "org.matrix.msc1767.audio_details", skip_serializing_if = "Option::is_none")]
|
||||
pub audio_details: Option<AudioDetailsContentBlock>,
|
||||
|
||||
/// The voice content of the message.
|
||||
#[serde(rename = "m.voice")]
|
||||
@ -49,7 +50,7 @@ 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: Default::default(), voice: Default::default(), relates_to: None }
|
||||
Self { text, file, audio_details: None, voice: Default::default(), relates_to: None }
|
||||
}
|
||||
|
||||
/// Creates a new `VoiceEventContent` with the given plain text fallback representation and
|
||||
@ -58,7 +59,7 @@ impl VoiceEventContent {
|
||||
Self {
|
||||
text: TextContentBlock::plain(text),
|
||||
file,
|
||||
audio: Default::default(),
|
||||
audio_details: None,
|
||||
voice: Default::default(),
|
||||
relates_to: None,
|
||||
}
|
||||
|
@ -1,14 +1,15 @@
|
||||
#![cfg(feature = "unstable-msc3246")]
|
||||
#![cfg(feature = "unstable-msc3927")]
|
||||
|
||||
use std::time::Duration;
|
||||
|
||||
use assert_matches::assert_matches;
|
||||
use assign::assign;
|
||||
use js_int::uint;
|
||||
#[cfg(feature = "unstable-msc3246")]
|
||||
use ruma_common::events::audio::Amplitude;
|
||||
use ruma_common::{
|
||||
event_id,
|
||||
events::{
|
||||
audio::{Amplitude, AudioContent, AudioEventContent, Waveform, WaveformError},
|
||||
audio::{AudioDetailsContentBlock, AudioEventContent},
|
||||
file::{EncryptedContentInit, FileContentBlock},
|
||||
message::TextContentBlock,
|
||||
relation::InReplyTo,
|
||||
@ -21,41 +22,18 @@ use ruma_common::{
|
||||
};
|
||||
use serde_json::{from_value as from_json_value, json, to_value as to_json_value};
|
||||
|
||||
#[cfg(feature = "unstable-msc3246")]
|
||||
#[test]
|
||||
fn waveform_deserialization_pass() {
|
||||
let json_data = json!([
|
||||
13, 34, 987, 937, 345, 648, 1, 366, 235, 125, 904, 783, 734, 13, 34, 987, 937, 345, 648, 1,
|
||||
366, 235, 125, 904, 783, 734, 13, 34, 987, 937, 345, 648, 1, 366, 235, 125, 904, 783, 734,
|
||||
13, 34, 987, 937, 345, 648, 1, 366, 235, 125, 904, 783, 734,
|
||||
]);
|
||||
fn amplitude_deserialization_clamp() {
|
||||
let json_data = json!(2000);
|
||||
|
||||
let waveform = from_json_value::<Waveform>(json_data).unwrap();
|
||||
assert_eq!(waveform.amplitudes().len(), 52);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn waveform_deserialization_not_enough() {
|
||||
let json_data = json!([]);
|
||||
|
||||
let err = from_json_value::<Waveform>(json_data).unwrap_err();
|
||||
assert!(err.is_data());
|
||||
assert_eq!(err.to_string(), WaveformError::NotEnoughValues.to_string());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn waveform_deserialization_clamp_amplitude() {
|
||||
let json_data = json!([
|
||||
2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000,
|
||||
2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000,
|
||||
]);
|
||||
|
||||
let waveform = from_json_value::<Waveform>(json_data).unwrap();
|
||||
assert!(waveform.amplitudes().iter().all(|amp| amp.get() == Amplitude::MAX.into()));
|
||||
let amplitude = from_json_value::<Amplitude>(json_data).unwrap();
|
||||
assert_eq!(amplitude.get(), Amplitude::MAX.into());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn plain_content_serialization() {
|
||||
let event_content = AudioEventContent::plain(
|
||||
let event_content = AudioEventContent::with_plain_text(
|
||||
"Upload: my_sound.ogg",
|
||||
FileContentBlock::plain(
|
||||
mxc_uri!("mxc://notareal.hs/abcdef").to_owned(),
|
||||
@ -73,14 +51,13 @@ fn plain_content_serialization() {
|
||||
"url": "mxc://notareal.hs/abcdef",
|
||||
"name": "my_sound.ogg",
|
||||
},
|
||||
"m.audio": {}
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn encrypted_content_serialization() {
|
||||
let event_content = AudioEventContent::plain(
|
||||
let event_content = AudioEventContent::with_plain_text(
|
||||
"Upload: my_sound.ogg",
|
||||
FileContentBlock::encrypted(
|
||||
mxc_uri!("mxc://notareal.hs/abcdef").to_owned(),
|
||||
@ -128,42 +105,25 @@ fn encrypted_content_serialization() {
|
||||
},
|
||||
"v": "v2",
|
||||
},
|
||||
"m.audio": {}
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn event_serialization() {
|
||||
let content = assign!(
|
||||
AudioEventContent::new(
|
||||
TextContentBlock::html(
|
||||
"Upload: my_mix.mp3",
|
||||
"Upload: <strong>my_mix.mp3</strong>",
|
||||
),
|
||||
assign!(
|
||||
FileContentBlock::plain(
|
||||
mxc_uri!("mxc://notareal.hs/abcdef").to_owned(),
|
||||
"my_mix.mp3".to_owned()
|
||||
),
|
||||
{
|
||||
mimetype: Some("audio/mp3".to_owned()),
|
||||
size: Some(uint!(897_774)),
|
||||
}
|
||||
)
|
||||
let mut content = AudioEventContent::new(
|
||||
TextContentBlock::html("Upload: my_mix.mp3", "Upload: <strong>my_mix.mp3</strong>"),
|
||||
FileContentBlock::plain(
|
||||
mxc_uri!("mxc://notareal.hs/abcdef").to_owned(),
|
||||
"my_mix.mp3".to_owned(),
|
||||
),
|
||||
{
|
||||
audio: assign!(
|
||||
AudioContent::new(),
|
||||
{
|
||||
duration: Some(Duration::from_secs(123))
|
||||
}
|
||||
),
|
||||
relates_to: Some(Relation::Reply {
|
||||
in_reply_to: InReplyTo::new(event_id!("$replyevent:example.com").to_owned()),
|
||||
}),
|
||||
}
|
||||
);
|
||||
content.file.mimetype = Some("audio/mp3".to_owned());
|
||||
content.file.size = Some(uint!(897_774));
|
||||
content.audio_details = Some(AudioDetailsContentBlock::new(Duration::from_secs(123)));
|
||||
content.relates_to = Some(Relation::Reply {
|
||||
in_reply_to: InReplyTo::new(event_id!("$replyevent:example.com").to_owned()),
|
||||
});
|
||||
|
||||
assert_eq!(
|
||||
to_json_value(&content).unwrap(),
|
||||
@ -178,8 +138,8 @@ fn event_serialization() {
|
||||
"mimetype": "audio/mp3",
|
||||
"size": 897_774,
|
||||
},
|
||||
"m.audio": {
|
||||
"duration": 123_000,
|
||||
"org.matrix.msc1767.audio_details": {
|
||||
"duration": 123,
|
||||
},
|
||||
"m.relates_to": {
|
||||
"m.in_reply_to": {
|
||||
@ -190,6 +150,7 @@ fn event_serialization() {
|
||||
);
|
||||
}
|
||||
|
||||
#[cfg(feature = "unstable-msc3246")]
|
||||
#[test]
|
||||
fn plain_content_deserialization() {
|
||||
let json_data = json!({
|
||||
@ -200,62 +161,63 @@ fn plain_content_deserialization() {
|
||||
"url": "mxc://notareal.hs/abcdef",
|
||||
"name": "my_new_song.webm",
|
||||
},
|
||||
"m.audio": {
|
||||
"waveform": [
|
||||
"org.matrix.msc1767.audio_details": {
|
||||
"duration": 14,
|
||||
"org.matrix.msc3246.waveform": [
|
||||
13,
|
||||
34,
|
||||
987,
|
||||
937,
|
||||
345,
|
||||
648,
|
||||
253,
|
||||
234,
|
||||
157,
|
||||
255,
|
||||
1,
|
||||
366,
|
||||
235,
|
||||
201,
|
||||
135,
|
||||
125,
|
||||
904,
|
||||
783,
|
||||
734,
|
||||
250,
|
||||
233,
|
||||
231,
|
||||
13,
|
||||
34,
|
||||
987,
|
||||
937,
|
||||
345,
|
||||
648,
|
||||
1,
|
||||
366,
|
||||
252,
|
||||
255,
|
||||
140,
|
||||
187,
|
||||
0,
|
||||
143,
|
||||
235,
|
||||
125,
|
||||
904,
|
||||
783,
|
||||
734,
|
||||
247,
|
||||
183,
|
||||
134,
|
||||
13,
|
||||
34,
|
||||
987,
|
||||
937,
|
||||
345,
|
||||
648,
|
||||
187,
|
||||
237,
|
||||
145,
|
||||
48,
|
||||
1,
|
||||
366,
|
||||
66,
|
||||
235,
|
||||
125,
|
||||
904,
|
||||
783,
|
||||
734,
|
||||
204,
|
||||
183,
|
||||
34,
|
||||
13,
|
||||
34,
|
||||
987,
|
||||
937,
|
||||
345,
|
||||
648,
|
||||
187,
|
||||
237,
|
||||
45,
|
||||
48,
|
||||
1,
|
||||
366,
|
||||
166,
|
||||
235,
|
||||
125,
|
||||
904,
|
||||
783,
|
||||
734,
|
||||
104,
|
||||
183,
|
||||
234,
|
||||
],
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
let content = from_json_value::<AudioEventContent>(json_data).unwrap();
|
||||
@ -263,8 +225,9 @@ fn plain_content_deserialization() {
|
||||
assert_eq!(content.text.find_html(), None);
|
||||
assert_eq!(content.file.url, "mxc://notareal.hs/abcdef");
|
||||
assert_eq!(content.file.name, "my_new_song.webm");
|
||||
let waveform = content.audio.waveform.unwrap();
|
||||
assert_eq!(waveform.amplitudes().len(), 52);
|
||||
let audio_details = content.audio_details.unwrap();
|
||||
assert_eq!(audio_details.duration, Duration::from_secs(14));
|
||||
assert_eq!(audio_details.waveform.len(), 52);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@ -287,9 +250,8 @@ fn encrypted_content_deserialization() {
|
||||
"hashes": {
|
||||
"sha256": "aWOHudBnDkJ9IwaR1Nd8XKoI7DOrqDTwt6xDPfVGN6Q"
|
||||
},
|
||||
"v": "v2"
|
||||
"v": "v2",
|
||||
},
|
||||
"m.audio": {},
|
||||
});
|
||||
|
||||
let content = from_json_value::<AudioEventContent>(json_data).unwrap();
|
||||
@ -298,6 +260,7 @@ fn encrypted_content_deserialization() {
|
||||
assert_eq!(content.file.url, "mxc://notareal.hs/abcdef");
|
||||
assert_eq!(content.file.name, "my_file.txt");
|
||||
assert!(content.file.encryption_info.is_some());
|
||||
assert!(content.audio_details.is_none());
|
||||
}
|
||||
|
||||
#[test]
|
||||
@ -313,15 +276,15 @@ fn message_event_deserialization() {
|
||||
"mimetype": "audio/opus",
|
||||
"size": 123_774,
|
||||
},
|
||||
"m.audio": {
|
||||
"duration": 5_300,
|
||||
}
|
||||
"org.matrix.msc1767.audio_details": {
|
||||
"duration": 53,
|
||||
},
|
||||
},
|
||||
"event_id": "$event:notareal.hs",
|
||||
"origin_server_ts": 134_829_848,
|
||||
"room_id": "!roomid:notareal.hs",
|
||||
"sender": "@user:notareal.hs",
|
||||
"type": "m.audio",
|
||||
"type": "org.matrix.msc1767.audio",
|
||||
});
|
||||
|
||||
let message_event = assert_matches!(
|
||||
@ -342,6 +305,8 @@ fn message_event_deserialization() {
|
||||
assert_eq!(content.file.name, "airplane_sound.opus");
|
||||
assert_eq!(content.file.mimetype.as_deref(), Some("audio/opus"));
|
||||
assert_eq!(content.file.size, Some(uint!(123_774)));
|
||||
assert_eq!(content.audio.duration, Some(Duration::from_millis(5_300)));
|
||||
assert_matches!(content.audio.waveform, None);
|
||||
let audio_details = content.audio_details.unwrap();
|
||||
assert_eq!(audio_details.duration, Duration::from_secs(53));
|
||||
#[cfg(feature = "unstable-msc3246")]
|
||||
assert!(audio_details.waveform.is_empty());
|
||||
}
|
||||
|
@ -3,13 +3,12 @@
|
||||
use std::time::Duration;
|
||||
|
||||
use assert_matches::assert_matches;
|
||||
use assign::assign;
|
||||
use js_int::uint;
|
||||
use ruma_common::{
|
||||
event_id,
|
||||
events::{
|
||||
audio::AudioContent, file::FileContentBlock, relation::InReplyTo, room::message::Relation,
|
||||
voice::VoiceEventContent, AnyMessageLikeEvent, MessageLikeEvent,
|
||||
audio::AudioDetailsContentBlock, file::FileContentBlock, relation::InReplyTo,
|
||||
room::message::Relation, voice::VoiceEventContent, AnyMessageLikeEvent, MessageLikeEvent,
|
||||
},
|
||||
mxc_uri,
|
||||
serde::CanBeEmpty,
|
||||
@ -29,12 +28,7 @@ fn event_serialization() {
|
||||
|
||||
content.file.mimetype = Some("audio/opus".to_owned());
|
||||
content.file.size = Some(uint!(897_774));
|
||||
content.audio = assign!(
|
||||
AudioContent::new(),
|
||||
{
|
||||
duration: Some(Duration::from_secs(23))
|
||||
}
|
||||
);
|
||||
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()),
|
||||
});
|
||||
@ -51,8 +45,8 @@ fn event_serialization() {
|
||||
"mimetype": "audio/opus",
|
||||
"size": 897_774,
|
||||
},
|
||||
"m.audio": {
|
||||
"duration": 23_000,
|
||||
"org.matrix.msc1767.audio_details": {
|
||||
"duration": 23,
|
||||
},
|
||||
"m.voice": {},
|
||||
"m.relates_to": {
|
||||
@ -77,8 +71,8 @@ fn message_event_deserialization() {
|
||||
"mimetype": "audio/opus",
|
||||
"size": 123_774,
|
||||
},
|
||||
"m.audio": {
|
||||
"duration": 5_300,
|
||||
"org.matrix.msc1767.audio_details": {
|
||||
"duration": 53,
|
||||
},
|
||||
"m.voice": {},
|
||||
},
|
||||
@ -106,6 +100,7 @@ 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)));
|
||||
assert_eq!(content.audio.duration, Some(Duration::from_millis(5_300)));
|
||||
assert_matches!(content.audio.waveform, None);
|
||||
let audio_details = content.audio_details.unwrap();
|
||||
assert_eq!(audio_details.duration, Duration::from_secs(53));
|
||||
assert!(audio_details.waveform.is_empty());
|
||||
}
|
||||
|
@ -153,6 +153,7 @@ unstable-msc3554 = ["ruma-common/unstable-msc3554"]
|
||||
unstable-msc3575 = ["ruma-client-api?/unstable-msc3575"]
|
||||
unstable-msc3618 = ["ruma-federation-api?/unstable-msc3618"]
|
||||
unstable-msc3723 = ["ruma-federation-api?/unstable-msc3723"]
|
||||
unstable-msc3927 = ["ruma-common/unstable-msc3927"]
|
||||
unstable-msc3931 = ["ruma-common/unstable-msc3931"]
|
||||
unstable-msc3932 = ["ruma-common/unstable-msc3932"]
|
||||
unstable-msc3954 = ["ruma-common/unstable-msc3954"]
|
||||
@ -194,6 +195,7 @@ __ci = [
|
||||
"unstable-msc3575",
|
||||
"unstable-msc3618",
|
||||
"unstable-msc3723",
|
||||
"unstable-msc3927",
|
||||
"unstable-msc3932",
|
||||
"unstable-msc3954",
|
||||
"unstable-msc3955",
|
||||
|
Loading…
x
Reference in New Issue
Block a user