use revolt_database::{ util::{idempotency::IdempotencyKey, reference::Reference}, Database, Message, }; use revolt_models::v0; use revolt_permissions::{ChannelPermission, PermissionValue}; use revolt_result::{create_error, Result}; use rocket::{serde::json::Json, State}; use validator::Validate; /// # Executes a webhook /// /// Executes a webhook and sends a message #[openapi(tag = "Webhooks")] #[post("//", data = "")] pub async fn webhook_execute( db: &State, webhook_id: Reference, token: String, data: Json, idempotency: IdempotencyKey, ) -> Result> { let data = data.into_inner(); data.validate().map_err(|error| { create_error!(FailedValidation { error: error.to_string() }) })?; let webhook = webhook_id.as_webhook(db).await?; webhook.assert_token(&token)?; let permissions: PermissionValue = webhook.permissions.into(); permissions.throw_if_lacking_channel_permission(ChannelPermission::SendMessage)?; if data.attachments.as_ref().map_or(false, |v| !v.is_empty()) { permissions.throw_if_lacking_channel_permission(ChannelPermission::UploadFiles)?; } if data.embeds.as_ref().map_or(false, |v| !v.is_empty()) { permissions.throw_if_lacking_channel_permission(ChannelPermission::SendEmbeds)?; } if data.masquerade.is_some() { permissions.throw_if_lacking_channel_permission(ChannelPermission::Masquerade)?; } if data.interactions.is_some() { permissions.throw_if_lacking_channel_permission(ChannelPermission::React)?; } let channel = db.fetch_channel(&webhook.channel_id).await?; Ok(Json( Message::create_from_api( db, channel, data, v0::MessageAuthor::Webhook(&webhook.into()), idempotency, true, true, ) .await? .into(), )) }