From b56083dfa95848c39d9290efdc5544ac07030028 Mon Sep 17 00:00:00 2001
From: Joseph Donofry <joedonofry@gmail.com>
Date: Mon, 5 Aug 2019 22:14:59 -0400
Subject: [PATCH] Add abilty to translate timeline events to json

---
 include/mtx/responses/common.hpp        | 162 ++++++++++++++++++++++++
 include/mtx/responses/notifications.hpp |   4 +
 lib/structs/responses/common.cpp        |   8 ++
 lib/structs/responses/notifications.cpp |  36 ++++++
 4 files changed, 210 insertions(+)

diff --git a/include/mtx/responses/common.hpp b/include/mtx/responses/common.hpp
index 2cda8c5d7..becc9831e 100644
--- a/include/mtx/responses/common.hpp
+++ b/include/mtx/responses/common.hpp
@@ -43,6 +43,165 @@ using TimelineEvents        = std::vector<mtx::events::collections::TimelineEven
 using StateEvents           = std::vector<mtx::events::collections::StateEvents>;
 using StrippedEvents        = std::vector<mtx::events::collections::StrippedEvents>;
 
+namespace states       = mtx::events::state;
+namespace msgs         = mtx::events::msg;
+
+struct TimelineEventVisitor : public boost::static_visitor<json>
+{
+        json operator()(const events::StateEvent<states::Aliases> &aliasEv) const
+        {
+                json j;
+                mtx::events::to_json(j, aliasEv);
+                return j;
+        }
+        json operator()(const events::StateEvent<states::Avatar> &avatarEv) const
+        {
+                json j;
+                mtx::events::to_json(j, avatarEv);
+                return j;
+        };
+        json operator()(const events::StateEvent<states::CanonicalAlias> &aliasEv) const
+        {
+                json j;
+                mtx::events::to_json(j, aliasEv);
+                return j;
+        };
+        json operator()(const events::StateEvent<states::Create> &createEv) const
+        {
+                json j;
+                mtx::events::to_json(j, createEv);
+                return j;
+        };
+        json operator()(const events::StateEvent<states::Encryption> &encEv) const
+        {
+                json j;
+                mtx::events::to_json(j, encEv);
+                return j;
+        };
+        json operator()(const events::StateEvent<states::GuestAccess> &guestEv) const
+        {
+                json j;
+                mtx::events::to_json(j, guestEv);
+                return j;
+        };
+        json operator()(const events::StateEvent<states::HistoryVisibility> &histEv) const
+        {
+                json j;
+                mtx::events::to_json(j, histEv);
+                return j;
+        };
+        json operator()(const events::StateEvent<states::JoinRules> &joinEv) const
+        {
+                json j;
+                mtx::events::to_json(j, joinEv);
+                return j;
+        };
+        json operator()(const events::StateEvent<states::Member> &membEv) const
+        {
+                json j;
+                mtx::events::to_json(j, membEv);
+                return j;
+        };
+        json operator()(const events::StateEvent<states::Name> &nameEv) const
+        {
+                json j;
+                mtx::events::to_json(j, nameEv);
+                return j;
+        };
+        json operator()(const events::StateEvent<states::PinnedEvents> &pinEv) const
+        {
+                json j;
+                mtx::events::to_json(j, pinEv);
+                return j;
+        };
+        json operator()(const events::StateEvent<states::PowerLevels> &powEv) const
+        {
+                json j;
+                mtx::events::to_json(j, powEv);
+                return j;
+        };
+        json operator()(const events::StateEvent<states::Tombstone> &tombEv) const
+        {
+                json j;
+                mtx::events::to_json(j, tombEv);
+                return j;
+        };
+        json operator()(const events::StateEvent<states::Topic> &topicEv) const
+        {
+                json j;
+                mtx::events::to_json(j, topicEv);
+                return j;
+        };
+        json operator()(const events::EncryptedEvent<msgs::Encrypted> &encEv) const
+        {
+                json j;
+                mtx::events::to_json(j, encEv);
+                return j;
+        };
+        json operator()(const events::RedactionEvent<msgs::Redaction> &redEv) const
+        {
+                json j;
+                mtx::events::to_json(j, redEv);
+                return j;
+        };
+        json operator()(const events::Sticker &stickEv) const
+        {
+                json j;
+                mtx::events::to_json(j, stickEv);
+                return j;
+        };
+        json operator()(const events::RoomEvent<msgs::Redacted> &redEv) const
+        {
+                json j;
+                mtx::events::to_json(j, redEv);
+                return j;
+        };
+        json operator()(const events::RoomEvent<msgs::Audio> &audioEv) const
+        {
+                json j;
+                mtx::events::to_json(j, audioEv);
+                return j;
+        };
+        json operator()(const events::RoomEvent<msgs::Emote> &emoteEv) const
+        {
+                json j;
+                mtx::events::to_json(j, emoteEv);
+                return j;
+        };
+        json operator()(const events::RoomEvent<msgs::File> &fileEv) const
+        {
+                json j;
+                mtx::events::to_json(j, fileEv);
+                return j;
+        };
+        json operator()(const events::RoomEvent<msgs::Image> &imageEv) const
+        {
+                json j;
+                mtx::events::to_json(j, imageEv);
+                return j;
+        };
+        // TODO: json operator()(const events::RoomEvent<msgs::Location> &locEv) const { json j;
+        // mtx::events::to_json(j, locEv); return j;};
+        json operator()(const events::RoomEvent<msgs::Notice> &noticeEv) const
+        {
+                json j;
+                mtx::events::to_json(j, noticeEv);
+                return j;
+        };
+        json operator()(const events::RoomEvent<msgs::Text> &textEv) const
+        {
+                json j;
+                mtx::events::to_json(j, textEv);
+                return j;
+        };
+        json operator()(const events::RoomEvent<msgs::Video> &videoEv) const
+        {
+                json j;
+                mtx::events::to_json(j, videoEv);
+                return j;
+        };
+};
+
 void
 log_error(json::exception &err, const json &event);
 
