matrix_sdk/widget/machine/
from_widget.rs

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.
14
15use as_variant::as_variant;
16use ruma::{
17    api::client::{
18        delayed_events::{delayed_message_event, delayed_state_event, update_delayed_event},
19        error::{ErrorBody, StandardErrorBody},
20    },
21    events::{AnyTimelineEvent, MessageLikeEventType, StateEventType},
22    serde::Raw,
23    OwnedEventId, OwnedRoomId,
24};
25use serde::{Deserialize, Serialize};
26
27use super::{SendEventRequest, UpdateDelayedEventRequest};
28use crate::{widget::StateKeySelector, Error, HttpError, RumaApiError};
29
30#[derive(Deserialize, Debug)]
31#[serde(tag = "action", rename_all = "snake_case", content = "data")]
32pub(super) enum FromWidgetRequest {
33    SupportedApiVersions {},
34    ContentLoaded {},
35    #[serde(rename = "get_openid")]
36    GetOpenId {},
37    #[serde(rename = "org.matrix.msc2876.read_events")]
38    ReadEvent(ReadEventRequest),
39    SendEvent(SendEventRequest),
40    #[serde(rename = "org.matrix.msc4157.update_delayed_event")]
41    DelayedEventUpdate(UpdateDelayedEventRequest),
42}
43
44/// The full response a client sends to a [`FromWidgetRequest`] in case of an
45/// error.
46#[derive(Serialize)]
47pub(super) struct FromWidgetErrorResponse {
48    error: FromWidgetError,
49}
50
51impl FromWidgetErrorResponse {
52    /// Create a error response to send to the widget from an http error.
53    pub(crate) fn from_http_error(error: HttpError) -> Self {
54        let message = error.to_string();
55        let matrix_api_error = as_variant!(error, HttpError::Api(ruma::api::error::FromHttpResponseError::Server(RumaApiError::ClientApi(err))) => err);
56
57        Self {
58            error: FromWidgetError {
59                message,
60                matrix_api_error: matrix_api_error.and_then(|api_error| match api_error.body {
61                    ErrorBody::Standard { kind, message } => Some(FromWidgetMatrixErrorBody {
62                        http_status: api_error.status_code.as_u16().into(),
63                        response: StandardErrorBody { kind, message },
64                    }),
65                    _ => None,
66                }),
67            },
68        }
69    }
70
71    /// Create a error response to send to the widget from a matrix sdk error.
72    pub(crate) fn from_error(error: Error) -> Self {
73        match error {
74            Error::Http(e) => FromWidgetErrorResponse::from_http_error(e),
75            // For UnknownError's we do not want to have the `unknown error` bit in the message.
76            // Hence we only convert the inner error to a string.
77            Error::UnknownError(e) => FromWidgetErrorResponse::from_string(e.to_string()),
78            _ => FromWidgetErrorResponse::from_string(error.to_string()),
79        }
80    }
81
82    /// Create a error response to send to the widget from a string.
83    pub(crate) fn from_string<S: Into<String>>(error: S) -> Self {
84        Self { error: FromWidgetError { message: error.into(), matrix_api_error: None } }
85    }
86}
87
88/// Serializable section of an error response send by the client as a
89/// response to a [`FromWidgetRequest`].
90#[derive(Serialize)]
91struct FromWidgetError {
92    /// Unspecified error message text that caused this widget action to
93    /// fail.
94    ///
95    /// This is useful to prompt the user on an issue but cannot be used to
96    /// decide on how to deal with the error.
97    message: String,
98
99    /// Optional matrix error hinting at workarounds for specific errors.
100    matrix_api_error: Option<FromWidgetMatrixErrorBody>,
101}
102
103/// Serializable section of a widget response that represents a matrix error.
104#[derive(Serialize)]
105struct FromWidgetMatrixErrorBody {
106    /// Status code of the http response.
107    http_status: u32,
108
109    /// Standard error response including the `errorcode` and the `error`
110    /// message as defined in the [spec](https://spec.matrix.org/v1.12/client-server-api/#standard-error-response).
111    response: StandardErrorBody,
112}
113
114/// The serializable section of a widget response containing the supported
115/// versions.
116#[derive(Serialize)]
117pub(super) struct SupportedApiVersionsResponse {
118    supported_versions: Vec<ApiVersion>,
119}
120
121impl SupportedApiVersionsResponse {
122    /// The currently supported widget api versions from the rust widget driver.
123    pub(super) fn new() -> Self {
124        Self {
125            supported_versions: vec![
126                ApiVersion::V0_0_1,
127                ApiVersion::V0_0_2,
128                ApiVersion::MSC2762,
129                ApiVersion::MSC2871,
130                ApiVersion::MSC3819,
131            ],
132        }
133    }
134}
135
136#[derive(Serialize)]
137#[allow(dead_code)] // not all variants used right now
138pub(super) enum ApiVersion {
139    /// First stable version.
140    #[serde(rename = "0.0.1")]
141    V0_0_1,
142
143    /// Second stable version.
144    #[serde(rename = "0.0.2")]
145    V0_0_2,
146
147    /// Supports sending and receiving of events.
148    #[serde(rename = "org.matrix.msc2762")]
149    MSC2762,
150
151    /// Supports sending of approved capabilities back to the widget.
152    #[serde(rename = "org.matrix.msc2871")]
153    MSC2871,
154
155    /// Supports navigating to a URI.
156    #[serde(rename = "org.matrix.msc2931")]
157    MSC2931,
158
159    /// Supports capabilities renegotiation.
160    #[serde(rename = "org.matrix.msc2974")]
161    MSC2974,
162
163    /// Supports reading events in a room (deprecated).
164    #[serde(rename = "org.matrix.msc2876")]
165    MSC2876,
166
167    /// Supports sending and receiving of to-device events.
168    #[serde(rename = "org.matrix.msc3819")]
169    MSC3819,
170
171    /// Supports access to the TURN servers.
172    #[serde(rename = "town.robin.msc3846")]
173    MSC3846,
174}
175
176#[derive(Deserialize, Debug)]
177#[serde(untagged)]
178pub(super) enum ReadEventRequest {
179    ReadStateEvent {
180        #[serde(rename = "type")]
181        event_type: StateEventType,
182        state_key: StateKeySelector,
183    },
184    ReadMessageLikeEvent {
185        #[serde(rename = "type")]
186        event_type: MessageLikeEventType,
187        limit: Option<u32>,
188    },
189}
190
191#[derive(Debug, Serialize)]
192pub(super) struct ReadEventResponse {
193    pub(super) events: Vec<Raw<AnyTimelineEvent>>,
194}
195
196#[derive(Serialize, Debug)]
197pub(crate) struct SendEventResponse {
198    /// The room id for the send event.
199    pub(crate) room_id: Option<OwnedRoomId>,
200    /// The event id of the send event. It's optional because if it's a delayed
201    /// event, it does not get the event_id at this point.
202    pub(crate) event_id: Option<OwnedEventId>,
203    /// The `delay_id` generated for this delayed event. Used to interact with
204    /// the delayed event.
205    pub(crate) delay_id: Option<String>,
206}
207
208impl SendEventResponse {
209    pub(crate) fn from_event_id(event_id: OwnedEventId) -> Self {
210        SendEventResponse { room_id: None, event_id: Some(event_id), delay_id: None }
211    }
212    pub(crate) fn set_room_id(&mut self, room_id: OwnedRoomId) {
213        self.room_id = Some(room_id);
214    }
215}
216
217impl From<delayed_message_event::unstable::Response> for SendEventResponse {
218    fn from(val: delayed_message_event::unstable::Response) -> Self {
219        SendEventResponse { room_id: None, event_id: None, delay_id: Some(val.delay_id) }
220    }
221}
222
223impl From<delayed_state_event::unstable::Response> for SendEventResponse {
224    fn from(val: delayed_state_event::unstable::Response) -> Self {
225        SendEventResponse { room_id: None, event_id: None, delay_id: Some(val.delay_id) }
226    }
227}
228
229/// A wrapper type for the empty okay response from
230/// [`update_delayed_event`](update_delayed_event::unstable::Response)
231/// which derives Serialize. (The response struct from Ruma does not derive
232/// serialize)
233#[derive(Serialize, Debug)]
234pub(crate) struct UpdateDelayedEventResponse {}
235impl From<update_delayed_event::unstable::Response> for UpdateDelayedEventResponse {
236    fn from(_: update_delayed_event::unstable::Response) -> Self {
237        Self {}
238    }
239}