ruma_client_api/delayed_events/
send_delayed_event.rs1pub mod unstable {
6 use std::time::Duration;
11
12 use ruma_common::{
13 OwnedRoomId, OwnedTransactionId,
14 api::{auth_scheme::AccessToken, request, response},
15 metadata,
16 serde::Raw,
17 };
18 #[cfg(feature = "unstable-msc4354")]
19 use ruma_events::sticky::StickyDurationMs;
20 use ruma_events::{AnyTimelineEventContent, TimelineEventType};
21
22 metadata! {
23 method: PUT,
24 rate_limited: true,
25 authentication: AccessToken,
26 history: {
27 unstable("org.matrix.msc4140") => "/_matrix/client/unstable/org.matrix.msc4140/rooms/{room_id}/delayed_event/{event_type}/{txn_id}",
28 }
29 }
30 #[request]
33 pub struct Request {
34 #[ruma_api(path)]
36 pub room_id: OwnedRoomId,
37
38 #[ruma_api(path)]
40 pub event_type: TimelineEventType,
41
42 #[ruma_api(path)]
52 pub txn_id: OwnedTransactionId,
53
54 #[serde(with = "ruma_common::serde::duration::ms")]
56 pub delay: Duration,
57
58 #[cfg(feature = "unstable-msc4354")]
65 #[ruma_api(query)]
66 #[serde(
67 skip_serializing_if = "Option::is_none",
68 rename = "org.matrix.msc4354.sticky_duration_ms"
69 )]
70 pub sticky_duration_ms: Option<StickyDurationMs>,
71
72 #[serde(skip_serializing_if = "Option::is_none")]
74 pub state_key: Option<String>,
75
76 pub content: Raw<AnyTimelineEventContent>,
78 }
79
80 #[response]
83 pub struct Response {
84 pub delay_id: String,
86 }
87
88 impl Request {
89 pub fn new(
97 room_id: OwnedRoomId,
98 txn_id: OwnedTransactionId,
99 delay: Duration,
100 state_key: Option<String>,
101 content: &AnyTimelineEventContent,
102 ) -> serde_json::Result<Self> {
103 Ok(Self {
104 room_id,
105 txn_id,
106 event_type: content.event_type(),
107 state_key,
108 delay,
109 #[cfg(feature = "unstable-msc4354")]
110 sticky_duration_ms: None,
111 content: Raw::new(content)?,
112 })
113 }
114
115 pub fn new_raw(
118 event_type: TimelineEventType,
119 room_id: OwnedRoomId,
120 txn_id: OwnedTransactionId,
121 delay: Duration,
122 state_key: Option<String>,
123 content: Raw<AnyTimelineEventContent>,
124 ) -> serde_json::Result<Self> {
125 Ok(Self {
126 room_id,
127 txn_id,
128 event_type,
129 state_key,
130 delay,
131 #[cfg(feature = "unstable-msc4354")]
132 sticky_duration_ms: None,
133 content,
134 })
135 }
136 }
137
138 impl Response {
139 pub fn new(delay_id: String) -> Self {
142 Self { delay_id }
143 }
144 }
145
146 #[cfg(all(test, feature = "client"))]
147 mod client_tests {
148 use std::borrow::Cow;
149
150 use ruma_common::{
151 api::{
152 MatrixVersion, OutgoingRequestExt as _, SupportedVersions,
153 auth_scheme::SendAccessToken,
154 },
155 owned_room_id,
156 };
157 use ruma_events::{AnyMessageLikeEventContent, room::message::RoomMessageEventContent};
158 use serde_json::{Value as JsonValue, json};
159 use web_time::Duration;
160
161 use super::Request;
162
163 #[test]
164 fn serialize_send_delayed_event_request() {
165 let room_id = owned_room_id!("!roomid:example.org");
166 let supported = SupportedVersions {
167 versions: [MatrixVersion::V1_1].into(),
168 features: Default::default(),
169 };
170
171 let req = Request::new(
172 room_id,
173 "1234".into(),
174 Duration::from_millis(103),
175 None,
176 &AnyMessageLikeEventContent::from(RoomMessageEventContent::text_plain("test"))
177 .into(),
178 )
179 .unwrap();
180 let request: http::Request<Vec<u8>> = req
181 .try_into_http_request(
182 "https://homeserver.tld",
183 SendAccessToken::IfRequired("auth_tok"),
184 Cow::Owned(supported),
185 )
186 .unwrap();
187 let (parts, body) = request.into_parts();
188 assert_eq!(
189 "https://homeserver.tld/_matrix/client/unstable/org.matrix.msc4140/rooms/!roomid:example.org/delayed_event/m.room.message/1234",
190 parts.uri.to_string()
191 );
192 assert_eq!("PUT", parts.method.to_string());
193 assert_eq!(
194 json!({"content":{"msgtype":"m.text","body":"test"}, "delay": 103}),
195 serde_json::from_str::<JsonValue>(std::str::from_utf8(&body).unwrap()).unwrap()
196 );
197 }
198
199 #[cfg(feature = "unstable-msc4354")]
200 #[test]
201 fn serialize_send_delayed_sticky_event_request() {
202 use ruma_events::sticky::StickyDurationMs;
203
204 let supported = SupportedVersions {
205 versions: [MatrixVersion::V1_1].into(),
206 features: Default::default(),
207 };
208
209 let mut req = Request::new(
210 owned_room_id!("!roomid:example.org"),
211 "1234".into(),
212 Duration::from_millis(30_000),
213 None,
214 &AnyMessageLikeEventContent::from(RoomMessageEventContent::text_plain("test"))
215 .into(),
216 )
217 .unwrap();
218 req.sticky_duration_ms = Some(StickyDurationMs::new_clamped(300_000_u32));
219
220 let request: http::Request<Vec<u8>> = req
221 .try_into_http_request(
222 "https://homeserver.tld",
223 SendAccessToken::IfRequired("auth_tok"),
224 Cow::Owned(supported),
225 )
226 .unwrap();
227 let (parts, body) = request.into_parts();
228 assert_eq!(
229 "https://homeserver.tld/_matrix/client/unstable/org.matrix.msc4140/rooms/!roomid:example.org/delayed_event/m.room.message/1234?org.matrix.msc4354.sticky_duration_ms=300000",
230 parts.uri.to_string()
231 );
232 assert_eq!(
233 json!({"content":{"msgtype":"m.text","body":"test"}, "delay": 30000}),
234 serde_json::from_str::<JsonValue>(std::str::from_utf8(&body).unwrap()).unwrap()
235 );
236 }
237 }
238
239 #[cfg(all(test, feature = "server"))]
240 mod server_tests {
241
242 use std::time::Duration;
243
244 use ruma_common::{OwnedTransactionId, api::IncomingRequest, owned_room_id};
245 use serde_json::json;
246
247 use super::Request;
248
249 #[test]
250 fn deserialize_send_delayed_events_request() {
251 let uri = http::Uri::builder()
252 .scheme("https")
253 .authority("matrix.org")
254 .path_and_query(
255 "/_matrix/client/unstable/org.matrix.msc4140/rooms/!roomid:example.org/delayed_event/m.room.message/5678",
256 )
257 .build()
258 .unwrap();
259
260 let body = json!({"content":{"msgtype":"m.text","body":"test"}, "delay": 103});
261
262 let req = Request::try_from_http_request(
263 http::Request::builder().method("PUT").uri(uri).body(body.to_string()).unwrap(),
264 &["!roomid:example.org", "m.room.message", "5678"],
265 )
266 .unwrap();
267
268 assert_eq!(req.room_id, owned_room_id!("!roomid:example.org"));
269 assert_eq!(req.event_type, "m.room.message".into());
270 assert_eq!(req.txn_id, OwnedTransactionId::from("5678"));
271 assert_eq!(req.delay, Duration::from_millis(103));
272 assert_eq!(req.state_key, None);
273 assert_eq!(
274 serde_json::from_str::<serde_json::Value>(req.content.json().get()).unwrap(),
275 json!({"msgtype":"m.text","body":"test"}),
276 );
277 }
278
279 #[cfg(feature = "unstable-msc4354")]
282 #[test]
283 fn deserialize_send_delayed_event_request_without_sticky() {
284 let uri = http::Uri::builder()
285 .scheme("https")
286 .authority("matrix.org")
287 .path_and_query(
288 "/_matrix/client/unstable/org.matrix.msc4140/rooms/!roomid:example.org/delayed_event/m.room.message/5678",
289 )
290 .build()
291 .unwrap();
292
293 let body = json!({"content":{"msgtype":"m.text","body":"test"}, "delay": 103});
294
295 let req = Request::try_from_http_request(
296 http::Request::builder().method("PUT").uri(uri).body(body.to_string()).unwrap(),
297 &["!roomid:example.org", "m.room.message", "5678"],
298 )
299 .unwrap();
300
301 assert_eq!(req.sticky_duration_ms, None);
302 }
303 }
304}