From fc0d8ee8e725b351c1902dd7d0f92a8cc95b5048 Mon Sep 17 00:00:00 2001 From: Isaiah Inuwa Date: Mon, 17 Feb 2020 20:45:46 -0600 Subject: [PATCH] Add send-to-device endpoint --- CHANGELOG.md | 1 + src/r0.rs | 1 + src/r0/client_exchange.rs | 71 +++++++++++++++++++ .../client_exchange/send_event_to_device.rs | 36 ++++++++++ 4 files changed, 109 insertions(+) create mode 100644 src/r0/client_exchange.rs create mode 100644 src/r0/client_exchange/send_event_to_device.rs diff --git a/CHANGELOG.md b/CHANGELOG.md index 1826ebd9..15cb638e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,7 @@ Improvements: * Add an `Error` type that represents the well-known errors in the client-server API * Add OpenID token request endpoint. +* Add `r0::client_exchange::send_event_to_device` (introduced in r0.3.0) Breaking changes: diff --git a/src/r0.rs b/src/r0.rs index 79123f05..9ed2405f 100644 --- a/src/r0.rs +++ b/src/r0.rs @@ -4,6 +4,7 @@ pub mod account; pub mod alias; pub mod appservice; pub mod capabilities; +pub mod client_exchange; pub mod config; pub mod contact; pub mod context; diff --git a/src/r0/client_exchange.rs b/src/r0/client_exchange.rs new file mode 100644 index 00000000..033d0fd1 --- /dev/null +++ b/src/r0/client_exchange.rs @@ -0,0 +1,71 @@ +//! Endpoints for client devices to exchange information not persisted in room DAG. + +use std::{ + convert::TryFrom, + fmt::{Display, Formatter, Result as FmtResult}, +}; + +use ruma_identifiers::DeviceId; +use serde::{ + de::{self, Unexpected}, + Deserialize, Deserializer, Serialize, Serializer, +}; + +pub mod send_event_to_device; +/// Represents one or all of a user's devices. +#[derive(Clone, Debug, Hash, PartialEq, Eq)] +pub enum DeviceIdOrAllDevices { + /// Represents a device Id for one of a user's devices. + DeviceId(DeviceId), + /// Represents all devices for a user. + AllDevices, +} + +impl Display for DeviceIdOrAllDevices { + fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult { + match self { + DeviceIdOrAllDevices::DeviceId(device_id) => write!(f, "{}", device_id.to_string()), + DeviceIdOrAllDevices::AllDevices => write!(f, "*"), + } + } +} + +impl TryFrom<&str> for DeviceIdOrAllDevices { + type Error = &'static str; + fn try_from(device_id_or_all_devices: &str) -> Result { + if device_id_or_all_devices.is_empty() { + Err("Device identifier cannot be empty") + } else if "*" == device_id_or_all_devices { + Ok(DeviceIdOrAllDevices::AllDevices) + } else { + Ok(DeviceIdOrAllDevices::DeviceId( + device_id_or_all_devices.to_string(), + )) + } + } +} + +impl Serialize for DeviceIdOrAllDevices { + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { + match self { + Self::DeviceId(ref device_id) => serializer.serialize_str(&device_id), + Self::AllDevices => serializer.serialize_str("*"), + } + } +} + +impl<'de> Deserialize<'de> for DeviceIdOrAllDevices { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + let value = &String::deserialize(deserializer)?; + + DeviceIdOrAllDevices::try_from(&value[..]).map_err(|_| { + de::Error::invalid_value(Unexpected::Str(&value), &"a valid device identifier or '*'") + }) + } +} diff --git a/src/r0/client_exchange/send_event_to_device.rs b/src/r0/client_exchange/send_event_to_device.rs new file mode 100644 index 00000000..36aefd36 --- /dev/null +++ b/src/r0/client_exchange/send_event_to_device.rs @@ -0,0 +1,36 @@ +//! [PUT /_matrix/client/r0/sendToDevice/{eventType}/{txnId}](https://matrix.org/docs/spec/client_server/r0.6.0#put-matrix-client-r0-sendtodevice-eventtype-txnid) + +use std::collections::HashMap; + +use ruma_api::ruma_api; +use ruma_events::{collections::all, EventResult}; +use ruma_identifiers::UserId; + +use super::DeviceIdOrAllDevices; + +ruma_api! { + metadata { + description: "Send an event to a device or devices.", + method: PUT, + name: "send_event_to_device", + path: "/_matrix/client/r0/sendToDevice/:event_type/:txn_id", + rate_limited: false, + requires_authentication: true, + } + + request { + /// Type of event being sent to each device. + #[ruma_api(path)] + event_type: String, + /// A request identifier unique to the access token used to send the request. + #[ruma_api(path)] + txn_id: String, + /// A map of users to devices to a message event to be sent to the user's + /// device. Individual message events can be sent to devices, but all + /// events must be of the same type. + #[wrap_incoming(all::Event with EventResult)] + messages: HashMap> + } + + response {} +}