refactor(quark): port invite_delete, invite_fetch, invite_join

This commit is contained in:
Paul Makles
2024-04-07 17:47:59 +01:00
parent 569bd1d5e1
commit f6a565385e
13 changed files with 428 additions and 113 deletions

View File

@@ -307,6 +307,13 @@ impl Channel {
return Err(create_error!(AlreadyInGroup));
}
let config = config().await;
if recipients.len() >= config.features.limits.default.group_size {
return Err(create_error!(GroupTooLarge {
max: config.features.limits.default.group_size
}));
}
recipients.push(String::from(&user.id));
}
@@ -696,6 +703,9 @@ impl Channel {
pub async fn delete(&self, db: &Database) -> Result<()> {
let id = self.id().to_string();
EventV1::ChannelDelete { id: id.clone() }.p(id).await;
// TODO: missing functionality:
// - group invites
// - channels list / categories list on server
db.delete_channel(self).await
}
}

View File

@@ -1,6 +1,6 @@
use super::AbstractChannels;
use crate::{Channel, FieldsChannel, IntoDocumentPath, MongoDb, PartialChannel};
use bson::Document;
use crate::{AbstractServers, Channel, FieldsChannel, IntoDocumentPath, MongoDb, PartialChannel};
use bson::{Bson, Document};
use futures::StreamExt;
use revolt_permissions::OverrideField;
use revolt_result::Result;
@@ -188,6 +188,125 @@ impl AbstractChannels for MongoDb {
// Delete a channel
async fn delete_channel(&self, channel: &Channel) -> Result<()> {
let id = channel.id().to_string();
let server_id = match channel {
Channel::TextChannel { server, .. } | Channel::VoiceChannel { server, .. } => {
Some(server)
}
_ => None,
};
// Delete invites and unreads.
self.delete_associated_channel_objects(Bson::String(id.to_string()))
.await?;
// Delete messages.
self.delete_bulk_messages(doc! {
"channel": &id
})
.await?;
// Remove from server object.
if let Some(server) = server_id {
let server = self.fetch_server(server).await?;
let mut update = doc! {
"$pull": {
"channels": &id
}
};
if let Some(sys) = &server.system_messages {
let mut unset = doc! {};
if let Some(cid) = &sys.user_joined {
if &id == cid {
unset.insert("system_messages.user_joined", 1_i32);
}
}
if let Some(cid) = &sys.user_left {
if &id == cid {
unset.insert("system_messages.user_left", 1_i32);
}
}
if let Some(cid) = &sys.user_kicked {
if &id == cid {
unset.insert("system_messages.user_kicked", 1_i32);
}
}
if let Some(cid) = &sys.user_banned {
if &id == cid {
unset.insert("system_messages.user_banned", 1_i32);
}
}
if !unset.is_empty() {
update.insert("$unset", unset);
}
}
self.col::<Document>("servers")
.update_one(
doc! {
"_id": server.id
},
update,
None,
)
.await
.map_err(|_| create_database_error!("update_one", "servers"))?;
}
// Delete associated attachments
self.delete_many_attachments(doc! {
"object_id": &id
})
.await?;
// Delete the channel itself
query!(self, delete_one_by_id, COL, &channel.id()).map(|_| ())
}
}
impl MongoDb {
pub async fn delete_associated_channel_objects(&self, id: Bson) -> Result<()> {
// Delete all invites to these channels.
self.col::<Document>("channel_invites")
.delete_many(
doc! {
"channel": &id
},
None,
)
.await
.map_err(|_| create_database_error!("delete_many", "channel_invites"))?;
// Delete unread message objects on channels.
self.col::<Document>("channel_unreads")
.delete_many(
doc! {
"_id.channel": &id
},
None,
)
.await
.map_err(|_| create_database_error!("delete_many", "channel_unreads"))
.map(|_| ())?;
// update many attachments with parent id
// Delete all webhooks on this channel.
self.col::<Document>("webhooks")
.delete_many(
doc! {
"channel": &id
},
None,
)
.await
.map_err(|_| create_database_error!("delete_many", "webhooks"))
.map(|_| ())
}
}

View File

@@ -115,3 +115,21 @@ impl AbstractAttachments for MongoDb {
.map_err(|_| create_database_error!("update_one", COL))
}
}
impl MongoDb {
pub async fn delete_many_attachments(&self, projection: Document) -> Result<()> {
self.col::<Document>(COL)
.update_many(
projection,
doc! {
"$set": {
"deleted": true
}
},
None,
)
.await
.map(|_| ())
.map_err(|_| create_database_error!("update_many", COL))
}
}

View File

@@ -4,7 +4,9 @@ use mongodb::options::FindOptions;
use revolt_models::v0::MessageSort;
use revolt_result::Result;
use crate::{AppendMessage, Message, MessageQuery, MessageTimePeriod, MongoDb, PartialMessage};
use crate::{
AppendMessage, DocumentId, Message, MessageQuery, MessageTimePeriod, MongoDb, PartialMessage,
};
use super::AbstractMessages;
@@ -293,3 +295,57 @@ impl AbstractMessages for MongoDb {
.map_err(|_| create_database_error!("delete_many", COL))
}
}
impl MongoDb {
pub async fn delete_bulk_messages(&self, projection: Document) -> Result<()> {
let mut for_attachments = projection.clone();
for_attachments.insert(
"attachments",
doc! {
"$exists": 1_i32
},
);
// Check if there are any attachments we need to delete.
let message_ids_with_attachments = self
.find_with_options::<_, DocumentId>(
COL,
for_attachments,
FindOptions::builder()
.projection(doc! { "_id": 1_i32 })
.build(),
)
.await
.map_err(|_| create_database_error!("find_many", "attachments"))?
.into_iter()
.map(|x| x.id)
.collect::<Vec<String>>();
// If we found any, mark them as deleted.
if !message_ids_with_attachments.is_empty() {
self.col::<Document>("attachments")
.update_many(
doc! {
"message_id": {
"$in": message_ids_with_attachments
}
},
doc! {
"$set": {
"deleted": true
}
},
None,
)
.await
.map_err(|_| create_database_error!("update_many", "attachments"))?;
}
// And then delete said messages.
self.col::<Document>(COL)
.delete_many(projection, None)
.await
.map(|_| ())
.map_err(|_| create_database_error!("delete_many", COL))
}
}

View File

@@ -214,6 +214,8 @@ impl Server {
.p(self.id.clone())
.await;
// TODO: missing functionality
db.delete_server(&self.id).await
}