@@ -52,6 +211,9 @@ log_error(std::string err, const json &event);
 void
 parse_room_account_data_events(const json &events, RoomAccountDataEvents &container);
 
+void
+compose_timeline_events(json &events, const TimelineEvents &container);
+
 void
 parse_timeline_events(const json &events, TimelineEvents &container);
 
diff --git a/include/mtx/responses/notifications.hpp b/include/mtx/responses/notifications.hpp
index d69853812..7c7804a1b 100644
--- a/include/mtx/responses/notifications.hpp
+++ b/include/mtx/responses/notifications.hpp
@@ -26,6 +26,8 @@ struct Notification
 
 void
 from_json(const nlohmann::json &obj, Notification &res);
+void
+to_json(nlohmann::json &obj, const Notification &res);
 
 //! Response from the `GET /_matrix/client/r0/notifications` endpoint.
 //
@@ -44,5 +46,7 @@ struct Notifications
 
 void
 from_json(const nlohmann::json &obj, Notifications &res);
+void
+to_json(nlohmann::json &obj, const Notifications &res);
 }
 }
diff --git a/lib/structs/responses/common.cpp b/lib/structs/responses/common.cpp
index 67ce418b7..b5164f515 100644
--- a/lib/structs/responses/common.cpp
+++ b/lib/structs/responses/common.cpp
@@ -104,6 +104,14 @@ parse_room_account_data_events(
         }
 }
 
+void
+compose_timeline_events(json &events,
+                        const std::vector<mtx::events::collections::TimelineEvents> &container)
+{
+        const auto c = container.at(0);
+        events = boost::apply_visitor(TimelineEventVisitor(), c);
+}
+
 void
 parse_timeline_events(const json &events,
                       std::vector<mtx::events::collections::TimelineEvents> &container)
diff --git a/lib/structs/responses/notifications.cpp b/lib/structs/responses/notifications.cpp
index 9bd214b02..5a132fe47 100644
--- a/lib/structs/responses/notifications.cpp
+++ b/lib/structs/responses/notifications.cpp
@@ -34,11 +34,47 @@ from_json(const json &obj, Notification &res)
                 res.event = tmp.at(0);
 }
 
+void
+to_json(json &obj, const Notification &res)
+{
+        obj["actions"] = res.actions;
+        obj["read"] = res.read;
+        obj["room_id"] = res.room_id;
+        obj["ts"] = res.ts;
+
+        // HACK to work around the fact that there isn't
+        // a method to parse a timeline event from a json object.
+        //
+        // TODO: Create method that retrieves a TimelineEvents variant from a json object.
+        // Ideally with an optional type to indicate failure.
+        std::vector<events::collections::TimelineEvents> tmp;
+        tmp.reserve(1);
+
+        json arr;
+        tmp.push_back(res.event);
+
+        utils::compose_timeline_events(arr, tmp);
+
+        if (!tmp.empty()) {
+                obj["event"] = arr;
+        }
+
+        if (!res.profile_tag.empty()) {
+                obj["profile_tag"] = res.profile_tag;
+        }
+}
+
 void
 from_json(const json &obj, Notifications &res)
 {
         // res.next_token    = obj.at("next_token").get<std::string>();
         res.notifications = obj.at("notifications").get<std::vector<Notification>>();
 }
+
+void
+to_json(json &obj, const Notifications &notif)
+{
+        obj["notifications"] = notif.notifications;
+}
 } // namespace responses
 } // namespace mtx
-- 
GitLab