Nheko-Reborn / mtxclient

Client API library for Matrix, built on top of libcurl
MIT License
40 stars 25 forks source link

PATCH: support location message type #87

Open hamzehnasajpour opened 1 year ago

hamzehnasajpour commented 1 year ago

Since I need the location messages and it was not implemented in the library so I decided to add this feature to the library. Please review this patch and apply it or let me know if there is any issue.

diff --git a/CMakeLists.txt b/CMakeLists.txt
index fd49555..98ea974 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -234,6 +234,7 @@ target_sources(matrix_client
    lib/structs/events/messages/emote.cpp
    lib/structs/events/messages/file.cpp
    lib/structs/events/messages/image.cpp
+   lib/structs/events/messages/location.cpp
    lib/structs/events/messages/notice.cpp
    lib/structs/events/messages/text.cpp
    lib/structs/events/messages/video.cpp
diff --git a/include/mtx.hpp b/include/mtx.hpp
index 4eb600b..81e76ad 100644
--- a/include/mtx.hpp
+++ b/include/mtx.hpp
@@ -27,6 +27,7 @@
 #include "mtx/events/messages/emote.hpp"
 #include "mtx/events/messages/file.hpp"
 #include "mtx/events/messages/image.hpp"
+#include "mtx/events/messages/location.hpp"
 #include "mtx/events/messages/notice.hpp"
 #include "mtx/events/messages/text.hpp"
 #include "mtx/events/messages/video.hpp"
diff --git a/include/mtx/events/collections.hpp b/include/mtx/events/collections.hpp
index f48aed6..aad7832 100644
--- a/include/mtx/events/collections.hpp
+++ b/include/mtx/events/collections.hpp
@@ -42,6 +42,7 @@
 #include "mtx/events/messages/emote.hpp"
 #include "mtx/events/messages/file.hpp"
 #include "mtx/events/messages/image.hpp"
+#include "mtx/events/messages/location.hpp"
 #include "mtx/events/messages/notice.hpp"
 #include "mtx/events/messages/text.hpp"
 #include "mtx/events/messages/video.hpp"
@@ -168,7 +169,7 @@ using TimelineEvents =
                mtx::events::RoomEvent<mtx::events::msg::Emote>,
                mtx::events::RoomEvent<mtx::events::msg::File>,
                mtx::events::RoomEvent<mtx::events::msg::Image>,
-               // TODO: events::RoomEvent<mtx::events::msg::Location>,
+               mtx::events::RoomEvent<mtx::events::msg::Location>,
                mtx::events::RoomEvent<mtx::events::msg::Notice>,
                mtx::events::RoomEvent<mtx::events::msg::Text>,
                mtx::events::RoomEvent<mtx::events::msg::Video>,
@@ -225,6 +226,9 @@ template<>
 constexpr inline EventType message_content_to_type<mtx::events::msg::Image> =
   EventType::RoomMessage;
 template<>
+constexpr inline EventType message_content_to_type<mtx::events::msg::Location> =
+  EventType::RoomMessage;
+template<>
 constexpr inline EventType message_content_to_type<mtx::events::msg::Notice> =
   EventType::RoomMessage;
 template<>
diff --git a/include/mtx/events/common.hpp b/include/mtx/events/common.hpp
index 094be0e..20e8271 100644
--- a/include/mtx/events/common.hpp
+++ b/include/mtx/events/common.hpp
@@ -146,10 +146,10 @@ struct LocationInfo
     std::string blurhash;

     //! Deserialization method needed by @p nlohmann::json.
-    friend void from_json(const nlohmann::json &obj, ThumbnailInfo &info);
+    friend void from_json(const nlohmann::json &obj, LocationInfo &info);

     //! Serialization method needed by @p nlohmann::json.
-    friend void to_json(nlohmann::json &obj, const ThumbnailInfo &info);
+    friend void to_json(nlohmann::json &obj, const LocationInfo &info);
 };

 //! Definition of rel_type for relations.
diff --git a/include/mtxclient/http/client.hpp b/include/mtxclient/http/client.hpp
index 2ca1c7e..b8d25fa 100644
--- a/include/mtxclient/http/client.hpp
+++ b/include/mtxclient/http/client.hpp
@@ -884,6 +884,7 @@ MTXCLIENT_SEND_ROOM_MESSAGE_FWD(mtx::events::msg::Audio)
 MTXCLIENT_SEND_ROOM_MESSAGE_FWD(mtx::events::msg::Emote)
 MTXCLIENT_SEND_ROOM_MESSAGE_FWD(mtx::events::msg::File)
 MTXCLIENT_SEND_ROOM_MESSAGE_FWD(mtx::events::msg::Image)
