ruma_client_api/delayed_events/delayed_state_event.rs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162
//! `PUT /_matrix/client/*/rooms/{roomId}/state/{eventType}/{txnId}`
//!
//! Send a delayed state event (a scheduled state event) to a room. [MSC](https://github.com/matrix-org/matrix-spec-proposals/pull/4140)
pub mod unstable {
//! `msc4140` ([MSC])
//!
//! [MSC]: https://github.com/matrix-org/matrix-spec-proposals/pull/4140
use ruma_common::{
api::{request, response, Metadata},
metadata,
serde::Raw,
OwnedRoomId,
};
use ruma_events::{AnyStateEventContent, StateEventContent, StateEventType};
use serde_json::value::to_raw_value as to_raw_json_value;
use crate::delayed_events::DelayParameters;
const METADATA: Metadata = metadata! {
method: PUT,
rate_limited: false,
authentication: AccessToken,
history: {
// We use the unstable prefix for the delay query parameter but the stable v3 endpoint.
unstable => "/_matrix/client/v3/rooms/:room_id/state/:event_type/:state_key",
}
};
/// Request type for the [`delayed_state_event`](crate::delayed_events::delayed_state_event)
/// endpoint.
#[request(error = crate::Error)]
pub struct Request {
/// The room to send the event to.
#[ruma_api(path)]
pub room_id: OwnedRoomId,
/// The type of event to send.
#[ruma_api(path)]
pub event_type: StateEventType,
/// The state_key for the state to send.
#[ruma_api(path)]
pub state_key: String,
/// Additional parameters to describe sending a delayed event.
///
/// Only three combinations for `timeout` and `delay_parent_id` are possible.
/// The enum [`DelayParameters`] enforces this.
#[ruma_api(query_all)]
pub delay_parameters: DelayParameters,
/// The event content to send.
#[ruma_api(body)]
pub body: Raw<AnyStateEventContent>,
}
/// Response type for the [`delayed_state_event`](crate::delayed_events::delayed_state_event)
/// endpoint.
#[response(error = crate::Error)]
pub struct Response {
/// The `delay_id` generated for this delayed event. Used to interact with delayed events.
pub delay_id: String,
}
impl Request {
/// Creates a new `Request` with the given room id, state_key delay_parameters and
/// event content.
///
/// # Errors
///
/// Since `Request` stores the request body in serialized form, this function can fail if
/// `T`s [`::serde::Serialize`] implementation can fail.
pub fn new<T>(
room_id: OwnedRoomId,
state_key: String,
delay_parameters: DelayParameters,
content: &T,
) -> serde_json::Result<Self>
where
T: StateEventContent,
{
Ok(Self {
room_id,
state_key,
event_type: content.event_type(),
delay_parameters,
body: Raw::from_json(to_raw_json_value(content)?),
})
}
/// Creates a new `Request` with the given room id, event type, state key,
/// delay parameters and raw event content.
pub fn new_raw(
room_id: OwnedRoomId,
state_key: String,
event_type: StateEventType,
delay_parameters: DelayParameters,
body: Raw<AnyStateEventContent>,
) -> Self {
Self { room_id, event_type, state_key, body, delay_parameters }
}
}
impl Response {
/// Creates a new `Response` with the tokens required to control the delayed event using the
/// [`crate::delayed_events::update_delayed_event::unstable::Request`] request.
pub fn new(delay_id: String) -> Self {
Self { delay_id }
}
}
#[cfg(all(test, feature = "client"))]
mod tests {
use ruma_common::{
api::{MatrixVersion, OutgoingRequest, SendAccessToken},
owned_room_id,
};
use ruma_events::room::topic::RoomTopicEventContent;
use serde_json::{json, Value as JsonValue};
use web_time::Duration;
use super::Request;
use crate::delayed_events::DelayParameters;
fn create_delayed_event_request(
delay_parameters: DelayParameters,
) -> (http::request::Parts, Vec<u8>) {
Request::new(
owned_room_id!("!roomid:example.org"),
"@userAsStateKey:example.org".to_owned(),
delay_parameters,
&RoomTopicEventContent::new("my_topic".to_owned()),
)
.unwrap()
.try_into_http_request(
"https://homeserver.tld",
SendAccessToken::IfRequired("auth_tok"),
&[MatrixVersion::V1_1],
)
.unwrap()
.into_parts()
}
#[test]
fn serialize_delayed_state_request() {
let (parts, body) = create_delayed_event_request(DelayParameters::Timeout {
timeout: Duration::from_millis(1_234_321),
});
assert_eq!(
"https://homeserver.tld/_matrix/client/v3/rooms/!roomid:example.org/state/m.room.topic/@userAsStateKey:example.org?org.matrix.msc4140.delay=1234321",
parts.uri.to_string()
);
assert_eq!("PUT", parts.method.to_string());
assert_eq!(
json!({"topic": "my_topic"}),
serde_json::from_str::<JsonValue>(std::str::from_utf8(&body).unwrap()).unwrap()
);
}
}
}