From 4918d362600da542131b6e7cf8df4c2015f0cb6e Mon Sep 17 00:00:00 2001
From: Daniel Schadt <kingdread@gmx.de>
Date: Mon, 8 Mar 2021 16:39:01 +0100
Subject: matrix: try better to find the last message

In matrix, every edit count is also sent as a room message, so are
joins, leaves, ... which makes 10 (the default) a pretty low number of
previous messages to check for. In comparison, the discord integration
checks the last 25 messages to find the correct one.

This patch increases the limit to 60 messages, loaded in 3 chunks a 20
messages each. This should ensure that even for more edited channels,
the message is found in more cases.
---
 src/matrix.rs | 43 +++++++++++++++++++++++++++++++++----------
 1 file changed, 33 insertions(+), 10 deletions(-)

diff --git a/src/matrix.rs b/src/matrix.rs
index ffd223d..5243db4 100644
--- a/src/matrix.rs
+++ b/src/matrix.rs
@@ -16,7 +16,7 @@ use matrix_sdk::{
     events::room::relationships::Replacement,
     events::{AnyMessageEvent, AnyMessageEventContent, AnyRoomEvent},
     identifiers::{EventId, RoomId, UserId},
-    Client,
+    Client, UInt,
 };
 
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
@@ -40,6 +40,10 @@ impl From<config::Matrix> for MatrixUser {
 
 /// Maximum age of the message to still be edited.
 const MAX_HOURS: u64 = 5;
+/// Amount of messages to be loaded in one chunk.
+const MESSAGE_CHUNK_SIZE: u16 = 20;
+/// Number of message chunks that should be loaded (in total) when searching for the last message.
+const MESSAGE_CHUNK_COUNT: u16 = 3;
 
 /// Posts a link to the log to a Matrix room.
 ///
@@ -91,20 +95,39 @@ async fn find_message(
     my_id: &UserId,
     room_id: &RoomId,
 ) -> Result<Option<(EventId, String)>> {
-    let request = get_message_events::Request::backward(room_id, "");
+    let limit = UInt::try_from(MESSAGE_CHUNK_SIZE).unwrap();
     let time_limit = SystemTime::now() - Duration::from_secs(MAX_HOURS * 60 * 60);
-    for raw_message in client.room_messages(request).await?.chunk {
-        if let Ok(AnyRoomEvent::Message(AnyMessageEvent::RoomMessage(msg))) =
-            raw_message.deserialize()
-        {
-            if &msg.sender == my_id && msg.origin_server_ts >= time_limit {
-                if let MessageEventContent::Text(text) = msg.content {
-                    if text.relates_to.is_none() {
-                        return Ok(Some((msg.event_id, text.body)));
+    let mut continue_from = String::new();
+
+    for chunk_nr in 0..MESSAGE_CHUNK_COUNT {
+        debug!(
+            "Loading {} items (chunk {} of {})",
+            MESSAGE_CHUNK_SIZE,
+            chunk_nr + 1,
+            MESSAGE_CHUNK_COUNT
+        );
+
+        let mut request = get_message_events::Request::backward(room_id, &continue_from);
+        request.limit = limit;
+        let response = client.room_messages(request).await?;
+        for raw_message in response.chunk {
+            if let Ok(AnyRoomEvent::Message(AnyMessageEvent::RoomMessage(msg))) =
+                raw_message.deserialize()
+            {
+                if &msg.sender == my_id && msg.origin_server_ts >= time_limit {
+                    if let MessageEventContent::Text(text) = msg.content {
+                        if text.relates_to.is_none() {
+                            return Ok(Some((msg.event_id, text.body)));
+                        }
                     }
                 }
             }
         }
+
+        match response.end {
+            Some(token) => continue_from = token,
+            None => break,
+        }
     }
     Ok(None)
 }
-- 
cgit v1.2.3