mirror of
https://github.com/stoatchat/stoatchat.git
synced 2026-07-14 05:26:59 +00:00
feat: Add webhook endpoints for editing and deleting messages (#682)
* feat: ErrorType.CannotDeleteMessage, needed later Signed-off-by: Taureon <taureon@noreply.codeberg.org> * feat: webhook edit/delete message endpoints Signed-off-by: Taureon <taureon@noreply.codeberg.org> * lol, lmao even Signed-off-by: Taureon <taureon@noreply.codeberg.org> * fix contradictory comment Signed-off-by: Taureon <taureon@noreply.codeberg.org> --------- Signed-off-by: Taureon <taureon@noreply.codeberg.org> Co-authored-by: Taureon <taureon@noreply.codeberg.org>
This commit is contained in:
@@ -24,6 +24,7 @@ impl IntoResponse for Error {
|
||||
ErrorType::UnknownChannel => StatusCode::NOT_FOUND,
|
||||
ErrorType::UnknownMessage => StatusCode::NOT_FOUND,
|
||||
ErrorType::UnknownAttachment => StatusCode::BAD_REQUEST,
|
||||
ErrorType::CannotDeleteMessage => StatusCode::FORBIDDEN,
|
||||
ErrorType::CannotEditMessage => StatusCode::FORBIDDEN,
|
||||
ErrorType::CannotJoinCall => StatusCode::BAD_REQUEST,
|
||||
ErrorType::TooManyAttachments { .. } => StatusCode::BAD_REQUEST,
|
||||
|
||||
@@ -78,6 +78,7 @@ pub enum ErrorType {
|
||||
UnknownChannel,
|
||||
UnknownAttachment,
|
||||
UnknownMessage,
|
||||
CannotDeleteMessage,
|
||||
CannotEditMessage,
|
||||
CannotJoinCall,
|
||||
TooManyAttachments {
|
||||
|
||||
@@ -30,6 +30,7 @@ impl<'r> Responder<'r, 'static> for Error {
|
||||
ErrorType::UnknownChannel => Status::NotFound,
|
||||
ErrorType::UnknownMessage => Status::NotFound,
|
||||
ErrorType::UnknownAttachment => Status::BadRequest,
|
||||
ErrorType::CannotDeleteMessage => Status::Forbidden,
|
||||
ErrorType::CannotEditMessage => Status::Forbidden,
|
||||
ErrorType::CannotJoinCall => Status::BadRequest,
|
||||
ErrorType::TooManyAttachments { .. } => Status::BadRequest,
|
||||
|
||||
@@ -1,19 +1,23 @@
|
||||
use rocket::Route;
|
||||
use revolt_rocket_okapi::revolt_okapi::openapi3::OpenApi;
|
||||
use rocket::Route;
|
||||
|
||||
mod webhook_delete;
|
||||
mod webhook_delete_message;
|
||||
mod webhook_delete_token;
|
||||
mod webhook_edit;
|
||||
mod webhook_edit_message;
|
||||
mod webhook_edit_token;
|
||||
mod webhook_execute;
|
||||
mod webhook_fetch_token;
|
||||
mod webhook_fetch;
|
||||
mod webhook_execute_github;
|
||||
mod webhook_fetch;
|
||||
mod webhook_fetch_token;
|
||||
|
||||
pub fn routes() -> (Vec<Route>, OpenApi) {
|
||||
openapi_get_routes_spec![
|
||||
webhook_delete_message::webhook_delete_message,
|
||||
webhook_delete_token::webhook_delete_token,
|
||||
webhook_delete::webhook_delete,
|
||||
webhook_edit_message::webhook_edit_message,
|
||||
webhook_edit_token::webhook_edit_token,
|
||||
webhook_edit::webhook_edit,
|
||||
webhook_execute_github::webhook_execute_github,
|
||||
|
||||
27
crates/delta/src/routes/webhooks/webhook_delete_message.rs
Normal file
27
crates/delta/src/routes/webhooks/webhook_delete_message.rs
Normal file
@@ -0,0 +1,27 @@
|
||||
use revolt_database::{util::reference::Reference, Database};
|
||||
use revolt_result::{create_error, Result};
|
||||
use rocket::State;
|
||||
use rocket_empty::EmptyResponse;
|
||||
|
||||
/// # Deletes a webhook message
|
||||
///
|
||||
/// Deletes a message sent by a webhook
|
||||
#[openapi(tag = "Webhooks")]
|
||||
#[delete("/<webhook_id>/<token>/<message_id>")]
|
||||
pub async fn webhook_delete_message(
|
||||
db: &State<Database>,
|
||||
webhook_id: Reference<'_>,
|
||||
token: String,
|
||||
message_id: Reference<'_>,
|
||||
) -> Result<EmptyResponse> {
|
||||
let webhook = webhook_id.as_webhook(db).await?;
|
||||
webhook.assert_token(&token)?;
|
||||
|
||||
let message = message_id.as_message(db).await?;
|
||||
|
||||
if message.author != webhook.id {
|
||||
return Err(create_error!(CannotDeleteMessage));
|
||||
}
|
||||
|
||||
message.delete(db).await.map(|_| EmptyResponse)
|
||||
}
|
||||
84
crates/delta/src/routes/webhooks/webhook_edit_message.rs
Normal file
84
crates/delta/src/routes/webhooks/webhook_edit_message.rs
Normal file
@@ -0,0 +1,84 @@
|
||||
use iso8601_timestamp::Timestamp;
|
||||
use revolt_config::config;
|
||||
use revolt_database::{
|
||||
tasks::process_embeds::queue, util::reference::Reference, Database, Message, PartialMessage,
|
||||
};
|
||||
use revolt_models::v0::{self, DataEditMessage, Embed};
|
||||
use revolt_models::validator::Validate;
|
||||
use revolt_result::{create_error, Result};
|
||||
use rocket::{serde::json::Json, State};
|
||||
|
||||
/// # Edits a webhook message
|
||||
///
|
||||
/// Edits a message sent by a webhook
|
||||
#[openapi(tag = "Webhooks")]
|
||||
#[patch("/<webhook_id>/<token>/<message_id>", data = "<data>")]
|
||||
pub async fn webhook_edit_message(
|
||||
db: &State<Database>,
|
||||
webhook_id: Reference<'_>,
|
||||
token: String,
|
||||
message_id: Reference<'_>,
|
||||
data: Json<DataEditMessage>,
|
||||
) -> Result<Json<v0::Message>> {
|
||||
let edit = data.into_inner();
|
||||
edit.validate().map_err(|error| {
|
||||
create_error!(FailedValidation {
|
||||
error: error.to_string()
|
||||
})
|
||||
})?;
|
||||
|
||||
Message::validate_sum(
|
||||
&edit.content,
|
||||
edit.embeds.as_deref().unwrap_or_default(),
|
||||
config().await.features.limits.default.message_length,
|
||||
)?;
|
||||
|
||||
let webhook = webhook_id.as_webhook(db).await?;
|
||||
webhook.assert_token(&token)?;
|
||||
|
||||
let mut message = message_id.as_message(db).await?;
|
||||
if message.author != webhook.id {
|
||||
return Err(create_error!(CannotEditMessage));
|
||||
}
|
||||
|
||||
message.edited = Some(Timestamp::now_utc());
|
||||
let mut partial = PartialMessage {
|
||||
edited: message.edited,
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
// 1. Handle content update
|
||||
if let Some(content) = &edit.content {
|
||||
partial.content = Some(content.clone());
|
||||
}
|
||||
|
||||
// 2. Clear any auto generated embeds
|
||||
let mut new_embeds = 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(message.create_embed(db, embed).await?);
|
||||
}
|
||||
}
|
||||
|
||||
partial.embeds = Some(new_embeds);
|
||||
|
||||
message.update(db, partial, vec![]).await?;
|
||||
|
||||
// Queue up a task for processing embeds
|
||||
if let Some(content) = edit.content {
|
||||
queue(message.channel.to_string(), message.id.to_string(), content).await;
|
||||
}
|
||||
|
||||
Ok(Json(message.into_model(None, None)))
|
||||
}
|
||||
Reference in New Issue
Block a user