common: Add support for voice message events

This commit is contained in:
Kévin Commaille 2022-03-18 12:13:26 +01:00 committed by GitHub
parent d1e70c3d9f
commit 9b870cd9af
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 225 additions and 0 deletions

View File

@ -33,6 +33,7 @@ unstable-msc2448 = []
unstable-msc2675 = []
unstable-msc2676 = []
unstable-msc2677 = []
unstable-msc3245 = ["unstable-msc3246"]
unstable-msc3246 = ["unstable-msc3551", "thiserror"]
unstable-msc3440 = []
unstable-msc3488 = ["unstable-msc1767"]

View File

@ -185,6 +185,8 @@ pub mod tag;
pub mod typing;
#[cfg(feature = "unstable-msc3553")]
pub mod video;
#[cfg(feature = "unstable-msc3245")]
pub mod voice;
#[cfg(feature = "unstable-msc2675")]
pub use self::relation::Relations;

View File

@ -67,6 +67,8 @@ event_enum! {
"m.sticker",
#[cfg(feature = "unstable-msc3553")]
"m.video",
#[cfg(feature = "unstable-msc3245")]
"m.voice",
}
/// Any state event.
@ -374,6 +376,8 @@ impl AnyMessageLikeEventContent {
Self::Notice(ev) => ev.relates_to.clone().map(Into::into),
#[cfg(feature = "unstable-msc1767")]
Self::Emote(ev) => ev.relates_to.clone().map(Into::into),
#[cfg(feature = "unstable-msc3245")]
Self::Voice(ev) => ev.relates_to.clone().map(Into::into),
#[cfg(feature = "unstable-msc3246")]
Self::Audio(ev) => ev.relates_to.clone().map(Into::into),
#[cfg(feature = "unstable-msc3488")]

View File

@ -0,0 +1,72 @@
//! Types for voice message events ([MSC3245]).
//!
//! [MSC3245]: https://github.com/matrix-org/matrix-spec-proposals/pull/3245
use ruma_macros::EventContent;
use serde::{Deserialize, Serialize};
use super::{
audio::AudioContent, file::FileContent, message::MessageContent, room::message::Relation,
};
/// The payload for an extensible audio message.
#[derive(Clone, Debug, Serialize, Deserialize, EventContent)]
#[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)]
#[ruma_event(type = "m.voice", kind = MessageLike)]
pub struct VoiceEventContent {
/// The text representation of the message.
#[serde(flatten)]
pub message: MessageContent,
/// The file content of the message.
#[serde(rename = "org.matrix.msc1767.file")]
pub file: FileContent,
/// The audio content of the message.
#[serde(rename = "org.matrix.msc1767.audio")]
pub audio: AudioContent,
/// The audio content of the message.
#[serde(rename = "org.matrix.msc3245.voice")]
pub voice: VoiceContent,
/// Information about related messages.
#[serde(flatten, skip_serializing_if = "Option::is_none")]
pub relates_to: Option<Relation>,
}
impl VoiceEventContent {
/// Creates a new `VoiceEventContent` with the given plain text representation and file.
pub fn plain(message: impl Into<String>, file: FileContent) -> Self {
Self {
message: MessageContent::plain(message),
file,
audio: Default::default(),
voice: Default::default(),
relates_to: None,
}
}
/// Creates a new `VoiceEventContent` with the given message and file.
pub fn with_message(message: MessageContent, file: FileContent) -> Self {
Self {
message,
file,
audio: Default::default(),
voice: Default::default(),
relates_to: None,
}
}
}
/// Voice content.
#[derive(Clone, Debug, Default, Serialize, Deserialize)]
#[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)]
pub struct VoiceContent {}
impl VoiceContent {
/// Creates a new empty `VoiceContent`.
pub fn new() -> Self {
Self::default()
}
}

View File

@ -22,3 +22,4 @@ mod state_event;
mod stripped;
mod to_device;
mod video;
mod voice;

View File

@ -0,0 +1,143 @@
#![cfg(feature = "unstable-msc3245")]
use std::time::Duration;
use assign::assign;
use js_int::uint;
use matches::assert_matches;
use ruma_common::{
event_id,
events::{
audio::AudioContent,
file::{FileContent, FileContentInfo},
room::message::{InReplyTo, Relation},
voice::VoiceEventContent,
AnyMessageLikeEvent, MessageLikeEvent, Unsigned,
},
mxc_uri, room_id, user_id, MilliSecondsSinceUnixEpoch,
};
use serde_json::{from_value as from_json_value, json, to_value as to_json_value};
#[test]
fn event_serialization() {
let event = MessageLikeEvent {
content: assign!(
VoiceEventContent::plain(
"Voice message",
FileContent::plain(
mxc_uri!("mxc://notareal.hs/abcdef").to_owned(),
Some(Box::new(assign!(
FileContentInfo::new(),
{
name: Some("voice_message.ogg".to_owned()),
mimetype: Some("audio/opus".to_owned()),
size: Some(uint!(897_774)),
}
))),
)
),
{
audio: assign!(
AudioContent::new(),
{
duration: Some(Duration::from_secs(23))
}
),
relates_to: Some(Relation::Reply {
in_reply_to: InReplyTo::new(event_id!("$replyevent:example.com").to_owned()),
}),
}
),
event_id: event_id!("$event:notareal.hs").to_owned(),
sender: user_id!("@user:notareal.hs").to_owned(),
origin_server_ts: MilliSecondsSinceUnixEpoch(uint!(134_829_848)),
room_id: room_id!("!roomid:notareal.hs").to_owned(),
unsigned: Unsigned::default(),
};
assert_eq!(
to_json_value(&event).unwrap(),
json!({
"content": {
"org.matrix.msc1767.text": "Voice message",
"org.matrix.msc1767.file": {
"url": "mxc://notareal.hs/abcdef",
"name": "voice_message.ogg",
"mimetype": "audio/opus",
"size": 897_774,
},
"org.matrix.msc1767.audio": {
"duration": 23_000,
},
"org.matrix.msc3245.voice": {},
"m.relates_to": {
"m.in_reply_to": {
"event_id": "$replyevent:example.com"
}
}
},
"event_id": "$event:notareal.hs",
"origin_server_ts": 134_829_848,
"room_id": "!roomid:notareal.hs",
"sender": "@user:notareal.hs",
"type": "m.voice",
})
);
}
#[test]
fn message_event_deserialization() {
let json_data = json!({
"content": {
"org.matrix.msc1767.text": "Voice message",
"org.matrix.msc1767.file": {
"url": "mxc://notareal.hs/abcdef",
"name": "voice_message.ogg",
"mimetype": "audio/opus",
"size": 123_774,
},
"org.matrix.msc1767.audio": {
"duration": 5_300,
},
"org.matrix.msc3245.voice": {},
},
"event_id": "$event:notareal.hs",
"origin_server_ts": 134_829_848,
"room_id": "!roomid:notareal.hs",
"sender": "@user:notareal.hs",
"type": "m.voice",
});
assert_matches!(
from_json_value::<AnyMessageLikeEvent>(json_data).unwrap(),
AnyMessageLikeEvent::Voice(MessageLikeEvent {
content: VoiceEventContent {
message,
file: FileContent {
url,
info: Some(info),
..
},
audio,
..
},
event_id,
origin_server_ts,
room_id,
sender,
unsigned
}) if event_id == event_id!("$event:notareal.hs")
&& message.find_plain() == Some("Voice message")
&& message.find_html().is_none()
&& url == "mxc://notareal.hs/abcdef"
&& info.name.as_deref() == Some("voice_message.ogg")
&& info.mimetype.as_deref() == Some("audio/opus")
&& info.size == Some(uint!(123_774))
&& audio.duration == Some(Duration::from_millis(5_300))
&& audio.waveform.is_none()
&& origin_server_ts == MilliSecondsSinceUnixEpoch(uint!(134_829_848))
&& room_id == room_id!("!roomid:notareal.hs")
&& sender == user_id!("@user:notareal.hs")
&& unsigned.is_empty()
);
}

View File

@ -117,6 +117,7 @@ unstable-msc2448 = [
unstable-msc2675 = ["ruma-common/unstable-msc2675"]
unstable-msc2676 = ["ruma-common/unstable-msc2676"]
unstable-msc2677 = ["ruma-common/unstable-msc2677"]
unstable-msc3245 = ["ruma-common/unstable-msc3245"]
unstable-msc3246 = ["ruma-common/unstable-msc3246"]
unstable-msc3440 = [
"ruma-client-api/unstable-msc3440",
@ -142,6 +143,7 @@ __ci = [
"unstable-msc2675",
"unstable-msc2676",
"unstable-msc2677",
"unstable-msc3245",
"unstable-msc3246",
"unstable-msc3440",
"unstable-msc3488",