common: Add support for voice message events
This commit is contained in:
parent
d1e70c3d9f
commit
9b870cd9af
@ -33,6 +33,7 @@ unstable-msc2448 = []
|
|||||||
unstable-msc2675 = []
|
unstable-msc2675 = []
|
||||||
unstable-msc2676 = []
|
unstable-msc2676 = []
|
||||||
unstable-msc2677 = []
|
unstable-msc2677 = []
|
||||||
|
unstable-msc3245 = ["unstable-msc3246"]
|
||||||
unstable-msc3246 = ["unstable-msc3551", "thiserror"]
|
unstable-msc3246 = ["unstable-msc3551", "thiserror"]
|
||||||
unstable-msc3440 = []
|
unstable-msc3440 = []
|
||||||
unstable-msc3488 = ["unstable-msc1767"]
|
unstable-msc3488 = ["unstable-msc1767"]
|
||||||
|
@ -185,6 +185,8 @@ pub mod tag;
|
|||||||
pub mod typing;
|
pub mod typing;
|
||||||
#[cfg(feature = "unstable-msc3553")]
|
#[cfg(feature = "unstable-msc3553")]
|
||||||
pub mod video;
|
pub mod video;
|
||||||
|
#[cfg(feature = "unstable-msc3245")]
|
||||||
|
pub mod voice;
|
||||||
|
|
||||||
#[cfg(feature = "unstable-msc2675")]
|
#[cfg(feature = "unstable-msc2675")]
|
||||||
pub use self::relation::Relations;
|
pub use self::relation::Relations;
|
||||||
|
@ -67,6 +67,8 @@ event_enum! {
|
|||||||
"m.sticker",
|
"m.sticker",
|
||||||
#[cfg(feature = "unstable-msc3553")]
|
#[cfg(feature = "unstable-msc3553")]
|
||||||
"m.video",
|
"m.video",
|
||||||
|
#[cfg(feature = "unstable-msc3245")]
|
||||||
|
"m.voice",
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Any state event.
|
/// Any state event.
|
||||||
@ -374,6 +376,8 @@ impl AnyMessageLikeEventContent {
|
|||||||
Self::Notice(ev) => ev.relates_to.clone().map(Into::into),
|
Self::Notice(ev) => ev.relates_to.clone().map(Into::into),
|
||||||
#[cfg(feature = "unstable-msc1767")]
|
#[cfg(feature = "unstable-msc1767")]
|
||||||
Self::Emote(ev) => ev.relates_to.clone().map(Into::into),
|
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")]
|
#[cfg(feature = "unstable-msc3246")]
|
||||||
Self::Audio(ev) => ev.relates_to.clone().map(Into::into),
|
Self::Audio(ev) => ev.relates_to.clone().map(Into::into),
|
||||||
#[cfg(feature = "unstable-msc3488")]
|
#[cfg(feature = "unstable-msc3488")]
|
||||||
|
72
crates/ruma-common/src/events/voice.rs
Normal file
72
crates/ruma-common/src/events/voice.rs
Normal 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()
|
||||||
|
}
|
||||||
|
}
|
@ -22,3 +22,4 @@ mod state_event;
|
|||||||
mod stripped;
|
mod stripped;
|
||||||
mod to_device;
|
mod to_device;
|
||||||
mod video;
|
mod video;
|
||||||
|
mod voice;
|
||||||
|
143
crates/ruma-common/tests/events/voice.rs
Normal file
143
crates/ruma-common/tests/events/voice.rs
Normal 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()
|
||||||
|
);
|
||||||
|
}
|
@ -117,6 +117,7 @@ unstable-msc2448 = [
|
|||||||
unstable-msc2675 = ["ruma-common/unstable-msc2675"]
|
unstable-msc2675 = ["ruma-common/unstable-msc2675"]
|
||||||
unstable-msc2676 = ["ruma-common/unstable-msc2676"]
|
unstable-msc2676 = ["ruma-common/unstable-msc2676"]
|
||||||
unstable-msc2677 = ["ruma-common/unstable-msc2677"]
|
unstable-msc2677 = ["ruma-common/unstable-msc2677"]
|
||||||
|
unstable-msc3245 = ["ruma-common/unstable-msc3245"]
|
||||||
unstable-msc3246 = ["ruma-common/unstable-msc3246"]
|
unstable-msc3246 = ["ruma-common/unstable-msc3246"]
|
||||||
unstable-msc3440 = [
|
unstable-msc3440 = [
|
||||||
"ruma-client-api/unstable-msc3440",
|
"ruma-client-api/unstable-msc3440",
|
||||||
@ -142,6 +143,7 @@ __ci = [
|
|||||||
"unstable-msc2675",
|
"unstable-msc2675",
|
||||||
"unstable-msc2676",
|
"unstable-msc2676",
|
||||||
"unstable-msc2677",
|
"unstable-msc2677",
|
||||||
|
"unstable-msc3245",
|
||||||
"unstable-msc3246",
|
"unstable-msc3246",
|
||||||
"unstable-msc3440",
|
"unstable-msc3440",
|
||||||
"unstable-msc3488",
|
"unstable-msc3488",
|
||||||
|
Loading…
x
Reference in New Issue
Block a user