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