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