summary refs log tree commit diff
path: root/src/Utils.cpp
diff options
context:
space:
mode:
authorNicolas Werner <nicolas.werner@hotmail.de>2023-07-05 00:08:37 +0200
committerNicolas Werner <nicolas.werner@hotmail.de>2023-07-05 00:08:37 +0200
commitad6e4fef6407b9e39ab8ee329b4e8c12376c8494 (patch)
treebfa2634aabea625a1479817700c35d846273371b /src/Utils.cpp
parentAdd some event expiration function (diff)
downloadnheko-ad6e4fef6407b9e39ab8ee329b4e8c12376c8494.tar.xz
Add experimental event expiration
Currently disabled by default.
Diffstat (limited to 'src/Utils.cpp')
-rw-r--r--src/Utils.cpp84
1 files changed, 54 insertions, 30 deletions
diff --git a/src/Utils.cpp b/src/Utils.cpp
index 7a412db0..663609fe 100644
--- a/src/Utils.cpp
+++ b/src/Utils.cpp
@@ -1610,8 +1610,7 @@ std::atomic<bool> event_expiration_running = false;
 void
 utils::removeExpiredEvents()
 {
-    // TODO(Nico): Add its own toggle...
-    if (!UserSettings::instance()->updateSpaceVias())
+    if (!UserSettings::instance()->expireEvents())
         return;
 
     if (event_expiration_running.exchange(true)) {
@@ -1645,18 +1644,20 @@ utils::removeExpiredEvents()
         std::string currentRoom;
         std::uint64_t currentRoomCount = 0;
         std::string currentRoomPrevToken;
+        std::set<std::pair<std::string, std::string>> currentRoomStateEvents;
         std::vector<std::string> currentRoomRedactionQueue;
         mtx::events::account_data::nheko_extensions::EventExpiry currentExpiry;
 
         static void next(std::shared_ptr<ApplyEventExpiration> state)
         {
             if (!state->currentRoomRedactionQueue.empty()) {
+                auto evid = state->currentRoomRedactionQueue.back();
+                auto room = state->currentRoom;
                 http::client()->redact_event(
-                  state->currentRoom,
-                  state->currentRoomRedactionQueue.back(),
-                  [state = std::move(state)](const mtx::responses::EventId &,
-                                             mtx::http::RequestErr e) mutable {
-                      const auto &event_id = state->currentRoomRedactionQueue.back();
+                  room,
+                  evid,
+                  [state = std::move(state), evid](const mtx::responses::EventId &,
+                                                   mtx::http::RequestErr e) mutable {
                       if (e) {
                           if (e->status_code == 429 && e->matrix_error.retry_after.count() != 0) {
                               ChatPage::instance()->callFunctionOnGuiThread(
@@ -1669,17 +1670,19 @@ utils::removeExpiredEvents()
                                                        });
                                 });
                               return;
+                          } else {
+                              nhlog::net()->error("Failed to redact event {} in {}: {}",
+                                                  evid,
+                                                  state->currentRoom,
+                                                  *e);
+                              state->currentRoomRedactionQueue.pop_back();
+                              next(std::move(state));
                           }
-
-                          nhlog::net()->error("Failed to redact event {} in {}: {}",
-                                              event_id,
-                                              state->currentRoom,
-                                              *e);
+                      } else {
+                          nhlog::net()->info("Redacted event {} in {}", evid, state->currentRoom);
+                          state->currentRoomRedactionQueue.pop_back();
+                          next(std::move(state));
                       }
-                      nhlog::net()->info(
-                        "Redacted event {} in {}: {}", event_id, state->currentRoom, *e);
-                      state->currentRoomRedactionQueue.pop_back();
-                      next(std::move(state));
                   });
             } else if (!state->currentRoom.empty()) {
                 mtx::http::MessagesOpts opts{};
@@ -1687,6 +1690,7 @@ utils::removeExpiredEvents()
                 opts.from  = state->currentRoomPrevToken;
                 opts.limit = 1000;
                 opts.filter = state->filter;
+                opts.room_id = state->currentRoom;
 
                 http::client()->messages(
                   opts,
@@ -1708,6 +1712,19 @@ utils::removeExpiredEvents()
                                     mtx::events::RedactionEvent<mtx::events::msg::Redaction>>(e))
                                   continue;
 
+                              if (std::holds_alternative<
+                                    mtx::events::RoomEvent<mtx::events::msg::Redacted>>(e))
+                                  continue;
+
+                              if (std::holds_alternative<
+                                    mtx::events::StateEvent<mtx::events::msg::Redacted>>(e))
+                                  continue;
+
+                              // skip events we don't know to protect us from mistakes.
+                              if (std::holds_alternative<
+                                    mtx::events::RoomEvent<mtx::events::Unknown>>(e))
+                                  continue;
+
                               if (mtx::accessors::sender(e) != us)
                                   continue;
 
@@ -1720,6 +1737,21 @@ utils::removeExpiredEvents()
                                   mtx::accessors::is_state_event(e))
                                   continue;
 
+                              if (mtx::accessors::is_state_event(e)) {
+                                  // skip the first state event of a type
+                                  if (std::visit(
+                                        [&state](const auto &se) {
+                                            if constexpr (requires { se.state_key; })
+                                                return state->currentRoomStateEvents
+                                                  .emplace(to_string(se.type), se.state_key)
+                                                  .second;
+                                            else
+                                                return false;
+                                        },
+                                        e))
+                                      continue;
+                              }
+
                               if (state->currentExpiry.keep_only_latest &&
                                   state->currentRoomCount > state->currentExpiry.keep_only_latest) {
                                   state->currentRoomRedactionQueue.push_back(
@@ -1738,6 +1770,7 @@ utils::removeExpiredEvents()
                           state->currentRoom.clear();
                           state->currentRoomCount = 0;
                           state->currentRoomPrevToken.clear();
+                          state->currentRoomStateEvents.clear();
                       }
 
                       next(std::move(state));
@@ -1764,20 +1797,11 @@ utils::removeExpiredEvents()
 
     auto asus = std::make_shared<ApplyEventExpiration>();
 
-    asus->filter =
-      nlohmann::json{
-        "room",
-        nlohmann::json::object({
-          {
-            "timeline",
-            nlohmann::json::object({
-              {"senders", nlohmann::json::array({us})},
-              {"not_types", nlohmann::json::array({"m.room.redaction"})},
-            }),
-          },
-        }),
-      }
-        .dump();
+    nlohmann::json filter;
+    filter["timeline"]["senders"]   = nlohmann::json::array({us});
+    filter["timeline"]["not_types"] = nlohmann::json::array({"m.room.redaction"});
+
+    asus->filter = filter.dump();
 
     asus->globalExpiry = getExpEv();