diff --git a/src/Kook.Net.Core/Entities/Roles/ColorType.cs b/src/Kook.Net.Core/Entities/Roles/ColorType.cs new file mode 100644 index 00000000..c333e120 --- /dev/null +++ b/src/Kook.Net.Core/Entities/Roles/ColorType.cs @@ -0,0 +1,16 @@ +namespace Kook; + +/// +/// Represents the type of color a role has. +/// +public enum ColorType : ushort +{ + /// + /// The color is a solid color. + /// + Solid = 1, + /// + /// The color is a gradient. + /// + Gradient = 2 +} diff --git a/src/Kook.Net.Core/Entities/Roles/GradientColor.cs b/src/Kook.Net.Core/Entities/Roles/GradientColor.cs new file mode 100644 index 00000000..ffc79046 --- /dev/null +++ b/src/Kook.Net.Core/Entities/Roles/GradientColor.cs @@ -0,0 +1,26 @@ +namespace Kook; + +/// +/// Represents a gradient color. +/// +public struct GradientColor +{ + public GradientColor(Color left, Color right) + { + Left = left; + Right = right; + } + + /// + /// The left color of the gradient. + /// + public Color Left { get; } + + /// + /// The right color of the gradient. + /// + public Color Right { get; } + + public static implicit operator (Color Left, Color Right)(GradientColor gradient) => (gradient.Left, gradient.Right); + public static implicit operator GradientColor((Color Left, Color Right) gradient) => new(gradient.Left, gradient.Right); +} diff --git a/src/Kook.Net.Core/Entities/Roles/IRole.cs b/src/Kook.Net.Core/Entities/Roles/IRole.cs index 01b4293a..c39732ad 100644 --- a/src/Kook.Net.Core/Entities/Roles/IRole.cs +++ b/src/Kook.Net.Core/Entities/Roles/IRole.cs @@ -36,6 +36,21 @@ public interface IRole : IEntity, IDeletable, IMentionable, IComparable Color Color { get; } /// + /// Gets the type of the color given to users of this role. + /// + /// + /// A struct representing the color type of this role. + /// + ColorType ColorType { get; } + /// + /// Gets the gradient color given to users of this role. + /// + /// + /// A struct representing the gradient color of this role; + /// null if the role does not have a gradient color. + /// + GradientColor? GradientColor { get; } + /// /// Gets this role's position relative to other roles in the same guild. /// /// diff --git a/src/Kook.Net.Rest/API/Common/Role.cs b/src/Kook.Net.Rest/API/Common/Role.cs index baa824bf..a759aeac 100644 --- a/src/Kook.Net.Rest/API/Common/Role.cs +++ b/src/Kook.Net.Rest/API/Common/Role.cs @@ -15,6 +15,13 @@ internal class Role [JsonConverter(typeof(RawValueColorConverter))] public Color Color { get; set; } + [JsonPropertyName("color_type")] + public ColorType ColorType { get; set; } + + [JsonPropertyName("color_map")] + [JsonConverter(typeof(NullableGradientColorConverter))] + public GradientColor? GradientColor { get; set; } + [JsonPropertyName("position")] public int Position { get; set; } diff --git a/src/Kook.Net.Rest/Entities/Roles/RestRole.cs b/src/Kook.Net.Rest/Entities/Roles/RestRole.cs index 7aa0c8b5..2686674a 100644 --- a/src/Kook.Net.Rest/Entities/Roles/RestRole.cs +++ b/src/Kook.Net.Rest/Entities/Roles/RestRole.cs @@ -24,6 +24,10 @@ public class RestRole : RestEntity, IRole /// public Color Color { get; private set; } /// + public ColorType ColorType { get; private set; } + /// + public GradientColor? GradientColor { get; private set; } + /// public bool IsHoisted { get; private set; } /// public bool IsMentionable { get; private set; } @@ -61,10 +65,12 @@ internal void Update(Model model) { Name = model.Name; Type = model.Type; + Color = model.Color; + ColorType = model.ColorType; + GradientColor = model.GradientColor; IsHoisted = model.Hoist == 1; IsMentionable = model.Mentionable == 1; Position = model.Position; - Color = model.Color; Permissions = new GuildPermissions(model.Permissions); } diff --git a/src/Kook.Net.Rest/Net/Converters/NullableGradientColorConverter.cs b/src/Kook.Net.Rest/Net/Converters/NullableGradientColorConverter.cs new file mode 100644 index 00000000..455c0b2f --- /dev/null +++ b/src/Kook.Net.Rest/Net/Converters/NullableGradientColorConverter.cs @@ -0,0 +1,70 @@ +using System.Text.Json; +using System.Text.Json.Serialization; + +namespace Kook.Net.Converters; + +internal class NullableGradientColorConverter : JsonConverter +{ + /// + public override GradientColor? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + { + if (reader.TokenType == JsonTokenType.StartObject) + { + reader.Read(); + if (reader.TokenType != JsonTokenType.PropertyName) + throw new JsonException($"{nameof(NullableGradientColorConverter)} expects property name token, but got {reader.TokenType}"); + string propertyName = reader.GetString(); + if (propertyName != "color_list") + throw new JsonException($"{nameof(NullableGradientColorConverter)} expects property name 'color_list', but got {propertyName}"); + reader.Read(); + if (reader.TokenType != JsonTokenType.StartArray) + throw new JsonException($"{nameof(NullableGradientColorConverter)} expects start array token, but got {reader.TokenType}"); + reader.Read(); + if (reader.TokenType != JsonTokenType.Number) + throw new JsonException($"{nameof(NullableGradientColorConverter)} expects number token, but got {reader.TokenType}"); + var left = reader.GetUInt32(); + reader.Read(); + if (reader.TokenType != JsonTokenType.Number) + throw new JsonException($"{nameof(NullableGradientColorConverter)} expects number token, but got {reader.TokenType}"); + var right = reader.GetUInt32(); + reader.Read(); + if (reader.TokenType != JsonTokenType.EndArray) + throw new JsonException($"{nameof(NullableGradientColorConverter)} expects end array token, but got {reader.TokenType}"); + reader.Read(); + if (reader.TokenType != JsonTokenType.EndObject) + throw new JsonException($"{nameof(NullableGradientColorConverter)} expects end object token, but got {reader.TokenType}"); + return new GradientColor(new Color(left), new Color(right)); + } + + if (reader.TokenType == JsonTokenType.StartArray) + { + reader.Read(); + if (reader.TokenType != JsonTokenType.EndArray) + throw new JsonException($"{nameof(NullableGradientColorConverter)} expects end array token, but got {reader.TokenType}"); + return null; + } + + throw new JsonException( + $"{nameof(NullableGradientColorConverter)} expects start object or start array token, but got {reader.TokenType}"); + } + + /// + public override void Write(Utf8JsonWriter writer, GradientColor? value, JsonSerializerOptions options) + { + if (value.HasValue) + { + writer.WriteStartObject(); + writer.WritePropertyName("color_list"); + writer.WriteStartArray(); + writer.WriteNumberValue(value.Value.Left); + writer.WriteNumberValue(value.Value.Right); + writer.WriteEndArray(); + writer.WriteEndObject(); + } + else + { + writer.WriteStartArray(); + writer.WriteEndArray(); + } + } +} diff --git a/src/Kook.Net.Rest/Net/Converters/NullableNumberBooleanConverter.cs b/src/Kook.Net.Rest/Net/Converters/NullableNumberBooleanConverter.cs index 36d8f594..9b67ceba 100644 --- a/src/Kook.Net.Rest/Net/Converters/NullableNumberBooleanConverter.cs +++ b/src/Kook.Net.Rest/Net/Converters/NullableNumberBooleanConverter.cs @@ -3,7 +3,7 @@ namespace Kook.Net.Converters; -public class NullableNumberBooleanConverter : JsonConverter +internal class NullableNumberBooleanConverter : JsonConverter { public override bool? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { diff --git a/src/Kook.Net.Rest/Net/Converters/NumberBooleanConverter.cs b/src/Kook.Net.Rest/Net/Converters/NumberBooleanConverter.cs index 9f5d528b..38aa5fc6 100644 --- a/src/Kook.Net.Rest/Net/Converters/NumberBooleanConverter.cs +++ b/src/Kook.Net.Rest/Net/Converters/NumberBooleanConverter.cs @@ -3,7 +3,7 @@ namespace Kook.Net.Converters; -public class NumberBooleanConverter : JsonConverter +internal class NumberBooleanConverter : JsonConverter { public override bool Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { diff --git a/src/Kook.Net.WebSocket/Entities/Roles/SocketRole.cs b/src/Kook.Net.WebSocket/Entities/Roles/SocketRole.cs index 141b5494..cf4e45e8 100644 --- a/src/Kook.Net.WebSocket/Entities/Roles/SocketRole.cs +++ b/src/Kook.Net.WebSocket/Entities/Roles/SocketRole.cs @@ -28,6 +28,10 @@ public class SocketRole : SocketEntity, IRole /// public Color Color { get; private set; } /// + public ColorType ColorType { get; private set; } + /// + public GradientColor? GradientColor { get; private set; } + /// public int Position { get; private set; } /// public bool IsHoisted { get; private set; } @@ -64,6 +68,8 @@ internal void Update(ClientState state, Model model) Name = model.Name; Type = model.Type; Color = model.Color; + ColorType = model.ColorType; + GradientColor = model.GradientColor; Position = model.Position; IsHoisted = model.Hoist switch {