events: Fix plain text reply constructors

Send a formatted_body, according to the spec
This commit is contained in:
Kévin Commaille 2022-04-05 19:44:21 +02:00 committed by Kévin Commaille
parent 002d863738
commit 1e1fa06342
3 changed files with 38 additions and 70 deletions

View File

@ -19,6 +19,9 @@ Breaking changes:
* Change `events::room` media types to use `Duration` where applicable
* Move `prev_content` into `unsigned`
* Rename `identifiers::Error` to `IdParseError`
* Fix the `RoomMessageEventContent::*_reply_plain` methods that now return a
message with a `formatted_body`, according to the spec. Therefore, they only
accept `OriginalRoomMessageEvent`s like their HTML counterparts.
Improvements:

View File

@ -42,8 +42,6 @@ pub mod feedback;
mod relation_serde;
mod reply;
pub use reply::ReplyBaseEvent;
/// The content of an `m.room.message` event.
///
/// This event is used when sending messages in a room.
@ -105,28 +103,34 @@ impl RoomMessageEventContent {
}
/// Creates a plain text reply to a message.
///
/// This constructor requires an [`OriginalRoomMessageEvent`] since it creates a permalink to
/// the previous message, for which the room ID is required. If you want to reply to an
/// [`OriginalSyncRoomMessageEvent`], you have to convert it first by calling
/// [`.into_full_event()`][crate::events::OriginalSyncMessageLikeEvent::into_full_event].
pub fn text_reply_plain(
reply: impl fmt::Display,
original_message: &impl ReplyBaseEvent,
original_message: &OriginalRoomMessageEvent,
) -> Self {
let quoted = reply::get_plain_quote_fallback(original_message);
let quoted_html = reply::get_html_quote_fallback(original_message);
let body = format!("{}\n\n{}", quoted, reply);
let html_body = format!("{}\n\n{}", quoted_html, reply);
Self {
relates_to: Some(Relation::Reply {
in_reply_to: InReplyTo { event_id: original_message.event_id().to_owned() },
in_reply_to: InReplyTo { event_id: original_message.event_id.to_owned() },
}),
..Self::text_plain(body)
..Self::text_html(body, html_body)
}
}
/// Creates a html text reply to a message.
///
/// Different from `text_reply_plain`, this constructor requires specifically a
/// [`RoomMessageEvent`] since it creates a permalink to the previous message, for which the
/// room ID is required. If you want to reply to a [`SyncRoomMessageEvent`], you have to convert
/// it first by calling
/// This constructor requires an [`OriginalRoomMessageEvent`] since it creates a permalink to
/// the previous message, for which the room ID is required. If you want to reply to an
/// [`OriginalSyncRoomMessageEvent`], you have to convert it first by calling
/// [`.into_full_event()`][crate::events::OriginalSyncMessageLikeEvent::into_full_event].
pub fn text_reply_html(
reply: impl fmt::Display,
@ -148,27 +152,34 @@ impl RoomMessageEventContent {
}
/// Creates a plain text notice reply to a message.
///
/// This constructor requires an [`OriginalRoomMessageEvent`] since it creates a permalink to
/// the previous message, for which the room ID is required. If you want to reply to an
/// [`OriginalSyncRoomMessageEvent`], you have to convert it first by calling
/// [`.into_full_event()`][crate::events::OriginalSyncMessageLikeEvent::into_full_event].
pub fn notice_reply_plain(
reply: impl fmt::Display,
original_message: &impl ReplyBaseEvent,
original_message: &OriginalRoomMessageEvent,
) -> Self {
let quoted = reply::get_plain_quote_fallback(original_message);
let quoted_html = reply::get_html_quote_fallback(original_message);
let body = format!("{}\n\n{}", quoted, reply);
let html_body = format!("{}\n\n{}", quoted_html, reply);
Self {
relates_to: Some(Relation::Reply {
in_reply_to: InReplyTo { event_id: original_message.event_id().to_owned() },
in_reply_to: InReplyTo { event_id: original_message.event_id.to_owned() },
}),
..Self::notice_plain(body)
..Self::notice_html(body, html_body)
}
}
/// Creates a html text notice reply to a message.
///
/// Different from `notice_reply_plain`, this constructor requires specifically a
/// [`RoomMessageEvent`] since it creates a permalink to the previous message, for which the
/// room ID is required. If you want to reply to a [`SyncRoomMessageEvent`], you have to convert
/// it first by calling
/// This constructor requires an [`OriginalRoomMessageEvent`] since it creates a permalink to
/// the previous message, for which the room ID is required. If you want to reply to an
/// [`OriginalSyncRoomMessageEvent`], you have to convert it first by calling
/// [`.into_full_event()`][crate::events::OriginalSyncMessageLikeEvent::into_full_event].
pub fn notice_reply_html(
reply: impl fmt::Display,

View File

@ -1,59 +1,11 @@
use indoc::formatdoc;
use super::{
FormattedBody, MessageType, OriginalRoomMessageEvent, OriginalSyncRoomMessageEvent,
RoomMessageEventContent,
};
use crate::{EventId, UserId};
use super::{FormattedBody, MessageType, OriginalRoomMessageEvent};
/// An event that can be replied to.
///
/// This trait only exists to allow the plain-text `reply` constructors on `MessageLikeEventContent`
/// to use either a [`RoomMessageEvent`] or a [`SyncRoomMessageEvent`] as the event being replied
/// to.
pub trait ReplyBaseEvent {
#[doc(hidden)]
fn event_id(&self) -> &EventId;
pub fn get_plain_quote_fallback(original_message: &OriginalRoomMessageEvent) -> String {
let sender = &original_message.sender;
#[doc(hidden)]
fn sender(&self) -> &UserId;
#[doc(hidden)]
fn content(&self) -> &RoomMessageEventContent;
}
impl ReplyBaseEvent for OriginalRoomMessageEvent {
fn event_id(&self) -> &EventId {
&self.event_id
}
fn sender(&self) -> &UserId {
&self.sender
}
fn content(&self) -> &RoomMessageEventContent {
&self.content
}
}
impl ReplyBaseEvent for OriginalSyncRoomMessageEvent {
fn event_id(&self) -> &EventId {
&self.event_id
}
fn sender(&self) -> &UserId {
&self.sender
}
fn content(&self) -> &RoomMessageEventContent {
&self.content
}
}
pub fn get_plain_quote_fallback(original_message: &impl ReplyBaseEvent) -> String {
let sender = original_message.sender();
match &original_message.content().msgtype {
match &original_message.content.msgtype {
MessageType::Audio(_) => {
format!("> <{}> sent an audio file.", sender)
}
@ -301,10 +253,12 @@ fn formatted_or_plain_body<'a>(formatted: &'a Option<FormattedBody>, body: &'a s
#[cfg(test)]
mod tests {
use crate::{
event_id, events::MessageLikeUnsigned, room_id, user_id, MilliSecondsSinceUnixEpoch,
event_id,
events::{room::message::RoomMessageEventContent, MessageLikeUnsigned},
room_id, user_id, MilliSecondsSinceUnixEpoch,
};
use super::{OriginalRoomMessageEvent, RoomMessageEventContent};
use super::OriginalRoomMessageEvent;
#[test]
fn plain_quote_fallback_multiline() {