From e3d8e46fa1fddae7f04ac791f09e0f8ec4c8f1ed Mon Sep 17 00:00:00 2001
From: Nicolas Werner <nicolas.werner@hotmail.de>
Date: Wed, 26 Jun 2019 20:47:32 +0200
Subject: [PATCH] Add predecessor to create event

---
 include/mtx/events/create.hpp | 16 ++++++++++++++++
 lib/structs/events/create.cpp | 27 +++++++++++++++++++++++++--
 tests/events.cpp              | 35 +++++++++++++++++++++++++++++++++++
 3 files changed, 76 insertions(+), 2 deletions(-)

diff --git a/include/mtx/events/create.hpp b/include/mtx/events/create.hpp
index cf853897a..61fd19c84 100644
--- a/include/mtx/events/create.hpp
+++ b/include/mtx/events/create.hpp
@@ -1,5 +1,6 @@
 #pragma once
 
+#include <boost/optional.hpp>
 #include <nlohmann/json.hpp>
 
 using json = nlohmann::json;
@@ -8,6 +9,14 @@ namespace mtx {
 namespace events {
 namespace state {
 
+struct PreviousRoom
+{
+        //! Required. The ID of the old room.
+        std::string room_id;
+        //! Required. The event ID of the last known event in the old room.
+        std::string event_id;
+};
+
 //! Content of the `m.room.create` event.
 //
 //! This is the first event in a room and cannot be changed.
@@ -16,9 +25,16 @@ struct Create
 {
         //! The `user_id` of the room creator. This is set by the homeserver.
         std::string creator;
+
         //! Whether users on other servers can join this room.
         //! Defaults to **true** if key does not exist.
         bool federate = true;
+
+        //! The version of the room. Defaults to "1" if the key does not exist.
+        std::string room_version = "1";
+
+        //! A reference to the room this room replaces, if the previous room was upgraded.
+        boost::optional<PreviousRoom> predecessor;
 };
 
 void
diff --git a/lib/structs/events/create.cpp b/lib/structs/events/create.cpp
index 5faacac61..9c8952bfb 100644
--- a/lib/structs/events/create.cpp
+++ b/lib/structs/events/create.cpp
@@ -8,6 +8,19 @@ namespace mtx {
 namespace events {
 namespace state {
 
+void
+from_json(const json &obj, PreviousRoom &predecessor)
+{
+        predecessor.room_id  = obj.at("room_id");
+        predecessor.event_id = obj.at("event_id");
+}
+void
+to_json(json &obj, const PreviousRoom &predecessor)
+{
+        obj["room_id"]  = predecessor.room_id;
+        obj["event_id"] = predecessor.event_id;
+}
+
 void
 from_json(const json &obj, Create &create)
 {
@@ -15,13 +28,23 @@ from_json(const json &obj, Create &create)
 
         if (obj.find("m.federate") != obj.end())
                 create.federate = obj.at("m.federate").get<bool>();
+
+        if (obj.find("room_version") != obj.end())
+                create.room_version = obj.at("room_version");
+
+        if (obj.find("predecessor") != obj.end())
+                create.predecessor = obj.at("predecessor").get<PreviousRoom>();
 }
 
 void
 to_json(json &obj, const Create &create)
 {
-        obj["creator"]    = create.creator;
-        obj["m.federate"] = create.federate;
+        obj["creator"]      = create.creator;
+        obj["m.federate"]   = create.federate;
+        obj["room_version"] = create.room_version;
+
+        if (create.predecessor)
+                obj["predecessor"] = *create.predecessor;
 }
 
 } // namespace state
diff --git a/tests/events.cpp b/tests/events.cpp
index a4bc027c0..574a07271 100644
--- a/tests/events.cpp
+++ b/tests/events.cpp
@@ -179,6 +179,41 @@ TEST(StateEvents, Create)
         EXPECT_EQ(event.origin_server_ts, 1506761923948L);
         EXPECT_EQ(event.state_key, "");
         EXPECT_EQ(event.content.creator, "@mujx:matrix.org");
+
+        json example_from_spec = R"({
+            "content": {
+                "creator": "@example:example.org",
+                "m.federate": true,
+                "predecessor": {
+                    "event_id": "$something:example.org",
+                    "room_id": "!oldroom:example.org"
+                },
+                "room_version": "1"
+            },
+            "event_id": "$143273582443PhrSn:example.org",
+            "origin_server_ts": 1432735824653,
+            "room_id": "!jEsUZKDJdhlrceRyVU:example.org",
+            "sender": "@example:example.org",
+            "state_key": "",
+            "type": "m.room.create",
+            "unsigned": {
+                "age": 1234
+            }
+        })"_json;
+
+        event = example_from_spec;
+
+        EXPECT_EQ(event.type, ns::EventType::RoomCreate);
+        EXPECT_EQ(event.event_id, "$143273582443PhrSn:example.org");
+        EXPECT_EQ(event.sender, "@example:example.org");
+        EXPECT_EQ(event.unsigned_data.age, 1234);
+        EXPECT_EQ(event.origin_server_ts, 1432735824653L);
+        EXPECT_EQ(event.state_key, "");
+        EXPECT_EQ(event.content.creator, "@example:example.org");
+        EXPECT_EQ(event.content.federate, true);
+        EXPECT_EQ(event.content.room_version, "1");
+        EXPECT_EQ(event.content.predecessor->room_id, "!oldroom:example.org");
+        EXPECT_EQ(event.content.predecessor->event_id, "$something:example.org");
 }
 
 TEST(StateEvents, GuestAccess)
-- 
GitLab