matrix_sdk/widget/machine/
incoming.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 ruma::{
16    api::client::{account::request_openid_token, delayed_events},
17    events::AnyTimelineEvent,
18    serde::Raw,
19};
20use serde::{de, Deserialize, Deserializer};
21use serde_json::value::RawValue as RawJsonValue;
22use uuid::Uuid;
23
24use super::{
25    from_widget::{FromWidgetRequest, SendEventResponse},
26    to_widget::ToWidgetResponse,
27};
28use crate::widget::Capabilities;
29
30/// Incoming event that the client API must process.
31pub(crate) enum IncomingMessage {
32    /// An incoming raw message from the widget.
33    WidgetMessage(String),
34
35    /// A response to a request to the `MatrixDriver`.
36    MatrixDriverResponse {
37        /// The ID of the request that this response corresponds to.
38        request_id: Uuid,
39
40        /// Result of the request: the response data, or a matrix sdk error.
41        ///
42        /// Http errors will be forwarded to the widget in a specified format so
43        /// the widget can parse the error.
44        response: Result<MatrixDriverResponse, crate::Error>,
45    },
46
47    /// The `MatrixDriver` notified the `WidgetMachine` of a new matrix event.
48    ///
49    /// This means that the machine previously subscribed to some events
50    /// ([`crate::widget::Action::Subscribe`] request).
51    MatrixEventReceived(Raw<AnyTimelineEvent>),
52}
53
54pub(crate) enum MatrixDriverResponse {
55    /// Client acquired capabilities from the user.
56    ///
57    /// A response to an `Action::AcquireCapabilities` command.
58    CapabilitiesAcquired(Capabilities),
59    /// Client got OpenId token for a given request ID.
60    /// A response to an `Action::GetOpenId` command.
61    OpenIdReceived(request_openid_token::v3::Response),
62    /// Client read some matrix event(s).
63    /// A response to an `Action::ReadMatrixEvent` commands.
64    MatrixEventRead(Vec<Raw<AnyTimelineEvent>>),
65    /// Client sent some matrix event. The response contains the event ID.
66    /// A response to an `Action::SendMatrixEvent` command.
67    MatrixEventSent(SendEventResponse),
68    MatrixDelayedEventUpdate(delayed_events::update_delayed_event::unstable::Response),
69}
70
71pub(super) struct IncomingWidgetMessage {
72    pub(super) widget_id: String,
73    pub(super) request_id: String,
74    pub(super) kind: IncomingWidgetMessageKind,
75}
76
77#[derive(Debug)]
78pub(super) enum IncomingWidgetMessageKind {
79    Request(Raw<FromWidgetRequest>),
80    Response(ToWidgetResponse),
81}
82
83impl<'de> Deserialize<'de> for IncomingWidgetMessage {
84    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
85    where
86        D: Deserializer<'de>,
87    {
88        let raw: Box<RawJsonValue> = Box::deserialize(deserializer)?;
89
90        #[derive(Deserialize)]
91        #[serde(rename_all = "camelCase")]
92        enum ApiTag {
93            FromWidget,
94            ToWidget,
95        }
96
97        #[derive(Deserialize)]
98        #[serde(rename_all = "camelCase")]
99        struct ExtractHeader {
100            api: ApiTag,
101            widget_id: String,
102            request_id: String,
103        }
104
105        let ExtractHeader { api, widget_id, request_id } =
106            serde_json::from_str(raw.get()).map_err(de::Error::custom)?;
107
108        let kind = match api {
109            ApiTag::FromWidget => IncomingWidgetMessageKind::Request(Raw::from_json(raw)),
110            ApiTag::ToWidget => serde_json::from_str(raw.get())
111                .map(IncomingWidgetMessageKind::Response)
112                .map_err(de::Error::custom)?,
113        };
114
115        Ok(Self { widget_id, request_id, kind })
116    }
117}