ruma_client_api/space/
get_hierarchy.rs

1//! `GET /_matrix/client/*/rooms/{roomId}/hierarchy`
2//!
3//! Paginates over the space tree in a depth-first manner to locate child rooms of a given space.
4
5pub mod v1 {
6    //! `/v1/` ([spec])
7    //!
8    //! [spec]: https://spec.matrix.org/latest/client-server-api/#get_matrixclientv1roomsroomidhierarchy
9
10    use js_int::UInt;
11    use ruma_common::{
12        OwnedRoomId,
13        api::{auth_scheme::AccessToken, request, response},
14        metadata,
15    };
16
17    use crate::space::SpaceHierarchyRoomsChunk;
18
19    metadata! {
20        method: GET,
21        rate_limited: true,
22        authentication: AccessToken,
23        history: {
24            unstable => "/_matrix/client/unstable/org.matrix.msc2946/rooms/{room_id}/hierarchy",
25            1.2 => "/_matrix/client/v1/rooms/{room_id}/hierarchy",
26        }
27    }
28
29    /// Request type for the `hierarchy` endpoint.
30    #[request(error = crate::Error)]
31    pub struct Request {
32        /// The room ID of the space to get a hierarchy for.
33        #[ruma_api(path)]
34        pub room_id: OwnedRoomId,
35
36        /// A pagination token from a previous result.
37        ///
38        /// If specified, `max_depth` and `suggested_only` cannot be changed from the first
39        /// request.
40        #[ruma_api(query)]
41        pub from: Option<String>,
42
43        /// The maximum number of rooms to include per response.
44        #[ruma_api(query)]
45        pub limit: Option<UInt>,
46
47        /// How far to go into the space.
48        ///
49        /// When reached, no further child rooms will be returned.
50        #[ruma_api(query)]
51        pub max_depth: Option<UInt>,
52
53        /// Whether or not the server should only consider suggested rooms.
54        ///
55        /// Suggested rooms are annotated in their `m.space.child` event contents.
56        ///
57        /// Defaults to `false`.
58        #[ruma_api(query)]
59        #[serde(default, skip_serializing_if = "ruma_common::serde::is_default")]
60        pub suggested_only: bool,
61    }
62
63    /// Response type for the `hierarchy` endpoint.
64    #[response(error = crate::Error)]
65    #[derive(Default)]
66    pub struct Response {
67        /// A token to supply to from to keep paginating the responses.
68        ///
69        /// Not present when there are no further results.
70        #[serde(skip_serializing_if = "Option::is_none")]
71        pub next_batch: Option<String>,
72
73        /// A paginated chunk of the space children.
74        pub rooms: Vec<SpaceHierarchyRoomsChunk>,
75    }
76
77    impl Request {
78        /// Creates a new `Request` with the given room ID.
79        pub fn new(room_id: OwnedRoomId) -> Self {
80            Self { room_id, from: None, limit: None, max_depth: None, suggested_only: false }
81        }
82    }
83
84    impl Response {
85        /// Creates an empty `Response`.
86        pub fn new() -> Self {
87            Default::default()
88        }
89    }
90}
91
92#[cfg(all(test, feature = "client"))]
93mod tests {
94    use ruma_common::api::IncomingResponse;
95    use serde_json::{json, to_vec as to_json_vec};
96
97    use super::v1::Response;
98
99    #[test]
100    fn deserialize_response() {
101        let body = json!({
102            "rooms": [
103                {
104                    "room_id": "!room:localhost",
105                    "num_joined_members": 5,
106                    "world_readable": false,
107                    "guest_can_join": false,
108                    "join_rule": "restricted",
109                    "allowed_room_ids": ["!otherroom:localhost"],
110                    "children_state": [
111                        {
112                            "content": {
113                                "via": [
114                                    "example.org"
115                                ]
116                            },
117                            "origin_server_ts": 1_629_413_349,
118                            "sender": "@alice:example.org",
119                            "state_key": "!a:example.org",
120                            "type": "m.space.child"
121                        }
122                    ],
123                },
124            ],
125        });
126        let response = http::Response::new(to_json_vec(&body).unwrap());
127
128        let response = Response::try_from_http_response(response).unwrap();
129        let room = &response.rooms[0];
130        assert_eq!(room.summary.room_id, "!room:localhost");
131        let space_child = room.children_state[0].deserialize().unwrap();
132        assert_eq!(space_child.state_key, "!a:example.org");
133    }
134}