revolt_database/models/channels/ops/
mongodb.rs1use super::AbstractChannels;
2use crate::{AbstractServers, Channel, FieldsChannel, IntoDocumentPath, MongoDb, PartialChannel};
3use bson::{Bson, Document};
4use futures::StreamExt;
5use revolt_permissions::OverrideField;
6use revolt_result::Result;
7
8static COL: &str = "channels";
9
10#[async_trait]
11impl AbstractChannels for MongoDb {
12 async fn insert_channel(&self, channel: &Channel) -> Result<()> {
14 query!(self, insert_one, COL, &channel).map(|_| ())
15 }
16
17 async fn fetch_channel(&self, channel_id: &str) -> Result<Channel> {
19 query!(self, find_one_by_id, COL, channel_id)?.ok_or_else(|| create_error!(NotFound))
20 }
21
22 async fn fetch_channels<'a>(&self, ids: &'a [String]) -> Result<Vec<Channel>> {
24 Ok(self
25 .col::<Channel>(COL)
26 .find(doc! {
27 "_id": {
28 "$in": ids
29 }
30 })
31 .await
32 .map_err(|_| create_database_error!("fetch", "channels"))?
33 .filter_map(|s| async {
34 if cfg!(debug_assertions) {
35 Some(s.unwrap())
36 } else {
37 s.ok()
38 }
39 })
40 .collect()
41 .await)
42 }
43
44 async fn find_direct_messages(&self, user_id: &str) -> Result<Vec<Channel>> {
46 query!(
47 self,
48 find,
49 COL,
50 doc! {
51 "$or": [
52 {
53 "$or": [
54 {
55 "channel_type": "DirectMessage"
56 },
57 {
58 "channel_type": "Group"
59 }
60 ],
61 "recipients": user_id
62 },
63 {
64 "channel_type": "SavedMessages",
65 "user": user_id
66 }
67 ]
68 }
69 )
70 }
71
72 async fn find_saved_messages_channel(&self, user_id: &str) -> Result<Channel> {
74 query!(
75 self,
76 find_one,
77 COL,
78 doc! {
79 "channel_type": "SavedMessages",
80 "user": user_id
81 }
82 )?
83 .ok_or_else(|| create_error!(InternalError))
84 }
85
86 async fn find_direct_message_channel(&self, user_a: &str, user_b: &str) -> Result<Channel> {
88 let doc = match (user_a, user_b) {
89 self_user if self_user.0 == self_user.1 => {
90 doc! {
91 "channel_type": "SavedMessages",
92 "user": self_user.0
93 }
94 }
95 users => {
96 doc! {
97 "channel_type": "DirectMessage",
98 "recipients": {
99 "$all": [ users.0, users.1 ]
100 }
101 }
102 }
103 };
104 query!(self, find_one, COL, doc)?.ok_or_else(|| create_error!(NotFound))
105 }
106
107 async fn add_user_to_group(&self, channel: &str, user: &str) -> Result<()> {
109 self.col::<Document>(COL)
110 .update_one(
111 doc! {
112 "_id": channel
113 },
114 doc! {
115 "$push": {
116 "recipients": user
117 }
118 },
119 )
120 .await
121 .map(|_| ())
122 .map_err(|_| create_database_error!("update_one", "channel"))
123 }
124
125 async fn set_channel_role_permission(
127 &self,
128 channel: &str,
129 role: &str,
130 permissions: OverrideField,
131 ) -> Result<()> {
132 self.col::<Document>(COL)
133 .update_one(
134 doc! { "_id": channel },
135 doc! {
136 "$set": {
137 "role_permissions.".to_owned() + role: permissions
138 }
139 },
140 )
141 .await
142 .map(|_| ())
143 .map_err(|_| create_database_error!("update_one", "channel"))
144 }
145
146 async fn update_channel(
148 &self,
149 id: &str,
150 channel: &PartialChannel,
151 remove: Vec<FieldsChannel>,
152 ) -> Result<()> {
153 query!(
154 self,
155 update_one_by_id,
156 COL,
157 id,
158 channel,
159 remove.iter().map(|x| x as &dyn IntoDocumentPath).collect(),
160 None
161 )
162 .map(|_| ())
163 }
164
165 async fn remove_user_from_group(&self, channel: &str, user: &str) -> Result<()> {
167 self.col::<Document>(COL)
168 .update_one(
169 doc! {
170 "_id": channel
171 },
172 doc! {
173 "$pull": {
174 "recipients": user
175 }
176 },
177 )
178 .await
179 .map(|_| ())
180 .map_err(|_| create_database_error!("update_one", "channels"))
181 }
182
183 async fn delete_channel(&self, channel: &Channel) -> Result<()> {
185 let id = channel.id().to_string();
186 let server_id = match channel {
187 Channel::TextChannel { server, .. } => {
188 Some(server)
189 }
190 _ => None,
191 };
192
193 self.delete_associated_channel_objects(Bson::String(id.to_string()))
195 .await?;
196
197 self.delete_bulk_messages(doc! {
199 "channel": &id
200 })
201 .await?;
202
203 if let Some(server) = server_id {
205 let server = self.fetch_server(server).await?;
206 let mut update = doc! {
207 "$pull": {
208 "channels": &id
209 }
210 };
211
212 if let Some(sys) = &server.system_messages {
213 let mut unset = doc! {};
214
215 if let Some(cid) = &sys.user_joined {
216 if &id == cid {
217 unset.insert("system_messages.user_joined", 1_i32);
218 }
219 }
220
221 if let Some(cid) = &sys.user_left {
222 if &id == cid {
223 unset.insert("system_messages.user_left", 1_i32);
224 }
225 }
226
227 if let Some(cid) = &sys.user_kicked {
228 if &id == cid {
229 unset.insert("system_messages.user_kicked", 1_i32);
230 }
231 }
232
233 if let Some(cid) = &sys.user_banned {
234 if &id == cid {
235 unset.insert("system_messages.user_banned", 1_i32);
236 }
237 }
238
239 if !unset.is_empty() {
240 update.insert("$unset", unset);
241 }
242 }
243
244 self.col::<Document>("servers")
245 .update_one(
246 doc! {
247 "_id": server.id
248 },
249 update,
250 )
251 .await
252 .map_err(|_| create_database_error!("update_one", "servers"))?;
253 }
254
255 self.delete_many_attachments(doc! {
257 "used_for.id": &id
258 })
259 .await?;
260
261 query!(self, delete_one_by_id, COL, channel.id()).map(|_| ())
263 }
264}
265
266impl MongoDb {
267 pub async fn delete_associated_channel_objects(&self, id: Bson) -> Result<()> {
268 self.col::<Document>("channel_invites")
270 .delete_many(doc! {
271 "channel": &id
272 })
273 .await
274 .map_err(|_| create_database_error!("delete_many", "channel_invites"))?;
275
276 self.col::<Document>("channel_unreads")
278 .delete_many(doc! {
279 "_id.channel": &id
280 })
281 .await
282 .map_err(|_| create_database_error!("delete_many", "channel_unreads"))
283 .map(|_| ())?;
284
285 self.col::<Document>("webhooks")
289 .delete_many(doc! {
290 "channel": &id
291 })
292 .await
293 .map_err(|_| create_database_error!("delete_many", "webhooks"))
294 .map(|_| ())
295 }
296}