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