From f64d9d6f22f189f6bacffd4585242b8f0a2b530c Mon Sep 17 00:00:00 2001
From: Mihail Gribkov <61027276+Misha-133@users.noreply.github.com>
Date: Sat, 18 Nov 2023 23:38:36 +0300
Subject: [PATCH] [Feature] Avatar decorations support (#2782)
* yup
* nullable...
* add props & methos to `GuildUser` & `IUser`
---
src/Discord.Net.Core/CDN.cs | 10 ++++++++
src/Discord.Net.Core/Entities/Users/IUser.cs | 25 +++++++++++++++++++
.../API/Common/AvatarDecorationData.cs | 12 +++++++++
src/Discord.Net.Rest/API/Common/User.cs | 3 +++
.../Entities/Users/RestUser.cs | 19 ++++++++++++++
.../Entities/Users/SocketUser.cs | 21 ++++++++++++++++
6 files changed, 90 insertions(+)
create mode 100644 src/Discord.Net.Rest/API/Common/AvatarDecorationData.cs
diff --git a/src/Discord.Net.Core/CDN.cs b/src/Discord.Net.Core/CDN.cs
index 95f20833..ecce668f 100644
--- a/src/Discord.Net.Core/CDN.cs
+++ b/src/Discord.Net.Core/CDN.cs
@@ -257,5 +257,15 @@ namespace Discord
_ => throw new ArgumentException(nameof(format)),
};
}
+
+ ///
+ /// Gets an avatar decoration url based off the hash.
+ ///
+ /// The hash of the avatar decoraition.
+ ///
+ /// A URL to the avatar decoration.
+ ///
+ public static string GetAvatarDecorationUrl(string avatarDecorationHash)
+ => $"{DiscordConfig.CDNUrl}avatar-decoration-presets/{avatarDecorationHash}.png";
}
}
diff --git a/src/Discord.Net.Core/Entities/Users/IUser.cs b/src/Discord.Net.Core/Entities/Users/IUser.cs
index a07e73e9..9c3dfb07 100644
--- a/src/Discord.Net.Core/Entities/Users/IUser.cs
+++ b/src/Discord.Net.Core/Entities/Users/IUser.cs
@@ -95,6 +95,22 @@ namespace Discord
///
string GlobalName { get; }
+ ///
+ /// Gets the hash of the avatar decoration.
+ ///
+ ///
+ /// if the user has no avatar decoration set.
+ ///
+ string AvatarDecorationHash { get; }
+
+ ///
+ /// Gets the id of the avatar decoration's SKU.
+ ///
+ ///
+ /// if the user has no avatar decoration set.
+ ///
+ ulong? AvatarDecorationSkuId { get; }
+
///
/// Creates the direct message channel of this user.
///
@@ -120,5 +136,14 @@ namespace Discord
/// contains the DM channel associated with this user.
///
Task CreateDMChannelAsync(RequestOptions options = null);
+
+
+ ///
+ /// Gets the URL for user's avatar decoration.
+ ///
+ ///
+ /// if the user has no avatar decoration set.
+ ///
+ string GetAvatarDecorationUrl();
}
}
diff --git a/src/Discord.Net.Rest/API/Common/AvatarDecorationData.cs b/src/Discord.Net.Rest/API/Common/AvatarDecorationData.cs
new file mode 100644
index 00000000..7bfe5905
--- /dev/null
+++ b/src/Discord.Net.Rest/API/Common/AvatarDecorationData.cs
@@ -0,0 +1,12 @@
+using Newtonsoft.Json;
+
+namespace Discord.API;
+
+internal class AvatarDecorationData
+{
+ [JsonProperty("asset")]
+ public string Asset { get; set; }
+
+ [JsonProperty("sku_id")]
+ public ulong SkuId { get; set; }
+}
diff --git a/src/Discord.Net.Rest/API/Common/User.cs b/src/Discord.Net.Rest/API/Common/User.cs
index 31235981..64a04f25 100644
--- a/src/Discord.Net.Rest/API/Common/User.cs
+++ b/src/Discord.Net.Rest/API/Common/User.cs
@@ -22,6 +22,9 @@ namespace Discord.API
[JsonProperty("global_name")]
public Optional GlobalName { get; set; }
+ [JsonProperty("avatar_decoration_data")]
+ public Optional AvatarDecoration { get; set; }
+
//CurrentUser
[JsonProperty("verified")]
public Optional Verified { get; set; }
diff --git a/src/Discord.Net.Rest/Entities/Users/RestUser.cs b/src/Discord.Net.Rest/Entities/Users/RestUser.cs
index cdba3e2d..43541c0a 100644
--- a/src/Discord.Net.Rest/Entities/Users/RestUser.cs
+++ b/src/Discord.Net.Rest/Entities/Users/RestUser.cs
@@ -4,6 +4,7 @@ using System.Collections.Immutable;
using System.Diagnostics;
using System.Globalization;
using System.Threading.Tasks;
+
using EventUserModel = Discord.API.GuildScheduledEventUser;
using Model = Discord.API.User;
@@ -50,6 +51,13 @@ namespace Discord.Rest
///
public virtual bool IsWebhook => false;
+ ///
+ public string AvatarDecorationHash { get; private set; }
+
+ ///
+ public ulong? AvatarDecorationSkuId { get; private set; }
+
+
internal RestUser(BaseDiscordClient discord, ulong id)
: base(discord, id)
{
@@ -96,6 +104,11 @@ namespace Discord.Rest
PublicFlags = model.PublicFlags.Value;
if (model.GlobalName.IsSpecified)
GlobalName = model.GlobalName.Value;
+ if (model.AvatarDecoration is { IsSpecified: true, Value: not null })
+ {
+ AvatarDecorationHash = model.AvatarDecoration.Value?.Asset;
+ AvatarDecorationSkuId = model.AvatarDecoration.Value?.SkuId;
+ }
}
///
@@ -129,6 +142,12 @@ namespace Discord.Rest
? CDN.GetDefaultUserAvatarUrl(DiscriminatorValue)
: CDN.GetDefaultUserAvatarUrl(Id);
+ ///
+ public string GetAvatarDecorationUrl()
+ => AvatarDecorationHash is not null
+ ? CDN.GetAvatarDecorationUrl(AvatarDecorationHash)
+ : null;
+
///
/// Gets the Username#Discriminator of the user.
///
diff --git a/src/Discord.Net.WebSocket/Entities/Users/SocketUser.cs b/src/Discord.Net.WebSocket/Entities/Users/SocketUser.cs
index 57444766..54b0cbff 100644
--- a/src/Discord.Net.WebSocket/Entities/Users/SocketUser.cs
+++ b/src/Discord.Net.WebSocket/Entities/Users/SocketUser.cs
@@ -47,6 +47,13 @@ namespace Discord.WebSocket
public IReadOnlyCollection ActiveClients => Presence.ActiveClients ?? ImmutableHashSet.Empty;
///
public IReadOnlyCollection Activities => Presence.Activities ?? ImmutableList.Empty;
+
+ ///
+ public string AvatarDecorationHash { get; private set; }
+
+ ///
+ public ulong? AvatarDecorationSkuId { get; private set; }
+
///
/// Gets mutual guilds shared with this user.
///
@@ -98,6 +105,14 @@ namespace Discord.WebSocket
GlobalName = model.GlobalName.Value;
hasChanges = true;
}
+ if (model.AvatarDecoration is { IsSpecified: true, Value: not null }
+ && (model.AvatarDecoration.Value.Asset != AvatarDecorationHash || model.AvatarDecoration.Value.SkuId != AvatarDecorationSkuId))
+ {
+ AvatarDecorationHash = model.AvatarDecoration.Value?.Asset;
+ AvatarDecorationSkuId = model.AvatarDecoration.Value?.SkuId;
+ hasChanges = true;
+ }
+
return hasChanges;
}
@@ -121,6 +136,12 @@ namespace Discord.WebSocket
? CDN.GetDefaultUserAvatarUrl(DiscriminatorValue)
: CDN.GetDefaultUserAvatarUrl(Id);
+ ///
+ public string GetAvatarDecorationUrl()
+ => AvatarDecorationHash is not null
+ ? CDN.GetAvatarDecorationUrl(AvatarDecorationHash)
+ : null;
+
///
/// Gets the full name of the user (e.g. Example#0001).
///