e6fcccc8bd
We don't get notified for every message. Sometimes we only get a read receipt for the newest message, which means old read receipts accumulate in the database. This least to some considerable CPU overhead, when checking if the timeline should be notified for new read receipts. Instead just always notify, since that has far less overhead in the worst case and doesn't need complicated cache cleanup. The old pending_receipts db is not removed for now. It should still have minimal storage overhead and we don't have a good mechanism for cache format upgrades atm.
282 lines
7.7 KiB
C++
282 lines
7.7 KiB
C++
/*
|
|
* nheko Copyright (C) 2017 Konstantinos Sideris <siderisk@auth.gr>
|
|
*
|
|
* This program is free software: you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation, either version 3 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
#pragma once
|
|
|
|
#include <QDateTime>
|
|
#include <QDir>
|
|
#include <QImage>
|
|
#include <QString>
|
|
|
|
#if __has_include(<lmdbxx/lmdb++.h>)
|
|
#include <lmdbxx/lmdb++.h>
|
|
#else
|
|
#include <lmdb++.h>
|
|
#endif
|
|
|
|
#include <mtx/responses.hpp>
|
|
|
|
#include "CacheCryptoStructs.h"
|
|
#include "CacheStructs.h"
|
|
|
|
namespace cache {
|
|
void
|
|
init(const QString &user_id);
|
|
|
|
std::string
|
|
displayName(const std::string &room_id, const std::string &user_id);
|
|
QString
|
|
displayName(const QString &room_id, const QString &user_id);
|
|
QString
|
|
avatarUrl(const QString &room_id, const QString &user_id);
|
|
|
|
void
|
|
removeDisplayName(const QString &room_id, const QString &user_id);
|
|
void
|
|
removeAvatarUrl(const QString &room_id, const QString &user_id);
|
|
|
|
void
|
|
insertDisplayName(const QString &room_id, const QString &user_id, const QString &display_name);
|
|
void
|
|
insertAvatarUrl(const QString &room_id, const QString &user_id, const QString &avatar_url);
|
|
|
|
//! Load saved data for the display names & avatars.
|
|
void
|
|
populateMembers();
|
|
std::vector<std::string>
|
|
joinedRooms();
|
|
|
|
QMap<QString, RoomInfo>
|
|
roomInfo(bool withInvites = true);
|
|
std::map<QString, bool>
|
|
invites();
|
|
|
|
//! Calculate & return the name of the room.
|
|
QString
|
|
getRoomName(lmdb::txn &txn, lmdb::dbi &statesdb, lmdb::dbi &membersdb);
|
|
//! Get room join rules
|
|
mtx::events::state::JoinRule
|
|
getRoomJoinRule(lmdb::txn &txn, lmdb::dbi &statesdb);
|
|
bool
|
|
getRoomGuestAccess(lmdb::txn &txn, lmdb::dbi &statesdb);
|
|
//! Retrieve the topic of the room if any.
|
|
QString
|
|
getRoomTopic(lmdb::txn &txn, lmdb::dbi &statesdb);
|
|
//! Retrieve the room avatar's url if any.
|
|
QString
|
|
getRoomAvatarUrl(lmdb::txn &txn, lmdb::dbi &statesdb, lmdb::dbi &membersdb, const QString &room_id);
|
|
//! Retrieve the version of the room if any.
|
|
QString
|
|
getRoomVersion(lmdb::txn &txn, lmdb::dbi &statesdb);
|
|
|
|
//! Retrieve member info from a room.
|
|
std::vector<RoomMember>
|
|
getMembers(const std::string &room_id, std::size_t startIndex = 0, std::size_t len = 30);
|
|
|
|
void
|
|
saveState(const mtx::responses::Sync &res);
|
|
bool
|
|
isInitialized();
|
|
|
|
std::string
|
|
nextBatchToken();
|
|
|
|
void
|
|
deleteData();
|
|
|
|
void
|
|
removeInvite(lmdb::txn &txn, const std::string &room_id);
|
|
void
|
|
removeInvite(const std::string &room_id);
|
|
void
|
|
removeRoom(lmdb::txn &txn, const std::string &roomid);
|
|
void
|
|
removeRoom(const std::string &roomid);
|
|
void
|
|
removeRoom(const QString &roomid);
|
|
void
|
|
setup();
|
|
|
|
bool
|
|
isFormatValid();
|
|
void
|
|
setCurrentFormat();
|
|
|
|
std::map<QString, mtx::responses::Timeline>
|
|
roomMessages();
|
|
|
|
QMap<QString, mtx::responses::Notifications>
|
|
getTimelineMentions();
|
|
|
|
//! Retrieve all the user ids from a room.
|
|
std::vector<std::string>
|
|
roomMembers(const std::string &room_id);
|
|
|
|
//! Check if the given user has power leve greater than than
|
|
//! lowest power level of the given events.
|
|
bool
|
|
hasEnoughPowerLevel(const std::vector<mtx::events::EventType> &eventTypes,
|
|
const std::string &room_id,
|
|
const std::string &user_id);
|
|
|
|
//! Retrieves the saved room avatar.
|
|
QImage
|
|
getRoomAvatar(const QString &id);
|
|
QImage
|
|
getRoomAvatar(const std::string &id);
|
|
|
|
//! Adds a user to the read list for the given event.
|
|
//!
|
|
//! There should be only one user id present in a receipt list per room.
|
|
//! The user id should be removed from any other lists.
|
|
using Receipts = std::map<std::string, std::map<std::string, uint64_t>>;
|
|
void
|
|
updateReadReceipt(lmdb::txn &txn, const std::string &room_id, const Receipts &receipts);
|
|
|
|
//! Retrieve all the read receipts for the given event id and room.
|
|
//!
|
|
//! Returns a map of user ids and the time of the read receipt in milliseconds.
|
|
using UserReceipts = std::multimap<uint64_t, std::string, std::greater<uint64_t>>;
|
|
UserReceipts
|
|
readReceipts(const QString &event_id, const QString &room_id);
|
|
|
|
QByteArray
|
|
image(const QString &url);
|
|
QByteArray
|
|
image(lmdb::txn &txn, const std::string &url);
|
|
inline QByteArray
|
|
image(const std::string &url)
|
|
{
|
|
return image(QString::fromStdString(url));
|
|
}
|
|
void
|
|
saveImage(const std::string &url, const std::string &data);
|
|
void
|
|
saveImage(const QString &url, const QByteArray &data);
|
|
|
|
RoomInfo
|
|
singleRoomInfo(const std::string &room_id);
|
|
std::vector<std::string>
|
|
roomsWithStateUpdates(const mtx::responses::Sync &res);
|
|
std::vector<std::string>
|
|
roomsWithTagUpdates(const mtx::responses::Sync &res);
|
|
std::map<QString, RoomInfo>
|
|
getRoomInfo(const std::vector<std::string> &rooms);
|
|
inline std::map<QString, RoomInfo>
|
|
roomUpdates(const mtx::responses::Sync &sync)
|
|
{
|
|
return getRoomInfo(roomsWithStateUpdates(sync));
|
|
}
|
|
inline std::map<QString, RoomInfo>
|
|
roomTagUpdates(const mtx::responses::Sync &sync)
|
|
{
|
|
return getRoomInfo(roomsWithTagUpdates(sync));
|
|
}
|
|
|
|
//! Calculates which the read status of a room.
|
|
//! Whether all the events in the timeline have been read.
|
|
bool
|
|
calculateRoomReadStatus(const std::string &room_id);
|
|
void
|
|
calculateRoomReadStatus();
|
|
|
|
std::vector<SearchResult>
|
|
searchUsers(const std::string &room_id, const std::string &query, std::uint8_t max_items = 5);
|
|
std::vector<RoomSearchResult>
|
|
searchRooms(const std::string &query, std::uint8_t max_items = 5);
|
|
|
|
void
|
|
markSentNotification(const std::string &event_id);
|
|
//! Removes an event from the sent notifications.
|
|
void
|
|
removeReadNotification(const std::string &event_id);
|
|
//! Check if we have sent a desktop notification for the given event id.
|
|
bool
|
|
isNotificationSent(const std::string &event_id);
|
|
|
|
//! Add all notifications containing a user mention to the db.
|
|
void
|
|
saveTimelineMentions(const mtx::responses::Notifications &res);
|
|
|
|
//! Remove old unused data.
|
|
void
|
|
deleteOldMessages();
|
|
void
|
|
deleteOldData() noexcept;
|
|
//! Retrieve all saved room ids.
|
|
std::vector<std::string>
|
|
getRoomIds(lmdb::txn &txn);
|
|
|
|
//! Mark a room that uses e2e encryption.
|
|
void
|
|
setEncryptedRoom(lmdb::txn &txn, const std::string &room_id);
|
|
bool
|
|
isRoomEncrypted(const std::string &room_id);
|
|
|
|
//! Check if a user is a member of the room.
|
|
bool
|
|
isRoomMember(const std::string &user_id, const std::string &room_id);
|
|
|
|
//
|
|
// Outbound Megolm Sessions
|
|
//
|
|
void
|
|
saveOutboundMegolmSession(const std::string &room_id,
|
|
const OutboundGroupSessionData &data,
|
|
mtx::crypto::OutboundGroupSessionPtr session);
|
|
OutboundGroupSessionDataRef
|
|
getOutboundMegolmSession(const std::string &room_id);
|
|
bool
|
|
outboundMegolmSessionExists(const std::string &room_id) noexcept;
|
|
void
|
|
updateOutboundMegolmSession(const std::string &room_id, int message_index);
|
|
|
|
void
|
|
importSessionKeys(const mtx::crypto::ExportedSessionKeys &keys);
|
|
mtx::crypto::ExportedSessionKeys
|
|
exportSessionKeys();
|
|
|
|
//
|
|
// Inbound Megolm Sessions
|
|
//
|
|
void
|
|
saveInboundMegolmSession(const MegolmSessionIndex &index,
|
|
mtx::crypto::InboundGroupSessionPtr session);
|
|
OlmInboundGroupSession *
|
|
getInboundMegolmSession(const MegolmSessionIndex &index);
|
|
bool
|
|
inboundMegolmSessionExists(const MegolmSessionIndex &index);
|
|
|
|
//
|
|
// Olm Sessions
|
|
//
|
|
void
|
|
saveOlmSession(const std::string &curve25519, mtx::crypto::OlmSessionPtr session);
|
|
std::vector<std::string>
|
|
getOlmSessions(const std::string &curve25519);
|
|
std::optional<mtx::crypto::OlmSessionPtr>
|
|
getOlmSession(const std::string &curve25519, const std::string &session_id);
|
|
|
|
void
|
|
saveOlmAccount(const std::string &pickled);
|
|
std::string
|
|
restoreOlmAccount();
|
|
|
|
void
|
|
restoreSessions();
|
|
}
|