From bb33fcb33d090316d7c3d71cb76f1232347d2008 Mon Sep 17 00:00:00 2001 From: Nicolas Werner <nicolas.werner@hotmail.de> Date: Sat, 10 Apr 2021 23:41:33 +0200 Subject: [PATCH] Add API to set and get account data --- include/mtx/events/collections.hpp | 19 +++++++ include/mtxclient/http/client.hpp | 61 ++++++++++++++++++++ include/mtxclient/http/client_impl.hpp | 78 ++++++++++++++++++++++++++ lib/http/client.cpp | 25 +++++++++ tests/client_api.cpp | 77 +++++++++++++++++++++++++ 5 files changed, 260 insertions(+) diff --git a/include/mtx/events/collections.hpp b/include/mtx/events/collections.hpp index 2e8c5fae2..0bbf18331 100644 --- a/include/mtx/events/collections.hpp +++ b/include/mtx/events/collections.hpp @@ -316,5 +316,24 @@ constexpr inline EventType to_device_content_to_type<mtx::events::msg::SecretSen template<> constexpr inline EventType to_device_content_to_type<mtx::events::msg::SecretRequest> = EventType::SecretRequest; + +//! Get the right event type for some type of account_data event content. +template<typename Content> +constexpr inline EventType account_data_content_to_type = EventType::Unsupported; + +template<> +constexpr inline EventType account_data_content_to_type<mtx::events::msc2545::ImagePack> = + EventType::ImagePackInAccountData; +template<> +constexpr inline EventType account_data_content_to_type<mtx::events::msc2545::ImagePackRooms> = + EventType::ImagePackRooms; +template<> +constexpr inline EventType account_data_content_to_type<mtx::events::account_data::Tags> = + EventType::Tag; +template<> +constexpr inline EventType + account_data_content_to_type<mtx::events::account_data::nheko_extensions::HiddenEvents> = + EventType::NhekoHiddenEvents; + } // namespace events } // namespace mtx diff --git a/include/mtxclient/http/client.hpp b/include/mtxclient/http/client.hpp index 89152130d..c6fd3af9f 100644 --- a/include/mtxclient/http/client.hpp +++ b/include/mtxclient/http/client.hpp @@ -421,6 +421,42 @@ public: void get_event(const std::string &room_id, const std::string &event_id, Callback<mtx::events::collections::TimelineEvents> cb); + + //! Store a room account_data event. + template<class Payload> + void put_room_account_data(const std::string &room_id, + const std::string &type, + const Payload &payload, + ErrCallback cb); + //! Store a room account_data event. + template<class Payload> + void put_room_account_data(const std::string &room_id, + const Payload &payload, + ErrCallback cb); + + //! Store an account_data event. + template<class Payload> + void put_account_data(const std::string &type, const Payload &payload, ErrCallback cb); + //! Store an account_data event. + template<class Payload> + void put_account_data(const Payload &payload, ErrCallback cb); + + //! Retrieve a room account_data event. + template<class Payload> + void get_room_account_data(const std::string &room_id, + const std::string &type, + Callback<Payload> payload); + //! Retrieve a room account_data event. + template<class Payload> + void get_room_account_data(const std::string &room_id, Callback<Payload> cb); + + //! Retrieve an account_data event. + template<class Payload> + void get_account_data(const std::string &type, Callback<Payload> payload); + //! Retrieve an account_data event. + template<class Payload> + void get_account_data(Callback<Payload> cb); + //! Send a room message with auto-generated transaction id. template<class Payload> void send_room_message(const std::string &room_id, @@ -717,3 +753,28 @@ MTXCLIENT_SEND_TO_DEVICE_FWD(mtx::events::msg::KeyVerificationKey) MTXCLIENT_SEND_TO_DEVICE_FWD(mtx::events::msg::KeyVerificationMac) MTXCLIENT_SEND_TO_DEVICE_FWD(mtx::events::msg::SecretSend) MTXCLIENT_SEND_TO_DEVICE_FWD(mtx::events::msg::SecretRequest) + +#define MTXCLIENT_ACCOUNT_DATA_FWD(Payload) \ + extern template void mtx::http::Client::put_room_account_data<Payload>( \ + const std::string &room_id, \ + const std::string &type, \ + const Payload &payload, \ + ErrCallback cb); \ + extern template void mtx::http::Client::put_room_account_data<Payload>( \ + const std::string &room_id, const Payload &payload, ErrCallback cb); \ + extern template void mtx::http::Client::put_account_data<Payload>( \ + const std::string &type, const Payload &payload, ErrCallback cb); \ + extern template void mtx::http::Client::put_account_data<Payload>(const Payload &payload, \ + ErrCallback cb); \ + extern template void mtx::http::Client::get_room_account_data<Payload>( \ + const std::string &room_id, const std::string &type, Callback<Payload> payload); \ + extern template void mtx::http::Client::get_room_account_data<Payload>( \ + const std::string &room_id, Callback<Payload> cb); \ + extern template void mtx::http::Client::get_account_data<Payload>( \ + const std::string &type, Callback<Payload> payload); \ + extern template void mtx::http::Client::get_account_data<Payload>(Callback<Payload> cb); + +MTXCLIENT_ACCOUNT_DATA_FWD(mtx::events::msc2545::ImagePack) +MTXCLIENT_ACCOUNT_DATA_FWD(mtx::events::msc2545::ImagePackRooms) +MTXCLIENT_ACCOUNT_DATA_FWD(mtx::events::account_data::nheko_extensions::HiddenEvents) +MTXCLIENT_ACCOUNT_DATA_FWD(mtx::events::account_data::Tags) diff --git a/include/mtxclient/http/client_impl.hpp b/include/mtxclient/http/client_impl.hpp index 54f54c8e3..ff7f99d43 100644 --- a/include/mtxclient/http/client_impl.hpp +++ b/include/mtxclient/http/client_impl.hpp @@ -234,3 +234,81 @@ mtx::http::Client::send_state_event(const std::string &room_id, { send_state_event<Payload>(room_id, "", payload, callback); } + +template<class Payload> +[[gnu::used, llvm::used]] void +mtx::http::Client::put_room_account_data(const std::string &room_id, + const std::string &type, + const Payload &payload, + ErrCallback cb) +{ + const auto api_path = "/client/r0/user/" + + mtx::client::utils::url_encode(user_id_.to_string()) + "/rooms/" + + mtx::client::utils::url_encode(room_id) + "/account_data/" + type; + put<Payload>(api_path, payload, cb); +} +template<class Payload> +[[gnu::used, llvm::used]] void +mtx::http::Client::put_room_account_data(const std::string &room_id, + const Payload &payload, + ErrCallback cb) +{ + constexpr auto event_type = mtx::events::account_data_content_to_type<Payload>; + static_assert(event_type != mtx::events::EventType::Unsupported); + put_room_account_data(room_id, to_string(event_type), payload, std::move(cb)); +} +template<class Payload> +[[gnu::used, llvm::used]] void +mtx::http::Client::put_account_data(const std::string &type, const Payload &payload, ErrCallback cb) +{ + const auto api_path = "/client/r0/user/" + + mtx::client::utils::url_encode(user_id_.to_string()) + + "/account_data/" + type; + put<Payload>(api_path, payload, cb); +} +template<class Payload> +[[gnu::used, llvm::used]] void +mtx::http::Client::put_account_data(const Payload &payload, ErrCallback cb) +{ + constexpr auto event_type = mtx::events::account_data_content_to_type<Payload>; + static_assert(event_type != mtx::events::EventType::Unsupported); + put_account_data(to_string(event_type), payload, std::move(cb)); +} +template<class Payload> +[[gnu::used, llvm::used]] void +mtx::http::Client::get_room_account_data(const std::string &room_id, + const std::string &type, + Callback<Payload> cb) +{ + const auto api_path = "/client/r0/user/" + + mtx::client::utils::url_encode(user_id_.to_string()) + "/rooms/" + + mtx::client::utils::url_encode(room_id) + "/account_data/" + type; + get<Payload>(api_path, + [cb](const Payload &res, HeaderFields, RequestErr err) { cb(res, err); }); +} +template<class Payload> +[[gnu::used, llvm::used]] void +mtx::http::Client::get_room_account_data(const std::string &room_id, Callback<Payload> cb) +{ + constexpr auto event_type = mtx::events::account_data_content_to_type<Payload>; + static_assert(event_type != mtx::events::EventType::Unsupported); + get_room_account_data(room_id, to_string(event_type), std::move(cb)); +} +template<class Payload> +[[gnu::used, llvm::used]] void +mtx::http::Client::get_account_data(const std::string &type, Callback<Payload> cb) +{ + const auto api_path = "/client/r0/user/" + + mtx::client::utils::url_encode(user_id_.to_string()) + + "/account_data/" + type; + get<Payload>(api_path, + [cb](const Payload &res, HeaderFields, RequestErr err) { cb(res, err); }); +} +template<class Payload> +[[gnu::used, llvm::used]] void +mtx::http::Client::get_account_data(Callback<Payload> cb) +{ + constexpr auto event_type = mtx::events::account_data_content_to_type<Payload>; + static_assert(event_type != mtx::events::EventType::Unsupported); + get_account_data(to_string(event_type), std::move(cb)); +} diff --git a/lib/http/client.cpp b/lib/http/client.cpp index 41709225a..826f41227 100644 --- a/lib/http/client.cpp +++ b/lib/http/client.cpp @@ -1493,3 +1493,28 @@ MTXCLIENT_SEND_TO_DEVICE(mtx::events::msg::KeyVerificationKey) MTXCLIENT_SEND_TO_DEVICE(mtx::events::msg::KeyVerificationMac) MTXCLIENT_SEND_TO_DEVICE(mtx::events::msg::SecretSend) MTXCLIENT_SEND_TO_DEVICE(mtx::events::msg::SecretRequest) + +#define MTXCLIENT_ACCOUNT_DATA(Payload) \ + template void mtx::http::Client::put_room_account_data<Payload>( \ + const std::string &room_id, \ + const std::string &type, \ + const Payload &payload, \ + ErrCallback cb); \ + template void mtx::http::Client::put_room_account_data<Payload>( \ + const std::string &room_id, const Payload &payload, ErrCallback cb); \ + template void mtx::http::Client::put_account_data<Payload>( \ + const std::string &type, const Payload &payload, ErrCallback cb); \ + template void mtx::http::Client::put_account_data<Payload>(const Payload &payload, \ + ErrCallback cb); \ + template void mtx::http::Client::get_room_account_data<Payload>( \ + const std::string &room_id, const std::string &type, Callback<Payload> payload); \ + template void mtx::http::Client::get_room_account_data<Payload>( \ + const std::string &room_id, Callback<Payload> cb); \ + template void mtx::http::Client::get_account_data<Payload>(const std::string &type, \ + Callback<Payload> payload); \ + template void mtx::http::Client::get_account_data<Payload>(Callback<Payload> cb); + +MTXCLIENT_ACCOUNT_DATA(mtx::events::msc2545::ImagePack) +MTXCLIENT_ACCOUNT_DATA(mtx::events::msc2545::ImagePackRooms) +MTXCLIENT_ACCOUNT_DATA(mtx::events::account_data::nheko_extensions::HiddenEvents) +MTXCLIENT_ACCOUNT_DATA(mtx::events::account_data::Tags) diff --git a/tests/client_api.cpp b/tests/client_api.cpp index b6f153efd..348ed6e86 100644 --- a/tests/client_api.cpp +++ b/tests/client_api.cpp @@ -328,6 +328,83 @@ TEST(ClientAPI, TagRoom) mtx_client->close(); } +TEST(ClientAPI, RoomAccountData) +{ + std::shared_ptr<Client> mtx_client = make_test_client(); + + mtx_client->login( + "alice", "secret", [mtx_client](const mtx::responses::Login &, RequestErr err) { + check_error(err); + }); + + while (mtx_client->access_token().empty()) + sleep(); + + mtx::requests::CreateRoom req; + req.name = "Name"; + req.topic = "Topic"; + mtx_client->create_room( + req, [mtx_client](const mtx::responses::CreateRoom &res, RequestErr err) { + auto room_id = res.room_id; + check_error(err); + + mtx::events::account_data::nheko_extensions::HiddenEvents hiddenEv; + hiddenEv.hidden_event_types.push_back(mtx::events::EventType::RoomMember); + + mtx_client->put_room_account_data( + room_id.to_string(), hiddenEv, [mtx_client, room_id](RequestErr err) { + check_error(err); + + mtx_client->get_room_account_data< + mtx::events::account_data::nheko_extensions::HiddenEvents>( + room_id.to_string(), + [](mtx::events::account_data::nheko_extensions::HiddenEvents hiddenEv, + RequestErr err) { + check_error(err); + + ASSERT_EQ(hiddenEv.hidden_event_types.size(), 1); + EXPECT_EQ(hiddenEv.hidden_event_types.at(0), + mtx::events::EventType::RoomMember); + }); + }); + }); + + mtx_client->close(); +} + +TEST(ClientAPI, AccountData) +{ + std::shared_ptr<Client> mtx_client = make_test_client(); + + mtx_client->login( + "alice", "secret", [mtx_client](const mtx::responses::Login &, RequestErr err) { + check_error(err); + }); + + while (mtx_client->access_token().empty()) + sleep(); + + mtx::events::account_data::nheko_extensions::HiddenEvents hiddenEv; + hiddenEv.hidden_event_types.push_back(mtx::events::EventType::RoomMember); + + mtx_client->put_account_data(hiddenEv, [mtx_client](RequestErr err) { + check_error(err); + + mtx_client + ->get_account_data<mtx::events::account_data::nheko_extensions::HiddenEvents>( + [mtx_client](mtx::events::account_data::nheko_extensions::HiddenEvents hiddenEv, + RequestErr err) { + check_error(err); + + ASSERT_EQ(hiddenEv.hidden_event_types.size(), 1); + EXPECT_EQ(hiddenEv.hidden_event_types.at(0), + mtx::events::EventType::RoomMember); + }); + }); + + mtx_client->close(); +} + TEST(ClientAPI, LogoutSuccess) { std::shared_ptr<Client> mtx_client = make_test_client(); -- GitLab