events: Require MessageType to always contain a body

This commit is contained in:
Jonas Platte 2021-09-17 19:08:57 +02:00
parent aa2388fe86
commit 4ec9f1aa03
No known key found for this signature in database
GPG Key ID: CC154DE0E30B7C67
3 changed files with 60 additions and 22 deletions

View File

@ -5,6 +5,12 @@ Breaking changes:
* Remove `RedactedStrippedStateEvent` * Remove `RedactedStrippedStateEvent`
* It was not used anywhere since stripped state events are never actually redacted. * It was not used anywhere since stripped state events are never actually redacted.
* Use `Box<RawJsonValue>` instead of `JsonValue` for PDU `content` field * Use `Box<RawJsonValue>` instead of `JsonValue` for PDU `content` field
* Require `room::message::MessageType` to always contain a body
* The `new` constructor now also has a body parameter
Improvements:
* Add `room::message::MessageType::body` accessor method
# 0.24.5 # 0.24.5

View File

@ -187,24 +187,35 @@ impl MessageType {
/// Prefer to use the public variants of `MessageType` where possible; this constructor is meant /// 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 /// be used for unsupported message types only and does not allow setting arbitrary data for
/// supported ones. /// 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> { /// # Errors
///
/// Returns an error if the `msgtype` is known and serialization of `data` to the corresponding
/// `MessageType` variant fails.
pub fn new(msgtype: &str, body: String, data: JsonObject) -> serde_json::Result<Self> {
fn deserialize_variant<T: DeserializeOwned>(
body: String,
mut obj: JsonObject,
) -> serde_json::Result<T> {
obj.insert("body".into(), body.into());
serde_json::from_value(JsonValue::Object(obj)) serde_json::from_value(JsonValue::Object(obj))
} }
Ok(match msgtype { Ok(match msgtype {
"m.audio" => Self::Audio(from_json_object(data)?), "m.audio" => Self::Audio(deserialize_variant(body, data)?),
"m.emote" => Self::Emote(from_json_object(data)?), "m.emote" => Self::Emote(deserialize_variant(body, data)?),
"m.file" => Self::File(from_json_object(data)?), "m.file" => Self::File(deserialize_variant(body, data)?),
"m.image" => Self::Image(from_json_object(data)?), "m.image" => Self::Image(deserialize_variant(body, data)?),
"m.location" => Self::Location(from_json_object(data)?), "m.location" => Self::Location(deserialize_variant(body, data)?),
"m.notice" => Self::Notice(from_json_object(data)?), "m.notice" => Self::Notice(deserialize_variant(body, data)?),
"m.server_notice" => Self::ServerNotice(from_json_object(data)?), "m.server_notice" => Self::ServerNotice(deserialize_variant(body, data)?),
"m.text" => Self::Text(from_json_object(data)?), "m.text" => Self::Text(deserialize_variant(body, data)?),
"m.video" => Self::Video(from_json_object(data)?), "m.video" => Self::Video(deserialize_variant(body, data)?),
#[cfg(feature = "unstable-pre-spec")] #[cfg(feature = "unstable-pre-spec")]
"m.key.verification.request" => Self::VerificationRequest(from_json_object(data)?), "m.key.verification.request" => {
_ => Self::_Custom(CustomEventContent { msgtype: msgtype.to_owned(), data }), Self::VerificationRequest(deserialize_variant(body, data)?)
}
_ => Self::_Custom(CustomEventContent { msgtype: msgtype.to_owned(), body, data }),
}) })
} }
@ -226,6 +237,24 @@ impl MessageType {
} }
} }
/// Return a reference to the message body.
pub fn body(&self) -> &str {
match self {
MessageType::Audio(m) => &m.body,
MessageType::Emote(m) => &m.body,
MessageType::File(m) => &m.body,
MessageType::Image(m) => &m.body,
MessageType::Location(m) => &m.body,
MessageType::Notice(m) => &m.body,
MessageType::ServerNotice(m) => &m.body,
MessageType::Text(m) => &m.body,
MessageType::Video(m) => &m.body,
#[cfg(feature = "unstable-pre-spec")]
MessageType::VerificationRequest(m) => &m.body,
MessageType::_Custom(m) => &m.body,
}
}
/// Returns the associated data. /// Returns the associated data.
/// ///
/// Prefer to use the public variants of `MessageType` where possible; this method is meant to /// Prefer to use the public variants of `MessageType` where possible; this method is meant to
@ -929,10 +958,13 @@ impl KeyVerificationRequestEventContent {
#[doc(hidden)] #[doc(hidden)]
#[derive(Clone, Debug, Deserialize, Serialize)] #[derive(Clone, Debug, Deserialize, Serialize)]
pub struct CustomEventContent { pub struct CustomEventContent {
/// A custom msgtype /// A custom msgtype.
msgtype: String, msgtype: String,
/// Remaining event content /// The message body.
body: String,
/// Remaining event content.
#[serde(flatten)] #[serde(flatten)]
data: JsonObject, data: JsonObject,
} }
@ -967,11 +999,7 @@ fn get_plain_quote_fallback(original_message: &MessageEvent) -> String {
format!("> <{:?}> sent a video.", original_message.sender) format!("> <{:?}> sent a video.", original_message.sender)
} }
MessageType::_Custom(content) => { MessageType::_Custom(content) => {
format!( format!("> <{:?}> {}", original_message.sender, content.body)
"> <{:?}> {}",
original_message.sender,
content.data["body"].as_str().unwrap_or(""),
)
} }
#[cfg(feature = "unstable-pre-spec")] #[cfg(feature = "unstable-pre-spec")]
MessageType::VerificationRequest(content) => { MessageType::VerificationRequest(content) => {
@ -1156,7 +1184,7 @@ fn get_html_quote_fallback(original_message: &MessageEvent) -> String {
room_id = original_message.room_id, room_id = original_message.room_id,
event_id = original_message.event_id, event_id = original_message.event_id,
sender = original_message.sender, sender = original_message.sender,
body = content.data["body"].as_str().unwrap_or(""), body = content.body,
) )
} }
#[cfg(feature = "unstable-pre-spec")] #[cfg(feature = "unstable-pre-spec")]

