use matrix_sdk::room::Room; use matrix_sdk::RoomMemberships; use ruma::events::room::message::{ MessageType, OriginalSyncRoomMessageEvent, Relation, RoomMessageEventContent, }; use ruma::events::relation::{Annotation, InReplyTo}; use ruma::events::reaction::ReactionEventContent; use ruma::OwnedEventId; /// Extract the plain-text body from a message event. pub fn extract_body(event: &OriginalSyncRoomMessageEvent) -> Option { match &event.content.msgtype { MessageType::Text(text) => Some(text.body.clone()), MessageType::Notice(notice) => Some(notice.body.clone()), MessageType::Emote(emote) => Some(emote.body.clone()), _ => None, } } /// Check if this event is an edit (m.replace relation) and return the new body. pub fn extract_edit(event: &OriginalSyncRoomMessageEvent) -> Option<(OwnedEventId, String)> { if let Some(Relation::Replacement(replacement)) = &event.content.relates_to { let new_body = match &replacement.new_content.msgtype { MessageType::Text(text) => text.body.clone(), MessageType::Notice(notice) => notice.body.clone(), _ => return None, }; return Some((replacement.event_id.clone(), new_body)); } None } /// Extract the event ID being replied to, if any. pub fn extract_reply_to(event: &OriginalSyncRoomMessageEvent) -> Option { if let Some(Relation::Reply { in_reply_to }) = &event.content.relates_to { return Some(in_reply_to.event_id.clone()); } None } /// Extract thread root event ID, if any. pub fn extract_thread_id(event: &OriginalSyncRoomMessageEvent) -> Option { if let Some(Relation::Thread(thread)) = &event.content.relates_to { return Some(thread.event_id.clone()); } None } /// Build a reply message content with m.in_reply_to relation and markdown rendering. pub fn make_reply_content(body: &str, reply_to_event_id: OwnedEventId) -> RoomMessageEventContent { let mut content = RoomMessageEventContent::text_markdown(body); content.relates_to = Some(Relation::Reply { in_reply_to: InReplyTo::new(reply_to_event_id), }); content } /// Send an emoji reaction to a message. pub async fn send_reaction( room: &Room, event_id: OwnedEventId, emoji: &str, ) -> anyhow::Result<()> { let annotation = Annotation::new(event_id, emoji.to_string()); let content = ReactionEventContent::new(annotation); room.send(content).await?; Ok(()) } /// Get the display name for a room. pub fn room_display_name(room: &Room) -> String { room.cached_display_name() .map(|n| n.to_string()) .unwrap_or_else(|| room.room_id().to_string()) } /// Get member display names for a room. pub async fn room_member_names(room: &Room) -> Vec { match room.members(RoomMemberships::JOIN).await { Ok(members) => members .iter() .map(|m| { m.display_name() .unwrap_or_else(|| m.user_id().as_str()) .to_string() }) .collect(), Err(_) => Vec::new(), } }