From adb8c64879b410d687cdd06a182f667825bcb2bf Mon Sep 17 00:00:00 2001
From: Konstantinos Sideris <sideris.konstantin@gmail.com>
Date: Sat, 7 Apr 2018 12:08:31 +0300
Subject: [PATCH] Add send_to_device method

---
 CMakeLists.txt            |  4 ++--
 cmake/MatrixStructs.cmake |  2 +-
 src/client.cpp            | 10 ++++++++++
 src/client.hpp            | 14 ++++++++++++++
 tests/client_api.cpp      | 34 ++++++++++++++++++++++++++++++++++
 tests/test_helpers.hpp    |  6 ++++++
 6 files changed, 67 insertions(+), 3 deletions(-)

diff --git a/CMakeLists.txt b/CMakeLists.txt
index f22d65a41..f45091367 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -111,7 +111,7 @@ if(NOT MATRIX_STRUCTS_LIBRARY)
     set(MTXCLIENT_DEPS ${MTXCLIENT_DEPS} MatrixStructs)
 endif()
 include_directories(${MATRIX_STRUCTS_INCLUDE_DIR})
-set(MTXCLIENT_LIBS ${MTXCLIENT_LIBS} matrix_structs)
+set(MTXCLIENT_LIBS ${MTXCLIENT_LIBS} ${MATRIX_STRUCTS_LIBRARY})
 
 
 #
@@ -134,7 +134,7 @@ target_include_directories(matrix_client SYSTEM PRIVATE $ENV{INCLUDE})
 
 if (BUILD_LIB_EXAMPLES)
     add_executable(room_feed examples/room_feed.cpp)
-    target_link_libraries(room_feed matrix_client matrix_structs)
+    target_link_libraries(room_feed matrix_client ${MATRIX_STRUCTS_LIBRARY})
 endif()
 
 if (BUILD_LIB_TESTS)
diff --git a/cmake/MatrixStructs.cmake b/cmake/MatrixStructs.cmake
index 18d91d687..568540b3a 100644
--- a/cmake/MatrixStructs.cmake
+++ b/cmake/MatrixStructs.cmake
@@ -21,7 +21,7 @@ ExternalProject_Add(
   MatrixStructs
 
   GIT_REPOSITORY https://github.com/mujx/matrix-structs
-  GIT_TAG 93fcce2d83d728cc0db31b0b9eed196409de0df1
+  GIT_TAG a65c0be6082af850f2e2cc7ef0c922e1ce319816
 
   BUILD_IN_SOURCE 1
   SOURCE_DIR ${MATRIX_STRUCTS_ROOT}
diff --git a/src/client.cpp b/src/client.cpp
index 4a378549b..2e322175c 100644
--- a/src/client.cpp
+++ b/src/client.cpp
@@ -501,6 +501,16 @@ Client::flow_response(const std::string &user,
         post<nlohmann::json, mtx::responses::Register>("/client/r0/register", req, callback, false);
 }
 
+void
+Client::send_to_device(const std::string &event_type,
+                       const std::string &txid,
+                       const nlohmann::json &body,
+                       std::function<void(RequestErr)> callback)
+{
+        const auto api_path = "/client/r0/sendToDevice/" + event_type + "/" + txid;
+        put<nlohmann::json>(api_path, body, callback);
+}
+
 //
 // Encryption related endpoints
 //
diff --git a/src/client.hpp b/src/client.hpp
index e3e65836a..a59af775f 100644
--- a/src/client.hpp
+++ b/src/client.hpp
@@ -195,6 +195,20 @@ public:
           const Payload &payload,
           std::function<void(const mtx::responses::EventId &, RequestErr)> callback);
 
+        //! Send send-to-device events to a set of client devices with a specified transaction id.
+        void send_to_device(const std::string &event_type,
+                            const std::string &txid,
+                            const nlohmann::json &body,
+                            std::function<void(RequestErr)> callback);
+
+        //! Send send-to-device events to a set of client devices with a generated transaction id.
+        void send_to_device(const std::string &event_type,
+                            const nlohmann::json &body,
+                            std::function<void(RequestErr)> callback)
+        {
+                send_to_device(event_type, generate_txn_id(), body, callback);
+        }
+
         //
         // Encryption related endpoints.
         //
diff --git a/tests/client_api.cpp b/tests/client_api.cpp
index df9f00fac..411323e04 100644
--- a/tests/client_api.cpp
+++ b/tests/client_api.cpp
@@ -966,3 +966,37 @@ TEST(ClientAPI, ReadMarkers)
 
         alice->close();
 }
+
+TEST(ClientAPI, SendToDevice)
+{
+        auto alice = std::make_shared<Client>("localhost");
+        auto bob   = std::make_shared<Client>("localhost");
+
+        alice->login("alice", "secret", &check_login);
+        bob->login("bob", "secret", &check_login);
+
+        while (alice->access_token().empty() || bob->access_token().empty())
+                sleep();
+
+        json body{{"messages",
+                   {{bob->user_id().to_string(),
+                     {{bob->device_id(), {{"example_content_key", "test"}}}}}}}};
+
+        alice->send_to_device("m.test", body, [bob](RequestErr err) {
+                check_error(err);
+
+                bob->sync("", "", false, 0, [](const mtx::responses::Sync &res, RequestErr err) {
+                        check_error(err);
+
+                        EXPECT_EQ(res.to_device.size(), 1);
+
+                        auto msg = res.to_device.at(0);
+                        EXPECT_EQ(msg.at("content").at("example_content_key"), "test");
+                        EXPECT_EQ(msg.at("type"), "m.test");
+                        EXPECT_EQ(msg.at("sender"), "@alice:localhost");
+                });
+        });
+
+        alice->close();
+        bob->close();
+}
diff --git a/tests/test_helpers.hpp b/tests/test_helpers.hpp
index bc5457272..60984c98d 100644
--- a/tests/test_helpers.hpp
+++ b/tests/test_helpers.hpp
@@ -31,6 +31,12 @@ check_error(mtx::client::RequestErr err)
         ASSERT_FALSE(err);
 }
 
+inline void
+check_login(const mtx::responses::Login &, mtx::client::RequestErr err)
+{
+        check_error(err);
+}
+
 inline void
 validate_login(const std::string &user, const mtx::responses::Login &res)
 {
-- 
GitLab