///|
fn validate_webhook_name(name : String) -> Unit raise DiscordHttpError {
validate_length("webhook name", Some(name), min=1, max=80)
}
///|
fn validate_execute_webhook(
content : String?,
embeds : Array[@model.Embed]?,
components : Array[@model.Component]?,
files : Array[FileUpload]?,
poll : @model.PollCreateRequest?,
) -> Unit raise DiscordHttpError {
validate_content(content)
if content is None &&
embeds is None &&
components is None &&
files is None &&
poll is None {
raise Validation(
message="one of content/embeds/components/files/poll is required",
)
}
}
///|
/// Create an incoming webhook for a channel.
pub async fn Client::create_webhook(
self : Client,
channel_id : @model.ChannelId,
name : String,
avatar? : String,
audit_reason? : String,
) -> @model.Webhook raise DiscordHttpError {
validate_webhook_name(name)
let body = @model.ObjBuilder()
.field("name", name)
.opt("avatar", avatar)
.build()
decode(self.request(CreateWebhook(channel_id~), body~, audit_reason?))
}
///|
/// List the webhooks created for a channel.
pub async fn Client::get_channel_webhooks(
self : Client,
channel_id : @model.ChannelId,
) -> Array[@model.Webhook] raise DiscordHttpError {
decode(self.request(GetChannelWebhooks(channel_id~)))
}
///|
/// List the webhooks belonging to a guild.
pub async fn Client::get_guild_webhooks(
self : Client,
guild_id : @model.GuildId,
) -> Array[@model.Webhook] raise DiscordHttpError {
decode(self.request(GetGuildWebhooks(guild_id~)))
}
///|
/// Fetch a webhook using bot authentication.
pub async fn Client::get_webhook(
self : Client,
webhook_id : @model.WebhookId,
) -> @model.Webhook raise DiscordHttpError {
decode(self.request(GetWebhook(webhook_id~)))
}
///|
/// Modify a webhook using bot authentication.
pub async fn Client::modify_webhook(
self : Client,
webhook_id : @model.WebhookId,
name? : String,
avatar? : String,
clear_avatar? : Bool = false,
channel_id? : @model.ChannelId,
audit_reason? : String,
) -> @model.Webhook raise DiscordHttpError {
if name is Some(value) {
validate_webhook_name(value)
}
let body = @model.ObjBuilder()
.opt("name", name)
.und("avatar", patch_nullable("avatar", avatar, clear_avatar))
.opt("channel_id", channel_id)
.build()
decode(self.request(ModifyWebhook(webhook_id~), body~, audit_reason?))
}
///|
/// Delete a webhook using bot authentication.
pub async fn Client::delete_webhook(
self : Client,
webhook_id : @model.WebhookId,
audit_reason? : String,
) -> Unit raise DiscordHttpError {
self.request(DeleteWebhook(webhook_id~), audit_reason?) |> ignore
}
///|
fn modify_webhook_with_token_body(
name : String?,
avatar : String?,
clear_avatar : Bool,
) -> Json raise DiscordHttpError {
if name is Some(value) {
validate_webhook_name(value)
}
@model.ObjBuilder()
.opt("name", name)
.und("avatar", patch_nullable("avatar", avatar, clear_avatar))
.build()
}
///|
fn compatible_webhook_query(
thread_id : @model.ChannelId?,
wait : Bool?,
) -> String {
let params : Array[String] = []
if thread_id is Some(value) {
params.push("thread_id=\{value}")
}
if wait is Some(value) {
params.push("wait=\{value}")
}
if params.length() == 0 {
""
} else {
"?" + params.join("&")
}
}
///|
/// Fetch a webhook using the webhook token embedded in the route.
pub async fn Client::get_webhook_with_token(
self : Client,
webhook_id : @model.WebhookId,
token : String,
) -> @model.Webhook raise DiscordHttpError {
decode(self.request(GetWebhookWithToken(webhook_id~, token~)))
}
///|
/// Modify a webhook using its token. This token-authenticated variant cannot
/// move the webhook to another channel.
pub async fn Client::modify_webhook_with_token(
self : Client,
webhook_id : @model.WebhookId,
token : String,
name? : String,
avatar? : String,
clear_avatar? : Bool = false,
) -> @model.Webhook raise DiscordHttpError {
let body = modify_webhook_with_token_body(name, avatar, clear_avatar)
decode(self.request(ModifyWebhookWithToken(webhook_id~, token~), body~))
}
///|
/// Delete a webhook using its token.
pub async fn Client::delete_webhook_with_token(
self : Client,
webhook_id : @model.WebhookId,
token : String,
) -> Unit raise DiscordHttpError {
self.request(DeleteWebhookWithToken(webhook_id~, token~)) |> ignore
}
///|
/// Execute a Slack-compatible webhook payload. `thread_id` targets a thread,
/// and `wait` asks Discord to wait for server confirmation.
pub async fn Client::execute_slack_compatible_webhook(
self : Client,
webhook_id : @model.WebhookId,
token : String,
payload : Json,
thread_id? : @model.ChannelId,
wait? : Bool,
) -> Unit raise DiscordHttpError {
let query = compatible_webhook_query(thread_id, wait)
self.request(
ExecuteSlackCompatibleWebhook(webhook_id~, token~, query~),
body=payload,
)
|> ignore
}
///|
/// Execute a GitHub-compatible webhook payload. Supported `github_event`
/// values are commit_comment, create, delete, fork, issue_comment, issues,
/// member, public, pull_request, pull_request_review,
/// pull_request_review_comment, push, release, watch, check_run, check_suite,
/// discussion, and discussion_comment.
pub async fn Client::execute_github_compatible_webhook(
self : Client,
webhook_id : @model.WebhookId,
token : String,
payload : Json,
github_event~ : String,
thread_id? : @model.ChannelId,
wait? : Bool,
) -> Unit raise DiscordHttpError {
let query = compatible_webhook_query(thread_id, wait)
self.request(
ExecuteGithubCompatibleWebhook(webhook_id~, token~, query~),
body=payload,
headers={ "x-github-event": github_event },
)
|> ignore
}
///|
/// Execute a webhook and wait for the created message (`wait=true` is fixed
/// because the typed return is the message; fire-and-forget would have no
/// body to decode). At least one of `content`, `embeds`, `components`,
/// `files`, or `poll` must be provided. When the webhook channel is a forum
/// or media channel, pass exactly one of `thread_id` (post to an existing
/// thread) or `thread_name` (create a thread); `applied_tags` only applies
/// with `thread_name`. `with_components` lets non-application-owned webhooks
/// send non-interactive components.
pub async fn Client::execute_webhook(
self : Client,
webhook_id : @model.WebhookId,
token : String,
content? : String,
embeds? : Array[@model.Embed],
components? : Array[@model.Component],
files? : Array[FileUpload],
username? : String,
avatar_url? : String,
tts? : Bool,
allowed_mentions? : @model.AllowedMentions,
thread_id? : @model.ChannelId,
thread_name? : String,
applied_tags? : Array[@model.GenericId],
poll? : @model.PollCreateRequest,
with_components? : Bool,
flags? : @model.MessageFlags,
) -> @model.Message raise DiscordHttpError {
validate_execute_webhook(content, embeds, components, files, poll)
if thread_id is Some(_) && thread_name is Some(_) {
raise Validation(message="thread_id and thread_name are mutually exclusive")
}
let query_params = ["wait=true"]
if thread_id is Some(value) {
query_params.push("thread_id=\{value}")
}
if with_components is Some(value) {
query_params.push("with_components=\{value}")
}
let flags = message_flags_with_components_v2(
flags, content, embeds, components,
)
let builder = @model.ObjBuilder()
.opt("content", content)
.opt("embeds", embeds)
.opt("components", components)
.opt("flags", flags)
.opt("username", username)
.opt("avatar_url", avatar_url)
.opt("tts", tts)
.opt("allowed_mentions", allowed_mentions)
.opt("thread_name", thread_name)
.opt("applied_tags", applied_tags)
.opt("poll", poll)
if files is Some(fs) && fs.length() > 0 {
builder.field("attachments", attachments_json(fs)) |> ignore
}
decode(
self.request(
ExecuteWebhook(webhook_id~, token~, query="?" + query_params.join("&")),
body=builder.build(),
files?,
),
)
}
///|
/// Fetch a message previously created by a webhook. Pass `thread_id` when
/// the message lives in a thread of the webhook's channel.
pub async fn Client::get_webhook_message(
self : Client,
webhook_id : @model.WebhookId,
token : String,
message_id : @model.MessageId,
thread_id? : @model.ChannelId,
) -> @model.Message raise DiscordHttpError {
let query = compatible_webhook_query(thread_id, None)
decode(
self.request(GetWebhookMessage(webhook_id~, token~, message_id~, query~)),
)
}
///|
/// Edit a message previously created by a webhook. `keep_attachments` lists
/// the existing attachments to retain; without it, uploaded files replace
/// the whole attachment list. `with_components=true` lets the edit change
/// components on a webhook without an application.
pub async fn Client::edit_webhook_message(
self : Client,
webhook_id : @model.WebhookId,
token : String,
message_id : @model.MessageId,
content? : String,
clear_content? : Bool = false,
embeds? : Array[@model.Embed],
components? : Array[@model.Component],
flags? : @model.MessageFlags,
allowed_mentions? : @model.AllowedMentions,
files? : Array[FileUpload],
keep_attachments? : Array[@model.AttachmentRequest],
thread_id? : @model.ChannelId,
with_components? : Bool,
) -> @model.Message raise DiscordHttpError {
let query_params : Array[String] = []
if thread_id is Some(value) {
query_params.push("thread_id=\{value}")
}
if with_components is Some(value) {
query_params.push("with_components=\{value}")
}
let query = if query_params.length() == 0 {
""
} else {
"?" + query_params.join("&")
}
let builder = edit_attachments_field(
message_patch_builder(content, clear_content, embeds, components, flags).opt(
"allowed_mentions", allowed_mentions,
),
keep_attachments,
files,
)
decode(
self.request(
EditWebhookMessage(webhook_id~, token~, message_id~, query~),
body=builder.build(),
files?,
),
)
}
///|
/// Delete a message previously created by a webhook. Pass `thread_id` when
/// the message lives in a thread of the webhook's channel.
pub async fn Client::delete_webhook_message(
self : Client,
webhook_id : @model.WebhookId,
token : String,
message_id : @model.MessageId,
thread_id? : @model.ChannelId,
) -> Unit raise DiscordHttpError {
let query = compatible_webhook_query(thread_id, None)
self.request(DeleteWebhookMessage(webhook_id~, token~, message_id~, query~))
|> ignore
}