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
{