ruma_client_api/state/
get_state_event_for_key.rs1pub mod v3 {
6 use ruma_common::{
11 OwnedRoomId,
12 api::{auth_scheme::AccessToken, response},
13 metadata,
14 serde::{Raw, StringEnum},
15 };
16 use ruma_events::{AnyStateEvent, AnyStateEventContent, StateEventType};
17 use serde_json::value::RawValue as RawJsonValue;
18
19 use crate::PrivOwnedStr;
20
21 metadata! {
22 method: GET,
23 rate_limited: false,
24 authentication: AccessToken,
25 history: {
26 1.0 => "/_matrix/client/r0/rooms/{room_id}/state/{event_type}/{state_key}",
27 1.1 => "/_matrix/client/v3/rooms/{room_id}/state/{event_type}/{state_key}",
28 }
29 }
30
31 #[derive(Clone, Debug)]
33 #[cfg_attr(not(ruma_unstable_exhaustive_types), non_exhaustive)]
34 pub struct Request {
35 pub room_id: OwnedRoomId,
37
38 pub event_type: StateEventType,
40
41 pub state_key: String,
43
44 pub format: StateEventFormat,
46 }
47
48 impl Request {
49 pub fn new(room_id: OwnedRoomId, event_type: StateEventType, state_key: String) -> Self {
51 Self { room_id, event_type, state_key, format: StateEventFormat::default() }
52 }
53 }
54
55 #[doc = include_str!(concat!(env!("CARGO_MANIFEST_DIR"), "/src/doc/string_enum.md"))]
57 #[derive(Default, Clone, StringEnum)]
58 #[ruma_enum(rename_all = "lowercase")]
59 #[cfg_attr(not(ruma_unstable_exhaustive_types), non_exhaustive)]
60 pub enum StateEventFormat {
61 #[default]
65 Content,
66
67 Event,
70
71 #[doc(hidden)]
72 _Custom(PrivOwnedStr),
73 }
74
75 #[response(error = crate::Error)]
81 pub struct Response {
82 #[ruma_api(body)]
84 pub event_or_content: Box<RawJsonValue>,
85 }
86
87 impl From<Raw<AnyStateEvent>> for Response {
88 fn from(value: Raw<AnyStateEvent>) -> Self {
89 Self { event_or_content: value.into_json() }
90 }
91 }
92
93 impl From<Raw<AnyStateEventContent>> for Response {
94 fn from(value: Raw<AnyStateEventContent>) -> Self {
95 Self { event_or_content: value.into_json() }
96 }
97 }
98
99 impl Response {
100 pub fn new(event_or_content: Box<RawJsonValue>) -> Self {
102 Self { event_or_content }
103 }
104
105 pub fn into_event(self) -> Raw<AnyStateEvent> {
110 Raw::from_json(self.event_or_content)
111 }
112
113 pub fn into_content(self) -> Raw<AnyStateEventContent> {
122 Raw::from_json(self.event_or_content)
123 }
124 }
125
126 #[cfg(feature = "client")]
127 impl ruma_common::api::OutgoingRequest for Request {
128 type EndpointError = crate::Error;
129 type IncomingResponse = Response;
130
131 fn try_into_http_request<T: Default + bytes::BufMut + AsRef<[u8]>>(
132 self,
133 base_url: &str,
134 access_token: ruma_common::api::auth_scheme::SendAccessToken<'_>,
135 considering: std::borrow::Cow<'_, ruma_common::api::SupportedVersions>,
136 ) -> Result<http::Request<T>, ruma_common::api::error::IntoHttpError> {
137 use ruma_common::api::{Metadata, auth_scheme::AuthScheme};
138
139 let query_string = serde_html_form::to_string(RequestQuery { format: self.format })?;
140
141 let mut http_request = http::Request::builder()
142 .method(Self::METHOD)
143 .uri(Self::make_endpoint_url(
144 considering,
145 base_url,
146 &[&self.room_id, &self.event_type, &self.state_key],
147 &query_string,
148 )?)
149 .body(T::default())?;
150
151 Self::Authentication::add_authentication(&mut http_request, access_token).map_err(
152 |error| ruma_common::api::error::IntoHttpError::Authentication(error.into()),
153 )?;
154
155 Ok(http_request)
156 }
157 }
158
159 #[cfg(feature = "server")]
160 impl ruma_common::api::IncomingRequest for Request {
161 type EndpointError = crate::Error;
162 type OutgoingResponse = Response;
163
164 fn try_from_http_request<B, S>(
165 request: http::Request<B>,
166 path_args: &[S],
167 ) -> Result<Self, ruma_common::api::error::FromHttpRequestError>
168 where
169 B: AsRef<[u8]>,
170 S: AsRef<str>,
171 {
172 Self::check_request_method(request.method())?;
173
174 let (room_id, event_type, state_key): (OwnedRoomId, StateEventType, String) =
177 if path_args.len() == 3 {
178 serde::Deserialize::deserialize(serde::de::value::SeqDeserializer::<
179 _,
180 serde::de::value::Error,
181 >::new(
182 path_args.iter().map(::std::convert::AsRef::as_ref),
183 ))?
184 } else {
185 let (a, b) =
186 serde::Deserialize::deserialize(serde::de::value::SeqDeserializer::<
187 _,
188 serde::de::value::Error,
189 >::new(
190 path_args.iter().map(::std::convert::AsRef::as_ref),
191 ))?;
192
193 (a, b, "".into())
194 };
195
196 let RequestQuery { format } =
197 serde_html_form::from_str(request.uri().query().unwrap_or(""))?;
198
199 Ok(Self { room_id, event_type, state_key, format })
200 }
201 }
202
203 #[derive(Debug)]
205 #[cfg_attr(feature = "client", derive(serde::Serialize))]
206 #[cfg_attr(feature = "server", derive(serde::Deserialize))]
207 struct RequestQuery {
208 #[serde(default, skip_serializing_if = "ruma_common::serde::is_default")]
210 format: StateEventFormat,
211 }
212}
213
214#[cfg(all(test, feature = "client"))]
215mod tests {
216 use ruma_common::api::IncomingResponse;
217 use ruma_events::room::name::RoomNameEventContent;
218 use serde_json::{json, to_vec as to_json_vec};
219
220 use super::v3::Response;
221
222 #[test]
223 fn deserialize_response() {
224 let body = json!({
225 "name": "Nice room 🙂"
226 });
227 let response = http::Response::new(to_json_vec(&body).unwrap());
228
229 let response = Response::try_from_http_response(response).unwrap();
230 let content =
231 response.into_content().deserialize_as_unchecked::<RoomNameEventContent>().unwrap();
232
233 assert_eq!(&content.name, "Nice room 🙂");
234 }
235}