summary refs log tree commit diff
path: root/src/Sync.cc
diff options
context:
space:
mode:
authorkrombel <krombel@krombel.de>2017-09-29 20:10:11 +0200
committermujx <mujx@users.noreply.github.com>2017-09-29 21:10:11 +0300
commit4c00e64f3fe92df3dbd2f0bc721469155b06683e (patch)
tree6d8340009f9ae5858eba015c1403ee17ead20ddf /src/Sync.cc
parentDon't mangle bot's display name (diff)
downloadnheko-4c00e64f3fe92df3dbd2f0bc721469155b06683e.tar.xz
Allow handling of incomplete /sync responses (#67)
matrix-org/synapse#2358 proposes a change to only contain objects
in the sync stream where values get updated.
The current behavior leads nheko to fail when that is used.
Diffstat (limited to '')
-rw-r--r--src/Sync.cc155
1 files changed, 112 insertions, 43 deletions
diff --git a/src/Sync.cc b/src/Sync.cc
index de469ff8..58c423d1 100644
--- a/src/Sync.cc
+++ b/src/Sync.cc
@@ -32,13 +32,45 @@ SyncResponse::deserialize(const QJsonDocument &data)
 
         QJsonObject object = data.object();
 
-        if (object.value("next_batch") == QJsonValue::Undefined)
+        if (!object.contains("next_batch"))
                 throw DeserializationException("Sync: missing next_batch parameter");
 
-        if (object.value("rooms") == QJsonValue::Undefined)
-                throw DeserializationException("Sync: missing rooms parameter");
+        if (object.contains("rooms")) {
+                if (!object.value("rooms").isObject()) {
+                        throw DeserializationException("Sync: rooms is not a JSON object");
+                }
+                rooms_.deserialize(object.value("rooms"));
+        }
+
+        if (object.contains("presence")) {
+                if (!object.value("presence").isObject()) {
+                        throw DeserializationException("Sync: presence is not a JSON object");
+                }
+                // TODO: implement presence handling
+        }
+
+        if (object.contains("account_data")) {
+                if (!object.value("account_data").isObject()) {
+                        throw DeserializationException("Sync: account_data is not a JSON object");
+                }
+                // TODO: implement account_data handling
+        }
+
+        if (object.contains("to_device")) {
+                if (!object.value("to_device").isObject()) {
+                        throw DeserializationException("Sync: to_device is not a JSON object");
+                }
+                // TODO: implement to_device handling
+        }
+
+        // for device_lists updates (for e2e)
+        if (object.contains("device_lists")) {
+                if (!object.value("device_lists").isObject()) {
+                        throw DeserializationException("Sync: device_lists is not a JSON object");
+                }
+                // TODO: implement device_lists handling
+        }
 
-        rooms_.deserialize(object.value("rooms"));
         next_batch_ = object.value("next_batch").toString();
 }
 
@@ -50,36 +82,37 @@ Rooms::deserialize(const QJsonValue &data)
 
         QJsonObject object = data.toObject();
 
-        if (!object.contains("join"))
-                throw DeserializationException("rooms/join is missing");
-
-        if (!object.contains("invite"))
-                throw DeserializationException("rooms/invite is missing");
+        if (object.contains("join")) {
+                if (!object.value("join").isObject())
+                        throw DeserializationException("rooms/join must be a JSON object");
 
-        if (!object.contains("leave"))
-                throw DeserializationException("rooms/leave is missing");
+                auto join = object.value("join").toObject();
 
-        if (!object.value("join").isObject())
-                throw DeserializationException("rooms/join must be a JSON object");
+                for (auto it = join.constBegin(); it != join.constEnd(); it++) {
+                        JoinedRoom tmp_room;
 
-        if (!object.value("invite").isObject())
-                throw DeserializationException("rooms/invite must be a JSON object");
-
-        if (!object.value("leave").isObject())
-                throw DeserializationException("rooms/leave must be a JSON object");
-
-        auto join = object.value("join").toObject();
+                        try {
+                                tmp_room.deserialize(it.value());
+                                join_.insert(it.key(), tmp_room);
+                        } catch (DeserializationException &e) {
+                                qWarning() << e.what();
+                                qWarning() << "Skipping malformed object for room" << it.key();
+                        }
+                }
+        }
 
