From b3221b09d6e12cda47a4ebc8443cac43bb71d29c Mon Sep 17 00:00:00 2001 From: Nicolas Werner Date: Sat, 5 Feb 2022 08:40:56 +0100 Subject: [PATCH] Add /reset-state command --- man/nheko.1.adoc | 4 ++++ src/Cache.cpp | 38 ++++++++++++++++++++++++++++++++++ src/Cache_p.h | 1 + src/MatrixClient.cpp | 2 ++ src/timeline/InputBar.cpp | 2 ++ src/timeline/TimelineModel.cpp | 25 ++++++++++++++++++++-- src/timeline/TimelineModel.h | 3 +++ 7 files changed, 73 insertions(+), 2 deletions(-) diff --git a/man/nheko.1.adoc b/man/nheko.1.adoc index fe3ff3b3..9914ba93 100644 --- a/man/nheko.1.adoc +++ b/man/nheko.1.adoc @@ -195,6 +195,10 @@ Inserts `ノ┬─┬ノ ︵ ( \\o°o)\\` Removes all but the most recent messages from the currently rendered timeline and then refetches it from the server; can be used to fix some cache issues. +*/reset-state*:: +Fetches all the state events in the current room again; can be used to fix some +cache issues. + */rotate-megolm-session*:: Rotates the encryption key used to send encrypted messages in a room. diff --git a/src/Cache.cpp b/src/Cache.cpp index b55d53a6..9f3ada58 100644 --- a/src/Cache.cpp +++ b/src/Cache.cpp @@ -1460,6 +1460,44 @@ Cache::calculateRoomReadStatus(const std::string &room_id) return getEventIndex(room_id, last_event_id_) > getEventIndex(room_id, fullyReadEventId_); } +void +Cache::updateState(const std::string &room, const mtx::responses::StateEvents &state) +{ + auto txn = lmdb::txn::begin(env_); + auto statesdb = getStatesDb(txn, room); + auto stateskeydb = getStatesKeyDb(txn, room); + auto membersdb = getMembersDb(txn, room); + auto eventsDb = getEventsDb(txn, room); + + saveStateEvents(txn, statesdb, stateskeydb, membersdb, eventsDb, room, state.events); + + RoomInfo updatedInfo; + updatedInfo.name = getRoomName(txn, statesdb, membersdb).toStdString(); + updatedInfo.topic = getRoomTopic(txn, statesdb).toStdString(); + updatedInfo.avatar_url = getRoomAvatarUrl(txn, statesdb, membersdb).toStdString(); + updatedInfo.version = getRoomVersion(txn, statesdb).toStdString(); + updatedInfo.is_space = getRoomIsSpace(txn, statesdb); + + { + std::string_view data; + if (roomsDb_.get(txn, room, data)) { + try { + RoomInfo tmp = json::parse(std::string_view(data.data(), data.size())); + updatedInfo.tags = tmp.tags; + } catch (const json::exception &e) { + nhlog::db()->warn("failed to parse room info: room_id ({}), {}: {}", + room, + std::string(data.data(), data.size()), + e.what()); + } + } + } + + roomsDb_.put(txn, room, json(updatedInfo).dump()); + updateSpaces(txn, {room}, {room}); + txn.commit(); +} + void Cache::saveState(const mtx::responses::Sync &res) { diff --git a/src/Cache_p.h b/src/Cache_p.h index 160ba626..8e5fa547 100644 --- a/src/Cache_p.h +++ b/src/Cache_p.h @@ -118,6 +118,7 @@ public: std::size_t len = 30); size_t memberCount(const std::string &room_id); + void updateState(const std::string &room, const mtx::responses::StateEvents &state); void saveState(const mtx::responses::Sync &res); bool isInitialized(); bool isDatabaseReady() { return databaseReady_ && isInitialized(); } diff --git a/src/MatrixClient.cpp b/src/MatrixClient.cpp index 1ef2bd3a..c565176e 100644 --- a/src/MatrixClient.cpp +++ b/src/MatrixClient.cpp @@ -20,6 +20,7 @@ Q_DECLARE_METATYPE(mtx::responses::Messages) Q_DECLARE_METATYPE(mtx::responses::Notifications) Q_DECLARE_METATYPE(mtx::responses::Rooms) Q_DECLARE_METATYPE(mtx::responses::Sync) +Q_DECLARE_METATYPE(mtx::responses::StateEvents) Q_DECLARE_METATYPE(mtx::responses::JoinedGroups) Q_DECLARE_METATYPE(mtx::responses::GroupProfile) @@ -52,6 +53,7 @@ init() qRegisterMetaType(); qRegisterMetaType(); qRegisterMetaType(); + qRegisterMetaType(); qRegisterMetaType(); qRegisterMetaType(); qRegisterMetaType(); diff --git a/src/timeline/InputBar.cpp b/src/timeline/InputBar.cpp index 18e224b2..cd7c4e0c 100644 --- a/src/timeline/InputBar.cpp +++ b/src/timeline/InputBar.cpp @@ -617,6 +617,8 @@ InputBar::command(const QString &command, QString args) message(QStringLiteral("ノ┬─┬ノ ︵ ( \\o°o)\\")); } else if (command == QLatin1String("clear-timeline")) { room->clearTimeline(); + } else if (command == QLatin1String("reset-state")) { + room->resetState(); } else if (command == QLatin1String("rotate-megolm-session")) { cache::dropOutboundMegolmSession(room->roomId().toStdString()); } else if (command == QLatin1String("md")) { diff --git a/src/timeline/TimelineModel.cpp b/src/timeline/TimelineModel.cpp index 6fc10142..719c7be6 100644 --- a/src/timeline/TimelineModel.cpp +++ b/src/timeline/TimelineModel.cpp @@ -440,6 +440,11 @@ TimelineModel::TimelineModel(TimelineViewManager *manager, QString room_id, QObj cache::client(), &Cache::verificationStatusChanged, this, &TimelineModel::trustlevelChanged); showEventTimer.callOnTimeout(this, &TimelineModel::scrollTimerEvent); + + connect(this, &TimelineModel::newState, this, [this](mtx::responses::StateEvents events_) { + cache::client()->updateState(room_id_.toStdString(), events_); + this->syncState({std::move(events_.events)}); + }); } QHash @@ -2170,6 +2175,21 @@ TimelineModel::resetEdit() } } +void +TimelineModel::resetState() +{ + http::client()->get_state( + room_id_.toStdString(), + [this](const mtx::responses::StateEvents &events_, mtx::http::RequestErr e) { + if (e) { + nhlog::net()->error("Failed to retrive current room state: {}", *e); + return; + } + + emit newState(events_); + }); +} + QString TimelineModel::roomName() const { @@ -2247,8 +2267,9 @@ TimelineModel::widgetLinks() const QStringList list; - auto user = utils::localUser(); - auto av = QUrl::toPercentEncoding(QString::fromStdString(http::client()->mxc_to_download_url(avatarUrl(user).toStdString()))); + auto user = utils::localUser(); + auto av = QUrl::toPercentEncoding( + QString::fromStdString(http::client()->mxc_to_download_url(avatarUrl(user).toStdString()))); auto disp = QUrl::toPercentEncoding(displayName(user)); auto theme = UserSettings::instance()->theme(); if (theme == QStringLiteral("system")) diff --git a/src/timeline/TimelineModel.h b/src/timeline/TimelineModel.h index b4267e8d..f6cc1e6b 100644 --- a/src/timeline/TimelineModel.h +++ b/src/timeline/TimelineModel.h @@ -359,6 +359,7 @@ public slots: void resetEdit(); void setDecryptDescription(bool decrypt) { decryptDescription = decrypt; } void clearTimeline() { events.clearTimeline(); } + void resetState(); void receivedSessionKey(const std::string &session_key) { events.receivedSessionKey(session_key); @@ -401,6 +402,8 @@ signals: void lastMessageChanged(); void notificationsChanged(); + void newState(mtx::responses::StateEvents events); + void newMessageToSend(mtx::events::collections::TimelineEvents event); void addPendingMessageToStore(mtx::events::collections::TimelineEvents event); void updateFlowEventId(std::string event_id);