+MTXCLIENT_SEND_ROOM_MESSAGE_FWD(mtx::events::msg::Location)
 MTXCLIENT_SEND_ROOM_MESSAGE_FWD(mtx::events::msg::Notice)
 MTXCLIENT_SEND_ROOM_MESSAGE_FWD(mtx::events::msg::Text)
 MTXCLIENT_SEND_ROOM_MESSAGE_FWD(mtx::events::msg::Video)
diff --git a/lib/http/client.cpp b/lib/http/client.cpp
index 979e2d7..7751a27 100644
--- a/lib/http/client.cpp
+++ b/lib/http/client.cpp
@@ -1718,6 +1718,7 @@ MTXCLIENT_SEND_ROOM_MESSAGE(mtx::events::msg::Audio)
 MTXCLIENT_SEND_ROOM_MESSAGE(mtx::events::msg::Emote)
 MTXCLIENT_SEND_ROOM_MESSAGE(mtx::events::msg::File)
 MTXCLIENT_SEND_ROOM_MESSAGE(mtx::events::msg::Image)
+MTXCLIENT_SEND_ROOM_MESSAGE(mtx::events::msg::Location)
 MTXCLIENT_SEND_ROOM_MESSAGE(mtx::events::msg::Notice)
 MTXCLIENT_SEND_ROOM_MESSAGE(mtx::events::msg::Text)
 MTXCLIENT_SEND_ROOM_MESSAGE(mtx::events::msg::Video)
diff --git a/lib/structs/events/collections.cpp b/lib/structs/events/collections.cpp
index 8211b75..f6e82ad 100644
--- a/lib/structs/events/collections.cpp
+++ b/lib/structs/events/collections.cpp
@@ -44,6 +44,7 @@ MTXCLIENT_INSTANTIATE_JSON_FUNCTIONS(events::RoomEvent, mtx::events::msg::Audio)
 MTXCLIENT_INSTANTIATE_JSON_FUNCTIONS(events::RoomEvent, mtx::events::msg::Emote)
 MTXCLIENT_INSTANTIATE_JSON_FUNCTIONS(events::RoomEvent, mtx::events::msg::File)
 MTXCLIENT_INSTANTIATE_JSON_FUNCTIONS(events::RoomEvent, mtx::events::msg::Image)
+MTXCLIENT_INSTANTIATE_JSON_FUNCTIONS(events::RoomEvent, mtx::events::msg::Location)
 MTXCLIENT_INSTANTIATE_JSON_FUNCTIONS(events::RoomEvent, mtx::events::msg::Notice)
 MTXCLIENT_INSTANTIATE_JSON_FUNCTIONS(events::RoomEvent, mtx::events::msg::Text)
 MTXCLIENT_INSTANTIATE_JSON_FUNCTIONS(events::RoomEvent, mtx::events::msg::Video)
@@ -298,8 +299,7 @@ from_json(const nlohmann::json &obj, TimelineEvent &e)
                 break;
             }
             case MsgType::Location: {
-                /* events::RoomEvent<events::msg::Location> location = e; */
-                /* container.emplace_back(location); */
+                e.data = events::RoomEvent<events::msg::Location>(obj);
                 break;
             }
             case MsgType::Notice: {
diff --git a/lib/structs/events/common.cpp b/lib/structs/events/common.cpp
index 9fb6f07..50dd712 100644
--- a/lib/structs/events/common.cpp
+++ b/lib/structs/events/common.cpp
@@ -169,6 +169,35 @@ to_json(json &obj, const VideoInfo &info)
         obj["xyz.amorgan.blurhash"] = info.blurhash;
 }

