client-api: Add future endpoints
This commit is contained in:
		
							parent
							
								
									e5a370f7e5
								
							
						
					
					
						commit
						862be071d2
					
				@ -20,6 +20,10 @@ Improvements:
 | 
				
			|||||||
- Stabilize support for animated thumbnails, according to Matrix 1.11
 | 
					- Stabilize support for animated thumbnails, according to Matrix 1.11
 | 
				
			||||||
- Add support for terms of service at registration, according to MSC1692 /
 | 
					- Add support for terms of service at registration, according to MSC1692 /
 | 
				
			||||||
  Matrix 1.11
 | 
					  Matrix 1.11
 | 
				
			||||||
 | 
					- Add unstable support for [MSC4140](https://github.com/matrix-org/matrix-spec-proposals/pull/4140)
 | 
				
			||||||
 | 
					  to send `Future` events and update `Future` events with `future_tokens`.
 | 
				
			||||||
 | 
					  (`Future` events are scheduled messages that can be controlled
 | 
				
			||||||
 | 
					  with `future_tokens` to send on demand or restart the timeout)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Bug fixes:
 | 
					Bug fixes:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -50,6 +50,7 @@ unstable-msc3843 = []
 | 
				
			|||||||
unstable-msc3983 = []
 | 
					unstable-msc3983 = []
 | 
				
			||||||
unstable-msc4108 = []
 | 
					unstable-msc4108 = []
 | 
				
			||||||
unstable-msc4121 = []
 | 
					unstable-msc4121 = []
 | 
				
			||||||
 | 
					unstable-msc4140 = []
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[dependencies]
 | 
					[dependencies]
 | 
				
			||||||
as_variant = { workspace = true }
 | 
					as_variant = { workspace = true }
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										38
									
								
								crates/ruma-client-api/src/future.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										38
									
								
								crates/ruma-client-api/src/future.rs
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,38 @@
 | 
				
			|||||||
 | 
					//! Endpoints for sending and receiving futures
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					pub mod send_future_message_event;
 | 
				
			||||||
 | 
					pub mod send_future_state_event;
 | 
				
			||||||
 | 
					pub mod update_future;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					use serde::{Deserialize, Serialize};
 | 
				
			||||||
 | 
					use web_time::Duration;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/// The query parameters for a future request.
 | 
				
			||||||
 | 
					/// It can contain the possible timeout and the future_group_id combinations.
 | 
				
			||||||
 | 
					#[derive(Clone, Debug, Serialize, Deserialize)]
 | 
				
			||||||
 | 
					#[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)]
 | 
				
			||||||
 | 
					#[serde(untagged)]
 | 
				
			||||||
 | 
					pub enum FutureParameters {
 | 
				
			||||||
 | 
					    /// Only sending the timeout creates a timeout future with a new (server generated)
 | 
				
			||||||
 | 
					    /// group id. The optional group id is used to create a secondary timeout.  
 | 
				
			||||||
 | 
					    /// In a future group with two timeouts only one of them will ever be sent.
 | 
				
			||||||
 | 
					    Timeout {
 | 
				
			||||||
 | 
					        /// The timeout duration for this Future.
 | 
				
			||||||
 | 
					        #[serde(with = "ruma_common::serde::duration::ms")]
 | 
				
			||||||
 | 
					        #[serde(rename = "future_timeout")]
 | 
				
			||||||
 | 
					        timeout: Duration,
 | 
				
			||||||
 | 
					        /// The associated group for this Future.
 | 
				
			||||||
 | 
					        #[serde(skip_serializing_if = "Option::is_none")]
 | 
				
			||||||
 | 
					        #[serde(rename = "future_group_id")]
 | 
				
			||||||
 | 
					        group_id: Option<String>,
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// Adds an additional action to a future without a timeout but requires a future group_id.
 | 
				
			||||||
 | 
					    /// A possible matrix event that this future group can resolve to. It can be sent by using the
 | 
				
			||||||
 | 
					    /// send_token as an alternative to the timeout future of an already existing group.
 | 
				
			||||||
 | 
					    Action {
 | 
				
			||||||
 | 
					        /// The associated group for this Future.
 | 
				
			||||||
 | 
					        #[serde(rename = "future_group_id")]
 | 
				
			||||||
 | 
					        group_id: String,
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										182
									
								
								crates/ruma-client-api/src/future/send_future_message_event.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										182
									
								
								crates/ruma-client-api/src/future/send_future_message_event.rs
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,182 @@
 | 
				
			|||||||
 | 
					//! `PUT /_matrix/client/*/rooms/{roomId}/send_future/{eventType}/{txnId}`
 | 
				
			||||||
 | 
					//!
 | 
				
			||||||
 | 
					//! Send a future (a scheduled message) to a room. [MSC4140](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, OwnedTransactionId,
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					    use ruma_events::{AnyMessageLikeEventContent, MessageLikeEventContent, MessageLikeEventType};
 | 
				
			||||||
 | 
					    use serde_json::value::to_raw_value as to_raw_json_value;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    use crate::future::FutureParameters;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const METADATA: Metadata = metadata! {
 | 
				
			||||||
 | 
					        method: PUT,
 | 
				
			||||||
 | 
					        rate_limited: false,
 | 
				
			||||||
 | 
					        authentication: AccessToken,
 | 
				
			||||||
 | 
					        history: {
 | 
				
			||||||
 | 
					            unstable => "/_matrix/client/unstable/org.matrix.msc4140/rooms/:room_id/send_future/:event_type/:txn_id",
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					    /// Request type for the [`send_future_message_event`](crate::future::send_future_message_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: MessageLikeEventType,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /// The transaction ID for this event.
 | 
				
			||||||
 | 
					        ///
 | 
				
			||||||
 | 
					        /// Clients should generate a unique ID across requests within the
 | 
				
			||||||
 | 
					        /// same session. A session is identified by an access token, and
 | 
				
			||||||
 | 
					        /// persists when the [access token is refreshed].
 | 
				
			||||||
 | 
					        ///
 | 
				
			||||||
 | 
					        /// It will be used by the server to ensure idempotency of requests.
 | 
				
			||||||
 | 
					        ///
 | 
				
			||||||
 | 
					        /// [access token is refreshed]: https://spec.matrix.org/latest/client-server-api/#refreshing-access-tokens
 | 
				
			||||||
 | 
					        #[ruma_api(path)]
 | 
				
			||||||
 | 
					        pub txn_id: OwnedTransactionId,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /// Additional parameters to describe sending a future.
 | 
				
			||||||
 | 
					        ///
 | 
				
			||||||
 | 
					        /// Only three combinations for `future_timeout` and `future_group_id` are possible.
 | 
				
			||||||
 | 
					        /// The enum [`FutureParameters`] enforces this.
 | 
				
			||||||
 | 
					        #[ruma_api(query_all)]
 | 
				
			||||||
 | 
					        pub future_parameters: FutureParameters,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /// The event content to send.
 | 
				
			||||||
 | 
					        #[ruma_api(body)]
 | 
				
			||||||
 | 
					        pub body: Raw<AnyMessageLikeEventContent>,
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// Response type for the
 | 
				
			||||||
 | 
					    /// [`send_future_message_event`](crate::future::send_future_message_event) endpoint.
 | 
				
			||||||
 | 
					    #[response(error = crate::Error)]
 | 
				
			||||||
 | 
					    pub struct Response {
 | 
				
			||||||
 | 
					        /// A token to send/insert the future into the DAG.
 | 
				
			||||||
 | 
					        pub send_token: String,
 | 
				
			||||||
 | 
					        /// A token to cancel this future. It will never be send if this is called.
 | 
				
			||||||
 | 
					        pub cancel_token: String,
 | 
				
			||||||
 | 
					        /// The `future_group_id` generated for this future. Used to connect multiple futures
 | 
				
			||||||
 | 
					        /// only one of the connected futures will be sent and inserted into the DAG.
 | 
				
			||||||
 | 
					        pub future_group_id: String,
 | 
				
			||||||
 | 
					        /// A token used to refresh the timer of the future. This allows
 | 
				
			||||||
 | 
					        /// to implement heartbeat like capabilities. An event is only sent once
 | 
				
			||||||
 | 
					        /// a refresh in the timeout interval is missed.
 | 
				
			||||||
 | 
					        ///
 | 
				
			||||||
 | 
					        /// If the future does not have a timeout this will be `None`.
 | 
				
			||||||
 | 
					        pub refresh_token: Option<String>,
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    impl Request {
 | 
				
			||||||
 | 
					        /// Creates a new `Request` with the given room id, transaction id future_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,
 | 
				
			||||||
 | 
					            txn_id: OwnedTransactionId,
 | 
				
			||||||
 | 
					            future_parameters: FutureParameters,
 | 
				
			||||||
 | 
					            content: &T,
 | 
				
			||||||
 | 
					        ) -> serde_json::Result<Self>
 | 
				
			||||||
 | 
					        where
 | 
				
			||||||
 | 
					            T: MessageLikeEventContent,
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            Ok(Self {
 | 
				
			||||||
 | 
					                room_id,
 | 
				
			||||||
 | 
					                txn_id,
 | 
				
			||||||
 | 
					                event_type: content.event_type(),
 | 
				
			||||||
 | 
					                future_parameters,
 | 
				
			||||||
 | 
					                body: Raw::from_json(to_raw_json_value(content)?),
 | 
				
			||||||
 | 
					            })
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /// Creates a new `Request` with the given room id, transaction id, event type,
 | 
				
			||||||
 | 
					        /// future parameters and raw event content.
 | 
				
			||||||
 | 
					        pub fn new_raw(
 | 
				
			||||||
 | 
					            room_id: OwnedRoomId,
 | 
				
			||||||
 | 
					            txn_id: OwnedTransactionId,
 | 
				
			||||||
 | 
					            event_type: MessageLikeEventType,
 | 
				
			||||||
 | 
					            future_parameters: FutureParameters,
 | 
				
			||||||
 | 
					            body: Raw<AnyMessageLikeEventContent>,
 | 
				
			||||||
 | 
					        ) -> Self {
 | 
				
			||||||
 | 
					            Self { room_id, event_type, txn_id, future_parameters, body }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    impl Response {
 | 
				
			||||||
 | 
					        /// Creates a new `Response` with the tokens required to control the future using the
 | 
				
			||||||
 | 
					        /// [`crate::future::update_future::unstable::Request`] request.
 | 
				
			||||||
 | 
					        pub fn new(
 | 
				
			||||||
 | 
					            send_token: String,
 | 
				
			||||||
 | 
					            cancel_token: String,
 | 
				
			||||||
 | 
					            future_group_id: String,
 | 
				
			||||||
 | 
					            refresh_token: Option<String>,
 | 
				
			||||||
 | 
					        ) -> Self {
 | 
				
			||||||
 | 
					            Self { send_token, cancel_token, future_group_id, refresh_token }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    #[cfg(all(test, feature = "client"))]
 | 
				
			||||||
 | 
					    mod tests {
 | 
				
			||||||
 | 
					        use ruma_common::{
 | 
				
			||||||
 | 
					            api::{MatrixVersion, OutgoingRequest, SendAccessToken},
 | 
				
			||||||
 | 
					            owned_room_id,
 | 
				
			||||||
 | 
					        };
 | 
				
			||||||
 | 
					        use ruma_events::room::message::RoomMessageEventContent;
 | 
				
			||||||
 | 
					        use serde_json::{json, Value as JsonValue};
 | 
				
			||||||
 | 
					        use web_time::Duration;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        use super::Request;
 | 
				
			||||||
 | 
					        use crate::future::send_future_message_event::unstable::FutureParameters;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        #[test]
 | 
				
			||||||
 | 
					        fn serialize_message_future_request() {
 | 
				
			||||||
 | 
					            let room_id = owned_room_id!("!roomid:example.org");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            let req = Request::new(
 | 
				
			||||||
 | 
					                room_id,
 | 
				
			||||||
 | 
					                "1234".into(),
 | 
				
			||||||
 | 
					                FutureParameters::Timeout {
 | 
				
			||||||
 | 
					                    timeout: Duration::from_millis(103),
 | 
				
			||||||
 | 
					                    group_id: Some("testId".to_owned()),
 | 
				
			||||||
 | 
					                },
 | 
				
			||||||
 | 
					                &RoomMessageEventContent::text_plain("test"),
 | 
				
			||||||
 | 
					            )
 | 
				
			||||||
 | 
					            .unwrap();
 | 
				
			||||||
 | 
					            let request: http::Request<Vec<u8>> = req
 | 
				
			||||||
 | 
					                .try_into_http_request(
 | 
				
			||||||
 | 
					                    "https://homeserver.tld",
 | 
				
			||||||
 | 
					                    SendAccessToken::IfRequired("auth_tok"),
 | 
				
			||||||
 | 
					                    &[MatrixVersion::V1_1],
 | 
				
			||||||
 | 
					                )
 | 
				
			||||||
 | 
					                .unwrap();
 | 
				
			||||||
 | 
					            let (parts, body) = request.into_parts();
 | 
				
			||||||
 | 
					            assert_eq!(
 | 
				
			||||||
 | 
					                "https://homeserver.tld/_matrix/client/unstable/org.matrix.msc4140/rooms/!roomid:example.org/send_future/m.room.message/1234?future_timeout=103&future_group_id=testId",
 | 
				
			||||||
 | 
					                parts.uri.to_string()
 | 
				
			||||||
 | 
					            );
 | 
				
			||||||
 | 
					            assert_eq!("PUT", parts.method.to_string());
 | 
				
			||||||
 | 
					            assert_eq!(
 | 
				
			||||||
 | 
					                json!({"msgtype":"m.text","body":"test"}),
 | 
				
			||||||
 | 
					                serde_json::from_str::<JsonValue>(std::str::from_utf8(&body).unwrap()).unwrap()
 | 
				
			||||||
 | 
					            );
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										175
									
								
								crates/ruma-client-api/src/future/send_future_state_event.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										175
									
								
								crates/ruma-client-api/src/future/send_future_state_event.rs
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,175 @@
 | 
				
			|||||||
 | 
					//! `PUT /_matrix/client/*/rooms/{roomId}/state_future/{eventType}/{txnId}`
 | 
				
			||||||
 | 
					//!
 | 
				
			||||||
 | 
					//! Send a future state (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::future::FutureParameters;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const METADATA: Metadata = metadata! {
 | 
				
			||||||
 | 
					        method: PUT,
 | 
				
			||||||
 | 
					        rate_limited: false,
 | 
				
			||||||
 | 
					        authentication: AccessToken,
 | 
				
			||||||
 | 
					        history: {
 | 
				
			||||||
 | 
					            unstable => "/_matrix/client/unstable/org.matrix.msc4140/rooms/:room_id/state_future/:event_type/:state_key",
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// Request type for the [`send_future_state_event`](crate::future::send_future_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 future.
 | 
				
			||||||
 | 
					        ///
 | 
				
			||||||
 | 
					        /// Only three combinations for `future_timeout` and `future_group_id` are possible.
 | 
				
			||||||
 | 
					        /// The enum [`FutureParameters`] enforces this.
 | 
				
			||||||
 | 
					        #[ruma_api(query_all)]
 | 
				
			||||||
 | 
					        pub future_parameters: FutureParameters,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /// The event content to send.
 | 
				
			||||||
 | 
					        #[ruma_api(body)]
 | 
				
			||||||
 | 
					        pub body: Raw<AnyStateEventContent>,
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// Response type for the [`send_future_state_event`](crate::future::send_future_state_event)
 | 
				
			||||||
 | 
					    /// endpoint.
 | 
				
			||||||
 | 
					    #[response(error = crate::Error)]
 | 
				
			||||||
 | 
					    pub struct Response {
 | 
				
			||||||
 | 
					        /// A token to send/insert the future into the DAG.
 | 
				
			||||||
 | 
					        pub send_token: String,
 | 
				
			||||||
 | 
					        /// A token to cancel this future. It will never be send if this is called.
 | 
				
			||||||
 | 
					        pub cancel_token: String,
 | 
				
			||||||
 | 
					        /// The `future_group_id` generated for this future. Used to connect multiple futures
 | 
				
			||||||
 | 
					        /// only one of the connected futures will be sent and inserted into the DAG.
 | 
				
			||||||
 | 
					        pub future_group_id: String,
 | 
				
			||||||
 | 
					        /// A token used to refresh the timer of the future. This allows
 | 
				
			||||||
 | 
					        /// to implement heardbeat like capabilities. An event is only send once
 | 
				
			||||||
 | 
					        /// a refresh in the timeout interval is missed.
 | 
				
			||||||
 | 
					        ///
 | 
				
			||||||
 | 
					        /// If the future does not have a timeout this will be `None`.
 | 
				
			||||||
 | 
					        pub refresh_token: Option<String>,
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    impl Request {
 | 
				
			||||||
 | 
					        /// Creates a new `Request` with the given room id, state_key future_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,
 | 
				
			||||||
 | 
					            future_parameters: FutureParameters,
 | 
				
			||||||
 | 
					            content: &T,
 | 
				
			||||||
 | 
					        ) -> serde_json::Result<Self>
 | 
				
			||||||
 | 
					        where
 | 
				
			||||||
 | 
					            T: StateEventContent,
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            Ok(Self {
 | 
				
			||||||
 | 
					                room_id,
 | 
				
			||||||
 | 
					                state_key,
 | 
				
			||||||
 | 
					                event_type: content.event_type(),
 | 
				
			||||||
 | 
					                future_parameters,
 | 
				
			||||||
 | 
					                body: Raw::from_json(to_raw_json_value(content)?),
 | 
				
			||||||
 | 
					            })
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /// Creates a new `Request` with the given room id, event type, state key,
 | 
				
			||||||
 | 
					        /// future parameters and raw event content.
 | 
				
			||||||
 | 
					        pub fn new_raw(
 | 
				
			||||||
 | 
					            room_id: OwnedRoomId,
 | 
				
			||||||
 | 
					            state_key: String,
 | 
				
			||||||
 | 
					            event_type: StateEventType,
 | 
				
			||||||
 | 
					            future_parameters: FutureParameters,
 | 
				
			||||||
 | 
					            body: Raw<AnyStateEventContent>,
 | 
				
			||||||
 | 
					        ) -> Self {
 | 
				
			||||||
 | 
					            Self { room_id, event_type, state_key, body, future_parameters }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    impl Response {
 | 
				
			||||||
 | 
					        /// Creates a new `Response` with the tokens required to control the future using the
 | 
				
			||||||
 | 
					        /// [`crate::future::update_future::unstable::Request`] request.
 | 
				
			||||||
 | 
					        pub fn new(
 | 
				
			||||||
 | 
					            send_token: String,
 | 
				
			||||||
 | 
					            cancel_token: String,
 | 
				
			||||||
 | 
					            future_group_id: String,
 | 
				
			||||||
 | 
					            refresh_token: Option<String>,
 | 
				
			||||||
 | 
					        ) -> Self {
 | 
				
			||||||
 | 
					            Self { send_token, cancel_token, future_group_id, refresh_token }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    #[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::future::FutureParameters;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        #[test]
 | 
				
			||||||
 | 
					        fn serialize_state_future_request() {
 | 
				
			||||||
 | 
					            let room_id = owned_room_id!("!roomid:example.org");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            let req = Request::new(
 | 
				
			||||||
 | 
					                room_id,
 | 
				
			||||||
 | 
					                "@userAsStateKey:example.org".to_owned(),
 | 
				
			||||||
 | 
					                FutureParameters::Timeout {
 | 
				
			||||||
 | 
					                    timeout: Duration::from_millis(1_234_321),
 | 
				
			||||||
 | 
					                    group_id: Some("abs1abs1abs1abs1".to_owned()),
 | 
				
			||||||
 | 
					                },
 | 
				
			||||||
 | 
					                &RoomTopicEventContent::new("my_topic".to_owned()),
 | 
				
			||||||
 | 
					            )
 | 
				
			||||||
 | 
					            .unwrap();
 | 
				
			||||||
 | 
					            let request: http::Request<Vec<u8>> = req
 | 
				
			||||||
 | 
					                .try_into_http_request(
 | 
				
			||||||
 | 
					                    "https://homeserver.tld",
 | 
				
			||||||
 | 
					                    SendAccessToken::IfRequired("auth_tok"),
 | 
				
			||||||
 | 
					                    &[MatrixVersion::V1_1],
 | 
				
			||||||
 | 
					                )
 | 
				
			||||||
 | 
					                .unwrap();
 | 
				
			||||||
 | 
					            let (parts, body) = request.into_parts();
 | 
				
			||||||
 | 
					            assert_eq!(
 | 
				
			||||||
 | 
					                "https://homeserver.tld/_matrix/client/unstable/org.matrix.msc4140/rooms/!roomid:example.org/state_future/m.room.topic/@userAsStateKey:example.org?future_timeout=1234321&future_group_id=abs1abs1abs1abs1",
 | 
				
			||||||
 | 
					                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()
 | 
				
			||||||
 | 
					            );
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										49
									
								
								crates/ruma-client-api/src/future/update_future.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										49
									
								
								crates/ruma-client-api/src/future/update_future.rs
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,49 @@
 | 
				
			|||||||
 | 
					//! `POST /_matrix/client/*/futures/{token}`
 | 
				
			||||||
 | 
					//!
 | 
				
			||||||
 | 
					//! Send a future token to update/cancel/send the associated future event.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					pub mod unstable {
 | 
				
			||||||
 | 
					    //! `msc3814` ([MSC])
 | 
				
			||||||
 | 
					    //!
 | 
				
			||||||
 | 
					    //! [MSC]: https://github.com/matrix-org/matrix-spec-proposals/pull/4140
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    use ruma_common::{
 | 
				
			||||||
 | 
					        api::{request, response, Metadata},
 | 
				
			||||||
 | 
					        metadata,
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const METADATA: Metadata = metadata! {
 | 
				
			||||||
 | 
					        method: POST,
 | 
				
			||||||
 | 
					        rate_limited: true,
 | 
				
			||||||
 | 
					        authentication: None,
 | 
				
			||||||
 | 
					        history: {
 | 
				
			||||||
 | 
					            unstable => "/_matrix/client/unstable/org.matrix.msc4140/future/:token",
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// Request type for the [`update_future`](crate::future::update_future) endpoint.
 | 
				
			||||||
 | 
					    #[request(error = crate::Error)]
 | 
				
			||||||
 | 
					    pub struct Request {
 | 
				
			||||||
 | 
					        /// The token.
 | 
				
			||||||
 | 
					        #[ruma_api(path)]
 | 
				
			||||||
 | 
					        pub token: String,
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    impl Request {
 | 
				
			||||||
 | 
					        /// Creates a new `Request` to update a future. This is an unauthenticated request and only
 | 
				
			||||||
 | 
					        /// requires the future token.
 | 
				
			||||||
 | 
					        pub fn new(token: String) -> serde_json::Result<Self> {
 | 
				
			||||||
 | 
					            Ok(Self { token })
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// Response type for the [`update_future`](crate::future::update_future) endpoint.
 | 
				
			||||||
 | 
					    #[response(error = crate::Error)]
 | 
				
			||||||
 | 
					    pub struct Response {}
 | 
				
			||||||
 | 
					    impl Response {
 | 
				
			||||||
 | 
					        /// Creates a new response for the [`update_future`](crate::future::update_future) endpoint.
 | 
				
			||||||
 | 
					        pub fn new() -> Self {
 | 
				
			||||||
 | 
					            Response {}
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -23,6 +23,8 @@ pub mod directory;
 | 
				
			|||||||
pub mod discovery;
 | 
					pub mod discovery;
 | 
				
			||||||
pub mod error;
 | 
					pub mod error;
 | 
				
			||||||
pub mod filter;
 | 
					pub mod filter;
 | 
				
			||||||
 | 
					#[cfg(feature = "unstable-msc4140")]
 | 
				
			||||||
 | 
					pub mod future;
 | 
				
			||||||
pub mod http_headers;
 | 
					pub mod http_headers;
 | 
				
			||||||
pub mod keys;
 | 
					pub mod keys;
 | 
				
			||||||
pub mod knock;
 | 
					pub mod knock;
 | 
				
			||||||
 | 
				
			|||||||
@ -227,6 +227,7 @@ unstable-msc4075 = ["ruma-events?/unstable-msc4075"]
 | 
				
			|||||||
unstable-msc4108 = ["ruma-client-api?/unstable-msc4108"]
 | 
					unstable-msc4108 = ["ruma-client-api?/unstable-msc4108"]
 | 
				
			||||||
unstable-msc4121 = ["ruma-client-api?/unstable-msc4121"]
 | 
					unstable-msc4121 = ["ruma-client-api?/unstable-msc4121"]
 | 
				
			||||||
unstable-msc4125 = ["ruma-federation-api?/unstable-msc4125"]
 | 
					unstable-msc4125 = ["ruma-federation-api?/unstable-msc4125"]
 | 
				
			||||||
 | 
					unstable-msc4140 = ["ruma-client-api?/unstable-msc4140"]
 | 
				
			||||||
unstable-pdu = ["ruma-events?/unstable-pdu"]
 | 
					unstable-pdu = ["ruma-events?/unstable-pdu"]
 | 
				
			||||||
unstable-unspecified = [
 | 
					unstable-unspecified = [
 | 
				
			||||||
    "ruma-common/unstable-unspecified",
 | 
					    "ruma-common/unstable-unspecified",
 | 
				
			||||||
@ -280,6 +281,7 @@ __ci = [
 | 
				
			|||||||
    "unstable-msc4108",
 | 
					    "unstable-msc4108",
 | 
				
			||||||
    "unstable-msc4121",
 | 
					    "unstable-msc4121",
 | 
				
			||||||
    "unstable-msc4125",
 | 
					    "unstable-msc4125",
 | 
				
			||||||
 | 
					    "unstable-msc4140"
 | 
				
			||||||
]
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[dependencies]
 | 
					[dependencies]
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user