From 7aad88ad3ff1e16963219be1f292e49cdc87b3e2 Mon Sep 17 00:00:00 2001 From: Paul <paulmakles@gmail.com> Date: Tue, 25 May 2021 17:23:47 +0100 Subject: [PATCH] =?UTF-8?q?Messages:=20Allow=20multiple=20attachments.=20(?= =?UTF-8?q?=E2=9A=A0=EF=B8=8F=20breaking=20change)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- set_version.sh | 2 +- src/database/entities/message.rs | 17 ++++++---- src/database/migrations/init.rs | 8 +++++ src/database/migrations/scripts.rs | 50 +++++++++++++++++++++++++++-- src/routes/channels/message_send.rs | 6 ++-- src/version.rs | 2 +- 6 files changed, 72 insertions(+), 13 deletions(-) diff --git a/set_version.sh b/set_version.sh index 44ddcfd..866f747 100755 --- a/set_version.sh +++ b/set_version.sh @@ -1,3 +1,3 @@ #!/bin/bash -export version=0.4.1-alpha.13 +export version=0.4.2-alpha.0 echo "pub const VERSION: &str = \"${version}\";" > src/version.rs diff --git a/src/database/entities/message.rs b/src/database/entities/message.rs index ccd9954..177c530 100644 --- a/src/database/entities/message.rs +++ b/src/database/entities/message.rs @@ -54,7 +54,7 @@ pub struct Message { pub content: Content, #[serde(skip_serializing_if = "Option::is_none")] - pub attachment: Option<File>, + pub attachments: Option<Vec<File>>, #[serde(skip_serializing_if = "Option::is_none")] pub edited: Option<DateTime>, #[serde(skip_serializing_if = "Option::is_none")] @@ -70,7 +70,7 @@ impl Message { author, content, - attachment: None, + attachments: None, edited: None, embeds: None, } @@ -275,8 +275,10 @@ impl Message { } pub async fn delete(&self) -> Result<()> { - if let Some(attachment) = &self.attachment { - attachment.delete().await?; + if let Some(attachments) = &self.attachments { + for attachment in attachments { + attachment.delete().await?; + } } get_collection("messages") @@ -299,11 +301,14 @@ impl Message { } .publish(channel); - if let Some(attachment) = &self.attachment { + if let Some(attachments) = &self.attachments { + let attachment_ids: Vec<String> = attachments.iter().map(|f| f.id.to_string()).collect(); get_collection("attachments") .update_one( doc! { - "_id": &attachment.id + "_id": { + "$in": attachment_ids + } }, doc! { "$set": { diff --git a/src/database/migrations/init.rs b/src/database/migrations/init.rs index fa1ab83..d089c0d 100644 --- a/src/database/migrations/init.rs +++ b/src/database/migrations/init.rs @@ -37,6 +37,14 @@ pub async fn create_database() { .await .expect("Failed to create attachments collection."); + db.create_collection("channel_unreads", None) + .await + .expect("Failed to create channel_unreads collection."); + + db.create_collection("user_settings", None) + .await + .expect("Failed to create user_settings collection."); + db.create_collection( "pubsub", CreateCollectionOptions::builder() diff --git a/src/database/migrations/scripts.rs b/src/database/migrations/scripts.rs index d123ab2..e085959 100644 --- a/src/database/migrations/scripts.rs +++ b/src/database/migrations/scripts.rs @@ -1,8 +1,9 @@ use crate::database::{get_collection, get_db}; use log::info; -use mongodb::bson::{doc, from_document}; +use futures::StreamExt; use serde::{Deserialize, Serialize}; +use mongodb::{bson::{doc, from_document}, options::FindOptions}; #[derive(Serialize, Deserialize)] struct MigrationInfo { @@ -10,7 +11,7 @@ struct MigrationInfo { revision: i32, } -pub const LATEST_REVISION: i32 = 3; +pub const LATEST_REVISION: i32 = 4; pub async fn migrate_database() { let migrations = get_collection("migrations"); @@ -87,6 +88,51 @@ pub async fn run_migrations(revision: i32) -> i32 { .expect("Failed to create servers collection."); } + if revision <= 3 { + info!("Running migration [revision 3 / 2021-05-25]: Support multiple file uploads, add channel_unreads and user_settings."); + + let messages = get_collection("messages"); + let mut cursor = messages.find( + doc! { + "attachment": { + "$exists": 1 + } + }, + FindOptions::builder() + .projection(doc! { + "_id": 1, + "attachments": [ "$attachment" ] + }) + .build() + ) + .await + .expect("Failed to fetch messages."); + + while let Some(result) = cursor.next().await { + let doc = result.unwrap(); + let id = doc.get_str("_id").unwrap(); + let attachments = doc.get_array("attachments").unwrap(); + + messages.update_one( + doc! { "_id": id }, + doc! { "$unset": { "attachment": 1 }, "$set": { "attachments": attachments } }, + None + ) + .await + .unwrap(); + } + + get_db() + .create_collection("channel_unreads", None) + .await + .expect("Failed to create channel_unreads collection."); + + get_db() + .create_collection("user_settings", None) + .await + .expect("Failed to create user_settings collection."); + } + // Reminder to update LATEST_REVISION when adding new migrations. LATEST_REVISION } diff --git a/src/routes/channels/message_send.rs b/src/routes/channels/message_send.rs index 3f2e439..38c529d 100644 --- a/src/routes/channels/message_send.rs +++ b/src/routes/channels/message_send.rs @@ -58,8 +58,8 @@ pub async fn req(user: User, target: Ref, message: Json<Data>) -> Result<JsonVal } let id = Ulid::new().to_string(); - let attachment = if let Some(attachment_id) = &message.attachment { - Some(File::find_and_use(attachment_id, "attachments", "message", &id).await?) + let attachments = if let Some(attachment_id) = &message.attachment { + Some(vec![ File::find_and_use(attachment_id, "attachments", "message", &id).await? ]) } else { None }; @@ -70,7 +70,7 @@ pub async fn req(user: User, target: Ref, message: Json<Data>) -> Result<JsonVal author: user.id, content: Content::Text(message.content.clone()), - attachment, + attachments, nonce: Some(message.nonce.clone()), edited: None, embeds: None, diff --git a/src/version.rs b/src/version.rs index 3ea1721..cc9aa59 100644 --- a/src/version.rs +++ b/src/version.rs @@ -1 +1 @@ -pub const VERSION: &str = "0.4.1-alpha.13"; +pub const VERSION: &str = "0.4.2-alpha.0"; -- GitLab