diff options
author | Nicolas Werner <nicolas.werner@hotmail.de> | 2023-03-14 03:02:54 +0100 |
---|---|---|
committer | Nicolas Werner <nicolas.werner@hotmail.de> | 2023-03-14 18:16:08 +0100 |
commit | 234ac79acc5d4ea1566b1b587c866e30f8cdfe83 (patch) | |
tree | cbfaac61845a32d352c298796bafac3152651b85 /src/Utils.cpp | |
parent | Speed up writes of events with statekeys to state db (diff) | |
download | nheko-234ac79acc5d4ea1566b1b587c866e30f8cdfe83.tar.xz |
Update spaces events automatically in the background
Diffstat (limited to 'src/Utils.cpp')
-rw-r--r-- | src/Utils.cpp | 180 |
1 files changed, 178 insertions, 2 deletions
diff --git a/src/Utils.cpp b/src/Utils.cpp index 54bd51ab..c5b2abd1 100644 --- a/src/Utils.cpp +++ b/src/Utils.cpp @@ -16,6 +16,7 @@ #include <QStringBuilder> #include <QTextBoundaryFinder> #include <QTextDocument> +#include <QTimer> #include <QWindow> #include <QXmlStreamReader> @@ -28,11 +29,13 @@ #include "Cache.h" #include "Cache_p.h" +#include "ChatPage.h" #include "Config.h" #include "EventAccessors.h" #include "Logging.h" #include "MatrixClient.h" #include "UserSettingsPage.h" +#include "timeline/Permissions.h" using TimelineEvent = mtx::events::collections::TimelineEvents; @@ -1294,8 +1297,6 @@ utils::roomVias(const std::string &roomid) deniedServers.reserve(acls->content.deny.size()); for (const auto &s : acls->content.deny) allowedServers.push_back(globToRegexp(s)); - - nhlog::ui()->critical("ACL: {}", nlohmann::json(acls->content).dump(2)); } auto isHostAllowed = [&acls, &allowedServers, &deniedServers](const std::string &host) { @@ -1423,3 +1424,178 @@ utils::roomVias(const std::string &roomid) return vias; } + +void +utils::updateSpaceVias() +{ + if (!UserSettings::instance()->updateSpaceVias()) + return; + + nhlog::net()->info("update space vias called"); + + auto rooms = cache::roomInfo(false); + + auto us = http::client()->user_id().to_string(); + + auto weekAgo = (uint64_t)QDateTime::currentDateTime().addDays(-7).toMSecsSinceEpoch(); + + struct ApplySpaceUpdatesState + { + std::vector<mtx::events::StateEvent<mtx::events::state::space::Child>> childrenToUpdate; + std::vector<mtx::events::StateEvent<mtx::events::state::space::Parent>> parentsToUpdate; + + static void next(std::shared_ptr<ApplySpaceUpdatesState> state) + { + if (!state->childrenToUpdate.empty()) { + const auto &child = state->childrenToUpdate.back(); + + http::client()->send_state_event( + child.room_id, + child.state_key, + child.content, + [state = std::move(state)](const mtx::responses::EventId &, + mtx::http::RequestErr e) mutable { + const auto &child_ = state->childrenToUpdate.back(); + if (e) { + if (e->status_code == 429 && e->matrix_error.retry_after.count() != 0) { + ChatPage::instance()->callFunctionOnGuiThread( + [state = std::move(state), + interval = e->matrix_error.retry_after]() { + QTimer::singleShot(interval, + ChatPage::instance(), + [self = std::move(state)]() mutable { + next(std::move(self)); + }); + }); + return; + } + + nhlog::net()->error("Failed to update space child {} -> {}: {}", + child_.room_id, + child_.state_key, + *e); + } + nhlog::net()->info( + "Updated space child {} -> {}", child_.room_id, child_.state_key); + state->childrenToUpdate.pop_back(); + next(std::move(state)); + }); + return; + } else if (!state->parentsToUpdate.empty()) { + const auto &parent = state->parentsToUpdate.back(); + + http::client()->send_state_event( + parent.room_id, + parent.state_key, + parent.content, + [state = std::move(state)](const mtx::responses::EventId &, + mtx::http::RequestErr e) mutable { + const auto &parent_ = state->parentsToUpdate.back(); + if (e) { + if (e->status_code == 429 && e->matrix_error.retry_after.count() != 0) { + ChatPage::instance()->callFunctionOnGuiThread( + [state = std::move(state), + interval = e->matrix_error.retry_after]() { + QTimer::singleShot(interval, + ChatPage::instance(), + [self = std::move(state)]() mutable { + next(std::move(self)); + }); + }); + return; + } + + nhlog::net()->error("Failed to update space parent {} -> {}: {}", + parent_.room_id, + parent_.state_key, + *e); + } + nhlog::net()->info( + "Updated space parent {} -> {}", parent_.room_id, parent_.state_key); + state->parentsToUpdate.pop_back(); + next(std::move(state)); + }); + return; + } + } + }; + + auto asus = std::make_shared<ApplySpaceUpdatesState>(); + + for (const auto &[roomid, info] : rooms.toStdMap()) { + if (!info.is_space) + continue; + + auto spaceid = roomid.toStdString(); + + if (auto pl = cache::client() + ->getStateEvent<mtx::events::state::PowerLevels>(spaceid) + .value_or(mtx::events::StateEvent<mtx::events::state::PowerLevels>{}) + .content; + pl.user_level(us) < pl.state_level(to_string(mtx::events::EventType::SpaceChild))) + continue; + + auto children = cache::client()->getChildRoomIds(spaceid); + + for (const auto &childid : children) { + // only update children we are joined to + if (!rooms.contains(QString::fromStdString(childid))) + continue; + + auto child = + cache::client()->getStateEvent<mtx::events::state::space::Child>(spaceid, childid); + if (child && + // don't update too often + child->origin_server_ts < weekAgo && + // ignore unset spaces + (child->content.via && !child->content.via->empty())) { + auto newVias = utils::roomVias(childid); + + if (!newVias.empty() && newVias != child->content.via) { + nhlog::net()->info("Will update {} -> {} child relation from {} to {}", + spaceid, + childid, + fmt::join(*child->content.via, ","), + fmt::join(newVias, ",")); + + child->content.via = std::move(newVias); + child->room_id = spaceid; + asus->childrenToUpdate.push_back(*std::move(child)); + } + } + + auto parent = + cache::client()->getStateEvent<mtx::events::state::space::Parent>(childid, spaceid); + if (parent && + // don't update too often + parent->origin_server_ts < weekAgo && + // ignore unset spaces + (parent->content.via && !parent->content.via->empty())) { + if (auto pl = + cache::client() + ->getStateEvent<mtx::events::state::PowerLevels>(childid) + .value_or(mtx::events::StateEvent<mtx::events::state::PowerLevels>{}) + .content; + pl.user_level(us) < + pl.state_level(to_string(mtx::events::EventType::SpaceParent))) + continue; + + auto newVias = utils::roomVias(spaceid); + + if (!newVias.empty() && newVias != parent->content.via) { + nhlog::net()->info("Will update {} -> {} parent relation from {} to {}", + childid, + spaceid, + fmt::join(*parent->content.via, ","), + fmt::join(newVias, ",")); + + parent->content.via = std::move(newVias); + parent->room_id = childid; + asus->parentsToUpdate.push_back(*std::move(parent)); + } + } + } + } + + ApplySpaceUpdatesState::next(std::move(asus)); +} |