1// Copyright 2023 The Matrix.org Foundation C.I.C.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
1415//! A high-level API for requests that we send to the matrix driver.
1617use std::marker::PhantomData;
1819use ruma::{
20 api::client::{account::request_openid_token, delayed_events::update_delayed_event},
21 events::{AnyTimelineEvent, MessageLikeEventType, StateEventType, TimelineEventType},
22 serde::Raw,
23};
24use serde::Deserialize;
25use serde_json::value::RawValue as RawJsonValue;
26use tracing::error;
2728use super::{
29 from_widget::SendEventResponse, incoming::MatrixDriverResponse, Action,
30 MatrixDriverRequestMeta, WidgetMachine,
31};
32use crate::widget::{Capabilities, StateKeySelector};
3334#[derive(Clone, Debug)]
35pub(crate) enum MatrixDriverRequestData {
36/// Acquire capabilities from the user given the set of desired
37 /// capabilities.
38 ///
39 /// Must eventually be answered with
40 /// [`MatrixDriverResponse::CapabilitiesAcquired`].
41AcquireCapabilities(AcquireCapabilities),
4243/// Get OpenId token for a given request ID.
44GetOpenId,
4546/// Read message event(s).
47ReadMessageLikeEvent(ReadMessageLikeEventRequest),
4849/// Read state event(s).
50ReadStateEvent(ReadStateEventRequest),
5152/// Send matrix event that corresponds to the given description.
53SendMatrixEvent(SendEventRequest),
5455/// Data for sending a UpdateDelayedEvent client server api request.
56UpdateDelayedEvent(UpdateDelayedEventRequest),
57}
5859/// A handle to a pending `toWidget` request.
60pub(crate) struct MatrixDriverRequestHandle<'m, T> {
61 request_meta: Option<&'m mut MatrixDriverRequestMeta>,
62 _phantom: PhantomData<fn() -> T>,
63}
6465impl<'m, T> MatrixDriverRequestHandle<'m, T>
66where
67T: FromMatrixDriverResponse,
68{
69pub(crate) fn new(request_meta: &'m mut MatrixDriverRequestMeta) -> Self {
70Self { request_meta: Some(request_meta), _phantom: PhantomData }
71 }
7273pub(crate) fn null() -> Self {
74Self { request_meta: None, _phantom: PhantomData }
75 }
7677/// Setup a callback function that will be called once the matrix driver has
78 /// processed the request.
79pub(crate) fn then(
80self,
81 response_handler: impl FnOnce(Result<T, crate::Error>, &mut WidgetMachine) -> Vec<Action>
82 + Send
83 + 'static,
84 ) {
85if let Some(request_meta) = self.request_meta {
86 request_meta.response_fn = Some(Box::new(move |response, machine| {
87if let Some(response_data) = response.map(T::from_response).transpose() {
88 response_handler(response_data, machine)
89 } else {
90 Vec::new()
91 }
92 }));
93 }
94 }
95}
9697/// Represents a request that the widget API state machine can send.
98pub(crate) trait MatrixDriverRequest: Into<MatrixDriverRequestData> {
99type Response: FromMatrixDriverResponse;
100}
101102pub(crate) trait FromMatrixDriverResponse: Sized {
103fn from_response(_: MatrixDriverResponse) -> Option<Self>;
104}
105106/// Ask the client (capability provider) to acquire given capabilities
107/// from the user. The client must eventually respond with granted capabilities.
108#[derive(Clone, Debug)]
109pub(crate) struct AcquireCapabilities {
110pub(crate) desired_capabilities: Capabilities,
111}
112113impl From<AcquireCapabilities> for MatrixDriverRequestData {
114fn from(value: AcquireCapabilities) -> Self {
115 MatrixDriverRequestData::AcquireCapabilities(value)
116 }
117}
118119impl MatrixDriverRequest for AcquireCapabilities {
120type Response = Capabilities;
121}
122123impl FromMatrixDriverResponse for Capabilities {
124fn from_response(ev: MatrixDriverResponse) -> Option<Self> {
125match ev {
126 MatrixDriverResponse::CapabilitiesAcquired(response) => Some(response),
127_ => {
128error!("bug in MatrixDriver, received wrong event response");
129None
130}
131 }
132 }
133}
134135/// Request open ID from the Matrix client.
136#[derive(Debug)]
137pub(crate) struct RequestOpenId;
138139impl From<RequestOpenId> for MatrixDriverRequestData {
140fn from(_: RequestOpenId) -> Self {
141 MatrixDriverRequestData::GetOpenId
142 }
143}
144145impl MatrixDriverRequest for RequestOpenId {
146type Response = request_openid_token::v3::Response;
147}
148149impl FromMatrixDriverResponse for request_openid_token::v3::Response {
150fn from_response(ev: MatrixDriverResponse) -> Option<Self> {
151match ev {
152 MatrixDriverResponse::OpenIdReceived(response) => Some(response),
153_ => {
154error!("bug in MatrixDriver, received wrong event response");
155None
156}
157 }
158 }
159}
160161/// Ask the client to read matrix event(s) that corresponds to the given
162/// description and return a list of events as a response.
163#[derive(Clone, Debug)]
164pub(crate) struct ReadMessageLikeEventRequest {
165/// The event type to read.
166pub(crate) event_type: MessageLikeEventType,
167168/// The maximum number of events to return.
169pub(crate) limit: u32,
170}
171172impl From<ReadMessageLikeEventRequest> for MatrixDriverRequestData {
173fn from(value: ReadMessageLikeEventRequest) -> Self {
174 MatrixDriverRequestData::ReadMessageLikeEvent(value)
175 }
176}
177178impl MatrixDriverRequest for ReadMessageLikeEventRequest {
179type Response = Vec<Raw<AnyTimelineEvent>>;
180}
181182impl FromMatrixDriverResponse for Vec<Raw<AnyTimelineEvent>> {
183fn from_response(ev: MatrixDriverResponse) -> Option<Self> {
184match ev {
185 MatrixDriverResponse::MatrixEventRead(response) => Some(response),
186_ => {
187error!("bug in MatrixDriver, received wrong event response");
188None
189}
190 }
191 }
192}
193194/// Ask the client to read matrix event(s) that corresponds to the given
195/// description and return a list of events as a response.
196#[derive(Clone, Debug)]
197pub(crate) struct ReadStateEventRequest {
198/// The event type to read.
199pub(crate) event_type: StateEventType,
200201/// The `state_key` to read, or `Any` to receive any/all events of the given
202 /// type, regardless of their `state_key`.
203pub(crate) state_key: StateKeySelector,
204}
205206impl From<ReadStateEventRequest> for MatrixDriverRequestData {
207fn from(value: ReadStateEventRequest) -> Self {
208 MatrixDriverRequestData::ReadStateEvent(value)
209 }
210}
211212impl MatrixDriverRequest for ReadStateEventRequest {
213type Response = Vec<Raw<AnyTimelineEvent>>;
214}
215216/// Ask the client to send matrix event that corresponds to the given
217/// description and returns an event ID (or a delay ID,
218/// see [MSC4140](https://github.com/matrix-org/matrix-spec-proposals/pull/4140)) as a response.
219#[derive(Clone, Debug, Deserialize)]
220pub(crate) struct SendEventRequest {
221/// The type of the event.
222#[serde(rename = "type")]
223pub(crate) event_type: TimelineEventType,
224/// State key of an event (if it's a state event).
225pub(crate) state_key: Option<String>,
226/// Raw content of an event.
227pub(crate) content: Box<RawJsonValue>,
228/// The optional delay (in ms) to send the event at.
229 /// If provided, the response will contain a delay_id instead of a event_id.
230 /// Defined by [MSC4157](https://github.com/matrix-org/matrix-spec-proposals/pull/4157)
231pub(crate) delay: Option<u64>,
232}
233234impl From<SendEventRequest> for MatrixDriverRequestData {
235fn from(value: SendEventRequest) -> Self {
236 MatrixDriverRequestData::SendMatrixEvent(value)
237 }
238}
239240impl MatrixDriverRequest for SendEventRequest {
241type Response = SendEventResponse;
242}
243244impl FromMatrixDriverResponse for SendEventResponse {
245fn from_response(ev: MatrixDriverResponse) -> Option<Self> {
246match ev {
247 MatrixDriverResponse::MatrixEventSent(response) => Some(response),
248_ => {
249error!("bug in MatrixDriver, received wrong event response");
250None
251}
252 }
253 }
254}
255256/// Ask the client to send a UpdateDelayedEventRequest with the given `delay_id`
257/// and `action`. Defined by [MSC4157](https://github.com/matrix-org/matrix-spec-proposals/pull/4157)
258#[derive(Deserialize, Debug, Clone)]
259pub(crate) struct UpdateDelayedEventRequest {
260pub(crate) action: update_delayed_event::unstable::UpdateAction,
261pub(crate) delay_id: String,
262}
263264impl From<UpdateDelayedEventRequest> for MatrixDriverRequestData {
265fn from(value: UpdateDelayedEventRequest) -> Self {
266 MatrixDriverRequestData::UpdateDelayedEvent(value)
267 }
268}
269270impl MatrixDriverRequest for UpdateDelayedEventRequest {
271type Response = update_delayed_event::unstable::Response;
272}
273274impl FromMatrixDriverResponse for update_delayed_event::unstable::Response {
275fn from_response(ev: MatrixDriverResponse) -> Option<Self> {
276match ev {
277 MatrixDriverResponse::MatrixDelayedEventUpdate(response) => Some(response),
278_ => {
279error!("bug in MatrixDriver, received wrong event response");
280None
281}
282 }
283 }
284}