diff --git a/include/mtx/responses/public_rooms.hpp b/include/mtx/responses/public_rooms.hpp index 4e85aea52..3151f838a 100644 --- a/include/mtx/responses/public_rooms.hpp +++ b/include/mtx/responses/public_rooms.hpp @@ -5,6 +5,7 @@ #include #include "mtx/common.hpp" +#include "mtx/events/collections.hpp" #if __has_include() #include @@ -48,6 +49,18 @@ struct PublicRoomsChunk bool guest_can_join; //! The URL for the room's avatar, if one is set. std::string avatar_url; + + //! The room’s join rule. When not present, the room is assumed to be public. + mtx::events::state::JoinRule join_rule = mtx::events::state::JoinRule::Public; + + //! Required: The type of room (from m.room.create), if any. + std::string room_type; + + //! The m.space.child events of the space-room, represented as Stripped State Events with an + //! added origin_server_ts key. + //! + //! If the room is not a space-room, this should be empty. + std::vector children_state; }; void @@ -75,5 +88,18 @@ struct PublicRooms void from_json(const nlohmann::json &obj, PublicRooms &publicRooms); +//! Response from the `GET /_matrix/client/v1/rooms/{roomId}/hierarchy` +struct HierarchyRooms +{ + //! Required: The rooms for the current page, with the current filters. + std::vector rooms; + //! A token to supply to from to keep paginating the responses. Not present when there are no + //! further results. + std::string next_batch; +}; + +void +from_json(const nlohmann::json &obj, HierarchyRooms &publicRooms); + } // namespace responses -} // namespace mtx \ No newline at end of file +} // namespace mtx diff --git a/include/mtxclient/http/client.hpp b/include/mtxclient/http/client.hpp index af870033a..dd938443f 100644 --- a/include/mtxclient/http/client.hpp +++ b/include/mtxclient/http/client.hpp @@ -72,6 +72,7 @@ struct Notifications; struct Profile; struct PublicRoomVisibility; struct PublicRooms; +struct HierarchyRooms; struct QueryDevices; struct QueryKeys; struct Register; @@ -595,6 +596,15 @@ class Client : public std::enable_shared_from_this Callback cb, const std::string &server = ""); + //! Paginates over the space tree in a depth-first manner to locate child rooms of a given + //! space. + void get_hierarchy(const std::string &room_id, + Callback cb, + const std::string &from = "", + size_t limit = 0, + size_t max_depth = 0, + bool suggested_only = false); + // // Group related endpoints. // diff --git a/lib/http/client.cpp b/lib/http/client.cpp index 39f7d69d7..438a7b900 100644 --- a/lib/http/client.cpp +++ b/lib/http/client.cpp @@ -1137,6 +1137,36 @@ Client::get_public_rooms(Callback cb, RequestErr err) { cb(res, err); }); } +void +Client::get_hierarchy(const std::string &room_id, + Callback cb, + const std::string &from, + size_t limit, + size_t max_depth, + bool suggested_only) +{ + std::string api_path = + "/client/v1/rooms/" + mtx::client::utils::url_encode(room_id) + "/hierarchy"; + + std::map params; + if (limit > 0) + params["limit"] = std::to_string(limit); + if (max_depth > 0) + params["max_depth"] = std::to_string(max_depth); + if (suggested_only) + params["suggested_only"] = "true"; + if (!from.empty()) + params["from"] = from; + + if (!params.empty()) + api_path += "?" + mtx::client::utils::query_params(params); + + get( + api_path, + [cb = std::move(cb)]( + const mtx::responses::HierarchyRooms &res, HeaderFields, RequestErr err) { cb(res, err); }); +} + // // Group related endpoints. // diff --git a/lib/structs/responses/public_rooms.cpp b/lib/structs/responses/public_rooms.cpp index dee4da60d..c599edba0 100644 --- a/lib/structs/responses/public_rooms.cpp +++ b/lib/structs/responses/public_rooms.cpp @@ -2,6 +2,7 @@ #include "mtx/common.hpp" #include "mtx/identifiers.hpp" +#include "mtx/responses/common.hpp" #include "mtx/responses/public_rooms.hpp" namespace mtx { @@ -33,6 +34,13 @@ from_json(const nlohmann::json &obj, PublicRoomsChunk &res) res.guest_can_join = obj.at("guest_can_join").get(); res.avatar_url = obj.value("avatar_url", std::string{}); + + res.join_rule = mtx::events::state::stringToJoinRule(obj.value("join_rule", "public")); + + res.room_type = obj.value("room_type", std::string{}); + + if (obj.contains("children_state")) + mtx::responses::utils::parse_stripped_events(obj.at("children_state"), res.children_state); } void @@ -55,5 +63,15 @@ from_json(const nlohmann::json &obj, PublicRooms &publicRooms) : std::nullopt; } +void +from_json(const nlohmann::json &obj, HierarchyRooms &publicRooms) +{ + publicRooms.rooms = obj.at("rooms").get>(); + + if (obj.count("next_batch")) { + publicRooms.next_batch = obj.at("next_batch").get(); + } +} + } // namespace responses -} // namespace mtx \ No newline at end of file +} // namespace mtx