From 7562a7fc612f807fd79fbb4ab306caff50807f03 Mon Sep 17 00:00:00 2001 From: Pierre HUBERT Date: Mon, 24 Nov 2025 11:20:20 +0100 Subject: [PATCH] Get latest message for a room --- .../matrix/matrix_event_controller.rs | 60 +++++++++++++++++++ .../matrix/matrix_room_controller.rs | 6 ++ .../src/controllers/matrix/mod.rs | 1 + 3 files changed, 67 insertions(+) create mode 100644 matrixgw_backend/src/controllers/matrix/matrix_event_controller.rs diff --git a/matrixgw_backend/src/controllers/matrix/matrix_event_controller.rs b/matrixgw_backend/src/controllers/matrix/matrix_event_controller.rs new file mode 100644 index 0000000..a8228de --- /dev/null +++ b/matrixgw_backend/src/controllers/matrix/matrix_event_controller.rs @@ -0,0 +1,60 @@ +use futures_util::{StreamExt, stream}; +use matrix_sdk::Room; +use matrix_sdk::deserialized_responses::{TimelineEvent, TimelineEventKind}; +use matrix_sdk::room::MessagesOptions; +use matrix_sdk::ruma::{MilliSecondsSinceUnixEpoch, OwnedEventId, OwnedUserId, RoomId, UInt}; +use serde::Serialize; +use serde_json::value::RawValue; + +#[derive(Serialize)] +pub struct APIEvent { + id: OwnedEventId, + time: MilliSecondsSinceUnixEpoch, + sender: OwnedUserId, + data: Box, +} + +impl APIEvent { + pub async fn from_evt(msg: TimelineEvent, room_id: &RoomId) -> anyhow::Result { + let (event, raw) = match &msg.kind { + TimelineEventKind::Decrypted(d) => (d.event.deserialize()?, d.event.json()), + TimelineEventKind::UnableToDecrypt { event, .. } + | TimelineEventKind::PlainText { event } => ( + event.deserialize()?.into_full_event(room_id.to_owned()), + event.json(), + ), + }; + + Ok(Self { + id: event.event_id().to_owned(), + time: event.origin_server_ts(), + sender: event.sender().to_owned(), + data: raw.to_owned(), + }) + } +} + +#[derive(Serialize)] +pub struct APIEventsList { + pub start: String, + pub end: Option, + pub messages: Vec, +} + +/// Get messages for a given room +pub(super) async fn get_events(room: &Room, limit: u32) -> anyhow::Result { + let mut msg_opts = MessagesOptions::backward(); + msg_opts.limit = UInt::from(limit); + + let messages = room.messages(msg_opts).await?; + Ok(APIEventsList { + start: messages.start, + end: messages.end, + messages: stream::iter(messages.chunk) + .then(async |msg| APIEvent::from_evt(msg, room.room_id()).await) + .collect::>() + .await + .into_iter() + .collect::, _>>()?, + }) +} diff --git a/matrixgw_backend/src/controllers/matrix/matrix_room_controller.rs b/matrixgw_backend/src/controllers/matrix/matrix_room_controller.rs index 4344877..3970c7d 100644 --- a/matrixgw_backend/src/controllers/matrix/matrix_room_controller.rs +++ b/matrixgw_backend/src/controllers/matrix/matrix_room_controller.rs @@ -1,4 +1,5 @@ use crate::controllers::HttpResult; +use crate::controllers::matrix::matrix_event_controller::{APIEvent, get_events}; use crate::controllers::matrix::matrix_media_controller; use crate::extractors::matrix_client_extractor::MatrixClientExtractor; use actix_web::{HttpRequest, HttpResponse, web}; @@ -15,10 +16,13 @@ pub struct APIRoomInfo { avatar: Option, is_space: bool, parents: Vec, + number_unread_messages: u64, + latest_event: Option, } impl APIRoomInfo { async fn from_room(r: &Room) -> anyhow::Result { + // Get parent spaces let parent_spaces = r .parent_spaces() .await? @@ -47,6 +51,8 @@ impl APIRoomInfo { avatar: r.avatar_url(), is_space: r.is_space(), parents: parent_spaces, + number_unread_messages: r.num_unread_messages(), + latest_event: get_events(r, 1).await?.messages.into_iter().next(), }) } } diff --git a/matrixgw_backend/src/controllers/matrix/mod.rs b/matrixgw_backend/src/controllers/matrix/mod.rs index 2d86649..3a34b16 100644 --- a/matrixgw_backend/src/controllers/matrix/mod.rs +++ b/matrixgw_backend/src/controllers/matrix/mod.rs @@ -1,3 +1,4 @@ +pub mod matrix_event_controller; pub mod matrix_media_controller; pub mod matrix_profile_controller; pub mod matrix_room_controller;