+void
+from_json(const json &obj, LocationInfo &info)
+{
+    if (obj.find("thumbnail_url") != obj.end())
+        info.thumbnail_url = obj.at("thumbnail_url").get<std::string>();
+
+    if (obj.find("thumbnail_info") != obj.end())
+        info.thumbnail_info = obj.at("thumbnail_info").get<ThumbnailInfo>();
+
+    if (obj.find("thumbnail_file") != obj.end())
+        info.thumbnail_file = obj.at("thumbnail_file").get<crypto::EncryptedFile>();
+
+    if (obj.find("xyz.amorgan.blurhash") != obj.end())
+        info.blurhash = obj.at("xyz.amorgan.blurhash").get<std::string>();
+}
+
+void
+to_json(json &obj, const LocationInfo &info)
+{
+    if (!info.thumbnail_url.empty()) {
+        obj["thumbnail_url"]  = info.thumbnail_url;
+        obj["thumbnail_info"] = info.thumbnail_info;
+    }
+    if (info.thumbnail_file)
+        obj["thumbnail_file"] = info.thumbnail_file.value();
+    if (!info.blurhash.empty())
+        obj["xyz.amorgan.blurhash"] = info.blurhash;
+}
+
 void
 to_json(json &obj, const RelationType &type)
 {
diff --git a/lib/structs/responses/common.cpp b/lib/structs/responses/common.cpp
index 79a0f4f..951696d 100644
--- a/lib/structs/responses/common.cpp
+++ b/lib/structs/responses/common.cpp
@@ -405,8 +405,7 @@ parse_timeline_events(const json &events,
                     break;
                 }
                 case MsgType::Location: {
-                    /* events::RoomEvent<events::msg::Location> location = e; */
-                    /* container.emplace_back(location); */
+                    container.emplace_back(events::RoomEvent<events::msg::Location>(e));
                     break;
                 }
                 case MsgType::Notice: {
diff --git a/meson.build b/meson.build
index 6984171..816de2d 100644
--- a/meson.build
+++ b/meson.build
@@ -82,6 +82,7 @@ src = [
    'lib/structs/events/messages/emote.cpp',
    'lib/structs/events/messages/file.cpp',
    'lib/structs/events/messages/image.cpp',
+   'lib/structs/events/messages/location.cpp',
    'lib/structs/events/messages/notice.cpp',
    'lib/structs/events/messages/text.cpp',
    'lib/structs/events/messages/video.cpp',
diff --git a/tests/messages.cpp b/tests/messages.cpp
index e9cc598..2c2581f 100644
--- a/tests/messages.cpp
+++ b/tests/messages.cpp
@@ -430,7 +430,53 @@ TEST(RoomEvents, ImageMessage)
               mtx::common::RelationType::InReplyTo);
 }

-TEST(RoomEvents, LocationMessage) {}
+TEST(RoomEvents, LocationMessage) {
+    json data = R"({
+            "content": {
+              "body": "Big Ben, London, UK",
+              "geo_uri": "geo:51.5008,0.1247",
+              "info": {
+                "thumbnail_info": {
+                  "h": 300,
+                  "mimetype": "image/jpeg",
+                  "size": 46144,
+                  "w": 300
+                },
+                "thumbnail_url": "mxc://matrix.org/FHyPlCeYUSFFxlgbQYZmoEoe"
+              },
+              "msgtype": "m.location",
+              "m.relates_to": {
+                    "m.in_reply_to": {
+                                    "event_id": "$6GKhAfJOcwNd69lgSizdcTob8z2pWQgBOZPrnsWMA1E"
+                                }
+                            }
+            },
+            "event_id": "$143273582443PhrSn:matrix.org",
+            "origin_server_ts": 1432735824653,
+            "room_id": "!jEsUZKDJdhlrceRyVU:matrix.org",
+            "sender": "@max:kamax.io",
+            "type": "m.room.message",
+            "unsigned": {
+              "age": 69168455
+            }
+          }
+        )"_json;
+    RoomEvent<msg::Location> event = data.get<RoomEvent<msg::Location>>();
+
+    EXPECT_EQ(event.type, EventType::RoomMessage);
+    EXPECT_EQ(event.event_id, "$143273582443PhrSn:matrix.org");
+    EXPECT_EQ(event.room_id, "!jEsUZKDJdhlrceRyVU:matrix.org");
+    EXPECT_EQ(event.sender, "@max:kamax.io");
+    EXPECT_EQ(event.origin_server_ts, 1432735824653);
+    EXPECT_EQ(event.unsigned_data.age, 69168455);
+    EXPECT_EQ(event.content.body,
+              "Big Ben, London, UK");
+    EXPECT_EQ(event.content.msgtype, "m.location");
+    EXPECT_EQ(event.content.relations.relations.at(0).event_id,
+              "$6GKhAfJOcwNd69lgSizdcTob8z2pWQgBOZPrnsWMA1E");
+    EXPECT_EQ(event.content.relations.relations.at(0).rel_type,
+              mtx::common::RelationType::InReplyTo);
+}

 TEST(RoomEvents, NoticeMessage)
 {

include "mtx/events/common.hpp"

include "mtx/events/messages/location.hpp"

using json = nlohmann::json;

namespace mtx { namespace events { namespace msg {

void from_json(const json &obj, Location &content) { content.body = obj.at("body").get(); content.msgtype = obj.at("msgtype").get(); if (obj.find("geo_uri") != obj.end()) content.geo_uri = obj.at("geo_uri").get();

if (obj.find("info") != obj.end())
    content.info = obj.at("info").get<common::LocationInfo>();

content.relations = common::parse_relations(obj);

}

void to_json(json &obj, const Location &content) { obj["msgtype"] = "m.location"; obj["body"] = content.body;

obj["geo_uri"] = content.geo_uri;
obj["info"]    = content.info;
common::apply_relations(obj, content.relations);

}

} // namespace msg } // namespace events } // namespace mtx

deepbluev7 commented 1 year ago

Can you create a pull request? :3