use std::{collections::BTreeMap, marker::PhantomData};
use ruma::{
OwnedUserId,
api::client::{account::request_openid_token, delayed_events::update_delayed_event},
events::{AnyStateEvent, AnyTimelineEvent, AnyToDeviceEventContent},
serde::Raw,
to_device::DeviceIdOrAllDevices,
};
use serde::Deserialize;
use serde_json::value::RawValue as RawJsonValue;
use tracing::error;
use super::{
Action, MatrixDriverRequestMeta, SendToDeviceEventResponse, WidgetMachine,
from_widget::SendEventResponse, incoming::MatrixDriverResponse,
};
use crate::widget::{Capabilities, StateKeySelector};
#[derive(Clone, Debug)]
pub(crate) enum MatrixDriverRequestData {
AcquireCapabilities(AcquireCapabilities),
GetOpenId,
ReadEvents(ReadEventsRequest),
ReadState(ReadStateRequest),
SendEvent(SendEventRequest),
SendToDeviceEvent(SendToDeviceRequest),
UpdateDelayedEvent(UpdateDelayedEventRequest),
}
pub(crate) struct MatrixDriverRequestHandle<'m, T> {
request_meta: &'m mut MatrixDriverRequestMeta,
_phantom: PhantomData<fn() -> T>,
}
impl<'m, T> MatrixDriverRequestHandle<'m, T>
where
T: FromMatrixDriverResponse,
{
pub(crate) fn new(request_meta: &'m mut MatrixDriverRequestMeta) -> Self {
Self { request_meta, _phantom: PhantomData }
}
pub(crate) fn add_response_handler(
self,
response_handler: impl FnOnce(Result<T, crate::Error>, &mut WidgetMachine) -> Vec<Action>
+ Send
+ 'static,
) {
self.request_meta.response_fn = Some(Box::new(move |response, machine| {
if let Some(response_data) = response.map(T::from_response).transpose() {
response_handler(response_data, machine)
} else {
Vec::new()
}
}));
}
}
pub(crate) trait MatrixDriverRequest: Into<MatrixDriverRequestData> {
type Response: FromMatrixDriverResponse;
}
pub(crate) trait FromMatrixDriverResponse: Sized {
fn from_response(_: MatrixDriverResponse) -> Option<Self>;
}
impl<T> FromMatrixDriverResponse for T
where
MatrixDriverResponse: TryInto<T>,
{
fn from_response(response: MatrixDriverResponse) -> Option<Self> {
response.try_into().ok()
}
}
#[derive(Clone, Debug)]
pub(crate) struct AcquireCapabilities {
pub(crate) desired_capabilities: Capabilities,
}
impl From<AcquireCapabilities> for MatrixDriverRequestData {
fn from(value: AcquireCapabilities) -> Self {
MatrixDriverRequestData::AcquireCapabilities(value)
}
}
impl MatrixDriverRequest for AcquireCapabilities {
type Response = Capabilities;
}
impl FromMatrixDriverResponse for Capabilities {
fn from_response(ev: MatrixDriverResponse) -> Option<Self> {
match ev {
MatrixDriverResponse::CapabilitiesAcquired(response) => Some(response),
_ => {
error!("bug in MatrixDriver, received wrong event response");
None
}
}
}
}
#[derive(Debug)]
pub(crate) struct RequestOpenId;
impl From<RequestOpenId> for MatrixDriverRequestData {
fn from(_: RequestOpenId) -> Self {
MatrixDriverRequestData::GetOpenId
}
}
impl MatrixDriverRequest for RequestOpenId {
type Response = request_openid_token::v3::Response;
}
impl FromMatrixDriverResponse for request_openid_token::v3::Response {
fn from_response(ev: MatrixDriverResponse) -> Option<Self> {
match ev {
MatrixDriverResponse::OpenIdReceived(response) => Some(response),
_ => {
error!("bug in MatrixDriver, received wrong event response");
None
}
}
}
}
#[derive(Clone, Debug)]
pub(crate) struct ReadEventsRequest {
pub(crate) event_type: String,
pub(crate) state_key: Option<StateKeySelector>,
pub(crate) limit: u32,
}
impl From<ReadEventsRequest> for MatrixDriverRequestData {
fn from(value: ReadEventsRequest) -> Self {
MatrixDriverRequestData::ReadEvents(value)
}
}
impl MatrixDriverRequest for ReadEventsRequest {
type Response = Vec<Raw<AnyTimelineEvent>>;
}
impl FromMatrixDriverResponse for Vec<Raw<AnyTimelineEvent>> {
fn from_response(ev: MatrixDriverResponse) -> Option<Self> {
match ev {
MatrixDriverResponse::EventsRead(response) => Some(response),
_ => {
error!("bug in MatrixDriver, received wrong event response");
None
}
}
}
}
#[derive(Clone, Debug)]
pub(crate) struct ReadStateRequest {
pub(crate) event_type: String,
pub(crate) state_key: StateKeySelector,
}
impl From<ReadStateRequest> for MatrixDriverRequestData {
fn from(value: ReadStateRequest) -> Self {
MatrixDriverRequestData::ReadState(value)
}
}
impl MatrixDriverRequest for ReadStateRequest {
type Response = Vec<Raw<AnyStateEvent>>;
}
impl FromMatrixDriverResponse for Vec<Raw<AnyStateEvent>> {
fn from_response(ev: MatrixDriverResponse) -> Option<Self> {
match ev {
MatrixDriverResponse::StateRead(response) => Some(response),
_ => {
error!("bug in MatrixDriver, received wrong event response");
None
}
}
}
}
#[derive(Clone, Debug, Deserialize)]
pub(crate) struct SendEventRequest {
#[serde(rename = "type")]
pub(crate) event_type: String,
pub(crate) state_key: Option<String>,
pub(crate) content: Box<RawJsonValue>,
pub(crate) delay: Option<u64>,
}
impl From<SendEventRequest> for MatrixDriverRequestData {
fn from(value: SendEventRequest) -> Self {
MatrixDriverRequestData::SendEvent(value)
}
}
impl MatrixDriverRequest for SendEventRequest {
type Response = SendEventResponse;
}
impl FromMatrixDriverResponse for SendEventResponse {
fn from_response(ev: MatrixDriverResponse) -> Option<Self> {
match ev {
MatrixDriverResponse::EventSent(response) => Some(response),
_ => {
error!("bug in MatrixDriver, received wrong event response");
None
}
}
}
}
#[derive(Clone, Debug, Deserialize)]
pub(crate) struct SendToDeviceRequest {
#[serde(rename = "type")]
pub(crate) event_type: String,
pub(crate) messages:
BTreeMap<OwnedUserId, BTreeMap<DeviceIdOrAllDevices, Raw<AnyToDeviceEventContent>>>,
}
impl From<SendToDeviceRequest> for MatrixDriverRequestData {
fn from(value: SendToDeviceRequest) -> Self {
MatrixDriverRequestData::SendToDeviceEvent(value)
}
}
impl MatrixDriverRequest for SendToDeviceRequest {
type Response = SendToDeviceEventResponse;
}
#[derive(Deserialize, Debug, Clone)]
pub(crate) struct UpdateDelayedEventRequest {
pub(crate) action: update_delayed_event::unstable::UpdateAction,
pub(crate) delay_id: String,
}
impl From<UpdateDelayedEventRequest> for MatrixDriverRequestData {
fn from(value: UpdateDelayedEventRequest) -> Self {
MatrixDriverRequestData::UpdateDelayedEvent(value)
}
}
impl MatrixDriverRequest for UpdateDelayedEventRequest {
type Response = update_delayed_event::unstable::Response;
}
impl FromMatrixDriverResponse for update_delayed_event::unstable::Response {
fn from_response(ev: MatrixDriverResponse) -> Option<Self> {
match ev {
MatrixDriverResponse::DelayedEventUpdated(response) => Some(response),
_ => {
error!("bug in MatrixDriver, received wrong event response");
None
}
}
}
}