diff --git a/CMakeLists.txt b/CMakeLists.txt
index 7e2e33a8..73054235 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -117,6 +117,8 @@ set(SRC_FILES
)
set(MATRIX_EVENTS
+ src/events/Event.cc
+
src/events/AliasesEventContent.cc
src/events/AvatarEventContent.cc
src/events/CanonicalAliasEventContent.cc
diff --git a/include/events/Event.h b/include/events/Event.h
new file mode 100644
index 00000000..25b340bb
--- /dev/null
+++ b/include/events/Event.h
@@ -0,0 +1,89 @@
+/*
+ * nheko Copyright (C) 2017 Konstantinos Sideris <siderisk@auth.gr>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef MATRIX_EVENT_H
+#define MATRIX_EVENT_H
+
+#include <QJsonValue>
+
+#include "Deserializable.h"
+
+enum EventType {
+ /// m.room.aliases
+ RoomAliases,
+ /// m.room.avatar
+ RoomAvatar,
+ /// m.room.canonical_alias
+ RoomCanonicalAlias,
+ /// m.room.create
+ RoomCreate,
+ /// m.room.history_visibility
+ RoomHistoryVisibility,
+ /// m.room.join_rules
+ RoomJoinRules,
+ /// m.room.member
+ RoomMember,
+ /// m.room.name
+ RoomName,
+ /// m.room.power_levels
+ RoomPowerLevels,
+ /// m.room.topic
+ RoomTopic,
+ // Unsupported event
+ Unsupported,
+};
+
+EventType extractEventType(const QJsonObject &data);
+
+template <class Content>
+class Event : public Deserializable
+{
+public:
+ inline Content content() const;
+ inline EventType eventType() const;
+
+ void deserialize(const QJsonValue &data) override;
+
+private:
+ Content content_;
+ EventType type_;
+};
+
+template <class Content>
+inline Content Event<Content>::content() const
+{
+ return content_;
+}
+
+template <class Content>
+inline EventType Event<Content>::eventType() const
+{
+ return type_;
+}
+
+template <class Content>
+void Event<Content>::deserialize(const QJsonValue &data)
+{
+ if (!data.isObject())
+ throw DeserializationException("Event is not a JSON object");
+
+ auto object = data.toObject();
+
+ content_.deserialize(object.value("content"));
+}
+
+#endif // MATRIX_EVENT_H
diff --git a/src/events/Event.cc b/src/events/Event.cc
new file mode 100644
index 00000000..f9596d18
--- /dev/null
+++ b/src/events/Event.cc
@@ -0,0 +1,61 @@
+/*
+ * nheko Copyright (C) 2017 Konstantinos Sideris <siderisk@auth.gr>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "Event.h"
+
+#include "AliasesEventContent.h"
+#include "AvatarEventContent.h"
+#include "CanonicalAliasEventContent.h"
+#include "CreateEventContent.h"
+#include "Deserializable.h"
+#include "HistoryVisibilityEventContent.h"
+#include "JoinRulesEventContent.h"
+#include "MemberEventContent.h"
+#include "NameEventContent.h"
+#include "PowerLevelsEventContent.h"
+#include "TopicEventContent.h"
+
+EventType extractEventType(const QJsonObject &object)
+{
+ if (!object.contains("type"))
+ throw DeserializationException("Missing event type");
+
+ auto type = object.value("type").toString();
+
+ if (type == "m.room.aliases")
+ return EventType::RoomAliases;
+ else if (type == "m.room.avatar")
+ return EventType::RoomAvatar;
+ else if (type == "m.room.canonical_alias")
+ return EventType::RoomCanonicalAlias;
+ else if (type == "m.room.create")
+ return EventType::RoomCreate;
+ else if (type == "m.room.history_visibility")
+ return EventType::RoomHistoryVisibility;
+ else if (type == "m.room.join_rules")
+ return EventType::RoomJoinRules;
+ else if (type == "m.room.member")
+ return EventType::RoomMember;
+ else if (type == "m.room.name")
+ return EventType::RoomName;
+ else if (type == "m.room.power_levels")
+ return EventType::RoomPowerLevels;
+ else if (type == "m.room.topic")
+ return EventType::RoomTopic;
+ else
+ return EventType::Unsupported;
+}
diff --git a/tests/events.cc b/tests/events.cc
index 79319f38..c9767e19 100644
--- a/tests/events.cc
+++ b/tests/events.cc
@@ -1,6 +1,8 @@
#include <gtest/gtest.h>
#include <QJsonArray>
+#include "Event.h"
+
#include "AliasesEventContent.h"
#include "AvatarEventContent.h"
#include "CanonicalAliasEventContent.h"
@@ -12,6 +14,77 @@
#include "PowerLevelsEventContent.h"
#include "TopicEventContent.h"
+TEST(BaseEvent, Deserialization)
+{
+ // NameEventContent
+ auto data = QJsonObject{
+ {"content", QJsonObject{{"name", "Room Name"}}},
+ {"type", "m.room.name"}};
+
+ Event<NameEventContent> name_event;
+ name_event.deserialize(data);
+ EXPECT_EQ(name_event.content().name(), "Room Name");
+
+ // TopicEventContent
+ data = QJsonObject{
+ {"content", QJsonObject{{"topic", "Room Topic"}}},
+ {"type", "m.room.topic"}};
+
+ Event<TopicEventContent> topic_event;
+ topic_event.deserialize(data);
+ EXPECT_EQ(topic_event.content().topic(), "Room Topic");
+
+ // AvatarEventContent
+ data = QJsonObject{
+ {"content", QJsonObject{{"url", "https://matrix.org"}}},
+ {"type", "m.room.avatar"}};
+
+ Event<AvatarEventContent> avatar_event;
+ avatar_event.deserialize(data);
+ EXPECT_EQ(avatar_event.content().url().toString(), "https://matrix.org");
+
+ // AliasesEventContent
+ data = QJsonObject{
+ {"content", QJsonObject{{"aliases", QJsonArray{"#test:matrix.org", "#test2:matrix.org"}}}},
+ {"type", "m.room.aliases"}};
+
+ Event<AliasesEventContent> aliases_event;
+ aliases_event.deserialize(data);
+ EXPECT_EQ(aliases_event.content().aliases().size(), 2);
+
+ // CreateEventContent
+ data = QJsonObject{
+ {"content", QJsonObject{{"creator", "@alice:matrix.org"}}},
+ {"type", "m.room.create"}};
+
+ Event<CreateEventContent> create_event;
+ create_event.deserialize(data);
+ EXPECT_EQ(create_event.content().creator(), "@alice:matrix.org");
+
+ // JoinRulesEventContent
+ data = QJsonObject{
+ {"content", QJsonObject{{"join_rule", "private"}}},
+ {"type", "m.room.join_rules"}};
+
+ Event<JoinRulesEventContent> join_rules_event;
+ join_rules_event.deserialize(data);
+ EXPECT_EQ(join_rules_event.content().joinRule(), JoinRule::Private);
+}
+
+TEST(EventType, Mapping)
+{
+ EXPECT_EQ(extractEventType(QJsonObject{{"type", "m.room.aliases"}}), EventType::RoomAliases);
+ EXPECT_EQ(extractEventType(QJsonObject{{"type", "m.room.avatar"}}), EventType::RoomAvatar);
+ EXPECT_EQ(extractEventType(QJsonObject{{"type", "m.room.canonical_alias"}}), EventType::RoomCanonicalAlias);
+ EXPECT_EQ(extractEventType(QJsonObject{{"type", "m.room.create"}}), EventType::RoomCreate);
+ EXPECT_EQ(extractEventType(QJsonObject{{"type", "m.room.history_visibility"}}), EventType::RoomHistoryVisibility);
+ EXPECT_EQ(extractEventType(QJsonObject{{"type", "m.room.join_rules"}}), EventType::RoomJoinRules);
+ EXPECT_EQ(extractEventType(QJsonObject{{"type", "m.room.member"}}), EventType::RoomMember);
+ EXPECT_EQ(extractEventType(QJsonObject{{"type", "m.room.name"}}), EventType::RoomName);
+ EXPECT_EQ(extractEventType(QJsonObject{{"type", "m.room.power_levels"}}), EventType::RoomPowerLevels);
+ EXPECT_EQ(extractEventType(QJsonObject{{"type", "m.room.topic"}}), EventType::RoomTopic);
+}
+
TEST(AliasesEventContent, Deserialization)
{
auto data = QJsonObject{
|