ruma_events/
do_not_disturb.rs

1//! Types for the [`dm.filament.do_not_disturb`] event.
2//!
3//! [`dm.filament.do_not_disturb`]: https://github.com/matrix-org/matrix-spec-proposals/pull/4359
4
5use std::collections::BTreeMap;
6
7use ruma_common::OwnedRoomId;
8use ruma_macros::EventContent;
9use serde::{Deserialize, Serialize};
10
11/// The content of a `dm.filament.do_not_disturb` event.
12///
13/// A list of rooms in "Do not Disturb" mode.
14#[derive(Clone, Debug, Default, Deserialize, Serialize, EventContent)]
15#[cfg_attr(not(ruma_unstable_exhaustive_types), non_exhaustive)]
16#[ruma_event(type = "dm.filament.do_not_disturb", kind = GlobalAccountData)]
17pub struct DoNotDisturbEventContent {
18    /// A map of rooms in which to inhibit notifications.
19    ///
20    /// As [`DoNotDisturbRoom`] is currently empty, only the room IDs are useful and
21    /// can be accessed with the `.keys()` and `into_keys()` iterators.
22    pub rooms: BTreeMap<DoNotDisturbRoomKey, DoNotDisturbRoom>,
23}
24
25impl DoNotDisturbEventContent {
26    /// Creates a new `DoNotDisturbEventContent` from the given map of [`DoNotDisturbRoom`]s.
27    pub fn new(rooms: BTreeMap<DoNotDisturbRoomKey, DoNotDisturbRoom>) -> Self {
28        Self { rooms }
29    }
30}
31
32impl FromIterator<DoNotDisturbRoomKey> for DoNotDisturbEventContent {
33    fn from_iter<T: IntoIterator<Item = DoNotDisturbRoomKey>>(iter: T) -> Self {
34        Self::new(iter.into_iter().map(|key| (key, DoNotDisturbRoom {})).collect())
35    }
36}
37
38impl FromIterator<OwnedRoomId> for DoNotDisturbEventContent {
39    fn from_iter<T: IntoIterator<Item = OwnedRoomId>>(iter: T) -> Self {
40        iter.into_iter().map(DoNotDisturbRoomKey::SingleRoom).collect()
41    }
42}
43
44impl Extend<DoNotDisturbRoomKey> for DoNotDisturbEventContent {
45    fn extend<T: IntoIterator<Item = DoNotDisturbRoomKey>>(&mut self, iter: T) {
46        self.rooms.extend(iter.into_iter().map(|key| (key, DoNotDisturbRoom {})));
47    }
48}
49
50impl Extend<OwnedRoomId> for DoNotDisturbEventContent {
51    fn extend<T: IntoIterator<Item = OwnedRoomId>>(&mut self, iter: T) {
52        self.extend(iter.into_iter().map(DoNotDisturbRoomKey::SingleRoom));
53    }
54}
55
56/// The key for a "Do not Disturb" setting.
57///
58/// This either matches a single room or all rooms.
59#[derive(Clone, Debug, Deserialize, Eq, Ord, PartialEq, PartialOrd, Serialize)]
60#[cfg_attr(not(ruma_unstable_exhaustive_types), non_exhaustive)]
61pub enum DoNotDisturbRoomKey {
62    /// Match any room.
63    #[serde(rename = "*")]
64    AllRooms,
65
66    /// Match a single room based on its room ID.
67    #[serde(untagged)]
68    SingleRoom(OwnedRoomId),
69}
70
71/// Details about a room in "Do not Disturb" mode.
72///
73/// This is currently empty.
74#[derive(Clone, Debug, Default, Deserialize, Serialize)]
75#[cfg_attr(not(ruma_unstable_exhaustive_types), non_exhaustive)]
76pub struct DoNotDisturbRoom {}
77
78impl DoNotDisturbRoom {
79    /// Creates an empty `DoNotDisturbRoom`.
80    pub fn new() -> Self {
81        Self::default()
82    }
83}
84
85#[cfg(test)]
86mod tests {
87    use std::collections::BTreeMap;
88
89    use assert_matches2::assert_matches;
90    use ruma_common::owned_room_id;
91    use serde_json::{from_value as from_json_value, json, to_value as to_json_value};
92
93    use super::DoNotDisturbEventContent;
94    use crate::{do_not_disturb::DoNotDisturbRoomKey, AnyGlobalAccountDataEvent};
95
96    #[test]
97    fn serialization_with_single_room() {
98        let do_not_disturb_room_list: DoNotDisturbEventContent =
99            vec![owned_room_id!("!foo:bar.baz")].into_iter().collect();
100
101        let json = json!({
102            "rooms": {
103                "!foo:bar.baz": {}
104            },
105        });
106
107        assert_eq!(to_json_value(do_not_disturb_room_list).unwrap(), json);
108    }
109
110    #[test]
111    fn serialization_with_all_rooms() {
112        let do_not_disturb_room_list = DoNotDisturbEventContent::new(BTreeMap::from([(
113            DoNotDisturbRoomKey::AllRooms,
114            Default::default(),
115        )]));
116
117        let json = json!({
118            "rooms": {
119                "*": {}
120            },
121        });
122
123        assert_eq!(to_json_value(do_not_disturb_room_list).unwrap(), json);
124    }
125
126    #[test]
127    fn deserialization_with_single_room() {
128        let json = json!({
129            "content": {
130                "rooms": {
131                    "!foo:bar.baz": {}
132                }
133            },
134            "type": "dm.filament.do_not_disturb"
135        });
136
137        assert_matches!(
138            from_json_value::<AnyGlobalAccountDataEvent>(json),
139            Ok(AnyGlobalAccountDataEvent::DoNotDisturb(ev))
140        );
141        assert_eq!(
142            ev.content.rooms.keys().collect::<Vec<_>>(),
143            vec![&DoNotDisturbRoomKey::SingleRoom(owned_room_id!("!foo:bar.baz"))]
144        );
145    }
146
147    #[test]
148    fn deserialization_with_all_room() {
149        let json = json!({
150            "content": {
151                "rooms": {
152                    "*": {}
153                }
154            },
155            "type": "dm.filament.do_not_disturb"
156        });
157
158        assert_matches!(
159            from_json_value::<AnyGlobalAccountDataEvent>(json),
160            Ok(AnyGlobalAccountDataEvent::DoNotDisturb(ev))
161        );
162        assert_eq!(
163            ev.content.rooms.keys().collect::<Vec<_>>(),
164            vec![&DoNotDisturbRoomKey::AllRooms]
165        );
166    }
167}