summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorNicolas Werner <nicolas.werner@hotmail.de>2021-01-26 22:36:35 +0100
committerNicolas Werner <nicolas.werner@hotmail.de>2021-02-09 20:22:02 +0100
commit2e77a1554f1572b7c7e59f8177a48e5dffa16c23 (patch)
treea6a6c22e64646683d8c283e391d922fa4da1b335 /src
parent463cee71460bfa64dfd64bf7018fb928e3589331 (diff)
Switch to new relations format
Diffstat (limited to 'src')
-rw-r--r--src/Cache.cpp72
-rw-r--r--src/DeviceVerificationFlow.cpp34
-rw-r--r--src/DeviceVerificationFlow.h10
-rw-r--r--src/EventAccessors.cpp35
-rw-r--r--src/EventAccessors.h6
-rw-r--r--src/Olm.cpp27
-rw-r--r--src/timeline/EventStore.cpp37
-rw-r--r--src/timeline/InputBar.cpp18
-rw-r--r--src/timeline/TimelineModel.cpp4
-rw-r--r--src/timeline/TimelineViewManager.cpp8
10 files changed, 110 insertions, 141 deletions
diff --git a/src/Cache.cpp b/src/Cache.cpp
index 3f2bf73a..94b9a6a6 100644
--- a/src/Cache.cpp
+++ b/src/Cache.cpp
@@ -2713,23 +2713,19 @@ Cache::saveTimelineMessages(lmdb::txn &txn,
lmdb::dbi_put(txn, evToOrderDb, event_id, txn_order);
lmdb::dbi_del(txn, evToOrderDb, lmdb::val(txn_id));
- if (event.contains("content") &&
- event["content"].contains("m.relates_to")) {
- auto temp = event["content"]["m.relates_to"];
- json relates_to_j = temp.contains("m.in_reply_to") &&
- temp["m.in_reply_to"].is_object()
- ? temp["m.in_reply_to"]["event_id"]
- : temp["event_id"];
- std::string relates_to =
- relates_to_j.is_string() ? relates_to_j.get<std::string>() : "";
-
- if (!relates_to.empty()) {
- lmdb::dbi_del(txn,
- relationsDb,
- lmdb::val(relates_to),
- lmdb::val(txn_id));
- lmdb::dbi_put(
- txn, relationsDb, lmdb::val(relates_to), event_id);
+ auto relations = mtx::accessors::relations(e);
+ if (!relations.relations.empty()) {
+ for (const auto &r : relations.relations) {
+ if (!r.event_id.empty()) {
+ lmdb::dbi_del(txn,
+ relationsDb,
+ lmdb::val(r.event_id),
+ lmdb::val(txn_id));
+ lmdb::dbi_put(txn,
+ relationsDb,
+ lmdb::val(r.event_id),
+ event_id);
+ }
}
}
@@ -2808,19 +2804,16 @@ Cache::saveTimelineMessages(lmdb::txn &txn,
lmdb::val(&msgIndex, sizeof(msgIndex)));
}
- if (event.contains("content") &&
- event["content"].contains("m.relates_to")) {
- auto temp = event["content"]["m.relates_to"];
- json relates_to_j = temp.contains("m.in_reply_to") &&
- temp["m.in_reply_to"].is_object()
- ? temp["m.in_reply_to"]["event_id"]
- : temp["event_id"];
- std::string relates_to =
- relates_to_j.is_string() ? relates_to_j.get<std::string>() : "";
-
- if (!relates_to.empty())
- lmdb::dbi_put(
- txn, relationsDb, lmdb::val(relates_to), event_id);
+ auto relations = mtx::accessors::relations(e);
+ if (!relations.relations.empty()) {
+ for (const auto &r : relations.relations) {
+ if (!r.event_id.empty()) {
+ lmdb::dbi_put(txn,
+ relationsDb,
+ lmdb::val(r.event_id),
+ event_id);
+ }
+ }
}
}
}
@@ -2901,17 +2894,14 @@ Cache::saveOldMessages(const std::string &room_id, const mtx::responses::Message
txn, msg2orderDb, event_id, lmdb::val(&msgIndex, sizeof(msgIndex)));
}
- if (event.contains("content") && event["content"].contains("m.relates_to")) {
- auto temp = event["content"]["m.relates_to"];
- json relates_to_j =
- temp.contains("m.in_reply_to") && temp["m.in_reply_to"].is_object()
- ? temp["m.in_reply_to"]["event_id"]
- : temp["event_id"];
- std::string relates_to =
- relates_to_j.is_string() ? relates_to_j.get<std::string>() : "";
-
- if (!relates_to.empty())
- lmdb::dbi_put(txn, relationsDb, lmdb::val(relates_to), event_id);
+ auto relations = mtx::accessors::relations(e);
+ if (!relations.relations.empty()) {
+ for (const auto &r : relations.relations) {
+ if (!r.event_id.empty()) {
+ lmdb::dbi_put(
+ txn, relationsDb, lmdb::val(r.event_id), event_id);
+ }
+ }
}
}
diff --git a/src/DeviceVerificationFlow.cpp b/src/DeviceVerificationFlow.cpp
index 51ef79fd..c6277a9d 100644
--- a/src/DeviceVerificationFlow.cpp
+++ b/src/DeviceVerificationFlow.cpp
@@ -105,8 +105,8 @@ DeviceVerificationFlow::DeviceVerificationFlow(QObject *,
if (msg.transaction_id.has_value()) {
if (msg.transaction_id.value() != this->transaction_id)
return;
- } else if (msg.relates_to.has_value()) {
- if (msg.relates_to.value().event_id != this->relation.event_id)
+ } else if (msg.relations.references()) {
+ if (msg.relations.references() != this->relation.event_id)
return;
}
if ((msg.key_agreement_protocol == "curve25519-hkdf-sha256") &&
@@ -136,8 +136,8 @@ DeviceVerificationFlow::DeviceVerificationFlow(QObject *,
if (msg.transaction_id.has_value()) {
if (msg.transaction_id.value() != this->transaction_id)
return;
- } else if (msg.relates_to.has_value()) {
- if (msg.relates_to.value().event_id != this->relation.event_id)
+ } else if (msg.relations.references()) {
+ if (msg.relations.references() != this->relation.event_id)
return;
}
error_ = User;
@@ -152,8 +152,8 @@ DeviceVerificationFlow::DeviceVerificationFlow(QObject *,
if (msg.transaction_id.has_value()) {
if (msg.transaction_id.value() != this->transaction_id)
return;
- } else if (msg.relates_to.has_value()) {
- if (msg.relates_to.value().event_id != this->relation.event_id)
+ } else if (msg.relations.references()) {
+ if (msg.relations.references() != this->relation.event_id)
return;
}
@@ -217,8 +217,8 @@ DeviceVerificationFlow::DeviceVerificationFlow(QObject *,
if (msg.transaction_id.has_value()) {
if (msg.transaction_id.value() != this->transaction_id)
return;
- } else if (msg.relates_to.has_value()) {
- if (msg.relates_to.value().event_id != this->relation.event_id)
+ } else if (msg.relations.references()) {
+ if (msg.relations.references() != this->relation.event_id)
return;
}
@@ -385,8 +385,8 @@ DeviceVerificationFlow::DeviceVerificationFlow(QObject *,
if (msg.transaction_id.has_value()) {
if (msg.transaction_id.value() != this->transaction_id)
return;
- } else if ((msg.relates_to.has_value() && sender)) {
- if (msg.relates_to.value().event_id != this->relation.event_id)
+ } else if (msg.relations.references()) {
+ if (msg.relations.references() != this->relation.event_id)
return;
else {
this->deviceId = QString::fromStdString(msg.from_device);
@@ -402,8 +402,8 @@ DeviceVerificationFlow::DeviceVerificationFlow(QObject *,
if (msg.transaction_id.has_value()) {
if (msg.transaction_id.value() != this->transaction_id)
return;
- } else if (msg.relates_to.has_value()) {
- if (msg.relates_to.value().event_id != this->relation.event_id)
+ } else if (msg.relations.references()) {
+ if (msg.relations.references() != this->relation.event_id)
return;
}
nhlog::ui()->info("Flow done on other side");
@@ -526,8 +526,8 @@ DeviceVerificationFlow::handleStartMessage(const mtx::events::msg::KeyVerificati
if (msg.transaction_id.has_value()) {
if (msg.transaction_id.value() != this->transaction_id)
return;
- } else if (msg.relates_to.has_value()) {
- if (msg.relates_to.value().event_id != this->relation.event_id)
+ } else if (msg.relations.references()) {
+ if (msg.relations.references() != this->relation.event_id)
return;
}
if ((std::find(msg.key_agreement_protocols.begin(),
@@ -625,8 +625,10 @@ DeviceVerificationFlow::startVerificationRequest()
req.transaction_id = this->transaction_id;
this->canonical_json = nlohmann::json(req);
} else if (this->type == DeviceVerificationFlow::Type::RoomMsg && model_) {
- req.relates_to = this->relation;
- this->canonical_json = nlohmann::json(req);
+ req.relations.relations.push_back(this->relation);
+ // Set synthesized to surpress the nheko relation extensions
+ req.relations.synthesized = true;
+ this->canonical_json = nlohmann::json(req);
}
send(req);
setState(WaitingForOtherToAccept);
diff --git a/src/DeviceVerificationFlow.h b/src/DeviceVerificationFlow.h
index 34b78962..6c613545 100644
--- a/src/DeviceVerificationFlow.h
+++ b/src/DeviceVerificationFlow.h
@@ -206,7 +206,7 @@ private:
std::vector<int> sasList;
UserKeyCache their_keys;
TimelineModel *model_;
- mtx::common::RelatesTo relation;
+ mtx::common::Relation relation;
State state_ = PromptStartVerification;
Error error_ = UnknownMethod;
@@ -230,8 +230,12 @@ private:
static_cast<int>(err->status_code));
});
} else if (this->type == DeviceVerificationFlow::Type::RoomMsg && model_) {
- if constexpr (!std::is_same_v<T, mtx::events::msg::KeyVerificationRequest>)
- msg.relates_to = this->relation;
+ if constexpr (!std::is_same_v<T,
+ mtx::events::msg::KeyVerificationRequest>) {
+ msg.relations.relations.push_back(this->relation);
+ // Set synthesized to surpress the nheko relation extensions
+ msg.relations.synthesized = true;
+ }
(model_)->sendMessageEvent(msg, mtx::events::to_device_content_to_type<T>);
}
diff --git a/src/EventAccessors.cpp b/src/EventAccessors.cpp
index 3ae781f0..4218f491 100644
--- a/src/EventAccessors.cpp
+++ b/src/EventAccessors.cpp
@@ -250,31 +250,17 @@ struct EventFilesize
}
};
-struct EventInReplyTo
+struct EventRelations
{
template<class Content>
- using related_ev_id_t = decltype(Content::relates_to.in_reply_to.event_id);
+ using related_ev_id_t = decltype(Content::relations);
template<class T>
- std::string operator()(const mtx::events::Event<T> &e)
+ mtx::common::Relations operator()(const mtx::events::Event<T> &e)
{
if constexpr (is_detected<related_ev_id_t, T>::value) {
- return e.content.relates_to.in_reply_to.event_id;
+ return e.content.relations;
}
- return "";
- }
-};
-
-struct EventRelatesTo
-{
- template<class Content>
- using related_ev_id_t = decltype(Content::relates_to.event_id);
- template<class T>
- std::string operator()(const mtx::events::Event<T> &e)
- {
- if constexpr (is_detected<related_ev_id_t, T>::value) {
- return e.content.relates_to.event_id;
- }
- return "";
+ return {};
}
};
@@ -434,15 +420,10 @@ mtx::accessors::mimetype(const mtx::events::collections::TimelineEvents &event)
{
return std::visit(EventMimeType{}, event);
}
-std::string
-mtx::accessors::in_reply_to_event(const mtx::events::collections::TimelineEvents &event)
-{
- return std::visit(EventInReplyTo{}, event);
-}
-std::string
-mtx::accessors::relates_to_event_id(const mtx::events::collections::TimelineEvents &event)
+mtx::common::Relations
+mtx::accessors::relations(const mtx::events::collections::TimelineEvents &event)
{
- return std::visit(EventRelatesTo{}, event);
+ return std::visit(EventRelations{}, event);
}
std::string
diff --git a/src/EventAccessors.h b/src/EventAccessors.h
index 0cdc5f89..60912497 100644
--- a/src/EventAccessors.h
+++ b/src/EventAccessors.h
@@ -53,10 +53,8 @@ std::string
blurhash(const mtx::events::collections::TimelineEvents &event);
std::string
mimetype(const mtx::events::collections::TimelineEvents &event);
-std::string
-in_reply_to_event(const mtx::events::collections::TimelineEvents &event);
-std::string
-relates_to_event_id(const mtx::events::collections::TimelineEvents &event);
+mtx::common::Relations
+relations(const mtx::events::collections::TimelineEvents &event);
std::string
transaction_id(const mtx::events::collections::TimelineEvents &event);
diff --git a/src/Olm.cpp b/src/Olm.cpp
index 4ccf8ab9..54be4751 100644
--- a/src/Olm.cpp
+++ b/src/Olm.cpp
@@ -575,29 +575,19 @@ encrypt_group_message(const std::string &room_id, const std::string &device_id,
if (!sendSessionTo.empty())
olm::send_encrypted_to_device_messages(sendSessionTo, megolm_payload);
- mtx::common::ReplyRelatesTo relation;
- mtx::common::RelatesTo r_relation;
-
// relations shouldn't be encrypted...
- if (body["content"].contains("m.relates_to")) {
- if (body["content"]["m.relates_to"].contains("m.in_reply_to")) {
- relation = body["content"]["m.relates_to"];
- } else if (body["content"]["m.relates_to"].contains("event_id")) {
- r_relation = body["content"]["m.relates_to"];
- }
- }
+ mtx::common::Relations relations = mtx::common::parse_relations(body["content"]);
auto payload = olm::client()->encrypt_group_message(session.get(), body.dump());
// Prepare the m.room.encrypted event.
msg::Encrypted data;
- data.ciphertext = std::string((char *)payload.data(), payload.size());
- data.sender_key = olm::client()->identity_keys().curve25519;
- data.session_id = mtx::crypto::session_id(session.get());
- data.device_id = device_id;
- data.algorithm = MEGOLM_ALGO;
- data.relates_to = relation;
- data.r_relates_to = r_relation;
+ data.ciphertext = std::string((char *)payload.data(), payload.size());
+ data.sender_key = olm::client()->identity_keys().curve25519;
+ data.session_id = mtx::crypto::session_id(session.get());
+ data.device_id = device_id;
+ data.algorithm = MEGOLM_ALGO;
+ data.relations = relations;
group_session_data.message_index = olm_outbound_group_session_message_index(session.get());
nhlog::crypto()->debug("next message_index {}", group_session_data.message_index);
@@ -910,8 +900,7 @@ decryptEvent(const MegolmSessionIndex &index,
body["unsigned"] = event.unsigned_data;
// relations are unencrypted in content...
- if (json old_ev = event; old_ev["content"].count("m.relates_to") != 0)
- body["content"]["m.relates_to"] = old_ev["content"]["m.relates_to"];
+ mtx::common::add_relations(body["content"], event.content.relations);
mtx::events::collections::TimelineEvent te;
try {
diff --git a/src/timeline/EventStore.cpp b/src/timeline/EventStore.cpp
index be4bc09e..4a90222f 100644
--- a/src/timeline/EventStore.cpp
+++ b/src/timeline/EventStore.cpp
@@ -293,16 +293,16 @@ EventStore::handleSync(const mtx::responses::Timeline &events)
}
for (const auto &event : events.events) {
- std::string relates_to;
+ std::set<std::string> relates_to;
if (auto redaction =
std::get_if<mtx::events::RedactionEvent<mtx::events::msg::Redaction>>(
&event)) {
// fixup reactions
auto redacted = events_by_id_.object({room_id_, redaction->redacts});
if (redacted) {
- auto id = mtx::accessors::relates_to_event_id(*redacted);
- if (!id.empty()) {
- auto idx = idToIndex(id);
+ auto id = mtx::accessors::relations(*redacted);
+ if (id.annotates()) {
+ auto idx = idToIndex(id.annotates()->event_id);
if (idx) {
events_by_id_.remove(
{room_id_, redaction->redacts});
@@ -312,20 +312,17 @@ EventStore::handleSync(const mtx::responses::Timeline &events)
}
}
- relates_to = redaction->redacts;
- } else if (auto reaction =
- std::get_if<mtx::events::RoomEvent<mtx::events::msg::Reaction>>(
- &event)) {
- relates_to = reaction->content.relates_to.event_id;
+ relates_to.insert(redaction->redacts);
} else {
- relates_to = mtx::accessors::in_reply_to_event(event);
+ for (const auto &r : mtx::accessors::relations(event).relations)
+ relates_to.insert(r.event_id);
}
- if (!relates_to.empty()) {
- auto idx = cache::client()->getTimelineIndex(room_id_, relates_to);
+ for (const auto &relates_to_id : relates_to) {
+ auto idx = cache::client()->getTimelineIndex(room_id_, relates_to_id);
if (idx) {
- events_by_id_.remove({room_id_, relates_to});
- decryptedEvents_.remove({room_id_, relates_to});
+ events_by_id_.remove({room_id_, relates_to_id});
+ decryptedEvents_.remove({room_id_, relates_to_id});
events_.remove({room_id_, *idx});
emit dataChanged(toExternalIdx(*idx), toExternalIdx(*idx));
}
@@ -430,13 +427,14 @@ EventStore::reactions(const std::string &event_id)
if (auto reaction = std::get_if<mtx::events::RoomEvent<mtx::events::msg::Reaction>>(
related_event);
- reaction && reaction->content.relates_to.key) {
- auto &agg = aggregation[reaction->content.relates_to.key.value()];
+ reaction && reaction->content.relations.annotates() &&
+ reaction->content.relations.annotates()->key) {
+ auto key = reaction->content.relations.annotates()->key.value();
+ auto &agg = aggregation[key];
if (agg.count == 0) {
Reaction temp{};
- temp.key_ =
- QString::fromStdString(reaction->content.relates_to.key.value());
+ temp.key_ = QString::fromStdString(key);
reactions.push_back(temp);
}
@@ -691,8 +689,7 @@ EventStore::decryptEvent(const IdIndex &idx,
body["unsigned"] = e.unsigned_data;
// relations are unencrypted in content...
- if (json old_ev = e; old_ev["content"].count("m.relates_to") != 0)
- body["content"]["m.relates_to"] = old_ev["content"]["m.relates_to"];
+ mtx::common::add_relations(body["content"], e.content.relations);
json event_array = json::array();
event_array.push_back(body);
diff --git a/src/timeline/InputBar.cpp b/src/timeline/InputBar.cpp
index b31c1f76..738fb37c 100644
--- a/src/timeline/InputBar.cpp
+++ b/src/timeline/InputBar.cpp
@@ -294,7 +294,8 @@ InputBar::message(QString msg, MarkdownOverride useMarkdown)
text.formatted_body =
utils::getFormattedQuoteBody(related, msg.toHtmlEscaped()).toStdString();
- text.relates_to.in_reply_to.event_id = related.related_event;
+ text.relations.relations.push_back(
+ {mtx::common::RelationType::InReplyTo, related.related_event});
room->resetReply();
}
@@ -316,7 +317,8 @@ InputBar::emote(QString msg)
}
if (!room->reply().isEmpty()) {
- emote.relates_to.in_reply_to.event_id = room->reply().toStdString();
+ emote.relations.relations.push_back(
+ {mtx::common::RelationType::InReplyTo, room->reply().toStdString()});
room->resetReply();
}
@@ -346,7 +348,8 @@ InputBar::image(const QString &filename,
image.url = url.toStdString();
if (!room->reply().isEmpty()) {
- image.relates_to.in_reply_to.event_id = room->reply().toStdString();
+ image.relations.relations.push_back(
+ {mtx::common::RelationType::InReplyTo, room->reply().toStdString()});
room->resetReply();
}
@@ -371,7 +374,8 @@ InputBar::file(const QString &filename,
file.url = url.toStdString();
if (!room->reply().isEmpty()) {
- file.relates_to.in_reply_to.event_id = room->reply().toStdString();
+ file.relations.relations.push_back(
+ {mtx::common::RelationType::InReplyTo, room->reply().toStdString()});
room->resetReply();
}
@@ -397,7 +401,8 @@ InputBar::audio(const QString &filename,
audio.url = url.toStdString();
if (!room->reply().isEmpty()) {
- audio.relates_to.in_reply_to.event_id = room->reply().toStdString();
+ audio.relations.relations.push_back(
+ {mtx::common::RelationType::InReplyTo, room->reply().toStdString()});
room->resetReply();
}
@@ -422,7 +427,8 @@ InputBar::video(const QString &filename,
video.url = url.toStdString();
if (!room->reply().isEmpty()) {
- video.relates_to.in_reply_to.event_id = room->reply().toStdString();
+ video.relations.relations.push_back(
+ {mtx::common::RelationType::InReplyTo, room->reply().toStdString()});
room->resetReply();
}
diff --git a/src/timeline/TimelineModel.cpp b/src/timeline/TimelineModel.cpp
index 968ec3c7..c47194f5 100644
--- a/src/timeline/TimelineModel.cpp
+++ b/src/timeline/TimelineModel.cpp
@@ -360,7 +360,7 @@ TimelineModel::data(const mtx::events::collections::TimelineEvents &event, int r
const static QRegularExpression replyFallback(
"<mx-reply>.*</mx-reply>", QRegularExpression::DotMatchesEverythingOption);
- bool isReply = !in_reply_to_event(event).empty();
+ bool isReply = relations(event).reply_to().has_value();
auto formattedBody_ = QString::fromStdString(formatted_body(event));
if (formattedBody_.isEmpty()) {
@@ -442,7 +442,7 @@ TimelineModel::data(const mtx::events::collections::TimelineEvents &event, int r
return cache::isRoomEncrypted(room_id_.toStdString());
}
case ReplyTo:
- return QVariant(QString::fromStdString(in_reply_to_event(event)));
+ return QVariant(QString::fromStdString(relations(event).reply_to().value_or("")));
case Reactions: {
auto id = event_id(event);
return QVariant::fromValue(events.reactions(id));
diff --git a/src/timeline/TimelineViewManager.cpp b/src/timeline/TimelineViewManager.cpp
index 9e045e83..e1e2b681 100644
--- a/src/timeline/TimelineViewManager.cpp
+++ b/src/timeline/TimelineViewManager.cpp
@@ -503,9 +503,11 @@ TimelineViewManager::queueReactionMessage(const QString &reactedEvent, const QSt
// If selfReactedEvent is empty, that means we haven't previously reacted
if (selfReactedEvent.isEmpty()) {
mtx::events::msg::Reaction reaction;
- reaction.relates_to.rel_type = mtx::common::RelationType::Annotation;
- reaction.relates_to.event_id = reactedEvent.toStdString();
- reaction.relates_to.key = reactionKey.toStdString();
+ mtx::common::Relation rel;
+ rel.rel_type = mtx::common::RelationType::Annotation;
+ rel.event_id = reactedEvent.toStdString();
+ rel.key = reactionKey.toStdString();
+ reaction.relations.relations.push_back(rel);
timeline_->sendMessageEvent(reaction, mtx::events::EventType::Reaction);
// Otherwise, we have previously reacted and the reaction should be redacted