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::{canonical_json::assert_to_canonical_json_eq, owned_room_id};
91    use serde_json::{from_value as from_json_value, json};
92
93    use super::DoNotDisturbEventContent;
94    use crate::{AnyGlobalAccountDataEvent, do_not_disturb::DoNotDisturbRoomKey};
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        assert_to_canonical_json_eq!(
102            do_not_disturb_room_list,
103            json!({
104                "rooms": {
105                    "!foo:bar.baz": {}
106                },
107            }),
108        );
109    }
110
111    #[test]
112    fn serialization_with_all_rooms() {
113        let do_not_disturb_room_list = DoNotDisturbEventContent::new(BTreeMap::from([(
114            DoNotDisturbRoomKey::AllRooms,
115            Default::default(),
116        )]));
117
118        assert_to_canonical_json_eq!(
119            do_not_disturb_room_list,
120            json!({
121                "rooms": {
122                    "*": {}
123                },
124            }),
125        );
126    }
127
128    #[test]
129    fn deserialization_with_single_room() {
130        let json = json!({
131            "content": {
132                "rooms": {
133                    "!foo:bar.baz": {}
134                }
135            },
136            "type": "dm.filament.do_not_disturb"
137        });
138
139        assert_matches!(
140            from_json_value::<AnyGlobalAccountDataEvent>(json),
141            Ok(AnyGlobalAccountDataEvent::DoNotDisturb(ev))
142        );
143        assert_eq!(
144            ev.content.rooms.keys().collect::<Vec<_>>(),
145            vec![&DoNotDisturbRoomKey::SingleRoom(owned_room_id!("!foo:bar.baz"))]
146        );
147    }
148
149    #[test]
150    fn deserialization_with_all_room() {
151        let json = json!({
152            "content": {
153                "rooms": {
154                    "*": {}
155                }
156            },
157            "type": "dm.filament.do_not_disturb"
158        });
159
160        assert_matches!(
161            from_json_value::<AnyGlobalAccountDataEvent>(json),
162            Ok(AnyGlobalAccountDataEvent::DoNotDisturb(ev))
163        );
164        assert_eq!(
165            ev.content.rooms.keys().collect::<Vec<_>>(),
166            vec![&DoNotDisturbRoomKey::AllRooms]
167        );
168    }
169}