events: Add public API for custom / unsupported message types
This commit is contained in:
parent
e2728a7081
commit
2803ee3721
@ -1,6 +1,6 @@
|
||||
//! Types for the *m.room.message* event.
|
||||
|
||||
use std::collections::BTreeMap;
|
||||
use std::borrow::Cow;
|
||||
|
||||
use js_int::UInt;
|
||||
use ruma_events_macros::MessageEventContent;
|
||||
@ -8,7 +8,7 @@ use ruma_identifiers::MxcUri;
|
||||
#[cfg(feature = "unstable-pre-spec")]
|
||||
use ruma_identifiers::{DeviceIdBox, UserId};
|
||||
use ruma_serde::StringEnum;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use serde::{de::DeserializeOwned, Deserialize, Serialize};
|
||||
use serde_json::Value as JsonValue;
|
||||
|
||||
#[cfg(feature = "unstable-pre-spec")]
|
||||
@ -23,12 +23,12 @@ pub use super::relationships::InReplyTo;
|
||||
mod content_serde;
|
||||
pub mod feedback;
|
||||
|
||||
use crate::MessageEvent as OuterMessageEvent;
|
||||
type JsonObject = serde_json::Map<String, JsonValue>;
|
||||
|
||||
/// This event is used when sending messages in a room.
|
||||
///
|
||||
/// Messages are not limited to be text.
|
||||
pub type MessageEvent = OuterMessageEvent<MessageEventContent>;
|
||||
pub type MessageEvent = crate::MessageEvent<MessageEventContent>;
|
||||
|
||||
/// The payload for `MessageEvent`.
|
||||
#[derive(Clone, Debug, Serialize, MessageEventContent)]
|
||||
@ -127,6 +127,80 @@ pub enum MessageType {
|
||||
_Custom(CustomEventContent),
|
||||
}
|
||||
|
||||
impl MessageType {
|
||||
/// Creates a `MessageType` with the given `msgtype` string and data.
|
||||
///
|
||||
/// Prefer to use the public variants of `MessageType` where possible; this constructor is meant
|
||||
/// be used for unsupported message types only and does not allow setting arbitrary data for
|
||||
/// supported ones.
|
||||
pub fn new(msgtype: &str, data: JsonObject) -> serde_json::Result<Self> {
|
||||
fn from_json_object<T: DeserializeOwned>(obj: JsonObject) -> serde_json::Result<T> {
|
||||
serde_json::from_value(JsonValue::Object(obj))
|
||||
}
|
||||
|
||||
Ok(match msgtype {
|
||||
"m.audio" => Self::Audio(from_json_object(data)?),
|
||||
"m.emote" => Self::Emote(from_json_object(data)?),
|
||||
"m.file" => Self::File(from_json_object(data)?),
|
||||
"m.image" => Self::Image(from_json_object(data)?),
|
||||
"m.location" => Self::Location(from_json_object(data)?),
|
||||
"m.notice" => Self::Notice(from_json_object(data)?),
|
||||
"m.server_notice" => Self::ServerNotice(from_json_object(data)?),
|
||||
"m.text" => Self::Text(from_json_object(data)?),
|
||||
"m.video" => Self::Video(from_json_object(data)?),
|
||||
#[cfg(feature = "unstable-pre-spec")]
|
||||
"m.key.verification.request" => Self::VerificationRequest(from_json_object(data)?),
|
||||
_ => Self::_Custom(CustomEventContent { msgtype: msgtype.to_owned(), data }),
|
||||
})
|
||||
}
|
||||
|
||||
/// Returns a reference to the `msgtype` string.
|
||||
pub fn msgtype(&self) -> &str {
|
||||
match self {
|
||||
Self::Audio(_) => "m.audio",
|
||||
Self::Emote(_) => "m.emote",
|
||||
Self::File(_) => "m.file",
|
||||
Self::Image(_) => "m.image",
|
||||
Self::Location(_) => "m.location",
|
||||
Self::Notice(_) => "m.notice",
|
||||
Self::ServerNotice(_) => "m.server_notice",
|
||||
Self::Text(_) => "m.text",
|
||||
Self::Video(_) => "m.video",
|
||||
#[cfg(feature = "unstable-pre-spec")]
|
||||
Self::VerificationRequest(_) => "m.key.verification.request",
|
||||
Self::_Custom(c) => &c.msgtype,
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the associated data.
|
||||
///
|
||||
/// Prefer to use the public variants of `MessageType` where possible; this method is meant to
|
||||
/// be used for unsupported message types only.
|
||||
pub fn data(&self) -> Cow<'_, JsonObject> {
|
||||
fn serialize<T: Serialize>(obj: &T) -> JsonObject {
|
||||
match serde_json::to_value(obj).expect("message type serialization to succeed") {
|
||||
JsonValue::Object(obj) => obj,
|
||||
_ => panic!("all message types must serialize to objects"),
|
||||
}
|
||||
}
|
||||
|
||||
match self {
|
||||
Self::Audio(d) => Cow::Owned(serialize(d)),
|
||||
Self::Emote(d) => Cow::Owned(serialize(d)),
|
||||
Self::File(d) => Cow::Owned(serialize(d)),
|
||||
Self::Image(d) => Cow::Owned(serialize(d)),
|
||||
Self::Location(d) => Cow::Owned(serialize(d)),
|
||||
Self::Notice(d) => Cow::Owned(serialize(d)),
|
||||
Self::ServerNotice(d) => Cow::Owned(serialize(d)),
|
||||
Self::Text(d) => Cow::Owned(serialize(d)),
|
||||
Self::Video(d) => Cow::Owned(serialize(d)),
|
||||
#[cfg(feature = "unstable-pre-spec")]
|
||||
Self::VerificationRequest(d) => Cow::Owned(serialize(d)),
|
||||
Self::_Custom(c) => Cow::Borrowed(&c.data),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<MessageType> for MessageEventContent {
|
||||
fn from(msgtype: MessageType) -> Self {
|
||||
Self::new(msgtype)
|
||||
@ -606,5 +680,5 @@ pub struct CustomEventContent {
|
||||
|
||||
/// Remaining event content
|
||||
#[serde(flatten)]
|
||||
pub data: BTreeMap<String, JsonValue>,
|
||||
pub data: JsonObject,
|
||||
}
|
||||
|
@ -1,7 +1,6 @@
|
||||
use std::time::{Duration, UNIX_EPOCH};
|
||||
|
||||
use assign::assign;
|
||||
use maplit::btreemap;
|
||||
use matches::assert_matches;
|
||||
#[cfg(feature = "unstable-pre-spec")]
|
||||
use ruma_events::{
|
||||
@ -23,6 +22,18 @@ use ruma_identifiers::{event_id, mxc_uri, room_id, user_id};
|
||||
use ruma_serde::Raw;
|
||||
use serde_json::{from_value as from_json_value, json, to_value as to_json_value};
|
||||
|
||||
macro_rules! json_object {
|
||||
( $($key:expr => $value:expr),* $(,)? ) => {
|
||||
{
|
||||
let mut _map = serde_json::Map::<String, serde_json::Value>::new();
|
||||
$(
|
||||
let _ = _map.insert($key, $value);
|
||||
)*
|
||||
_map
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn serialization() {
|
||||
let ev = MessageEvent {
|
||||
@ -78,7 +89,7 @@ fn content_serialization() {
|
||||
|
||||
#[test]
|
||||
fn custom_content_serialization() {
|
||||
let json_data = btreemap! {
|
||||
let json_data = json_object! {
|
||||
"custom_field".into() => json!("baba"),
|
||||
"another_one".into() => json!("abab"),
|
||||
};
|
||||
@ -105,7 +116,7 @@ fn custom_content_deserialization() {
|
||||
"another_one": "abab",
|
||||
});
|
||||
|
||||
let expected_json_data = btreemap! {
|
||||
let expected_json_data = json_object! {
|
||||
"custom_field".into() => json!("baba"),
|
||||
"another_one".into() => json!("abab"),
|
||||
};
|
||||
|
Loading…
x
Reference in New Issue
Block a user