Skip to content
Snippets Groups Projects
Cache.h 8.55 KiB
Newer Older
  • Learn to ignore specific revisions
  • /*
     * 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 <QImage>
    
    #if __has_include(<lmdbxx/lmdb++.h>)
    #include <lmdbxx/lmdb++.h>
    #else
    
    #include <lmdb++.h>
    
    Nicolas Werner's avatar
    Nicolas Werner committed
    
    
    #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);
    
    
    // presence
    mtx::presence::PresenceState
    presenceState(const std::string &user_id);
    std::string
    statusMessage(const std::string &user_id);
    
    
    // user cache stores user keys
    std::optional<UserKeyCache>
    userKeys(const std::string &user_id);
    
    updateUserKeys(const std::string &sync_token, const mtx::responses::QueryKeys &keyQuery);
    
    // device & user verification cache
    
    verificationStatus(const std::string &user_id);
    void
    
    markDeviceVerified(const std::string &user_id, const std::string &device);
    
    markDeviceUnverified(const std::string &user_id, const std::string &device);
    
    //! 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();
    
    
    //! returns if the format is current, older or newer
    cache::CacheVersion
    formatVersion();
    //! set the format version to the current version
    
    void
    setCurrentFormat();
    
    //! migrates db to the current format
    bool
    runMigrations();
    
    
    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);
    
    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
    dropOutboundMegolmSession(const std::string &room_id);
    
    
    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();