From a94839b6ba14c0787c1823037eb129c917be97a6 Mon Sep 17 00:00:00 2001
From: Thulinma <jaron@vietors.com>
Date: Sun, 10 Oct 2021 18:02:42 +0200
Subject: [PATCH] Device query endpoint

---
 CMakeLists.txt                    |  1 +
 include/mtx/responses.hpp         |  1 +
 include/mtx/responses/device.hpp  | 54 +++++++++++++++++++++++++++++++
 include/mtxclient/http/client.hpp | 13 ++++++++
 lib/http/client.cpp               | 13 ++++++++
 lib/structs/responses/device.cpp  | 35 ++++++++++++++++++++
 meson.build                       |  1 +
 7 files changed, 118 insertions(+)
 create mode 100644 include/mtx/responses/device.hpp
 create mode 100644 lib/structs/responses/device.cpp

diff --git a/CMakeLists.txt b/CMakeLists.txt
index 5496bb1a2..a8e64ed70 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -232,6 +232,7 @@ target_sources(matrix_client
 	lib/structs/responses/common.cpp
 	lib/structs/responses/create_room.cpp
 	lib/structs/responses/crypto.cpp
+	lib/structs/responses/device.cpp
 	lib/structs/responses/empty.cpp
 	lib/structs/responses/groups.cpp
 	lib/structs/responses/login.cpp
diff --git a/include/mtx/responses.hpp b/include/mtx/responses.hpp
index 8d844cc9e..176c5973a 100644
--- a/include/mtx/responses.hpp
+++ b/include/mtx/responses.hpp
@@ -7,6 +7,7 @@
 
 #include "responses/create_room.hpp"
 #include "responses/crypto.hpp"
+#include "responses/device.hpp"
 #include "responses/empty.hpp"
 #include "responses/groups.hpp"
 #include "responses/login.hpp"
diff --git a/include/mtx/responses/device.hpp b/include/mtx/responses/device.hpp
new file mode 100644
index 000000000..e79539572
--- /dev/null
+++ b/include/mtx/responses/device.hpp
@@ -0,0 +1,54 @@
+#pragma once
+
+/// @file
+/// @brief device related endpoints.
+
+#if __has_include(<nlohmann/json_fwd.hpp>)
+#include <nlohmann/json_fwd.hpp>
+#else
+#include <nlohmann/json.hpp>
+#endif
+
+#include "mtx/common.hpp"
+#include "mtx/lightweight_error.hpp"
+
+#include <string>
+#include <vector>
+
+namespace mtx {
+namespace responses {
+
+struct Device
+{
+    //! **Required.** Identifier of this device.
+    std::string device_id;
+
+    //! Display name set by the user for this device. Absent if no name has been set.
+    std::string display_name;
+
+    //! The IP address where this device was last seen. (May be a few minutes out of date, for
+    //! efficiency reasons).
+    std::string last_seen_ip;
+
+    //! The timestamp (in milliseconds since the unix epoch) when this devices was last seen. (May
+    //! be a few minutes out of date, for efficiency reasons).
+    size_t last_seen_ts;
+};
+
+void
+from_json(const nlohmann::json &obj, Device &res);
+
+//! Response from the `GET /_matrix/client/r0/devices` endpoint.
+struct QueryDevices
+{
+    //! Gets information about all devices for the current user.
+    //! A list of all registered devices for this user.
+    //
+    std::vector<Device> devices;
+};
+
+void
+from_json(const nlohmann::json &obj, QueryDevices &response);
+
+}
+}
diff --git a/include/mtxclient/http/client.hpp b/include/mtxclient/http/client.hpp
index 9f99b2adb..f52c65df7 100644
--- a/include/mtxclient/http/client.hpp
+++ b/include/mtxclient/http/client.hpp
@@ -79,6 +79,7 @@ struct Versions;
 struct WellKnown;
 struct PublicRoomVisibility;
 struct PublicRooms;
+struct QueryDevices;
 namespace backup {
 struct SessionBackup;
 struct RoomKeysBackup;
@@ -581,6 +582,18 @@ public:
                            Callback<nlohmann::json> cb);
     void add_room_to_group(const std::string &room_id, const std::string &group_id, ErrCallback cb);
 
+    //
+    // Device related endpoints.
+    //
+
+    //! List devices
+    void query_devices(Callback<mtx::responses::QueryDevices> cb);
+
+    /////! Rename device
+    // void rename_device(const mtx::requests::DeviceSigningUpload,
+    //                           UIAHandler uia_handler,
+    //                           ErrCallback cb);
+
     //
     // Encryption related endpoints.
     //
diff --git a/lib/http/client.cpp b/lib/http/client.cpp
index 0d55eb253..dc5a9fb6c 100644
--- a/lib/http/client.cpp
+++ b/lib/http/client.cpp
@@ -1082,6 +1082,19 @@ Client::add_room_to_group(const std::string &room_id, const std::string &group_i
       "/client/r0/groups/" + group_id + "/admin/rooms/" + room_id, json::object(), cb);
 }
 
+//
+// Device related endpoints
+//
+
+void
+Client::query_devices(Callback<mtx::responses::QueryDevices> cb)
+{
+    get<mtx::responses::QueryDevices>("/client/r0/devices",
+                                      [cb](const mtx::responses::QueryDevices &res,
+                                           HeaderFields,
+                                           RequestErr err) { cb(res, err); });
+}
+
 //
 // Encryption related endpoints
 //
diff --git a/lib/structs/responses/device.cpp b/lib/structs/responses/device.cpp
new file mode 100644
index 000000000..1973c3770
--- /dev/null
+++ b/lib/structs/responses/device.cpp
@@ -0,0 +1,35 @@
+#include "mtx/responses/device.hpp"
+
+#include <nlohmann/json.hpp>
+
+namespace mtx {
+namespace responses {
+
+void
+from_json(const nlohmann::json &obj, Device &res)
+{
+    res.device_id = obj.at("device_id").get<std::string>();
+
+    // This is needed because synapse sometimes sends null instead -_-
+    if (obj.contains("display_name") && obj["display_name"].is_string()) {
+        res.display_name = obj.value("display_name", std::string{});
+    }
+
+    // This is needed because synapse sometimes sends null instead -_-
+    if (obj.contains("last_seen_ip") && obj["last_seen_ip"].is_string()) {
+        res.last_seen_ip = obj.value("last_seen_ip", std::string{});
+    }
+
+    // This is needed because synapse sometimes sends null instead -_-
+    if (obj.contains("last_seen_ts") && obj["last_seen_ts"].is_number()) {
+        res.last_seen_ts = obj.value("last_seen_ts", size_t{});
+    }
+}
+
+void
+from_json(const nlohmann::json &obj, QueryDevices &response)
+{
+    response.devices = obj.at("devices").get<std::vector<Device>>();
+}
+}
+}
diff --git a/meson.build b/meson.build
index e2d166076..33db9e5a6 100644
--- a/meson.build
+++ b/meson.build
@@ -97,6 +97,7 @@ src = [
 	'lib/structs/responses/common.cpp',
 	'lib/structs/responses/create_room.cpp',
 	'lib/structs/responses/crypto.cpp',
+	'lib/structs/responses/device.cpp',
 	'lib/structs/responses/empty.cpp',
 	'lib/structs/responses/groups.cpp',
 	'lib/structs/responses/login.cpp',
-- 
GitLab