1use std::collections::BTreeMap;
8
9use ruma_common::{OwnedRoomId, OwnedServerName, OwnedUserId};
10use ruma_macros::{EventContent, StringEnum};
11use serde::{Deserialize, Serialize};
12
13use crate::PrivOwnedStr;
14
15#[derive(Clone, StringEnum)]
17#[cfg_attr(not(ruma_unstable_exhaustive_types), non_exhaustive)]
18#[ruma_enum(rename_all = "snake_case")]
19pub enum UserPresenceSharingState {
20 Allow,
22
23 Deny,
25
26 #[doc(hidden)]
27 _Custom(PrivOwnedStr),
28}
29
30#[derive(Clone, StringEnum)]
32#[cfg_attr(not(ruma_unstable_exhaustive_types), non_exhaustive)]
33#[ruma_enum(rename_all = "snake_case")]
34pub enum RoomPresenceSharingState {
35 Allow,
37
38 #[doc(hidden)]
39 _Custom(PrivOwnedStr),
40}
41
42#[derive(Clone, StringEnum)]
44#[cfg_attr(not(ruma_unstable_exhaustive_types), non_exhaustive)]
45#[ruma_enum(rename_all = "snake_case")]
46pub enum ServerPresenceSharingState {
47 Deny,
49
50 #[doc(hidden)]
51 _Custom(PrivOwnedStr),
52}
53
54#[derive(Clone, Default, Debug, Deserialize, Serialize, EventContent)]
60#[cfg_attr(not(ruma_unstable_exhaustive_types), non_exhaustive)]
61#[ruma_event(type = "org.continuwuity.presence_v2.msc4495.presence.sharing", kind = GlobalAccountData)]
62pub struct PresenceSharingEventContent {
63 #[serde(default, skip_serializing_if = "std::ops::Not::not")]
65 pub share_locally: bool,
66
67 #[serde(default, skip_serializing_if = "BTreeMap::is_empty")]
69 pub users: BTreeMap<OwnedUserId, UserPresenceSharingState>,
70
71 #[serde(default, skip_serializing_if = "BTreeMap::is_empty")]
75 pub rooms: BTreeMap<OwnedRoomId, RoomPresenceSharingState>,
76
77 #[serde(default, skip_serializing_if = "BTreeMap::is_empty")]
79 pub servers: BTreeMap<OwnedServerName, ServerPresenceSharingState>,
80}
81
82impl PresenceSharingEventContent {
83 pub fn new(
85 share_locally: bool,
86 users: BTreeMap<OwnedUserId, UserPresenceSharingState>,
87 rooms: BTreeMap<OwnedRoomId, RoomPresenceSharingState>,
88 servers: BTreeMap<OwnedServerName, ServerPresenceSharingState>,
89 ) -> Self {
90 Self { share_locally, users, rooms, servers }
91 }
92}
93
94#[cfg(test)]
95mod tests {
96 use ruma_common::{
97 canonical_json::assert_to_canonical_json_eq, owned_room_id, owned_server_name,
98 owned_user_id, room_id, server_name, user_id,
99 };
100 use serde_json::{from_value as from_json_value, json};
101
102 use crate::presence::sharing::{
103 PresenceSharingEventContent, RoomPresenceSharingState, ServerPresenceSharingState,
104 UserPresenceSharingState,
105 };
106
107 #[test]
108 fn serialization() {
109 let content = PresenceSharingEventContent {
110 share_locally: true,
111 users: [
112 (owned_user_id!("@alice:example.com"), UserPresenceSharingState::Allow),
113 (owned_user_id!("@mallory:example.com"), UserPresenceSharingState::Deny),
114 ]
115 .into(),
116 rooms: [(owned_room_id!("!family-group-chat"), RoomPresenceSharingState::Allow)].into(),
117 servers: [(owned_server_name!("matrix.org"), ServerPresenceSharingState::Deny)].into(),
118 };
119
120 assert_to_canonical_json_eq!(
121 content,
122 json!({
123 "share_locally": true,
124 "users": {
125 "@alice:example.com": "allow",
126 "@mallory:example.com": "deny",
127 },
128 "rooms": {
129 "!family-group-chat": "allow",
130 },
131 "servers": {
132 "matrix.org": "deny",
133 },
134 }),
135 );
136 }
137
138 #[test]
139 fn deserialization() {
140 let json_data = json!({
141 "share_locally": true,
142 "users": {
143 "@alice:example.com": "allow",
144 "@mallory:example.com": "deny",
145 },
146 "rooms": {
147 "!family-group-chat": "allow",
148 },
149 "servers": {
150 "matrix.org": "deny",
151 }
152 });
153
154 let content = from_json_value::<PresenceSharingEventContent>(json_data).unwrap();
155
156 assert!(content.share_locally);
157 assert_eq!(content.users.len(), 2);
158 assert_eq!(
159 content.users.get(user_id!("@alice:example.com")).unwrap(),
160 &UserPresenceSharingState::Allow
161 );
162 assert_eq!(
163 content.users.get(user_id!("@mallory:example.com")).unwrap(),
164 &UserPresenceSharingState::Deny
165 );
166 assert_eq!(content.rooms.len(), 1);
167 assert_eq!(
168 content.rooms.get(room_id!("!family-group-chat")).unwrap(),
169 &RoomPresenceSharingState::Allow
170 );
171 assert_eq!(content.servers.len(), 1);
172 assert_eq!(
173 content.servers.get(server_name!("matrix.org")).unwrap(),
174 &ServerPresenceSharingState::Deny
175 );
176 }
177}