diff --git a/src/collections/all.rs b/src/collections/all.rs index 49e5640d..26d8918c 100644 --- a/src/collections/all.rs +++ b/src/collections/all.rs @@ -7,6 +7,7 @@ use crate::{ }, direct::DirectEvent, fully_read::FullyReadEvent, + ignored_user_list::IgnoredUserListEvent, presence::PresenceEvent, receipt::ReceiptEvent, room::{ @@ -50,6 +51,8 @@ pub enum Event { Direct(DirectEvent), /// m.fully_read FullyRead(FullyReadEvent), + /// m.ignored_user_list + IgnoredUserList(IgnoredUserListEvent), /// m.presence Presence(PresenceEvent), /// m.receipt @@ -194,6 +197,7 @@ impl Serialize for Event { Event::CallInvite(ref event) => event.serialize(serializer), Event::Direct(ref event) => event.serialize(serializer), Event::FullyRead(ref event) => event.serialize(serializer), + Event::IgnoredUserList(ref event) => event.serialize(serializer), Event::Presence(ref event) => event.serialize(serializer), Event::Receipt(ref event) => event.serialize(serializer), Event::RoomAliases(ref event) => event.serialize(serializer), @@ -287,6 +291,14 @@ impl<'de> Deserialize<'de> for Event { Ok(Event::FullyRead(event)) } + EventType::IgnoredUserList => { + let event = match from_value::(value) { + Ok(event) => event, + Err(error) => return Err(D::Error::custom(error.to_string())), + }; + + Ok(Event::IgnoredUserList(event)) + } EventType::Presence => { let event = match from_value::(value) { Ok(event) => event, @@ -707,6 +719,7 @@ impl<'de> Deserialize<'de> for RoomEvent { } EventType::Direct | EventType::FullyRead + | EventType::IgnoredUserList | EventType::Presence | EventType::Receipt | EventType::Tag @@ -875,6 +888,7 @@ impl<'de> Deserialize<'de> for StateEvent { | EventType::CallInvite | EventType::Direct | EventType::FullyRead + | EventType::IgnoredUserList | EventType::Presence | EventType::Receipt | EventType::RoomMessage @@ -902,6 +916,7 @@ impl_from_t_for_event!(HangupEvent, CallHangup); impl_from_t_for_event!(InviteEvent, CallInvite); impl_from_t_for_event!(DirectEvent, Direct); impl_from_t_for_event!(FullyReadEvent, FullyRead); +impl_from_t_for_event!(IgnoredUserListEvent, IgnoredUserList); impl_from_t_for_event!(PresenceEvent, Presence); impl_from_t_for_event!(ReceiptEvent, Receipt); impl_from_t_for_event!(AliasesEvent, RoomAliases); diff --git a/src/collections/only.rs b/src/collections/only.rs index f90d84ef..62805365 100644 --- a/src/collections/only.rs +++ b/src/collections/only.rs @@ -11,6 +11,7 @@ use crate::{ }, direct::DirectEvent, fully_read::FullyReadEvent, + ignored_user_list::IgnoredUserListEvent, presence::PresenceEvent, receipt::ReceiptEvent, room::{ @@ -29,6 +30,8 @@ pub enum Event { Direct(DirectEvent), /// m.fully_read FullyRead(FullyReadEvent), + /// m.ignored_user_list + IgnoredUserList(IgnoredUserListEvent), /// m.presence Presence(PresenceEvent), /// m.receipt @@ -71,6 +74,7 @@ impl Serialize for Event { match *self { Event::Direct(ref event) => event.serialize(serializer), Event::FullyRead(ref event) => event.serialize(serializer), + Event::IgnoredUserList(ref event) => event.serialize(serializer), Event::Presence(ref event) => event.serialize(serializer), Event::Receipt(ref event) => event.serialize(serializer), Event::Tag(ref event) => event.serialize(serializer), @@ -114,6 +118,14 @@ impl<'de> Deserialize<'de> for Event { Ok(Event::FullyRead(event)) } + EventType::IgnoredUserList => { + let event = match from_value::(value) { + Ok(event) => event, + Err(error) => return Err(D::Error::custom(error.to_string())), + }; + + Ok(Event::IgnoredUserList(event)) + } EventType::Presence => { let event = match from_value::(value) { Ok(event) => event, @@ -282,6 +294,7 @@ impl<'de> Deserialize<'de> for RoomEvent { } EventType::Direct | EventType::FullyRead + | EventType::IgnoredUserList | EventType::Presence | EventType::Receipt | EventType::RoomAliases @@ -316,6 +329,7 @@ macro_rules! impl_from_t_for_event { impl_from_t_for_event!(DirectEvent, Direct); impl_from_t_for_event!(FullyReadEvent, FullyRead); +impl_from_t_for_event!(IgnoredUserListEvent, IgnoredUserList); impl_from_t_for_event!(PresenceEvent, Presence); impl_from_t_for_event!(ReceiptEvent, Receipt); impl_from_t_for_event!(TagEvent, Tag); diff --git a/src/ignored_user_list.rs b/src/ignored_user_list.rs new file mode 100644 index 00000000..e4dfefa4 --- /dev/null +++ b/src/ignored_user_list.rs @@ -0,0 +1,69 @@ +//! Types for the *m.ignored_user_list* event. + +use std::collections::HashMap; + +use ruma_identifiers::UserId; +use serde::{Deserialize, Serialize}; + +event! { + /// A list of users to ignore. + pub struct IgnoredUserListEvent(IgnoredUserListEventContent) {} +} + +/// The payload of an `IgnoredUserListEvent`. +#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)] +pub struct IgnoredUserListEventContent { + /// A list of users to ignore. + /// + /// The values in the hash map are not meaningful. They are used to generate an empty JSON + /// object to support the odd structure used by the Matrix specification: + /// + /// ```text + /// "@someone:example.org": {} + /// ``` + pub ignored_users: HashMap>, +} + +#[cfg(test)] +mod tests { + use std::{collections::HashMap, convert::TryFrom}; + + use ruma_identifiers::UserId; + + use super::IgnoredUserListEventContent; + + #[test] + fn serialize_to_empty_json_object() { + let mut ignored_user_list_event_content = IgnoredUserListEventContent { + ignored_users: HashMap::new(), + }; + + let user_id = UserId::try_from("@carl:example.com").unwrap(); + + ignored_user_list_event_content + .ignored_users + .insert(user_id, HashMap::new()); + + let json = serde_json::to_string(&ignored_user_list_event_content).unwrap(); + + assert_eq!(json, r#"{"ignored_users":{"@carl:example.com":{}}}"#); + } + + #[test] + fn deserialize_from_empty_json_object() { + let json = r#"{"ignored_users":{"@carl:example.com":{}}}"#; + + let ignored_user_list_event_content: IgnoredUserListEventContent = + serde_json::from_str(&json).unwrap(); + + let mut expected = IgnoredUserListEventContent { + ignored_users: HashMap::new(), + }; + + let user_id = UserId::try_from("@carl:example.com").unwrap(); + + expected.ignored_users.insert(user_id, HashMap::new()); + + assert_eq!(ignored_user_list_event_content, expected); + } +} diff --git a/src/lib.rs b/src/lib.rs index 2e63dd8d..fc6c44e0 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -119,6 +119,7 @@ pub mod collections { } pub mod direct; pub mod fully_read; +pub mod ignored_user_list; pub mod presence; pub mod receipt; pub mod room; @@ -145,6 +146,8 @@ pub enum EventType { Direct, /// m.fully_read FullyRead, + /// m.ignored_user_list + IgnoredUserList, /// m.presence Presence, /// m.receipt @@ -259,6 +262,7 @@ impl Display for EventType { EventType::CallInvite => "m.call.invite", EventType::Direct => "m.direct", EventType::FullyRead => "m.fully_read", + EventType::IgnoredUserList => "m.ignored_user_list", EventType::Presence => "m.presence", EventType::Receipt => "m.receipt", EventType::RoomAliases => "m.room.aliases", @@ -295,6 +299,7 @@ impl<'a> From<&'a str> for EventType { "m.call.invite" => EventType::CallInvite, "m.direct" => EventType::Direct, "m.fully_read" => EventType::FullyRead, + "m.ignored_user_list" => EventType::IgnoredUserList, "m.presence" => EventType::Presence, "m.receipt" => EventType::Receipt, "m.room.aliases" => EventType::RoomAliases,