events: Move message reply helper functions into a separate module

This commit is contained in:
Jonas Platte 2021-11-18 20:20:43 +01:00
parent 1a87403ba2
commit 824ef40bd9
No known key found for this signature in database
GPG Key ID: 7D261D771D915378
2 changed files with 286 additions and 275 deletions

View File

@ -2,7 +2,6 @@
use std::{borrow::Cow, fmt}; use std::{borrow::Cow, fmt};
use indoc::formatdoc;
use js_int::UInt; use js_int::UInt;
use ruma_events_macros::EventContent; use ruma_events_macros::EventContent;
#[cfg(feature = "unstable-pre-spec")] #[cfg(feature = "unstable-pre-spec")]
@ -19,6 +18,7 @@ use crate::key::verification::VerificationMethod;
mod content_serde; mod content_serde;
pub mod feedback; pub mod feedback;
mod relation_serde; mod relation_serde;
mod reply;
/// The content of an `m.room.message` event. /// The content of an `m.room.message` event.
/// ///
@ -82,7 +82,7 @@ impl RoomMessageEventContent {
/// Creates a plain text reply to a message. /// Creates a plain text reply to a message.
pub fn text_reply_plain(reply: impl fmt::Display, original_message: &RoomMessageEvent) -> Self { pub fn text_reply_plain(reply: impl fmt::Display, original_message: &RoomMessageEvent) -> Self {
let quoted = get_plain_quote_fallback(original_message); let quoted = reply::get_plain_quote_fallback(original_message);
let body = format!("{}\n\n{}", quoted, reply); let body = format!("{}\n\n{}", quoted, reply);
@ -100,8 +100,8 @@ impl RoomMessageEventContent {
html_reply: impl fmt::Display, html_reply: impl fmt::Display,
original_message: &RoomMessageEvent, original_message: &RoomMessageEvent,
) -> Self { ) -> Self {
let quoted = get_plain_quote_fallback(original_message); let quoted = reply::get_plain_quote_fallback(original_message);
let quoted_html = get_html_quote_fallback(original_message); let quoted_html = reply::get_html_quote_fallback(original_message);
let body = format!("{}\n\n{}", quoted, reply); let body = format!("{}\n\n{}", quoted, reply);
let html_body = format!("{}\n\n{}", quoted_html, html_reply); let html_body = format!("{}\n\n{}", quoted_html, html_reply);
@ -119,7 +119,7 @@ impl RoomMessageEventContent {
reply: impl fmt::Display, reply: impl fmt::Display,
original_message: &RoomMessageEvent, original_message: &RoomMessageEvent,
) -> Self { ) -> Self {
let quoted = get_plain_quote_fallback(original_message); let quoted = reply::get_plain_quote_fallback(original_message);
let body = format!("{}\n\n{}", quoted, reply); let body = format!("{}\n\n{}", quoted, reply);
Self { Self {
@ -136,8 +136,8 @@ impl RoomMessageEventContent {
html_reply: impl fmt::Display, html_reply: impl fmt::Display,
original_message: &RoomMessageEvent, original_message: &RoomMessageEvent,
) -> Self { ) -> Self {
let quoted = get_plain_quote_fallback(original_message); let quoted = reply::get_plain_quote_fallback(original_message);
let quoted_html = get_html_quote_fallback(original_message); let quoted_html = reply::get_html_quote_fallback(original_message);
let body = format!("{}\n\n{}", quoted, reply); let body = format!("{}\n\n{}", quoted, reply);
let html_body = format!("{}\n\n{}", quoted_html, html_reply); let html_body = format!("{}\n\n{}", quoted_html, html_reply);
@ -979,263 +979,13 @@ pub struct CustomEventContent {
data: JsonObject, data: JsonObject,
} }
fn get_plain_quote_fallback(original_message: &RoomMessageEvent) -> String {
match &original_message.content.msgtype {
MessageType::Audio(_) => {
format!("> <{:?}> sent an audio file.", original_message.sender)
}
MessageType::Emote(content) => {
format!("> * <{:?}> {}", original_message.sender, content.body)
}
MessageType::File(_) => {
format!("> <{:?}> sent a file.", original_message.sender)
}
MessageType::Image(_) => {
format!("> <{:?}> sent an image.", original_message.sender)
}
MessageType::Location(content) => {
format!("> <{:?}> {}", original_message.sender, content.body)
}
MessageType::Notice(content) => {
format!("> <{:?}> {}", original_message.sender, content.body)
}
MessageType::ServerNotice(content) => {
format!("> <{:?}> {}", original_message.sender, content.body)
}
MessageType::Text(content) => {
format!("> <{:?}> {}", original_message.sender, content.body)
}
MessageType::Video(_) => {
format!("> <{:?}> sent a video.", original_message.sender)
}
MessageType::_Custom(content) => {
format!("> <{:?}> {}", original_message.sender, content.body)
}
#[cfg(feature = "unstable-pre-spec")]
MessageType::VerificationRequest(content) => {
format!("> <{:?}> {}", original_message.sender, content.body)
}
}
.replace('\n', "\n> ")
}
#[allow(clippy::nonstandard_macro_braces)]
fn get_html_quote_fallback(original_message: &RoomMessageEvent) -> String {
match &original_message.content.msgtype {
MessageType::Audio(_) => {
formatdoc!(
"
<mx-reply>
<blockquote>
<a href=\"https://matrix.to/#/{room_id}/{event_id}\">In reply to</a>
<a href=\"https://matrix.to/#/{sender}\">{sender}</a>
<br />
sent an audio file.
</blockquote>
</mx-reply>
",
room_id = original_message.room_id,
event_id = original_message.event_id,
sender = original_message.sender,
)
}
MessageType::Emote(content) => {
formatdoc!(
"
<mx-reply>
<blockquote>
<a href=\"https://matrix.to/#/{room_id}/{event_id}\">In reply to</a>
* <a href=\"https://matrix.to/#/{sender}\">{sender}</a>
<br />
{body}
</blockquote>
</mx-reply>
",
room_id = original_message.room_id,
event_id = original_message.event_id,
sender = original_message.sender,
body = formatted_or_plain_body(&content.formatted, &content.body),
)
}
MessageType::File(_) => {
formatdoc!(
"
<mx-reply>
<blockquote>
<a href=\"https://matrix.to/#/{room_id}/{event_id}\">In reply to</a>
<a href=\"https://matrix.to/#/{sender}\">{sender}</a>
<br />
sent a file.
</blockquote>
</mx-reply>
",
room_id = original_message.room_id,
event_id = original_message.event_id,
sender = original_message.sender,
)
}
MessageType::Image(_) => {
formatdoc!(
"
<mx-reply>
<blockquote>
<a href=\"https://matrix.to/#/{room_id}/{event_id}\">In reply to</a>
<a href=\"https://matrix.to/#/{sender}\">{sender}</a>
<br />
sent an image.
</blockquote>
</mx-reply>
",
room_id = original_message.room_id,
event_id = original_message.event_id,
sender = original_message.sender,
)
}
MessageType::Location(_) => {
formatdoc!(
"
<mx-reply>
<blockquote>
<a href=\"https://matrix.to/#/{room_id}/{event_id}\">In reply to</a>
<a href=\"https://matrix.to/#/{sender}\">{sender}</a>
<br />
sent a location.
</blockquote>
</mx-reply>
",
room_id = original_message.room_id,
event_id = original_message.event_id,
sender = original_message.sender,
)
}
MessageType::Notice(content) => {
formatdoc!(
"
<mx-reply>
<blockquote>
<a href=\"https://matrix.to/#/{room_id}/{event_id}\">In reply to</a>
<a href=\"https://matrix.to/#/{sender}\">{sender}</a>
<br />
{body}
</blockquote>
</mx-reply>
",
room_id = original_message.room_id,
event_id = original_message.event_id,
sender = original_message.sender,
body = formatted_or_plain_body(&content.formatted, &content.body),
)
}
MessageType::ServerNotice(content) => {
formatdoc!(
"
<mx-reply>
<blockquote>
<a href=\"https://matrix.to/#/{room_id}/{event_id}\">In reply to</a>
<a href=\"https://matrix.to/#/{sender}\">{sender}</a>
<br />
{body}
</blockquote>
</mx-reply>
",
room_id = original_message.room_id,
event_id = original_message.event_id,
sender = original_message.sender,
body = content.body,
)
}
MessageType::Text(content) => {
formatdoc!(
"
<mx-reply>
<blockquote>
<a href=\"https://matrix.to/#/{room_id}/{event_id}\">In reply to</a>
<a href=\"https://matrix.to/#/{sender}\">{sender}</a>
<br />
{body}
</blockquote>
</mx-reply>
",
room_id = original_message.room_id,
event_id = original_message.event_id,
sender = original_message.sender,
body = formatted_or_plain_body(&content.formatted, &content.body),
)
}
MessageType::Video(_) => {
formatdoc!(
"
<mx-reply>
<blockquote>
<a href=\"https://matrix.to/#/{room_id}/{event_id}\">In reply to</a>
<a href=\"https://matrix.to/#/{sender}\">{sender}</a>
<br />
sent a video.
</blockquote>
</mx-reply>
",
room_id = original_message.room_id,
event_id = original_message.event_id,
sender = original_message.sender,
)
}
MessageType::_Custom(content) => {
formatdoc!(
"
<mx-reply>
<blockquote>
<a href=\"https://matrix.to/#/{room_id}/{event_id}\">In reply to</a>
<a href=\"https://matrix.to/#/{sender}\">{sender}</a>
<br />
{body}
</blockquote>
</mx-reply>
",
room_id = original_message.room_id,
event_id = original_message.event_id,
sender = original_message.sender,
body = content.body,
)
}
#[cfg(feature = "unstable-pre-spec")]
MessageType::VerificationRequest(content) => {
formatdoc!(
"
<mx-reply>
<blockquote>
<a href=\"https://matrix.to/#/{server_name}/{event_id}\">In reply to</a>
<a href=\"https://matrix.to/#/{sender}\">{sender}</a>
<br />
{body}
</blockquote>
</mx-reply>
",
server_name = original_message.room_id,
event_id = original_message.event_id,
sender = original_message.sender,
body = content.body,
)
}
}
}
fn formatted_or_plain_body<'a>(formatted: &'a Option<FormattedBody>, body: &'a str) -> &'a str {
if let Some(formatted_body) = formatted {
&formatted_body.body
} else {
body
}
}
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use std::convert::TryFrom;
use matches::assert_matches; use matches::assert_matches;
use ruma_identifiers::{event_id, EventId, RoomId, UserId}; use ruma_identifiers::event_id;
use serde_json::{from_value as from_json_value, json}; use serde_json::{from_value as from_json_value, json};
use super::{InReplyTo, MessageType, Relation, RoomMessageEvent, RoomMessageEventContent}; use super::{InReplyTo, MessageType, Relation, RoomMessageEventContent};
#[test] #[test]
fn deserialize_reply() { fn deserialize_reply() {
@ -1259,20 +1009,4 @@ mod tests {
} if event_id == ev_id } if event_id == ev_id
); );
} }
#[test]
fn plain_quote_fallback_multiline() {
let sender = UserId::try_from("@alice:example.com").unwrap();
assert_eq!(
super::get_plain_quote_fallback(&RoomMessageEvent {
content: RoomMessageEventContent::text_plain("multi\nline"),
event_id: EventId::new(sender.server_name()),
sender,
origin_server_ts: ruma_common::MilliSecondsSinceUnixEpoch::now(),
room_id: RoomId::try_from("!n8f893n9:example.com").unwrap(),
unsigned: crate::Unsigned::new(),
}),
"> <@alice:example.com> multi\n> line"
);
}
} }

View File

@ -0,0 +1,277 @@
use indoc::formatdoc;
use super::{FormattedBody, MessageType, RoomMessageEvent};
pub fn get_plain_quote_fallback(original_message: &RoomMessageEvent) -> String {
match &original_message.content.msgtype {
MessageType::Audio(_) => {
format!("> <{:?}> sent an audio file.", original_message.sender)
}
MessageType::Emote(content) => {
format!("> * <{:?}> {}", original_message.sender, content.body)
}
MessageType::File(_) => {
format!("> <{:?}> sent a file.", original_message.sender)
}
MessageType::Image(_) => {
format!("> <{:?}> sent an image.", original_message.sender)
}
MessageType::Location(content) => {
format!("> <{:?}> {}", original_message.sender, content.body)
}
MessageType::Notice(content) => {
format!("> <{:?}> {}", original_message.sender, content.body)
}
MessageType::ServerNotice(content) => {
format!("> <{:?}> {}", original_message.sender, content.body)
}
MessageType::Text(content) => {
format!("> <{:?}> {}", original_message.sender, content.body)
}
MessageType::Video(_) => {
format!("> <{:?}> sent a video.", original_message.sender)
}
MessageType::_Custom(content) => {
format!("> <{:?}> {}", original_message.sender, content.body)
}
#[cfg(feature = "unstable-pre-spec")]
MessageType::VerificationRequest(content) => {
format!("> <{:?}> {}", original_message.sender, content.body)
}
}
.replace('\n', "\n> ")
}
#[allow(clippy::nonstandard_macro_braces)]
pub fn get_html_quote_fallback(original_message: &RoomMessageEvent) -> String {
match &original_message.content.msgtype {
MessageType::Audio(_) => {
formatdoc!(
"
<mx-reply>
<blockquote>
<a href=\"https://matrix.to/#/{room_id}/{event_id}\">In reply to</a>
<a href=\"https://matrix.to/#/{sender}\">{sender}</a>
<br />
sent an audio file.
</blockquote>
</mx-reply>
",
room_id = original_message.room_id,
event_id = original_message.event_id,
sender = original_message.sender,
)
}
MessageType::Emote(content) => {
formatdoc!(
"
<mx-reply>
<blockquote>
<a href=\"https://matrix.to/#/{room_id}/{event_id}\">In reply to</a>
* <a href=\"https://matrix.to/#/{sender}\">{sender}</a>
<br />
{body}
</blockquote>
</mx-reply>
",
room_id = original_message.room_id,
event_id = original_message.event_id,
sender = original_message.sender,
body = formatted_or_plain_body(&content.formatted, &content.body),
)
}
MessageType::File(_) => {
formatdoc!(
"
<mx-reply>
<blockquote>
<a href=\"https://matrix.to/#/{room_id}/{event_id}\">In reply to</a>
<a href=\"https://matrix.to/#/{sender}\">{sender}</a>
<br />
sent a file.
</blockquote>
</mx-reply>
",
room_id = original_message.room_id,
event_id = original_message.event_id,
sender = original_message.sender,
)
}
MessageType::Image(_) => {
formatdoc!(
"
<mx-reply>
<blockquote>
<a href=\"https://matrix.to/#/{room_id}/{event_id}\">In reply to</a>
<a href=\"https://matrix.to/#/{sender}\">{sender}</a>
<br />
sent an image.
</blockquote>
</mx-reply>
",
room_id = original_message.room_id,
event_id = original_message.event_id,
sender = original_message.sender,
)
}
MessageType::Location(_) => {
formatdoc!(
"
<mx-reply>
<blockquote>
<a href=\"https://matrix.to/#/{room_id}/{event_id}\">In reply to</a>
<a href=\"https://matrix.to/#/{sender}\">{sender}</a>
<br />
sent a location.
</blockquote>
</mx-reply>
",
room_id = original_message.room_id,
event_id = original_message.event_id,
sender = original_message.sender,
)
}
MessageType::Notice(content) => {
formatdoc!(
"
<mx-reply>
<blockquote>
<a href=\"https://matrix.to/#/{room_id}/{event_id}\">In reply to</a>
<a href=\"https://matrix.to/#/{sender}\">{sender}</a>
<br />
{body}
</blockquote>
</mx-reply>
",
room_id = original_message.room_id,
event_id = original_message.event_id,
sender = original_message.sender,
body = formatted_or_plain_body(&content.formatted, &content.body),
)
}
MessageType::ServerNotice(content) => {
formatdoc!(
"
<mx-reply>
<blockquote>
<a href=\"https://matrix.to/#/{room_id}/{event_id}\">In reply to</a>
<a href=\"https://matrix.to/#/{sender}\">{sender}</a>
<br />
{body}
</blockquote>
</mx-reply>
",
room_id = original_message.room_id,
event_id = original_message.event_id,
sender = original_message.sender,
body = content.body,
)
}
MessageType::Text(content) => {
formatdoc!(
"
<mx-reply>
<blockquote>
<a href=\"https://matrix.to/#/{room_id}/{event_id}\">In reply to</a>
<a href=\"https://matrix.to/#/{sender}\">{sender}</a>
<br />
{body}
</blockquote>
</mx-reply>
",
room_id = original_message.room_id,
event_id = original_message.event_id,
sender = original_message.sender,
body = formatted_or_plain_body(&content.formatted, &content.body),
)
}
MessageType::Video(_) => {
formatdoc!(
"
<mx-reply>
<blockquote>
<a href=\"https://matrix.to/#/{room_id}/{event_id}\">In reply to</a>
<a href=\"https://matrix.to/#/{sender}\">{sender}</a>
<br />
sent a video.
</blockquote>
</mx-reply>
",
room_id = original_message.room_id,
event_id = original_message.event_id,
sender = original_message.sender,
)
}
MessageType::_Custom(content) => {
formatdoc!(
"
<mx-reply>
<blockquote>
<a href=\"https://matrix.to/#/{room_id}/{event_id}\">In reply to</a>
<a href=\"https://matrix.to/#/{sender}\">{sender}</a>
<br />
{body}
</blockquote>
</mx-reply>
",
room_id = original_message.room_id,
event_id = original_message.event_id,
sender = original_message.sender,
body = content.body,
)
}
#[cfg(feature = "unstable-pre-spec")]
MessageType::VerificationRequest(content) => {
formatdoc!(
"
<mx-reply>
<blockquote>
<a href=\"https://matrix.to/#/{server_name}/{event_id}\">In reply to</a>
<a href=\"https://matrix.to/#/{sender}\">{sender}</a>
<br />
{body}
</blockquote>
</mx-reply>
",
server_name = original_message.room_id,
event_id = original_message.event_id,
sender = original_message.sender,
body = content.body,
)
}
}
}
fn formatted_or_plain_body<'a>(formatted: &'a Option<FormattedBody>, body: &'a str) -> &'a str {
if let Some(formatted_body) = formatted {
&formatted_body.body
} else {
body
}
}
#[cfg(test)]
mod tests {
use std::convert::TryFrom;
use ruma_identifiers::{EventId, RoomId, UserId};
use super::RoomMessageEvent;
use crate::room::message::RoomMessageEventContent;
#[test]
fn plain_quote_fallback_multiline() {
let sender = UserId::try_from("@alice:example.com").unwrap();
assert_eq!(
super::get_plain_quote_fallback(&RoomMessageEvent {
content: RoomMessageEventContent::text_plain("multi\nline"),
event_id: EventId::new(sender.server_name()),
sender,
origin_server_ts: ruma_common::MilliSecondsSinceUnixEpoch::now(),
room_id: RoomId::try_from("!n8f893n9:example.com").unwrap(),
unsigned: crate::Unsigned::new(),
}),
"> <@alice:example.com> multi\n> line"
);
}
}