From 898ee565573f2c3f0f288f5448a7d139d735ae09 Mon Sep 17 00:00:00 2001
From: Misha133 <61027276+Misha-133@users.noreply.github.com>
Date: Fri, 31 Mar 2023 14:26:09 +0300
Subject: [PATCH] [Feature] Refactor `SendMessageAsync` & `SendFile(s)Async`
methods & modify webhook message attachments (#2609)
* initial commit
* resolve merge conficts
* code review suggestions
---
.../Entities/Channels/IMessageChannel.cs | 11 +-
src/Discord.Net.Core/Utils/Preconditions.cs | 46 ++
.../API/Rest/CreateMessageParams.cs | 7 +-
src/Discord.Net.Rest/DiscordRestApiClient.cs | 107 +++--
.../Entities/Channels/ChannelHelper.cs | 22 +-
.../Entities/Channels/RestDMChannel.cs | 8 +-
.../Entities/Channels/RestGroupChannel.cs | 8 +-
.../Entities/Channels/RestTextChannel.cs | 18 +-
.../Entities/Channels/SocketDMChannel.cs | 8 +-
.../Entities/Channels/SocketGroupChannel.cs | 8 +-
.../Entities/Channels/SocketTextChannel.cs | 18 +-
.../DiscordWebhookClient.cs | 401 ++++++++++--------
.../Messages/WebhookMessageProperties.cs | 4 +
.../WebhookClientHelper.cs | 61 ++-
14 files changed, 439 insertions(+), 288 deletions(-)
diff --git a/src/Discord.Net.Core/Entities/Channels/IMessageChannel.cs b/src/Discord.Net.Core/Entities/Channels/IMessageChannel.cs
index dc2441f6..7bd9fabf 100644
--- a/src/Discord.Net.Core/Entities/Channels/IMessageChannel.cs
+++ b/src/Discord.Net.Core/Entities/Channels/IMessageChannel.cs
@@ -31,7 +31,8 @@ namespace Discord
/// The message components to be included with this message. Used for interactions.
/// A collection of stickers to send with the message.
/// A array of s to send with this response. Max 10.
- /// A message flag to be applied to the sent message, only is permitted.
+ /// A message flag to be applied to the sent message, only
+ /// and is permitted.
///
/// A task that represents an asynchronous send operation for delivering the message. The task result
/// contains the sent message.
@@ -72,7 +73,7 @@ namespace Discord
/// The message components to be included with this message. Used for interactions.
/// A collection of stickers to send with the file.
/// A array of s to send with this response. Max 10.
- /// A message flag to be applied to the sent message, only is permitted.
+ /// A message flag to be applied to the sent message, only and is permitted.
///
/// A task that represents an asynchronous send operation for delivering the message. The task result
/// contains the sent message.
@@ -110,7 +111,7 @@ namespace Discord
/// The message components to be included with this message. Used for interactions.
/// A collection of stickers to send with the file.
/// A array of s to send with this response. Max 10.
- /// A message flag to be applied to the sent message, only is permitted.
+ /// A message flag to be applied to the sent message, only and is permitted.
///
/// A task that represents an asynchronous send operation for delivering the message. The task result
/// contains the sent message.
@@ -140,7 +141,7 @@ namespace Discord
/// The message components to be included with this message. Used for interactions.
/// A collection of stickers to send with the file.
/// A array of s to send with this response. Max 10.
- /// A message flag to be applied to the sent message, only is permitted.
+ /// A message flag to be applied to the sent message, only and is permitted.
///
/// A task that represents an asynchronous send operation for delivering the message. The task result
/// contains the sent message.
@@ -170,7 +171,7 @@ namespace Discord
/// The message components to be included with this message. Used for interactions.
/// A collection of stickers to send with the file.
/// A array of s to send with this response. Max 10.
- /// A message flag to be applied to the sent message, only is permitted.
+ /// A message flag to be applied to the sent message, only and is permitted.
///
/// A task that represents an asynchronous send operation for delivering the message. The task result
/// contains the sent message.
diff --git a/src/Discord.Net.Core/Utils/Preconditions.cs b/src/Discord.Net.Core/Utils/Preconditions.cs
index 37bd82df..c3f2785d 100644
--- a/src/Discord.Net.Core/Utils/Preconditions.cs
+++ b/src/Discord.Net.Core/Utils/Preconditions.cs
@@ -1,4 +1,6 @@
using System;
+using System.Collections.Generic;
+using System.Linq;
namespace Discord
{
@@ -69,6 +71,50 @@ namespace Discord
private static ArgumentException CreateNotEmptyException(string name, string msg)
=> new ArgumentException(message: msg ?? "Argument cannot be blank.", paramName: name);
+
+ #endregion
+
+ #region Message Validation
+
+ public static void WebhookMessageAtLeastOneOf(string text = null, MessageComponent components = null, ICollection embeds = null,
+ IEnumerable attachments = null)
+ {
+ if (!string.IsNullOrEmpty(text))
+ return;
+
+ if (components != null && components.Components.Count != 0)
+ return;
+
+ if (attachments != null && attachments.Count() != 0)
+ return;
+
+ if (embeds != null && embeds.Count != 0)
+ return;
+
+ throw new ArgumentException($"At least one of 'Content', 'Embeds', 'Components' or 'Attachments' must be specified.");
+ }
+
+ public static void MessageAtLeastOneOf(string text = null, MessageComponent components = null, ICollection embeds = null,
+ ICollection stickers = null, IEnumerable attachments = null)
+ {
+ if (!string.IsNullOrEmpty(text))
+ return;
+
+ if (components != null && components.Components.Count != 0)
+ return;
+
+ if (stickers != null && stickers.Count != 0)
+ return;
+
+ if (attachments != null && attachments.Count() != 0)
+ return;
+
+ if (embeds != null && embeds.Count != 0)
+ return;
+
+ throw new ArgumentException($"At least one of 'Content', 'Embeds', 'Components', 'Stickers' or 'Attachments' must be specified.");
+ }
+
#endregion
#region Numerics
diff --git a/src/Discord.Net.Rest/API/Rest/CreateMessageParams.cs b/src/Discord.Net.Rest/API/Rest/CreateMessageParams.cs
index 7b0d842d..a79c7f70 100644
--- a/src/Discord.Net.Rest/API/Rest/CreateMessageParams.cs
+++ b/src/Discord.Net.Rest/API/Rest/CreateMessageParams.cs
@@ -6,7 +6,7 @@ namespace Discord.API.Rest
internal class CreateMessageParams
{
[JsonProperty("content")]
- public string Content { get; }
+ public Optional Content { get; set; }
[JsonProperty("nonce")]
public Optional Nonce { get; set; }
@@ -31,10 +31,5 @@ namespace Discord.API.Rest
[JsonProperty("flags")]
public Optional Flags { get; set; }
-
- public CreateMessageParams(string content)
- {
- Content = content;
- }
}
}
diff --git a/src/Discord.Net.Rest/DiscordRestApiClient.cs b/src/Discord.Net.Rest/DiscordRestApiClient.cs
index cd7d18a4..6c011676 100644
--- a/src/Discord.Net.Rest/DiscordRestApiClient.cs
+++ b/src/Discord.Net.Rest/DiscordRestApiClient.cs
@@ -816,16 +816,16 @@ namespace Discord.API
endpoint = () => $"channels/{channelId}/messages?limit={limit}";
return await SendAsync>("GET", endpoint, ids, options: options).ConfigureAwait(false);
}
+
/// Message content is too long, length must be less or equal to .
public async Task CreateMessageAsync(ulong channelId, CreateMessageParams args, RequestOptions options = null)
{
Preconditions.NotNull(args, nameof(args));
Preconditions.NotEqual(channelId, 0, nameof(channelId));
- if ((!args.Embeds.IsSpecified || args.Embeds.Value == null || args.Embeds.Value.Length == 0) && (!args.Stickers.IsSpecified || args.Stickers.Value == null || args.Stickers.Value.Length == 0))
- Preconditions.NotNullOrEmpty(args.Content, nameof(args.Content));
- if (args.Content?.Length > DiscordConfig.MaxMessageSize)
- throw new ArgumentException(message: $"Message content is too long, length must be less or equal to {DiscordConfig.MaxMessageSize}.", paramName: nameof(args.Content));
+ if (args.Content.IsSpecified && args.Content.Value is not null)
+ Preconditions.AtMost(args.Content.Value.Length, DiscordConfig.MaxMessageSize, nameof(args.Content), $"Message content is too long, length must be less or equal to {DiscordConfig.MaxMessageSize}.");
+
options = RequestOptions.CreateOrClone(options);
var ids = new BucketIds(channelId: channelId);
@@ -840,13 +840,10 @@ namespace Discord.API
if (AuthTokenType != TokenType.Webhook)
throw new InvalidOperationException($"This operation may only be called with a {nameof(TokenType.Webhook)} token.");
- Preconditions.NotNull(args, nameof(args));
- Preconditions.NotEqual(webhookId, 0, nameof(webhookId));
- if (!args.Embeds.IsSpecified || args.Embeds.Value == null || args.Embeds.Value.Length == 0)
- Preconditions.NotNullOrEmpty(args.Content, nameof(args.Content));
-
- if (args.Content.IsSpecified && args.Content.Value?.Length > DiscordConfig.MaxMessageSize)
- throw new ArgumentException(message: $"Message content is too long, length must be less or equal to {DiscordConfig.MaxMessageSize}.", paramName: nameof(args.Content));
+ if (args.Embeds.IsSpecified)
+ Preconditions.AtMost(args.Embeds.Value.Length, DiscordConfig.MaxEmbedsPerMessage, nameof(args.Embeds), "A max of 10 Embeds are allowed.");
+ if (args.Content.IsSpecified && args.Content.Value is not null)
+ Preconditions.AtMost(args.Content.Value.Length, DiscordConfig.MaxMessageSize, nameof(args.Content), $"Message content is too long, length must be less or equal to {DiscordConfig.MaxMessageSize}.");
options = RequestOptions.CreateOrClone(options);
@@ -866,15 +863,38 @@ namespace Discord.API
Preconditions.NotEqual(messageId, 0, nameof(messageId));
if (args.Embeds.IsSpecified)
- Preconditions.AtMost(args.Embeds.Value.Length, 10, nameof(args.Embeds), "A max of 10 Embeds are allowed.");
- if (args.Content.IsSpecified && args.Content.Value.Length > DiscordConfig.MaxMessageSize)
- throw new ArgumentException(message: $"Message content is too long, length must be less or equal to {DiscordConfig.MaxMessageSize}.", paramName: nameof(args.Content));
+ Preconditions.AtMost(args.Embeds.Value.Length, DiscordConfig.MaxEmbedsPerMessage, nameof(args.Embeds), $"A max of {DiscordConfig.MaxEmbedsPerMessage} Embeds are allowed.");
+ if (args.Content.IsSpecified && args.Content.Value is not null)
+ Preconditions.AtMost(args.Content.Value.Length, DiscordConfig.MaxMessageSize, nameof(args.Content), $"Message content is too long, length must be less or equal to {DiscordConfig.MaxMessageSize}.");
+
options = RequestOptions.CreateOrClone(options);
var ids = new BucketIds(webhookId: webhookId);
await SendJsonAsync("PATCH", () => $"webhooks/{webhookId}/{AuthToken}/messages/{messageId}?{WebhookQuery(false, threadId)}", args, ids, clientBucket: ClientBucketType.SendEdit, options: options).ConfigureAwait(false);
}
+ /// Message content is too long, length must be less or equal to .
+ /// This operation may only be called with a token.
+ public async Task ModifyWebhookMessageAsync(ulong webhookId, ulong messageId, UploadWebhookFileParams args, RequestOptions options = null, ulong? threadId = null)
+ {
+ if (AuthTokenType != TokenType.Webhook)
+ throw new InvalidOperationException($"This operation may only be called with a {nameof(TokenType.Webhook)} token.");
+
+ Preconditions.NotNull(args, nameof(args));
+ Preconditions.NotEqual(webhookId, 0, nameof(webhookId));
+ Preconditions.NotEqual(messageId, 0, nameof(messageId));
+
+ if (args.Embeds.IsSpecified)
+ Preconditions.AtMost(args.Embeds.Value.Length, DiscordConfig.MaxEmbedsPerMessage, nameof(args.Embeds), $"A max of {DiscordConfig.MaxEmbedsPerMessage} Embeds are allowed.");
+ if (args.Content.IsSpecified && args.Content.Value is not null)
+ Preconditions.AtMost(args.Content.Value.Length, DiscordConfig.MaxMessageSize, nameof(args.Content), $"Message content is too long, length must be less or equal to {DiscordConfig.MaxMessageSize}.");
+
+ options = RequestOptions.CreateOrClone(options);
+
+ var ids = new BucketIds(webhookId: webhookId);
+ await SendMultipartAsync("PATCH", () => $"webhooks/{webhookId}/{AuthToken}/messages/{messageId}?{WebhookQuery(false, threadId)}", args.ToDictionary(), ids, clientBucket: ClientBucketType.SendEdit, options: options).ConfigureAwait(false);
+ }
+
/// This operation may only be called with a token.
public async Task DeleteWebhookMessageAsync(ulong webhookId, ulong messageId, RequestOptions options = null, ulong? threadId = null)
{
@@ -897,10 +917,10 @@ namespace Discord.API
Preconditions.NotEqual(channelId, 0, nameof(channelId));
options = RequestOptions.CreateOrClone(options);
- if (args.Content.GetValueOrDefault(null) == null)
- args.Content = "";
- else if (args.Content.IsSpecified && args.Content.Value?.Length > DiscordConfig.MaxMessageSize)
- throw new ArgumentOutOfRangeException($"Message content is too long, length must be less or equal to {DiscordConfig.MaxMessageSize}.", nameof(args.Content));
+ if (args.Embeds.IsSpecified)
+ Preconditions.AtMost(args.Embeds.Value.Length, DiscordConfig.MaxEmbedsPerMessage, nameof(args.Embeds), $"A max of {DiscordConfig.MaxEmbedsPerMessage} Embeds are allowed.");
+ if (args.Content.IsSpecified && args.Content.Value is not null)
+ Preconditions.AtMost(args.Content.Value.Length, DiscordConfig.MaxMessageSize, nameof(args.Content), $"Message content is too long, length must be less or equal to {DiscordConfig.MaxMessageSize}.");
var ids = new BucketIds(channelId: channelId);
return await SendMultipartAsync("POST", () => $"channels/{channelId}/messages", args.ToDictionary(), ids, clientBucket: ClientBucketType.SendEdit, options: options).ConfigureAwait(false);
@@ -917,19 +937,15 @@ namespace Discord.API
Preconditions.NotEqual(webhookId, 0, nameof(webhookId));
options = RequestOptions.CreateOrClone(options);
- if (args.Content.GetValueOrDefault(null) == null)
- args.Content = "";
- else if (args.Content.IsSpecified)
- {
- if (args.Content.Value == null)
- args.Content = "";
- if (args.Content.Value?.Length > DiscordConfig.MaxMessageSize)
- throw new ArgumentOutOfRangeException($"Message content is too long, length must be less or equal to {DiscordConfig.MaxMessageSize}.", nameof(args.Content));
- }
+ if (args.Embeds.IsSpecified)
+ Preconditions.AtMost(args.Embeds.Value.Length, DiscordConfig.MaxEmbedsPerMessage, nameof(args.Embeds), $"A max of {DiscordConfig.MaxEmbedsPerMessage} Embeds are allowed.");
+ if (args.Content.IsSpecified && args.Content.Value is not null)
+ Preconditions.AtMost(args.Content.Value.Length, DiscordConfig.MaxMessageSize, nameof(args.Content), $"Message content is too long, length must be less or equal to {DiscordConfig.MaxMessageSize}.");
var ids = new BucketIds(webhookId: webhookId);
return await SendMultipartAsync("POST", () => $"webhooks/{webhookId}/{AuthToken}?{WebhookQuery(true, threadId)}", args.ToDictionary(), ids, clientBucket: ClientBucketType.SendEdit, options: options).ConfigureAwait(false);
}
+
public async Task DeleteMessageAsync(ulong channelId, ulong messageId, RequestOptions options = null)
{
Preconditions.NotEqual(channelId, 0, nameof(channelId));
@@ -939,6 +955,7 @@ namespace Discord.API
var ids = new BucketIds(channelId: channelId);
await SendAsync("DELETE", () => $"channels/{channelId}/messages/{messageId}", ids, options: options).ConfigureAwait(false);
}
+
public async Task DeleteMessagesAsync(ulong channelId, DeleteMessagesParams args, RequestOptions options = null)
{
Preconditions.NotEqual(channelId, 0, nameof(channelId));
@@ -967,8 +984,12 @@ namespace Discord.API
Preconditions.NotEqual(channelId, 0, nameof(channelId));
Preconditions.NotEqual(messageId, 0, nameof(messageId));
Preconditions.NotNull(args, nameof(args));
- if (args.Content.IsSpecified && args.Content.Value?.Length > DiscordConfig.MaxMessageSize)
- throw new ArgumentOutOfRangeException($"Message content is too long, length must be less or equal to {DiscordConfig.MaxMessageSize}.", nameof(args.Content));
+
+ if (args.Embeds.IsSpecified)
+ Preconditions.AtMost(args.Embeds.Value.Length, DiscordConfig.MaxEmbedsPerMessage, nameof(args.Embeds), "A max of 10 Embeds are allowed.");
+ if (args.Content.IsSpecified && args.Content.Value is not null)
+ Preconditions.AtMost(args.Content.Value.Length, DiscordConfig.MaxMessageSize, nameof(args.Content), $"Message content is too long, length must be less or equal to {DiscordConfig.MaxMessageSize}.");
+
options = RequestOptions.CreateOrClone(options);
var ids = new BucketIds(channelId: channelId);
@@ -980,8 +1001,12 @@ namespace Discord.API
Preconditions.NotEqual(channelId, 0, nameof(channelId));
Preconditions.NotEqual(messageId, 0, nameof(messageId));
Preconditions.NotNull(args, nameof(args));
- if (args.Content.IsSpecified && args.Content.Value?.Length > DiscordConfig.MaxMessageSize)
- throw new ArgumentOutOfRangeException($"Message content is too long, length must be less or equal to {DiscordConfig.MaxMessageSize}.", nameof(args.Content));
+
+ if (args.Embeds.IsSpecified)
+ Preconditions.AtMost(args.Embeds.Value.Length, DiscordConfig.MaxEmbedsPerMessage, nameof(args.Embeds), "A max of 10 Embeds are allowed.");
+ if (args.Content.IsSpecified && args.Content.Value is not null)
+ Preconditions.AtMost(args.Content.Value.Length, DiscordConfig.MaxMessageSize, nameof(args.Content), $"Message content is too long, length must be less or equal to {DiscordConfig.MaxMessageSize}.");
+
options = RequestOptions.CreateOrClone(options);
var ids = new BucketIds(channelId: channelId);
@@ -1444,8 +1469,15 @@ namespace Discord.API
public async Task CreateInteractionFollowupMessageAsync(CreateWebhookMessageParams args, string token, RequestOptions options = null)
{
- if ((!args.Embeds.IsSpecified || args.Embeds.Value == null || args.Embeds.Value.Length == 0) && !args.File.IsSpecified)
- Preconditions.NotNullOrEmpty(args.Content, nameof(args.Content));
+ if ((!args.Embeds.IsSpecified || args.Embeds.Value == null || args.Embeds.Value.Length == 0)
+ && (!args.Content.IsSpecified || args.Content.Value is null || string.IsNullOrWhiteSpace(args.Content.Value))
+ && (!args.Components.IsSpecified || args.Components.Value is null || args.Components.Value.Length == 0))
+ {
+ throw new ArgumentException("At least one of 'Content', 'Embeds', 'File' or 'Components' must be specified.", nameof(args));
+ }
+
+ if (args.Content.IsSpecified && args.Content.Value is not null && args.Content.Value.Length > DiscordConfig.MaxMessageSize)
+ throw new ArgumentException(message: $"Message content is too long, length must be less or equal to {DiscordConfig.MaxMessageSize}.", paramName: nameof(args.Content));
if (args.Content.IsSpecified && args.Content.Value?.Length > DiscordConfig.MaxMessageSize)
throw new ArgumentException(message: $"Message content is too long, length must be less or equal to {DiscordConfig.MaxMessageSize}.", paramName: nameof(args.Content));
@@ -1460,9 +1492,12 @@ namespace Discord.API
public async Task CreateInteractionFollowupMessageAsync(UploadWebhookFileParams args, string token, RequestOptions options = null)
{
- if ((!args.Embeds.IsSpecified || args.Embeds.Value == null || args.Embeds.Value.Length == 0) && !args.Files.Any())
- Preconditions.NotNullOrEmpty(args.Content, nameof(args.Content));
-
+ if ((!args.Embeds.IsSpecified || args.Embeds.Value == null || args.Embeds.Value.Length == 0)
+ && (!args.Content.IsSpecified || args.Content.Value is null || string.IsNullOrWhiteSpace(args.Content.Value))
+ && (!args.MessageComponents.IsSpecified || args.MessageComponents.Value is null || args.MessageComponents.Value.Length == 0))
+ {
+ throw new ArgumentException("At least one of 'Content', 'Embeds', 'Files' or 'Components' must be specified.", nameof(args));
+ }
if (args.Content.IsSpecified && args.Content.Value?.Length > DiscordConfig.MaxMessageSize)
throw new ArgumentException(message: $"Message content is too long, length must be less or equal to {DiscordConfig.MaxMessageSize}.", paramName: nameof(args.Content));
diff --git a/src/Discord.Net.Rest/Entities/Channels/ChannelHelper.cs b/src/Discord.Net.Rest/Entities/Channels/ChannelHelper.cs
index f04cb3d3..1cf2bdc5 100644
--- a/src/Discord.Net.Rest/Entities/Channels/ChannelHelper.cs
+++ b/src/Discord.Net.Rest/Entities/Channels/ChannelHelper.cs
@@ -281,7 +281,9 @@ namespace Discord.Rest
Preconditions.AtMost(allowedMentions?.RoleIds?.Count ?? 0, 100, nameof(allowedMentions.RoleIds), "A max of 100 role Ids are allowed.");
Preconditions.AtMost(allowedMentions?.UserIds?.Count ?? 0, 100, nameof(allowedMentions.UserIds), "A max of 100 user Ids are allowed.");
- Preconditions.AtMost(embeds.Length, 10, nameof(embeds), "A max of 10 embeds are allowed.");
+ Preconditions.AtMost(embeds.Length, DiscordConfig.MaxEmbedsPerMessage, nameof(embeds), $"A max of {DiscordConfig.MaxEmbedsPerMessage} Embeds are allowed.");
+
+ Preconditions.MessageAtLeastOneOf(text, components, embeds, stickers);
// check that user flag and user Id list are exclusive, same with role flag and role Id list
if (allowedMentions != null && allowedMentions.AllowedTypes.HasValue)
@@ -304,12 +306,12 @@ namespace Discord.Rest
Preconditions.AtMost(stickers.Length, 3, nameof(stickers), "A max of 3 stickers are allowed.");
}
-
- if (flags is not MessageFlags.None and not MessageFlags.SuppressEmbeds)
+ if (flags is not MessageFlags.None and not MessageFlags.SuppressEmbeds and not MessageFlags.SuppressNotification)
throw new ArgumentException("The only valid MessageFlags are SuppressEmbeds and none.", nameof(flags));
- var args = new CreateMessageParams(text)
+ var args = new CreateMessageParams
{
+ Content = text,
IsTTS = isTTS,
Embeds = embeds.Any() ? embeds.Select(x => x.ToModel()).ToArray() : Optional.Unspecified,
AllowedMentions = allowedMentions?.ToModel(),
@@ -346,7 +348,7 @@ namespace Discord.Rest
/// is in an invalid format.
/// An I/O error occurred while opening the file.
/// Message content is too long, length must be less or equal to .
- /// The only valid are and .
+ /// The only valid are , and .
public static async Task SendFileAsync(IMessageChannel channel, BaseDiscordClient client,
string filePath, string text, bool isTTS, Embed embed, AllowedMentions allowedMentions,
MessageReference messageReference, MessageComponent components, ISticker[] stickers, RequestOptions options,
@@ -379,7 +381,7 @@ namespace Discord.Rest
=> SendFilesAsync(channel, client, new[] { attachment }, text, isTTS, embed, allowedMentions, messageReference,
components, stickers, options, embeds, flags);
- /// The only valid are and .
+ /// The only valid are , and .
public static async Task SendFilesAsync(IMessageChannel channel, BaseDiscordClient client,
IEnumerable attachments, string text, bool isTTS, Embed embed, AllowedMentions allowedMentions,
MessageReference messageReference, MessageComponent components, ISticker[] stickers, RequestOptions options,
@@ -391,7 +393,9 @@ namespace Discord.Rest
Preconditions.AtMost(allowedMentions?.RoleIds?.Count ?? 0, 100, nameof(allowedMentions.RoleIds), "A max of 100 role Ids are allowed.");
Preconditions.AtMost(allowedMentions?.UserIds?.Count ?? 0, 100, nameof(allowedMentions.UserIds), "A max of 100 user Ids are allowed.");
- Preconditions.AtMost(embeds.Length, 10, nameof(embeds), "A max of 10 embeds are allowed.");
+ Preconditions.AtMost(embeds.Length, DiscordConfig.MaxEmbedsPerMessage, nameof(embeds), $"A max of {DiscordConfig.MaxEmbedsPerMessage} Embeds are allowed.");
+
+ Preconditions.MessageAtLeastOneOf(text, components, embeds, stickers, attachments);
foreach (var attachment in attachments)
{
@@ -424,8 +428,8 @@ namespace Discord.Rest
}
}
- if (flags is not MessageFlags.None and not MessageFlags.SuppressEmbeds)
- throw new ArgumentException("The only valid MessageFlags are SuppressEmbeds and none.", nameof(flags));
+ if (flags is not MessageFlags.None and not MessageFlags.SuppressEmbeds and not MessageFlags.SuppressNotification)
+ throw new ArgumentException("The only valid MessageFlags are SuppressEmbeds, SuppressNotification and none.", nameof(flags));
if (stickers != null)
{
diff --git a/src/Discord.Net.Rest/Entities/Channels/RestDMChannel.cs b/src/Discord.Net.Rest/Entities/Channels/RestDMChannel.cs
index 35c2411b..59c502f1 100644
--- a/src/Discord.Net.Rest/Entities/Channels/RestDMChannel.cs
+++ b/src/Discord.Net.Rest/Entities/Channels/RestDMChannel.cs
@@ -127,7 +127,7 @@ namespace Discord.Rest
/// An I/O error occurred while opening the file.
/// Message content is too long, length must be less or equal to .
/// The only valid are and .
- public Task SendFileAsync(string filePath, string text, bool isTTS = false, Embed embed = null,
+ public Task SendFileAsync(string filePath, string text = null, bool isTTS = false, Embed embed = null,
RequestOptions options = null, bool isSpoiler = false, AllowedMentions allowedMentions = null,
MessageReference messageReference = null, MessageComponent components = null, ISticker[] stickers = null,
Embed[] embeds = null, MessageFlags flags = MessageFlags.None)
@@ -135,7 +135,7 @@ namespace Discord.Rest
components, stickers, options, isSpoiler, embeds, flags);
///
/// Message content is too long, length must be less or equal to .
- public Task SendFileAsync(Stream stream, string filename, string text, bool isTTS = false,
+ public Task SendFileAsync(Stream stream, string filename, string text = null, bool isTTS = false,
Embed embed = null, RequestOptions options = null, bool isSpoiler = false, AllowedMentions allowedMentions = null,
MessageReference messageReference = null, MessageComponent components = null, ISticker[] stickers = null,
Embed[] embeds = null, MessageFlags flags = MessageFlags.None)
@@ -144,7 +144,7 @@ namespace Discord.Rest
///
/// Message content is too long, length must be less or equal to .
- public Task SendFileAsync(FileAttachment attachment, string text, bool isTTS = false,
+ public Task SendFileAsync(FileAttachment attachment, string text = null, bool isTTS = false,
Embed embed = null, RequestOptions options = null, AllowedMentions allowedMentions = null,
MessageReference messageReference = null, MessageComponent components = null, ISticker[] stickers = null,
Embed[] embeds = null, MessageFlags flags = MessageFlags.None)
@@ -153,7 +153,7 @@ namespace Discord.Rest
///
/// Message content is too long, length must be less or equal to .
- public Task SendFilesAsync(IEnumerable attachments, string text, bool isTTS = false,
+ public Task SendFilesAsync(IEnumerable attachments, string text = null, bool isTTS = false,
Embed embed = null, RequestOptions options = null, AllowedMentions allowedMentions = null,
MessageReference messageReference = null, MessageComponent components = null, ISticker[] stickers = null,
Embed[] embeds = null, MessageFlags flags = MessageFlags.None)
diff --git a/src/Discord.Net.Rest/Entities/Channels/RestGroupChannel.cs b/src/Discord.Net.Rest/Entities/Channels/RestGroupChannel.cs
index ba4cbdb2..38e20e8f 100644
--- a/src/Discord.Net.Rest/Entities/Channels/RestGroupChannel.cs
+++ b/src/Discord.Net.Rest/Entities/Channels/RestGroupChannel.cs
@@ -137,7 +137,7 @@ namespace Discord.Rest
/// An I/O error occurred while opening the file.
/// Message content is too long, length must be less or equal to .
/// The only valid are and .
- public Task SendFileAsync(string filePath, string text, bool isTTS = false, Embed embed = null,
+ public Task SendFileAsync(string filePath, string text = null, bool isTTS = false, Embed embed = null,
RequestOptions options = null, bool isSpoiler = false, AllowedMentions allowedMentions = null,
MessageReference messageReference = null, MessageComponent components = null, ISticker[] stickers = null,
Embed[] embeds = null, MessageFlags flags = MessageFlags.None)
@@ -146,7 +146,7 @@ namespace Discord.Rest
///
/// Message content is too long, length must be less or equal to .
/// The only valid are and .
- public Task SendFileAsync(Stream stream, string filename, string text, bool isTTS = false,
+ public Task SendFileAsync(Stream stream, string filename, string text = null, bool isTTS = false,
Embed embed = null, RequestOptions options = null, bool isSpoiler = false, AllowedMentions allowedMentions = null,
MessageReference messageReference = null, MessageComponent components = null, ISticker[] stickers = null,
Embed[] embeds = null, MessageFlags flags = MessageFlags.None)
@@ -155,7 +155,7 @@ namespace Discord.Rest
///
/// Message content is too long, length must be less or equal to .
/// The only valid are and .
- public Task SendFileAsync(FileAttachment attachment, string text, bool isTTS = false,
+ public Task SendFileAsync(FileAttachment attachment, string text = null, bool isTTS = false,
Embed embed = null, RequestOptions options = null, AllowedMentions allowedMentions = null,
MessageReference messageReference = null, MessageComponent components = null, ISticker[] stickers = null,
Embed[] embeds = null, MessageFlags flags = MessageFlags.None)
@@ -164,7 +164,7 @@ namespace Discord.Rest
///
/// Message content is too long, length must be less or equal to .
/// The only valid are and .
- public Task SendFilesAsync(IEnumerable attachments, string text, bool isTTS = false,
+ public Task SendFilesAsync(IEnumerable attachments, string text = null, bool isTTS = false,
Embed embed = null, RequestOptions options = null, AllowedMentions allowedMentions = null,
MessageReference messageReference = null, MessageComponent components = null, ISticker[] stickers = null,
Embed[] embeds = null, MessageFlags flags = MessageFlags.None)
diff --git a/src/Discord.Net.Rest/Entities/Channels/RestTextChannel.cs b/src/Discord.Net.Rest/Entities/Channels/RestTextChannel.cs
index 14f531de..798d15ef 100644
--- a/src/Discord.Net.Rest/Entities/Channels/RestTextChannel.cs
+++ b/src/Discord.Net.Rest/Entities/Channels/RestTextChannel.cs
@@ -114,7 +114,7 @@ namespace Discord.Rest
///
/// Message content is too long, length must be less or equal to .
- /// The only valid are and .
+ /// The only valid are , and .
public virtual Task SendMessageAsync(string text = null, bool isTTS = false, Embed embed = null,
RequestOptions options = null, AllowedMentions allowedMentions = null, MessageReference messageReference = null,
MessageComponent components = null, ISticker[] stickers = null, Embed[] embeds = null, MessageFlags flags = MessageFlags.None)
@@ -146,8 +146,8 @@ namespace Discord.Rest
/// is in an invalid format.
/// An I/O error occurred while opening the file.
/// Message content is too long, length must be less or equal to .
- /// The only valid are and .
- public virtual Task SendFileAsync(string filePath, string text, bool isTTS = false, Embed embed = null,
+ /// The only valid are , and .
+ public virtual Task SendFileAsync(string filePath, string text = null, bool isTTS = false, Embed embed = null,
RequestOptions options = null, bool isSpoiler = false, AllowedMentions allowedMentions = null,
MessageReference messageReference = null, MessageComponent components = null, ISticker[] stickers = null,
Embed[] embeds = null, MessageFlags flags = MessageFlags.None)
@@ -156,8 +156,8 @@ namespace Discord.Rest
///
/// Message content is too long, length must be less or equal to .
- /// The only valid are and .
- public virtual Task SendFileAsync(Stream stream, string filename, string text, bool isTTS = false,
+ /// The only valid are , and .
+ public virtual Task SendFileAsync(Stream stream, string filename, string text = null, bool isTTS = false,
Embed embed = null, RequestOptions options = null, bool isSpoiler = false, AllowedMentions allowedMentions = null,
MessageReference messageReference = null, MessageComponent components = null, ISticker[] stickers = null,
Embed[] embeds = null, MessageFlags flags = MessageFlags.None)
@@ -166,8 +166,8 @@ namespace Discord.Rest
///
/// Message content is too long, length must be less or equal to .
- /// The only valid are and .
- public virtual Task SendFileAsync(FileAttachment attachment, string text, bool isTTS = false,
+ /// The only valid are , and .
+ public virtual Task SendFileAsync(FileAttachment attachment, string text = null, bool isTTS = false,
Embed embed = null, RequestOptions options = null, AllowedMentions allowedMentions = null,
MessageReference messageReference = null, MessageComponent components = null, ISticker[] stickers = null,
Embed[] embeds = null, MessageFlags flags = MessageFlags.None)
@@ -176,8 +176,8 @@ namespace Discord.Rest
///
/// Message content is too long, length must be less or equal to .
- /// The only valid are and .
- public virtual Task SendFilesAsync(IEnumerable attachments, string text, bool isTTS = false,
+ /// The only valid are , and .
+ public virtual Task SendFilesAsync(IEnumerable attachments, string text = null, bool isTTS = false,
Embed embed = null, RequestOptions options = null, AllowedMentions allowedMentions = null,
MessageReference messageReference = null, MessageComponent components = null, ISticker[] stickers = null,
Embed[] embeds = null, MessageFlags flags = MessageFlags.None)
diff --git a/src/Discord.Net.WebSocket/Entities/Channels/SocketDMChannel.cs b/src/Discord.Net.WebSocket/Entities/Channels/SocketDMChannel.cs
index 47e92626..e2031fef 100644
--- a/src/Discord.Net.WebSocket/Entities/Channels/SocketDMChannel.cs
+++ b/src/Discord.Net.WebSocket/Entities/Channels/SocketDMChannel.cs
@@ -148,7 +148,7 @@ namespace Discord.WebSocket
///
/// The only valid are and .
- public Task SendFileAsync(string filePath, string text, bool isTTS = false, Embed embed = null,
+ public Task SendFileAsync(string filePath, string text = null, bool isTTS = false, Embed embed = null,
RequestOptions options = null, bool isSpoiler = false, AllowedMentions allowedMentions = null,
MessageReference messageReference = null, MessageComponent components = null, ISticker[] stickers = null,
Embed[] embeds = null, MessageFlags flags = MessageFlags.None)
@@ -157,7 +157,7 @@ namespace Discord.WebSocket
///
/// Message content is too long, length must be less or equal to .
/// The only valid are and .
- public Task SendFileAsync(Stream stream, string filename, string text, bool isTTS = false,
+ public Task SendFileAsync(Stream stream, string filename, string text = null, bool isTTS = false,
Embed embed = null, RequestOptions options = null, bool isSpoiler = false, AllowedMentions allowedMentions = null,
MessageReference messageReference = null, MessageComponent components = null, ISticker[] stickers = null,
Embed[] embeds = null, MessageFlags flags = MessageFlags.None)
@@ -166,7 +166,7 @@ namespace Discord.WebSocket
///
/// Message content is too long, length must be less or equal to .
/// The only valid are and .
- public Task SendFileAsync(FileAttachment attachment, string text, bool isTTS = false,
+ public Task SendFileAsync(FileAttachment attachment, string text = null, bool isTTS = false,
Embed embed = null, RequestOptions options = null, AllowedMentions allowedMentions = null,
MessageReference messageReference = null, MessageComponent components = null, ISticker[] stickers = null,
Embed[] embeds = null, MessageFlags flags = MessageFlags.None)
@@ -175,7 +175,7 @@ namespace Discord.WebSocket
///
/// Message content is too long, length must be less or equal to .
/// The only valid are and .
- public Task SendFilesAsync(IEnumerable attachments, string text, bool isTTS = false,
+ public Task SendFilesAsync(IEnumerable attachments, string text = null, bool isTTS = false,
Embed embed = null, RequestOptions options = null, AllowedMentions allowedMentions = null,
MessageReference messageReference = null, MessageComponent components = null, ISticker[] stickers = null,
Embed[] embeds = null, MessageFlags flags = MessageFlags.None)
diff --git a/src/Discord.Net.WebSocket/Entities/Channels/SocketGroupChannel.cs b/src/Discord.Net.WebSocket/Entities/Channels/SocketGroupChannel.cs
index 90dfafb0..7502a4e2 100644
--- a/src/Discord.Net.WebSocket/Entities/Channels/SocketGroupChannel.cs
+++ b/src/Discord.Net.WebSocket/Entities/Channels/SocketGroupChannel.cs
@@ -187,7 +187,7 @@ namespace Discord.WebSocket
///
/// The only valid are and .
- public Task SendFileAsync(string filePath, string text, bool isTTS = false, Embed embed = null,
+ public Task SendFileAsync(string filePath, string text = null, bool isTTS = false, Embed embed = null,
RequestOptions options = null, bool isSpoiler = false, AllowedMentions allowedMentions = null,
MessageReference messageReference = null, MessageComponent components = null, ISticker[] stickers = null,
Embed[] embeds = null, MessageFlags flags = MessageFlags.None)
@@ -196,7 +196,7 @@ namespace Discord.WebSocket
///
/// Message content is too long, length must be less or equal to .
/// The only valid are and .
- public Task SendFileAsync(Stream stream, string filename, string text, bool isTTS = false,
+ public Task SendFileAsync(Stream stream, string filename, string text = null, bool isTTS = false,
Embed embed = null, RequestOptions options = null, bool isSpoiler = false, AllowedMentions allowedMentions = null,
MessageReference messageReference = null, MessageComponent components = null, ISticker[] stickers = null,
Embed[] embeds = null, MessageFlags flags = MessageFlags.None)
@@ -205,7 +205,7 @@ namespace Discord.WebSocket
///
/// Message content is too long, length must be less or equal to .
/// The only valid are and .
- public Task SendFileAsync(FileAttachment attachment, string text, bool isTTS = false,
+ public Task SendFileAsync(FileAttachment attachment, string text = null, bool isTTS = false,
Embed embed = null, RequestOptions options = null, AllowedMentions allowedMentions = null,
MessageReference messageReference = null, MessageComponent components = null, ISticker[] stickers = null,
Embed[] embeds = null, MessageFlags flags = MessageFlags.None)
@@ -214,7 +214,7 @@ namespace Discord.WebSocket
///
/// Message content is too long, length must be less or equal to .
/// The only valid are and .
- public Task SendFilesAsync(IEnumerable attachments, string text, bool isTTS = false,
+ public Task SendFilesAsync(IEnumerable attachments, string text = null, bool isTTS = false,
Embed embed = null, RequestOptions options = null, AllowedMentions allowedMentions = null,
MessageReference messageReference = null, MessageComponent components = null, ISticker[] stickers = null,
Embed[] embeds = null, MessageFlags flags = MessageFlags.None)
diff --git a/src/Discord.Net.WebSocket/Entities/Channels/SocketTextChannel.cs b/src/Discord.Net.WebSocket/Entities/Channels/SocketTextChannel.cs
index 7f7ebc2b..5545048c 100644
--- a/src/Discord.Net.WebSocket/Entities/Channels/SocketTextChannel.cs
+++ b/src/Discord.Net.WebSocket/Entities/Channels/SocketTextChannel.cs
@@ -222,7 +222,7 @@ namespace Discord.WebSocket
///
/// Message content is too long, length must be less or equal to .
- /// The only valid are and .
+ /// The only valid are , and .
public virtual Task SendMessageAsync(string text = null, bool isTTS = false, Embed embed = null,
RequestOptions options = null, AllowedMentions allowedMentions = null, MessageReference messageReference = null,
MessageComponent components = null, ISticker[] stickers = null, Embed[] embeds = null, MessageFlags flags = MessageFlags.None)
@@ -230,8 +230,8 @@ namespace Discord.WebSocket
components, stickers, options, embeds, flags);
///
- /// The only valid are and .
- public virtual Task SendFileAsync(string filePath, string text, bool isTTS = false, Embed embed = null,
+ /// The only valid are , and .
+ public virtual Task SendFileAsync(string filePath, string text = null, bool isTTS = false, Embed embed = null,
RequestOptions options = null, bool isSpoiler = false, AllowedMentions allowedMentions = null,
MessageReference messageReference = null, MessageComponent components = null, ISticker[] stickers = null,
Embed[] embeds = null, MessageFlags flags = MessageFlags.None)
@@ -239,8 +239,8 @@ namespace Discord.WebSocket
components, stickers, options, isSpoiler, embeds, flags);
///
/// Message content is too long, length must be less or equal to .
- /// The only valid are and .
- public virtual Task SendFileAsync(Stream stream, string filename, string text, bool isTTS = false,
+ /// The only valid are , and .
+ public virtual Task SendFileAsync(Stream stream, string filename, string text = null, bool isTTS = false,
Embed embed = null, RequestOptions options = null, bool isSpoiler = false, AllowedMentions allowedMentions = null,
MessageReference messageReference = null, MessageComponent components = null, ISticker[] stickers = null,
Embed[] embeds = null, MessageFlags flags = MessageFlags.None)
@@ -248,8 +248,8 @@ namespace Discord.WebSocket
messageReference, components, stickers, options, isSpoiler, embeds, flags);
///
/// Message content is too long, length must be less or equal to .
- /// The only valid are and .
- public virtual Task SendFileAsync(FileAttachment attachment, string text, bool isTTS = false,
+ /// The only valid are , and .
+ public virtual Task SendFileAsync(FileAttachment attachment, string text = null, bool isTTS = false,
Embed embed = null, RequestOptions options = null, AllowedMentions allowedMentions = null,
MessageReference messageReference = null, MessageComponent components = null, ISticker[] stickers = null,
Embed[] embeds = null, MessageFlags flags = MessageFlags.None)
@@ -257,8 +257,8 @@ namespace Discord.WebSocket
messageReference, components, stickers, options, embeds, flags);
///
/// Message content is too long, length must be less or equal to .
- /// The only valid are and .
- public virtual Task SendFilesAsync(IEnumerable attachments, string text, bool isTTS = false,
+ /// The only valid are , and .
+ public virtual Task SendFilesAsync(IEnumerable attachments, string text = null, bool isTTS = false,
Embed embed = null, RequestOptions options = null, AllowedMentions allowedMentions = null,
MessageReference messageReference = null, MessageComponent components = null, ISticker[] stickers = null,
Embed[] embeds = null, MessageFlags flags = MessageFlags.None)
diff --git a/src/Discord.Net.Webhook/DiscordWebhookClient.cs b/src/Discord.Net.Webhook/DiscordWebhookClient.cs
index 1b05fb04..833dcebb 100644
--- a/src/Discord.Net.Webhook/DiscordWebhookClient.cs
+++ b/src/Discord.Net.Webhook/DiscordWebhookClient.cs
@@ -1,5 +1,6 @@
using Discord.Logging;
using Discord.Rest;
+
using System;
using System.Collections.Generic;
using System.Globalization;
@@ -7,195 +8,235 @@ using System.IO;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
-namespace Discord.Webhook
+namespace Discord.Webhook;
+
+///
+/// A client responsible for connecting as a Webhook.
+///
+public class DiscordWebhookClient : IDisposable
{
- /// A client responsible for connecting as a Webhook.
- public class DiscordWebhookClient : IDisposable
+ public event Func Log
{
- public event Func Log { add { _logEvent.Add(value); } remove { _logEvent.Remove(value); } }
- internal readonly AsyncEvent> _logEvent = new AsyncEvent>();
+ add => _logEvent.Add(value);
+ remove => _logEvent.Remove(value);
+ }
- private readonly ulong _webhookId;
- internal IWebhook Webhook;
- internal readonly Logger _restLogger;
+ internal readonly AsyncEvent> _logEvent = new AsyncEvent>();
- internal API.DiscordRestApiClient ApiClient { get; }
- internal LogManager LogManager { get; }
+ private readonly ulong _webhookId;
+ internal IWebhook Webhook;
+ internal readonly Logger _restLogger;
- /// Creates a new Webhook Discord client.
- public DiscordWebhookClient(IWebhook webhook)
- : this(webhook.Id, webhook.Token, new DiscordRestConfig()) { }
- /// Creates a new Webhook Discord client.
- public DiscordWebhookClient(ulong webhookId, string webhookToken)
- : this(webhookId, webhookToken, new DiscordRestConfig()) { }
- /// Creates a new Webhook Discord client.
- public DiscordWebhookClient(string webhookUrl)
- : this(webhookUrl, new DiscordRestConfig()) { }
+ internal API.DiscordRestApiClient ApiClient { get; }
+ internal LogManager LogManager { get; }
- // regex pattern to match webhook urls
- private static Regex WebhookUrlRegex = new Regex(@"^.*(discord|discordapp)\.com\/api\/webhooks\/([\d]+)\/([a-z0-9_-]+)$", RegexOptions.Compiled | RegexOptions.IgnoreCase | RegexOptions.CultureInvariant);
+ ///
+ /// Creates a new Webhook Discord client.
+ ///
+ public DiscordWebhookClient(IWebhook webhook)
+ : this(webhook.Id, webhook.Token, new DiscordRestConfig()) { }
- /// Creates a new Webhook Discord client.
- public DiscordWebhookClient(ulong webhookId, string webhookToken, DiscordRestConfig config)
- : this(config)
+ ///
+ /// Creates a new Webhook Discord client.
+ ///
+ public DiscordWebhookClient(ulong webhookId, string webhookToken)
+ : this(webhookId, webhookToken, new DiscordRestConfig()) { }
+
+ ///
+ /// Creates a new Webhook Discord client.
+ ///
+ public DiscordWebhookClient(string webhookUrl)
+ : this(webhookUrl, new DiscordRestConfig()) { }
+
+ // regex pattern to match webhook urls
+ private static Regex WebhookUrlRegex = new Regex(@"^.*(discord|discordapp)\.com\/api\/webhooks\/([\d]+)\/([a-z0-9_-]+)$", RegexOptions.Compiled | RegexOptions.IgnoreCase | RegexOptions.CultureInvariant);
+
+ ///
+ /// Creates a new Webhook Discord client.
+ ///
+ public DiscordWebhookClient(ulong webhookId, string webhookToken, DiscordRestConfig config)
+ : this(config)
+ {
+ _webhookId = webhookId;
+ ApiClient.LoginAsync(TokenType.Webhook, webhookToken).GetAwaiter().GetResult();
+ Webhook = WebhookClientHelper.GetWebhookAsync(this, webhookId).GetAwaiter().GetResult();
+ }
+
+ ///
+ /// Creates a new Webhook Discord client.
+ ///
+ public DiscordWebhookClient(IWebhook webhook, DiscordRestConfig config)
+ : this(config)
+ {
+ Webhook = webhook;
+ _webhookId = Webhook.Id;
+ }
+
+ ///
+ /// Creates a new Webhook Discord client.
+ ///
+ /// The url of the webhook.
+ /// The configuration options to use for this client.
+ /// Thrown if the is an invalid format.
+ /// Thrown if the is null or whitespace.
+ public DiscordWebhookClient(string webhookUrl, DiscordRestConfig config) : this(config)
+ {
+ ParseWebhookUrl(webhookUrl, out _webhookId, out string token);
+ ApiClient.LoginAsync(TokenType.Webhook, token).GetAwaiter().GetResult();
+ Webhook = WebhookClientHelper.GetWebhookAsync(this, _webhookId).GetAwaiter().GetResult();
+ }
+
+ private DiscordWebhookClient(DiscordRestConfig config)
+ {
+ ApiClient = CreateApiClient(config);
+ LogManager = new LogManager(config.LogLevel);
+ LogManager.Message += async msg => await _logEvent.InvokeAsync(msg).ConfigureAwait(false);
+
+ _restLogger = LogManager.CreateLogger("Rest");
+
+ ApiClient.RequestQueue.RateLimitTriggered += async (id, info, endpoint) =>
{
- _webhookId = webhookId;
- ApiClient.LoginAsync(TokenType.Webhook, webhookToken).GetAwaiter().GetResult();
- Webhook = WebhookClientHelper.GetWebhookAsync(this, webhookId).GetAwaiter().GetResult();
- }
- /// Creates a new Webhook Discord client.
- public DiscordWebhookClient(IWebhook webhook, DiscordRestConfig config)
- : this(config)
- {
- Webhook = webhook;
- _webhookId = Webhook.Id;
- }
-
- ///
- /// Creates a new Webhook Discord client.
- ///
- /// The url of the webhook.
- /// The configuration options to use for this client.
- /// Thrown if the is an invalid format.
- /// Thrown if the is null or whitespace.
- public DiscordWebhookClient(string webhookUrl, DiscordRestConfig config) : this(config)
- {
- ParseWebhookUrl(webhookUrl, out _webhookId, out string token);
- ApiClient.LoginAsync(TokenType.Webhook, token).GetAwaiter().GetResult();
- Webhook = WebhookClientHelper.GetWebhookAsync(this, _webhookId).GetAwaiter().GetResult();
- }
-
- private DiscordWebhookClient(DiscordRestConfig config)
- {
- ApiClient = CreateApiClient(config);
- LogManager = new LogManager(config.LogLevel);
- LogManager.Message += async msg => await _logEvent.InvokeAsync(msg).ConfigureAwait(false);
-
- _restLogger = LogManager.CreateLogger("Rest");
-
- ApiClient.RequestQueue.RateLimitTriggered += async (id, info, endpoint) =>
- {
- if (info == null)
- await _restLogger.VerboseAsync($"Preemptive Rate limit triggered: {endpoint} {(id.IsHashBucket ? $"(Bucket: {id.BucketHash})" : "")}").ConfigureAwait(false);
- else
- await _restLogger.WarningAsync($"Rate limit triggered: {endpoint} {(id.IsHashBucket ? $"(Bucket: {id.BucketHash})" : "")}").ConfigureAwait(false);
- };
- ApiClient.SentRequest += async (method, endpoint, millis) => await _restLogger.VerboseAsync($"{method} {endpoint}: {millis} ms").ConfigureAwait(false);
- }
- private static API.DiscordRestApiClient CreateApiClient(DiscordRestConfig config)
- => new API.DiscordRestApiClient(config.RestClientProvider, DiscordRestConfig.UserAgent, useSystemClock: config.UseSystemClock, defaultRatelimitCallback: config.DefaultRatelimitCallback);
- /// Sends a message to the channel for this webhook.
- /// Returns the ID of the created message.
- public Task SendMessageAsync(string text = null, bool isTTS = false, IEnumerable