feat(messages): implement message editing

This commit is contained in:
Paul Makles
2022-02-10 13:33:13 +00:00
parent a4cbbfea51
commit 57d114fee9
5 changed files with 91 additions and 26 deletions

1
Cargo.lock generated
View File

@@ -2943,6 +2943,7 @@ dependencies = [
"async-std", "async-std",
"async-trait", "async-trait",
"bitfield", "bitfield",
"bson 2.1.0",
"futures", "futures",
"impl_ops", "impl_ops",
"lazy_static", "lazy_static",

View File

@@ -1,7 +1,12 @@
use revolt_quark::{EmptyResponse, Result}; use revolt_quark::{
bson::DateTime,
models::message::{PartialMessage, SendableEmbed},
models::{message::Content, Message, User},
types::january::Embed,
Db, Error, Ref, Result,
};
use chrono::Utc; use chrono::Utc;
use mongodb::bson::{doc, to_document, Bson, Document};
use rocket::serde::json::Json; use rocket::serde::json::Json;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use validator::Validate; use validator::Validate;
@@ -10,15 +15,65 @@ use validator::Validate;
pub struct Data { pub struct Data {
#[validate(length(min = 1, max = 2000))] #[validate(length(min = 1, max = 2000))]
content: Option<String>, content: Option<String>,
// #[validate(length(min = 0, max = 10))] #[validate(length(min = 0, max = 10))]
// embeds: Option<Vec<SendableEmbed>> embeds: Option<Vec<SendableEmbed>>,
} }
#[patch("/<target>/messages/<msg>", data = "<edit>")] #[patch("/<target>/messages/<msg>", data = "<edit>")]
pub async fn req( pub async fn req(
/*user: UserRef, target: Ref, msg: Ref,*/ target: String, db: &Db,
msg: String, user: User,
target: String,
msg: Ref,
edit: Json<Data>, edit: Json<Data>,
) -> Result<EmptyResponse> { ) -> Result<Json<Message>> {
todo!() let edit = edit.into_inner();
edit.validate()
.map_err(|error| Error::FailedValidation { error })?;
let mut message = msg.as_message(db).await?;
if message.channel != target {
return Err(Error::NotFound);
}
if message.author != user.id {
return Err(Error::CannotEditMessage);
}
message.edited = Some(DateTime::from_chrono(Utc::now()));
let mut partial = PartialMessage {
edited: message.edited,
..Default::default()
};
// 1. Handle content update
if let Some(content) = edit.content {
message.content = Content::Text(content);
partial.content = Some(message.content.clone());
}
// 2. Clear any auto generated embeds
let mut new_embeds: Vec<Embed> = vec![];
if let Some(embeds) = &message.embeds {
for embed in embeds {
if let Embed::Text(embed) = embed {
new_embeds.push(Embed::Text(embed.clone()))
}
}
}
// 3. Replace if we are given new embeds
if let Some(embeds) = edit.embeds {
new_embeds.clear();
for embed in embeds {
new_embeds.push(embed.clone().into_embed(db, message.id.clone()).await?);
}
}
message.embeds = Some(new_embeds);
partial.embeds = message.embeds.clone();
db.update_message(&message.id, &partial, vec![]).await?;
Ok(Json(message))
} }

View File

@@ -3,8 +3,7 @@ use revolt_quark::{
message::{BulkMessageResponse, MessageSort}, message::{BulkMessageResponse, MessageSort},
User, User,
}, },
perms, perms, Db, Error, Ref, Result,
Db, Error, Ref, Result,
}; };
use rocket::serde::json::Json; use rocket::serde::json::Json;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
@@ -66,5 +65,7 @@ pub async fn req(
.fetch_messages(channel.id(), limit, before, after, sort, nearby) .fetch_messages(channel.id(), limit, before, after, sort, nearby)
.await?; .await?;
BulkMessageResponse::transform(db, &channel, messages, include_users).await.map(Json) BulkMessageResponse::transform(db, &channel, messages, include_users)
.await
.map(Json)
} }

View File

@@ -1,7 +1,5 @@
use revolt_quark::{Error, Result}; use revolt_quark::{models::User, Ref, Result};
use futures::StreamExt;
use mongodb::bson::{doc, from_document};
use rocket::serde::json::{Json, Value}; use rocket::serde::json::{Json, Value};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
@@ -10,10 +8,7 @@ pub struct Options {
ids: Vec<String>, ids: Vec<String>,
} }
#[post("/<target>/messages/stale", data = "<data>")] #[post("/<_target>/messages/stale", data = "<_data>")]
pub async fn req( pub async fn req(_user: User, _target: Ref, _data: Json<Options>) -> Result<Value> {
/*user: UserRef, target: Ref,*/ target: String, unimplemented!()
data: Json<Options>,
) -> Result<Value> {
todo!()
} }

View File

@@ -1,4 +1,10 @@
use revolt_quark::{models::{User, message::{MessageSort, BulkMessageResponse}}, Ref, Error, Result, Db, perms}; use revolt_quark::{
models::{
message::{BulkMessageResponse, MessageSort},
User,
},
perms, Db, Error, Ref, Result,
};
use rocket::serde::json::Json; use rocket::serde::json::Json;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
@@ -21,7 +27,12 @@ pub struct Options {
} }
#[post("/<target>/search", data = "<options>")] #[post("/<target>/search", data = "<options>")]
pub async fn req(db: &Db, user: User, target: Ref, options: Json<Options>) -> Result<Json<BulkMessageResponse>> { pub async fn req(
db: &Db,
user: User,
target: Ref,
options: Json<Options>,
) -> Result<Json<BulkMessageResponse>> {
let options = options.into_inner(); let options = options.into_inner();
options options
.validate() .validate()
@@ -43,12 +54,14 @@ pub async fn req(db: &Db, user: User, target: Ref, options: Json<Options>) -> Re
before, before,
after, after,
sort, sort,
include_users include_users,
} = options; } = options;
let messages = db let messages = db
.search_messages(channel.id(), &query, limit, before, after, sort) .search_messages(channel.id(), &query, limit, before, after, sort)
.await?; .await?;
BulkMessageResponse::transform(db, &channel, messages, include_users).await.map(Json) BulkMessageResponse::transform(db, &channel, messages, include_users)
.await
.map(Json)
} }