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). ///