diff --git a/DisCatSharp/Entities/Webhook/DiscordWebhook.cs b/DisCatSharp/Entities/Webhook/DiscordWebhook.cs
index 403882156..de134aeea 100644
--- a/DisCatSharp/Entities/Webhook/DiscordWebhook.cs
+++ b/DisCatSharp/Entities/Webhook/DiscordWebhook.cs
@@ -1,316 +1,324 @@
// This file is part of the DisCatSharp project, based off DSharpPlus.
//
// Copyright (c) 2021-2023 AITSYS
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
using System;
+using System.Collections.Generic;
using System.IO;
using System.Threading.Tasks;
using DisCatSharp.Enums;
using DisCatSharp.Exceptions;
using DisCatSharp.Net;
using Newtonsoft.Json;
namespace DisCatSharp.Entities;
///
/// Represents information about a Discord webhook.
///
public class DiscordWebhook : SnowflakeObject, IEquatable
{
///
/// Gets the api client.
///
internal DiscordApiClient ApiClient { get; set; }
///
/// Gets the id of the guild this webhook belongs to.
///
[JsonProperty("guild_id", NullValueHandling = NullValueHandling.Ignore)]
public ulong GuildId { get; internal set; }
///
/// Gets the ID of the channel this webhook belongs to.
///
[JsonProperty("channel_id", NullValueHandling = NullValueHandling.Ignore)]
public ulong ChannelId { get; internal set; }
+ ///
+ /// Gets the ID of the application this webhook belongs to, if applicable.
+ ///
+ [JsonProperty("application_id", NullValueHandling = NullValueHandling.Ignore)]
+ public ulong? ApplicationId { get; internal set; }
+
///
/// Gets the user this webhook was created by.
///
[JsonProperty("user", NullValueHandling = NullValueHandling.Ignore)]
public DiscordUser User { get; internal set; }
///
/// Gets the default name of this webhook.
///
[JsonProperty("name", NullValueHandling = NullValueHandling.Ignore)]
public string Name { get; internal set; }
///
/// Gets hash of the default avatar for this webhook.
///
[JsonProperty("avatar", NullValueHandling = NullValueHandling.Ignore)]
internal string AvatarHash { get; set; }
///
/// Gets the partial source guild for this webhook (For Channel Follower Webhooks).
///
[JsonProperty("source_guild", NullValueHandling = NullValueHandling.Ignore)]
public DiscordGuild SourceGuild { get; set; }
///
/// Gets the partial source channel for this webhook (For Channel Follower Webhooks).
///
[JsonProperty("source_channel", NullValueHandling = NullValueHandling.Ignore)]
public DiscordChannel SourceChannel { get; set; }
///
/// Gets the url used for executing the webhook.
///
[JsonProperty("url", NullValueHandling = NullValueHandling.Ignore)]
public string Url { get; set; }
///
/// Gets the default avatar url for this webhook.
///
public string AvatarUrl
=> !string.IsNullOrWhiteSpace(this.AvatarHash) ? $"{DiscordDomain.GetDomain(CoreDomain.DiscordCdn).Url}{Endpoints.AVATARS}/{this.Id}/{this.AvatarHash}.png?size=1024" : null;
///
/// Gets the secure token of this webhook.
///
[JsonProperty("token", NullValueHandling = NullValueHandling.Ignore)]
public string Token { get; internal set; }
///
/// Initializes a new instance of the class.
///
internal DiscordWebhook()
+ : base(new List() { "type" })
{ }
///
/// Modifies this webhook.
///
/// New default name for this webhook.
/// New avatar for this webhook.
/// The new channel id to move the webhook to.
/// Reason for audit logs.
/// The modified webhook.
/// Thrown when the client does not have the permission.
/// Thrown when the webhook does not exist.
/// Thrown when an invalid parameter was provided.
/// Thrown when Discord is unable to process the request.
public Task ModifyAsync(string name = null, Optional avatar = default, ulong? channelId = null, string reason = null)
{
var avatarb64 = ImageTool.Base64FromStream(avatar);
var newChannelId = channelId ?? this.ChannelId;
return this.Discord.ApiClient.ModifyWebhookAsync(this.Id, newChannelId, name, avatarb64, reason);
}
///
/// Gets a previously-sent webhook message.
///
/// Thrown when the webhook does not exist.
/// Thrown when an invalid parameter was provided.
/// Thrown when Discord is unable to process the request.
public Task GetMessageAsync(ulong messageId)
=> (this.Discord?.ApiClient ?? this.ApiClient).GetWebhookMessageAsync(this.Id, this.Token, messageId);
///
/// Tries to get a previously-sent webhook message.
///
/// Thrown when an invalid parameter was provided.
/// Thrown when Discord is unable to process the request.
#pragma warning disable CS8632 // The annotation for nullable reference types should only be used in code within a '#nullable' annotations context.
public async Task TryGetMessageAsync(ulong messageId)
#pragma warning restore CS8632 // The annotation for nullable reference types should only be used in code within a '#nullable' annotations context.
{
try
{
return await this.GetMessageAsync(messageId).ConfigureAwait(false);
}
catch (NotFoundException)
{
return null;
}
}
///
/// Gets a previously-sent webhook message.
///
/// Thrown when the webhook does not exist.
/// Thrown when an invalid parameter was provided.
/// Thrown when Discord is unable to process the request.
public Task GetMessageAsync(ulong messageId, ulong threadId)
=> (this.Discord?.ApiClient ?? this.ApiClient).GetWebhookMessageAsync(this.Id, this.Token, messageId, threadId);
///
/// Tries to get a previously-sent webhook message.
///
/// Thrown when an invalid parameter was provided.
/// Thrown when Discord is unable to process the request.
public async Task TryGetMessageAsync(ulong messageId, ulong threadId)
{
try
{
return await this.GetMessageAsync(messageId, threadId).ConfigureAwait(false);
}
catch (NotFoundException)
{
return null;
}
}
///
/// Permanently deletes this webhook.
///
/// Thrown when the client does not have the permission.
/// Thrown when the webhook does not exist.
/// Thrown when an invalid parameter was provided.
/// Thrown when Discord is unable to process the request.
public Task DeleteAsync()
- => this.Discord.ApiClient.DeleteWebhookAsync(this.Id, this.Token);
+ => (this.Discord?.ApiClient ?? this.ApiClient).DeleteWebhookAsync(this.Id, this.Token);
///
/// Executes this webhook with the given .
///
/// Webhook builder filled with data to send.
/// Target thread id (Optional). Defaults to null.
/// Thrown when the webhook does not exist.
/// Thrown when an invalid parameter was provided.
/// Thrown when Discord is unable to process the request.
public Task ExecuteAsync(DiscordWebhookBuilder builder, string threadId = null)
=> (this.Discord?.ApiClient ?? this.ApiClient).ExecuteWebhookAsync(this.Id, this.Token, builder, threadId);
///
/// Executes this webhook in Slack compatibility mode.
///
/// JSON containing Slack-compatible payload for this webhook.
/// Target thread id (Optional). Defaults to null.
/// Thrown when the webhook does not exist.
/// Thrown when an invalid parameter was provided.
/// Thrown when Discord is unable to process the request.
public Task ExecuteSlackAsync(string json, string threadId = null)
=> (this.Discord?.ApiClient ?? this.ApiClient).ExecuteWebhookSlackAsync(this.Id, this.Token, json, threadId);
///
/// Executes this webhook in GitHub compatibility mode.
///
/// JSON containing GitHub-compatible payload for this webhook.
/// Target thread id (Optional). Defaults to null.
/// Thrown when the webhook does not exist.
/// Thrown when an invalid parameter was provided.
/// Thrown when Discord is unable to process the request.
public Task ExecuteGithubAsync(string json, string threadId = null)
=> (this.Discord?.ApiClient ?? this.ApiClient).ExecuteWebhookGithubAsync(this.Id, this.Token, json, threadId);
///
/// Edits a previously-sent webhook message.
///
/// The id of the message to edit.
/// The builder of the message to edit.
/// Target thread id (Optional). Defaults to null.
/// The modified
/// Thrown when the webhook does not exist.
/// Thrown when an invalid parameter was provided.
/// Thrown when Discord is unable to process the request.
public async Task EditMessageAsync(ulong messageId, DiscordWebhookBuilder builder, string threadId = null)
{
builder.Validate(true);
if (builder.KeepAttachmentsInternal.HasValue && builder.KeepAttachmentsInternal.Value)
{
builder.AttachmentsInternal.AddRange(this.ApiClient.GetWebhookMessageAsync(this.Id, this.Token, messageId.ToString(), threadId).Result.Attachments);
}
else if (builder.KeepAttachmentsInternal.HasValue)
{
builder.AttachmentsInternal.Clear();
}
return await (this.Discord?.ApiClient ?? this.ApiClient).EditWebhookMessageAsync(this.Id, this.Token, messageId.ToString(), builder, threadId).ConfigureAwait(false);
}
///
/// Deletes a message that was created by the webhook.
///
/// The id of the message to delete
/// Thrown when the webhook does not exist.
/// Thrown when an invalid parameter was provided.
/// Thrown when Discord is unable to process the request.
public Task DeleteMessageAsync(ulong messageId)
=> (this.Discord?.ApiClient ?? this.ApiClient).DeleteWebhookMessageAsync(this.Id, this.Token, messageId);
///
/// Deletes a message that was created by the webhook.
///
/// The id of the message to delete
/// Target thread id (Optional). Defaults to null.
/// Thrown when the webhook does not exist.
/// Thrown when an invalid parameter was provided.
/// Thrown when Discord is unable to process the request.
public Task DeleteMessageAsync(ulong messageId, ulong threadId)
=> (this.Discord?.ApiClient ?? this.ApiClient).DeleteWebhookMessageAsync(this.Id, this.Token, messageId, threadId);
///
/// Checks whether this is equal to another object.
///
/// Object to compare to.
/// Whether the object is equal to this .
public override bool Equals(object obj) => this.Equals(obj as DiscordWebhook);
///
/// Checks whether this is equal to another .
///
/// to compare to.
/// Whether the is equal to this .
public bool Equals(DiscordWebhook e) => e is not null && (ReferenceEquals(this, e) || this.Id == e.Id);
///
/// Gets the hash code for this .
///
/// The hash code for this .
public override int GetHashCode() => this.Id.GetHashCode();
///
/// Gets whether the two objects are equal.
///
/// First webhook to compare.
/// Second webhook to compare.
/// Whether the two webhooks are equal.
public static bool operator ==(DiscordWebhook e1, DiscordWebhook e2)
{
var o1 = e1 as object;
var o2 = e2 as object;
return (o1 != null || o2 == null) && (o1 == null || o2 != null) && ((o1 == null && o2 == null) || e1.Id == e2.Id);
}
///
/// Gets whether the two objects are not equal.
///
/// First webhook to compare.
/// Second webhook to compare.
/// Whether the two webhooks are not equal.
public static bool operator !=(DiscordWebhook e1, DiscordWebhook e2)
=> !(e1 == e2);
}