diff --git a/CMakeLists.txt b/CMakeLists.txt index 7bfd58b3e7cb46452206e89e7388df563f48bfaf..22970b787e79e2ac7e217f85ce7ffb56eb48ed00 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -191,7 +191,8 @@ target_sources(matrix_client lib/structs/responses/sync.cpp lib/structs/responses/turn_server.cpp lib/structs/responses/version.cpp - lib/structs/responses/well-known.cpp) + lib/structs/responses/well-known.cpp + lib/structs/responses/public_rooms.cpp) add_library(MatrixClient::MatrixClient ALIAS matrix_client) set_property(TARGET matrix_client PROPERTY CXX_STANDARD 17) set_property(TARGET matrix_client PROPERTY CXX_EXTENSIONS OFF) diff --git a/include/mtx/filters.hpp b/include/mtx/filters.hpp deleted file mode 100644 index 1950f917da7b105df2feecb4c3b016c0d6c62c55..0000000000000000000000000000000000000000 --- a/include/mtx/filters.hpp +++ /dev/null @@ -1,30 +0,0 @@ -#pragma once - -#if __has_include(<nlohmann/json_fwd.hpp>) -#include <nlohmann/json_fwd.hpp> -#else -#include <nlohmann/json.hpp> -#endif - -#include <string> - -//! Filters can be created on the server and can be -//! passed as a parameter to APIs which return events. - -namespace mtx { -namespace filters { - -struct Filter { - //! A string to search for in the room metadata, - //! e.g. name, topic, canonical alias etc. (Optional). - std::string generic_search_term; -}; - -void -from_json(const nlohmann::json &obj, Filter &res); - -void -to_json(nlohmann::json &obj, const Filter &res); - -} // namespace filters -} // namespace mtx diff --git a/include/mtx/public_rooms_chunk.hpp b/include/mtx/public_rooms_chunk.hpp deleted file mode 100644 index b2410935b0331a6b54effc9d352ed2e97a5a7a4b..0000000000000000000000000000000000000000 --- a/include/mtx/public_rooms_chunk.hpp +++ /dev/null @@ -1,45 +0,0 @@ -#pragma once - -#include <string> -#include <vector> - -#if __has_include(<nlohmann/json_fwd.hpp>) -#include <nlohmann/json_fwd.hpp> -#else -#include <nlohmann/json.hpp> -#endif - -namespace mtx { -namespace responses { -struct PublicRoomsChunk -{ - //! Aliases of the room. May be empty. - std::vector<std::string> aliases; - //! The canonical alias of the room, if any. - std::string canonical_alias - //! The name of the room, if any. - std::string name; - //! **Required.** The number of members joined to the room. - int num_joined_members; - //! **Required.** The ID of the room. - std::string room_id; - //! The topic of the room, if any. - std::string topic; - //! **Required.** Whether the room may be viewed by guest users without joining. - bool world_readable; - //! **Required.** Whether guest users may join the room - //! and participate in it. If they can, they will be subject - //! to ordinary power level rules like any other user. - bool guest_can_join; - //! The URL for the room's avatar, if one is set. - std::string avatar_url; -}; - -void -from_json(const nlohmann::json &obj, PublicRoomsChunk &res); - -void -to_json(nlohmann::json &obj, const PublicRoomsChunk &res); - -} // namespace responses -} // namespace mtx \ No newline at end of file diff --git a/include/mtx/requests.hpp b/include/mtx/requests.hpp index 940cf2037423b1b7e1806ed72da47276ab721194..b765c20947829a3406b02618304c50968b904fbe 100644 --- a/include/mtx/requests.hpp +++ b/include/mtx/requests.hpp @@ -5,7 +5,6 @@ #include <mtx/common.hpp> #include <mtx/events/collections.hpp> -#include <mtx/filters.hpp> #if __has_include(<nlohmann/json_fwd.hpp>) #include <nlohmann/json_fwd.hpp> #else @@ -138,6 +137,15 @@ struct TypingNotification void to_json(json &obj, const TypingNotification &request); +struct PublicRoomsFilter { + //! A string to search for in the room metadata, + //! e.g. name, topic, canonical alias etc. (Optional). + std::string generic_search_term; +}; + +void +to_json(nlohmann::json &obj, const PublicRoomsFilter &req); + //! Request payload for the `POST /_matrix/client/r0/publicRooms` endpoint. struct PublicRooms { @@ -149,7 +157,7 @@ struct PublicRooms //! rather than via an explicit flag. std::string since; //! Filter to apply to the results. - Filter filter; + PublicRoomsFilter filter; //! Whether or not to include all known networks/protocols from //! application services on the homeserver. Defaults to false. bool include_all_networks = false; @@ -159,7 +167,7 @@ struct PublicRooms }; void -to_json(json &obj, const PostPublicRooms &request); +to_json(json &obj, const PublicRooms &request); struct Empty {}; diff --git a/include/mtx/responses/public_rooms.hpp b/include/mtx/responses/public_rooms.hpp index c0df3419e2249696e8cbfc515279498890118162..61fc55ab549eaf73ff389854357337c0726d3b81 100644 --- a/include/mtx/responses/public_rooms.hpp +++ b/include/mtx/responses/public_rooms.hpp @@ -9,10 +9,34 @@ #include <nlohmann/json.hpp> #endif -#include "mtx/public_rooms_chunk.hpp" - namespace mtx { namespace responses { +struct PublicRoomsChunk +{ + //! Aliases of the room. May be empty. + std::vector<std::string> aliases; + //! The canonical alias of the room, if any. + std::string canonical_alias; + //! The name of the room, if any. + std::string name; + //! **Required.** The number of members joined to the room. + int num_joined_members; + //! **Required.** The ID of the room. + std::string room_id; + //! The topic of the room, if any. + std::string topic; + //! **Required.** Whether the room may be viewed by guest users without joining. + bool world_readable; + //! **Required.** Whether guest users may join the room + //! and participate in it. If they can, they will be subject + //! to ordinary power level rules like any other user. + bool guest_can_join; + //! The URL for the room's avatar, if one is set. + std::string avatar_url; +}; + +void +from_json(const nlohmann::json &obj, PublicRoomsChunk &res); //! Response from the `GET /_matrix/client/r0/publicRooms` & //! `POST /_matrix/client/r0/publicRooms` endpoints. diff --git a/include/mtxclient/http/client.hpp b/include/mtxclient/http/client.hpp index 7b960e43d355640b1c967dc04377036764221f06..345dab66afaacef7b3c7efa962e9991522be8314 100644 --- a/include/mtxclient/http/client.hpp +++ b/include/mtxclient/http/client.hpp @@ -449,11 +449,14 @@ public: ErrCallback callback); //! POST a new room listing to the public rooms directory. - void post_public_rooms(const std::string &server, const nhlomann::json &j, - Callback<mtx::responses::PublicRooms> cb); + void post_public_rooms(const mtx::requests::PublicRooms &req, + Callback<mtx::responses::PublicRooms> cb, + const std::string &server = "matrix.org"); //! GET the public rooms directory listing. - void get_public_rooms(int limit, const std::string &since, const std::string &server, - Callback<mtx::responses::PublicRooms> cb); + void get_public_rooms(Callback<mtx::responses::PublicRooms> cb, + const std::string &server = "matrix.org", + int limit = std::numeric_limits<int>::max(), + const std::string &since = ""); // // Group related endpoints. // diff --git a/lib/http/client.cpp b/lib/http/client.cpp index 0ead749393d4a96d5b79a91df41fbfc8c200141a..9b93b787fcf9676ba16dcb1d9dece4c14d5dc165 100644 --- a/lib/http/client.cpp +++ b/lib/http/client.cpp @@ -963,21 +963,27 @@ Client::send_to_device(const std::string &event_type, } void -Client::post_public_rooms(const std::string &server, const nhlomann::json &j, - Callback<mtx::responses::PublicRooms> cb) -{ - const auto api_path = "/client/r0/publicRooms" + " " + server; +Client::post_public_rooms(const mtx::requests::PublicRooms &req, + Callback<mtx::responses::PublicRooms> cb, const std::string &server) +{ + const auto api_path = "/client/r0/publicRooms?" + + mtx::client::utils::query_params({{"server", server}}); post<mtx::requests::PublicRooms, mtx::responses::PublicRooms>( - api_path, j, cb); + api_path, req, cb); } void -Client::get_public_rooms(int limit, const std::string &since, const std::string &server, - Callback<mtx::responses::PublicRooms> cb) +Client::get_public_rooms(Callback<mtx::responses::PublicRooms> cb, const std::string &server, + int limit, const std::string &since) { const auto api_path = - "/client/r0/publicRooms" + " " + std::to_string(limit) + " " + since + " " + server; - get<mtx::requests::PublicRooms, mtx::responses::PublicRooms>(api_path, cb); + "/client/r0/publicRooms" + + mtx::client::utils::query_params({{"server", server}, {"limit", std::to_string(limit)}, {"since", since}}); + + get<mtx::responses::PublicRooms>(api_path, + [cb](const mtx::responses::PublicRooms &res, + HeaderFields, + RequestErr err) { cb(res, err); }); } diff --git a/lib/structs/requests.cpp b/lib/structs/requests.cpp index c36ee42b3bb14442819a219b349707ba37168bf3..e89d6963653314ff22df72107782c43f93b11db0 100644 --- a/lib/structs/requests.cpp +++ b/lib/structs/requests.cpp @@ -111,6 +111,29 @@ to_json(json &obj, const TypingNotification &request) obj["timeout"] = request.timeout; } +void +to_json(json &obj, const PublicRoomsFilter &request) +{ + obj["generic_search_term"] = request.generic_search_term; +} + +void +to_json(json &obj, const PublicRooms &request) +{ + obj["limit"] = request.limit; + obj["since"] = request.since; + obj["filter"] = request.filter; + + // Based on the spec, third_party_instance_id can only be used if + // include_all_networks is false. A case where the latter is true and + // the former is set is invalid. + if (request.include_all_networks && !request.third_party_instance_id.empty()) { + throw std::invalid_argument("third_party_instance_id id can only be set if include_all_networks is false"); + } + obj["third_party_instance_id"] = request.third_party_instance_id; + obj["include_all_networks"] = !request.third_party_instance_id.empty(); +} + void to_json(json &obj, const SignedOneTimeKey &request) { diff --git a/lib/structs/responses/public_rooms.cpp b/lib/structs/responses/public_rooms.cpp new file mode 100644 index 0000000000000000000000000000000000000000..b468c64288730ab1463abb601e792e7044029ab7 --- /dev/null +++ b/lib/structs/responses/public_rooms.cpp @@ -0,0 +1,71 @@ +#include <nlohmann/json.hpp> + +#include "mtx/identifiers.hpp" +#include "mtx/responses/public_rooms.hpp" + +namespace mtx { +namespace responses { + +void +from_json(const nlohmann::json &obj, PublicRoomsChunk &res) +{ + if (obj.count("aliases") != 0 && !obj.at("aliases").is_null()) { + res.aliases = obj.at("aliases").get<std::vector<std::string>>(); + } + + if (obj.count("canonical_alias") != 0 && !obj.at("canonical_alias").is_null()) { + res.canonical_alias = obj.at("canonical_alias").get<std::string>(); + } + + if (obj.count("name") != 0 && !obj.at("name").is_null()) { + res.name = obj.at("name").get<std::string>(); + } + + if (obj.count("num_joined_members") != 0 && !obj.at("num_joined_members").is_null()) { + res.num_joined_members = obj.at("num_joined_members").get<int>(); + } + + if (obj.count("room_id") != 0 && !obj.at("room_id").is_null()) { + res.room_id = obj.at("room_id").get<std::string>(); + } + + if (obj.count("topic") != 0 && !obj.at("topic").is_null()) { + res.topic = obj.at("topic").get<std::string>(); + } + + if (obj.count("world_readable") != 0 && !obj.at("world_readable").is_null()) { + res.world_readable = obj.at("world_readable").get<bool>(); + } + + if (obj.count("guest_can_join") != 0 && !obj.at("guest_can_join").is_null()) { + res.guest_can_join = obj.at("guest_can_join").get<bool>(); + } + + if (obj.count("avatar_url") != 0 && !obj.at("avatar_url").is_null()) { + res.avatar_url = obj.at("avatar_url").get<std::string>(); + } +} + +void +from_json(const nlohmann::json &obj, PublicRooms &publicRooms) +{ + // PublicRoomsChunk is CopyConstructible & DefaultConstructible + if (obj.count("chunk") != 0 && !obj.at("chunk").is_null()) { + publicRooms.chunk = obj.at("chunk").get<std::vector<PublicRoomsChunk>>(); + } + + if (obj.count("next_batch") != 0 && !obj.at("next_batch").is_null()) { + publicRooms.next_batch = obj.at("next_batch").get<std::string>(); + } + + if (obj.count("prev_batch") != 0 && !obj.at("prev_batch").is_null()) { + publicRooms.prev_batch = obj.at("prev_batch").get<std::string>(); + } + + if (obj.count("total_room_count_estimate") != 0 && !obj.at("total_room_count_estimate").is_null()) { + publicRooms.total_room_count_estimate = obj.at("total_room_count_estimate").get<int>(); + } +} + +} // namespace responses +} // namespace mtx \ No newline at end of file