summary refs log tree commit diff
path: root/src/Cache.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/Cache.cc')
-rw-r--r--src/Cache.cc103
1 files changed, 98 insertions, 5 deletions
diff --git a/src/Cache.cc b/src/Cache.cc
index 06e45f13..e4e700b2 100644
--- a/src/Cache.cc
+++ b/src/Cache.cc
@@ -36,6 +36,7 @@ Cache::Cache(const QString &userId)
   , roomDb_{0}
   , invitesDb_{0}
   , imagesDb_{0}
+  , readReceiptsDb_{0}
   , isMounted_{false}
   , userId_{userId}
 {}
@@ -89,11 +90,12 @@ Cache::setup()
                 env_.open(statePath.toStdString().c_str());
         }
 
-        auto txn   = lmdb::txn::begin(env_);
-        stateDb_   = lmdb::dbi::open(txn, "state", MDB_CREATE);
-        roomDb_    = lmdb::dbi::open(txn, "rooms", MDB_CREATE);
-        invitesDb_ = lmdb::dbi::open(txn, "invites", MDB_CREATE);
-        imagesDb_  = lmdb::dbi::open(txn, "images", MDB_CREATE);
+        auto txn        = lmdb::txn::begin(env_);
+        stateDb_        = lmdb::dbi::open(txn, "state", MDB_CREATE);
+        roomDb_         = lmdb::dbi::open(txn, "rooms", MDB_CREATE);
+        invitesDb_      = lmdb::dbi::open(txn, "invites", MDB_CREATE);
+        imagesDb_       = lmdb::dbi::open(txn, "images", MDB_CREATE);
+        readReceiptsDb_ = lmdb::dbi::open(txn, "read_receipts", MDB_CREATE);
 
         txn.commit();
 
@@ -449,3 +451,94 @@ Cache::setInvites(const std::map<std::string, mtx::responses::InvitedRoom> &invi
                 unmount();
         }
 }
+
+std::multimap<uint64_t, std::string>
+Cache::readReceipts(const QString &event_id, const QString &room_id)
+{
+        std::multimap<uint64_t, std::string> receipts;
+
+        ReadReceiptKey receipt_key{event_id.toStdString(), room_id.toStdString()};
+        nlohmann::json json_key = receipt_key;
+
+        try {
+                auto txn = lmdb::txn::begin(env_, nullptr, MDB_RDONLY);
+                auto key = json_key.dump();
+
+                lmdb::val value;
+
+                bool res =
+                  lmdb::dbi_get(txn, readReceiptsDb_, lmdb::val(key.data(), key.size()), value);
+
+                txn.commit();
+
+                if (res) {
+                        auto json_response = json::parse(std::string(value.data(), value.size()));
+                        auto values        = json_response.get<std::vector<ReadReceiptValue>>();
+
+                        for (auto v : values)
+                                receipts.emplace(v.ts, v.user_id);
+                }
+
+        } catch (const lmdb::error &e) {
+                qCritical() << "readReceipts:" << e.what();
+        }
+
+        return receipts;
+}
+
+using Receipts = std::map<std::string, std::map<std::string, uint64_t>>;
+void
+Cache::updateReadReceipt(const std::string &room_id, const Receipts &receipts)
+{
+        for (auto receipt : receipts) {
+                const auto event_id = receipt.first;
+                auto event_receipts = receipt.second;
+
+                ReadReceiptKey receipt_key{event_id, room_id};
+                nlohmann::json json_key = receipt_key;
+
+                try {
+                        auto read_txn  = lmdb::txn::begin(env_, nullptr, MDB_RDONLY);
+                        const auto key = json_key.dump();
+
+                        lmdb::val prev_value;
+
+                        bool exists = lmdb::dbi_get(
+                          read_txn, readReceiptsDb_, lmdb::val(key.data(), key.size()), prev_value);
+
+                        read_txn.commit();
+
+                        std::vector<ReadReceiptValue> saved_receipts;
+
+                        // If an entry for the event id already exists, we would
+                        // merge the existing receipts with the new ones.
+                        if (exists) {
+                                auto json_value =
+                                  json::parse(std::string(prev_value.data(), prev_value.size()));
+
+                                // Retrieve the saved receipts.
+                                saved_receipts = json_value.get<std::vector<ReadReceiptValue>>();
+                        }
+
+                        // Append the new ones.
+                        for (auto event_receipt : event_receipts)
+                                saved_receipts.push_back(
+                                  ReadReceiptValue{event_receipt.first, event_receipt.second});
+
+                        // Save back the merged (or only the new) receipts.
+                        nlohmann::json json_updated_value = saved_receipts;
+                        std::string merged_receipts       = json_updated_value.dump();
+
+                        auto txn = lmdb::txn::begin(env_);
+
+                        lmdb::dbi_put(txn,
+                                      readReceiptsDb_,
+                                      lmdb::val(key.data(), key.size()),
+                                      lmdb::val(merged_receipts.data(), merged_receipts.size()));
+
+                        txn.commit();
+                } catch (const lmdb::error &e) {
+                        qCritical() << "updateReadReceipts:" << e.what();
+                }
+        }
+}