diff --git a/src/builder/execute_webhook.rs b/src/builder/execute_webhook.rs index 4265e9c38b8..09e361cf993 100644 --- a/src/builder/execute_webhook.rs +++ b/src/builder/execute_webhook.rs @@ -79,6 +79,8 @@ pub struct ExecuteWebhook { #[serde(skip)] thread_id: Option, + #[serde(skip)] + with_components: Option, } impl ExecuteWebhook { @@ -222,6 +224,9 @@ impl ExecuteWebhook { /// the webhook's `kind` field is set to [`WebhookType::Application`], or it was created by an /// application (and has kind [`WebhookType::Incoming`]). /// + /// If [`Self::with_components`] is set, non-interactive components can be used on non + /// application-owned webhooks. + /// /// [`WebhookType::Application`]: crate::model::webhook::WebhookType /// [`WebhookType::Incoming`]: crate::model::webhook::WebhookType pub fn components(mut self, components: Vec) -> Self { @@ -337,6 +342,12 @@ impl ExecuteWebhook { self.thread_name = Some(thread_name); self } + + /// Allows sending non interactive components on non application owned webhooks. + pub fn with_components(mut self, with_components: bool) -> Self { + self.with_components = Some(with_components); + self + } } #[cfg(feature = "http")] @@ -367,6 +378,11 @@ impl Builder for ExecuteWebhook { self.allowed_mentions.clone_from(&http.default_allowed_mentions); } - http.execute_webhook(ctx.0, self.thread_id, ctx.1, ctx.2, files, &self).await + if self.with_components.unwrap_or_default() { + http.execute_webhook_with_components(ctx.0, self.thread_id, ctx.1, ctx.2, files, &self) + .await + } else { + http.execute_webhook(ctx.0, self.thread_id, ctx.1, ctx.2, files, &self).await + } } } diff --git a/src/http/client.rs b/src/http/client.rs index 97d16bf1064..80d010c0847 100644 --- a/src/http/client.rs +++ b/src/http/client.rs @@ -2572,12 +2572,48 @@ impl Http { wait: bool, files: Vec, map: &impl serde::Serialize, + ) -> Result> { + self.execute_webhook_(webhook_id, thread_id, token, wait, files, map, false).await + } + + /// Same as [`Self::execute_webhook`] but allows sending non interactive components on non + /// app-owned webhooks. + /// + /// Refer to the [Discord docs] for more information on how this works. + /// + /// [Discord docs]: https://discord.com/developers/docs/resources/webhook#execute-webhook-query-string-params + pub async fn execute_webhook_with_components( + &self, + webhook_id: WebhookId, + thread_id: Option, + token: &str, + wait: bool, + files: Vec, + map: &impl serde::Serialize, + ) -> Result> { + self.execute_webhook_(webhook_id, thread_id, token, wait, files, map, true).await + } + + #[expect(clippy::too_many_arguments)] + async fn execute_webhook_( + &self, + webhook_id: WebhookId, + thread_id: Option, + token: &str, + wait: bool, + files: Vec, + map: &impl serde::Serialize, + with_components: bool, ) -> Result> { let mut params = vec![("wait", wait.to_string())]; if let Some(thread_id) = thread_id { params.push(("thread_id", thread_id.to_string())); } + if with_components { + params.push(("with_components", with_components.to_string())); + } + let mut request = Request { body: None, multipart: None,