View File

@ -90,12 +90,14 @@ fn custom_msgtype_serialization() {
"custom_field".into() => json!("baba"), "custom_field".into() => json!("baba"),
"another_one".into() => json!("abab"), "another_one".into() => json!("abab"),
}; };
let custom_msgtype = MessageType::new("my_custom_msgtype", json_data).unwrap(); let custom_msgtype =
MessageType::new("my_custom_msgtype", "my message body".into(), json_data).unwrap();
assert_eq!( assert_eq!(
to_json_value(&custom_msgtype).unwrap(), to_json_value(&custom_msgtype).unwrap(),
json!({ json!({
"msgtype": "my_custom_msgtype", "msgtype": "my_custom_msgtype",
"body": "my message body",
"custom_field": "baba", "custom_field": "baba",
"another_one": "abab", "another_one": "abab",
}) })
@ -106,6 +108,7 @@ fn custom_msgtype_serialization() {
fn custom_content_deserialization() { fn custom_content_deserialization() {
let json_data = json!({ let json_data = json!({
"msgtype": "my_custom_msgtype", "msgtype": "my_custom_msgtype",
"body": "my custom message",
"custom_field": "baba", "custom_field": "baba",
"another_one": "abab", "another_one": "abab",
}); });
@ -119,6 +122,7 @@ fn custom_content_deserialization() {
from_json_value::<Raw<MessageType>>(json_data).unwrap().deserialize().unwrap(); from_json_value::<Raw<MessageType>>(json_data).unwrap().deserialize().unwrap();
assert_eq!(custom_event.msgtype(), "my_custom_msgtype"); assert_eq!(custom_event.msgtype(), "my_custom_msgtype");
assert_eq!(custom_event.body(), "my custom message");
assert_eq!(custom_event.data(), Cow::Owned(expected_json_data)); assert_eq!(custom_event.data(), Cow::Owned(expected_json_data));
} }