-        for (auto it = join.constBegin(); it != join.constEnd(); it++) {
-                JoinedRoom tmp_room;
+        if (object.contains("invite")) {
+                if (!object.value("invite").isObject()) {
+                        throw DeserializationException("rooms/invite must be a JSON object");
+                }
+                // TODO: Implement invite handling
+        }
 
-                try {
-                        tmp_room.deserialize(it.value());
-                        join_.insert(it.key(), tmp_room);
-                } catch (DeserializationException &e) {
-                        qWarning() << e.what();
-                        qWarning() << "Skipping malformed object for room" << it.key();
+        if (object.contains("leave")) {
+                if (!object.value("leave").isObject()) {
+                        throw DeserializationException("rooms/leave must be a JSON object");
                 }
+                // TODO: Implement leave handling
         }
 }
 
@@ -91,28 +124,64 @@ JoinedRoom::deserialize(const QJsonValue &data)
 
         QJsonObject object = data.toObject();
 
-        if (!object.contains("state"))
-                throw DeserializationException("join/state is missing");
+        if (object.contains("state")) {
+                if (!object.value("state").isObject()) {
+                        throw DeserializationException("join/state should be an object");
+                }
+
+                QJsonObject state = object.value("state").toObject();
+
+                if (state.contains("events")) {
+                        if (!state.value("events").isArray()) {
+                                throw DeserializationException(
+                                  "join/state/events should be an array");
+                        }
+
+                        state_.deserialize(state.value("events"));
+                }
+        }
+
+        if (object.contains("timeline")) {
+                if (!object.value("timeline").isObject())
+                        throw DeserializationException("join/timeline should be an object");
+                timeline_.deserialize(object.value("timeline"));
+        }
 
-        if (!object.contains("timeline"))
-                throw DeserializationException("join/timeline is missing");
+        if (object.contains("ephemeral")) {
+                if (!object.value("ephemeral").isObject())
+                        throw DeserializationException("join/ephemeral should be an object");
 
-        if (!object.contains("account_data"))
-                throw DeserializationException("join/account_data is missing");
+                QJsonObject ephemeral = object.value("ephemeral").toObject();
 
-        if (!object.contains("unread_notifications"))
-                throw DeserializationException("join/unread_notifications is missing");
+                if (ephemeral.contains("events")) {
+                        if (!ephemeral.value("events").isArray())
+                                qWarning() << "join/ephemeral/events should be an array";
 
-        if (!object.value("state").isObject())
-                throw DeserializationException("join/state should be an object");
+                        // TODO: Implement ephemeral handling
+                }
+        }
 
-        QJsonObject state = object.value("state").toObject();
+        if (object.contains("account_data")) {
+                if (!object.value("account_data").isObject())
+                        throw DeserializationException("join/account_data is not a JSON object");
+                // TODO: Implement account_data handling
+        }
 
-        if (!state.contains("events"))
-                throw DeserializationException("join/state/events is missing");
+        if (object.contains("unread_notifications")) {
+                if (!object.value("unread_notifications").isObject()) {
+                        throw DeserializationException(
+                          "join/unread_notifications is not a JSON object");
+                }
 
-        state_.deserialize(state.value("events"));
-        timeline_.deserialize(object.value("timeline"));
+                QJsonObject unreadNotifications = object.value("unread_notifications").toObject();
+
+                if (unreadNotifications.contains("highlight_count")) {
+                        // TODO: Implement unread_notifications handling
+                }
+                if (unreadNotifications.contains("notification_count")) {
+                        // TODO: Implement unread_notifications handling
+                }
+        }
 }
 
 void