1// SPDX-FileCopyrightText: 2018 Kitsune Ral <Kitsune-Ral@users.sf.net>
2// SPDX-License-Identifier: LGPL-2.1-or-later
3
4/*
5Example of a Receipt Event:
6{
7 "content": {
8 "$1435641916114394fHBLK:matrix.org": {
9 "m.read": {
10 "@rikj:jki.re": {
11 "ts": 1436451550453
12 }
13 }
14 }
15 },
16 "room_id": "!KpjVgQyZpzBwvMBsnT:matrix.org",
17 "type": "m.receipt"
18}
19*/
20
21#include "receiptevent.h"
22
23#include "../logging_categories_p.h"
24
25using namespace Quotient;
26
27// The library loads the event-ids-to-receipts JSON map into a vector because
28// map lookups are not used and vectors are massively faster. Same goes for
29// de-/serialization of ReceiptsForEvent::receipts.
30// (XXX: would this be generally preferred across CS API JSON maps?..)
31QJsonObject Quotient::toJson(const EventsWithReceipts& ewrs)
32{
33 QJsonObject json;
34 for (const auto& e : ewrs) {
35 QJsonObject receiptsJson;
36 for (const auto& r : e.receipts)
37 receiptsJson.insert(key: r.userId,
38 value: QJsonObject { { "ts"_ls, toJson(val: r.timestamp) } });
39 json.insert(key: e.evtId, value: QJsonObject { { "m.read"_ls, receiptsJson } });
40 }
41 return json;
42}
43
44template<>
45EventsWithReceipts Quotient::fromJson(const QJsonObject& json)
46{
47 EventsWithReceipts result;
48 result.reserve(asize: json.size());
49 for (auto eventIt = json.begin(); eventIt != json.end(); ++eventIt) {
50 if (eventIt.key().isEmpty()) {
51 qCWarning(EPHEMERAL)
52 << "ReceiptEvent has an empty event id, skipping";
53 qCDebug(EPHEMERAL) << "ReceiptEvent content follows:\n" << json;
54 continue;
55 }
56 const auto reads =
57 eventIt.value().toObject().value(key: "m.read"_ls).toObject();
58 QVector<UserTimestamp> usersAtEvent;
59 usersAtEvent.reserve(asize: reads.size());
60 for (auto userIt = reads.begin(); userIt != reads.end(); ++userIt) {
61 const auto user = userIt.value().toObject();
62 usersAtEvent.push_back(
63 t: { .userId: userIt.key(), .timestamp: fromJson<QDateTime>(jv: user["ts"_ls]) });
64 }
65 result.push_back(t: { .evtId: eventIt.key(), .receipts: std::move(usersAtEvent) });
66 }
67 return result;
68}
69