2017-07-29 11:49:00 +03:00
|
|
|
/*
|
|
|
|
* 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
|
|
|
|
|
2018-06-28 16:16:43 +03:00
|
|
|
#include <QDateTime>
|
2017-08-26 14:31:23 +03:00
|
|
|
#include <QDir>
|
2018-04-29 15:42:40 +03:00
|
|
|
#include <QImage>
|
2018-06-28 16:16:43 +03:00
|
|
|
#include <QString>
|
2018-06-10 20:03:45 +03:00
|
|
|
|
2017-07-29 11:49:00 +03:00
|
|
|
#include <lmdb++.h>
|
2019-12-14 19:08:36 +03:00
|
|
|
|
2017-12-19 23:36:12 +03:00
|
|
|
#include <mtx/responses.hpp>
|
2018-06-10 20:03:45 +03:00
|
|
|
|
2019-12-15 01:39:02 +03:00
|
|
|
#include "CacheCryptoStructs.h"
|
|
|
|
#include "CacheStructs.h"
|
2018-06-18 18:36:19 +03:00
|
|
|
|
2019-12-15 04:56:04 +03:00
|
|
|
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);
|
|
|
|
QString
|
|
|
|
userColor(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
|
|
|
|
removeUserColor(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);
|
|
|
|
void
|
|
|
|
insertUserColor(const QString &user_id, const QString &color_name);
|
|
|
|
|
|
|
|
void
|
|
|
|
clearUserColors();
|
|
|
|
|
|
|
|
//! 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);
|
2018-06-10 20:03:45 +03:00
|
|
|
|
2019-12-15 04:56:04 +03:00
|
|
|
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);
|
|
|
|
|
|
|
|
//! Filter the events that have at least one read receipt.
|
|
|
|
std::vector<QString>
|
|
|
|
filterReadEvents(const QString &room_id,
|
|
|
|
const std::vector<QString> &event_ids,
|
|
|
|
const std::string &excluded_user);
|
|
|
|
//! Add event for which we are expecting some read receipts.
|
|
|
|
void
|
|
|
|
addPendingReceipt(const QString &room_id, const QString &event_id);
|
|
|
|
void
|
|
|
|
removePendingReceipt(lmdb::txn &txn, const std::string &room_id, const std::string &event_id);
|
|
|
|
void
|
|
|
|
notifyForReadReceipts(const std::string &room_id);
|
|
|
|
std::vector<QString>
|
|
|
|
pendingReceiptsEvents(lmdb::txn &txn, const std::string &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)
|
2017-07-29 11:49:00 +03:00
|
|
|
{
|
2019-12-15 04:56:04 +03:00
|
|
|
return getRoomInfo(roomsWithStateUpdates(sync));
|
|
|
|
}
|
|
|
|
inline std::map<QString, RoomInfo>
|
|
|
|
roomTagUpdates(const mtx::responses::Sync &sync)
|
|
|
|
{
|
|
|
|
return getRoomInfo(roomsWithTagUpdates(sync));
|
|
|
|
}
|
2018-05-08 20:30:09 +03:00
|
|
|
|
2019-12-15 04:56:04 +03:00
|
|
|
//! 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);
|
2018-05-08 20:30:09 +03:00
|
|
|
void
|
2019-12-15 04:56:04 +03:00
|
|
|
calculateRoomReadStatus();
|
|
|
|
|
|
|
|
QVector<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);
|
2018-05-08 20:30:09 +03:00
|
|
|
|
2019-12-15 04:56:04 +03:00
|
|
|
//! 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();
|
2018-05-08 20:30:09 +03:00
|
|
|
}
|