diff --git a/Discord.API/DataTypes/ChannelData.cs b/Discord.API/DataTypes/ChannelData.cs index e48c17d..a55c69b 100644 --- a/Discord.API/DataTypes/ChannelData.cs +++ b/Discord.API/DataTypes/ChannelData.cs @@ -5,7 +5,7 @@ namespace Discord.API; public class ChannelData { public required ulong Id { get; init; } - public int? Type { get; init; } + public required int Type { get; init; } public ulong? GuildId { get; init; } public int? Position { get; init; } public string? Name { get; init; } diff --git a/Discord.API/DataTypes/GuildCreateData.cs b/Discord.API/DataTypes/GuildCreateData.cs new file mode 100644 index 0000000..56a0cfd --- /dev/null +++ b/Discord.API/DataTypes/GuildCreateData.cs @@ -0,0 +1,10 @@ +namespace Discord.API; + +public class GuildCreateData : GuildData{ + public required DateTime JoinedAt { get; init; } + public required bool Large { get; init; } + public required uint MemberCount { get; init; } + public required VoiceStateData[] VoiceStates { get; init; } + public required GuildMemberData[] Members { get; init; } + public required ChannelData[] Channels { get; init; } +} \ No newline at end of file diff --git a/Discord.API/DataTypes/GuildData.cs b/Discord.API/DataTypes/GuildData.cs index 829b162..fe9098f 100644 --- a/Discord.API/DataTypes/GuildData.cs +++ b/Discord.API/DataTypes/GuildData.cs @@ -1,20 +1,20 @@ +using System.Text.Json.Serialization; + namespace Discord.API; -public class GuildData : UnavailableGuildData + +[JsonPolymorphic(UnknownDerivedTypeHandling = JsonUnknownDerivedTypeHandling.FallBackToNearestAncestor)] +[JsonDerivedType(typeof(GuildCreateData))] +[JsonDerivedType(typeof(GuildUpdateData))] +public abstract class GuildData : UnavailableGuildData { public override bool Unavailable => false; - public string? Name { get; init; } - public ulong? AfkChannelId { get; init; } - public int? AfkTimeout { get; init; } - public RoleData[]? Roles { get; init; } - public ulong? SystemChannelId { get; init; } - public uint? SystemChannelFlags { get; init; } - public string? Description { get; init; } - public int? NsfwLevel { get; init; } - public DateTime? JoinedAt { get; init; } - public bool? Large { get; init; } - public uint? MemberCount { get; init; } - public VoiceStateData[]? VoiceStates { get; init; } - public GuildMemberData[]? Members { get; init; } - public ChannelData[]? Channels { get; init; } + public required string Name { get; init; } + public required ulong? AfkChannelId { get; init; } + public required int AfkTimeout { get; init; } + public required RoleData[] Roles { get; init; } + public required ulong? SystemChannelId { get; init; } + public required uint SystemChannelFlags { get; init; } + public required string? Description { get; init; } + public required int NsfwLevel { get; init; } } \ No newline at end of file diff --git a/Discord.API/DataTypes/GuildDataConverter.cs b/Discord.API/DataTypes/GuildDataConverter.cs index 9cdfed3..04f353f 100644 --- a/Discord.API/DataTypes/GuildDataConverter.cs +++ b/Discord.API/DataTypes/GuildDataConverter.cs @@ -3,49 +3,31 @@ using System.Text.Json.Serialization; namespace Discord.API; -internal class GuildDataConverter : JsonConverter +internal class GuildDataConverter : JsonConverter { - public override UnavailableGuildData? Read(ref Utf8JsonReader reader, Type typeToConvert, - JsonSerializerOptions options) + public override GuildData? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { JsonDocument json_doc = JsonDocument.ParseValue(ref reader); - if (!json_doc.RootElement.TryGetProperty("unavailable", out var unavailable_prop) || - unavailable_prop.ValueKind == JsonValueKind.False) - { - return json_doc.Deserialize(SourceGenerationContext.Default.GuildData); - } - else - { - if (json_doc.RootElement.TryGetProperty("id", out var id_prop) && - id_prop.ValueKind is JsonValueKind.String or JsonValueKind.Number) - { - ulong id = id_prop.ValueKind switch - { - JsonValueKind.Number => id_prop.GetUInt64(), - JsonValueKind.String => ulong.Parse(id_prop.GetString() ?? "") - }; - return new UnavailableGuildData() - { - Id = id - }; - } - else - { - throw new JsonException("Id property not found in guild data"); - } + if(json_doc.RootElement.TryGetProperty("joined_at", out _)){ + return json_doc.Deserialize(SourceGenerationContext.Default.GuildCreateData); + }else{ + return json_doc.Deserialize(SourceGenerationContext.Default.GuildUpdateData); } } - public override void Write(Utf8JsonWriter writer, UnavailableGuildData value, JsonSerializerOptions options) + public override void Write(Utf8JsonWriter writer, GuildData value, JsonSerializerOptions options) { - if (value is GuildData) - { - writer.WriteRawValue(JsonSerializer.SerializeToUtf8Bytes(value, SourceGenerationContext.Default.GuildData)); - } - else - { - writer.WriteStartObject(); - writer.WriteBoolean("unavailable", true); + switch(value){ + case GuildCreateData gcd: + writer.WriteRawValue(JsonSerializer.SerializeToUtf8Bytes(gcd, SourceGenerationContext.Default.GuildCreateData)); + break; + case GuildUpdateData gud: + writer.WriteRawValue(JsonSerializer.SerializeToUtf8Bytes(gud, SourceGenerationContext.Default.GuildUpdateData)); + break; + default: + writer.WriteStartObject(); + writer.WriteEndObject(); + break; } } } \ No newline at end of file diff --git a/Discord.API/DataTypes/GuildUpdateData.cs b/Discord.API/DataTypes/GuildUpdateData.cs new file mode 100644 index 0000000..8ca81fe --- /dev/null +++ b/Discord.API/DataTypes/GuildUpdateData.cs @@ -0,0 +1,5 @@ +namespace Discord.API; + +public class GuildUpdateData : GuildData{ + +} \ No newline at end of file diff --git a/Discord.API/DataTypes/UnavailableGuildDataConverter.cs b/Discord.API/DataTypes/UnavailableGuildDataConverter.cs new file mode 100644 index 0000000..2c6a460 --- /dev/null +++ b/Discord.API/DataTypes/UnavailableGuildDataConverter.cs @@ -0,0 +1,52 @@ +using System.Text.Json; +using System.Text.Json.Serialization; + +namespace Discord.API; + +internal class UnavailableGuildDataConverter : JsonConverter +{ + public override UnavailableGuildData? Read(ref Utf8JsonReader reader, Type typeToConvert, + JsonSerializerOptions options) + { + JsonDocument json_doc = JsonDocument.ParseValue(ref reader); + if (!json_doc.RootElement.TryGetProperty("unavailable", out var unavailable_prop) || + unavailable_prop.ValueKind == JsonValueKind.False) + { + return json_doc.Deserialize(SourceGenerationContext.Default.GuildData); + } + else + { + if (json_doc.RootElement.TryGetProperty("id", out var id_prop) && + id_prop.ValueKind is JsonValueKind.String or JsonValueKind.Number) + { + ulong id = id_prop.ValueKind switch + { + JsonValueKind.Number => id_prop.GetUInt64(), + JsonValueKind.String => ulong.Parse(id_prop.GetString() ?? ""), + _ => throw new JsonException("This should be impossible") + }; + return new UnavailableGuildData() + { + Id = id + }; + } + else + { + throw new JsonException("Id property not found in guild data"); + } + } + } + + public override void Write(Utf8JsonWriter writer, UnavailableGuildData value, JsonSerializerOptions options) + { + if (value is GuildData) + { + writer.WriteRawValue(JsonSerializer.SerializeToUtf8Bytes(value, SourceGenerationContext.Default.GuildData)); + } + else + { + writer.WriteStartObject(); + writer.WriteBoolean("unavailable", true); + } + } +} \ No newline at end of file diff --git a/Discord.API/SourceGenerationContext.cs b/Discord.API/SourceGenerationContext.cs index 950be11..6496f22 100644 --- a/Discord.API/SourceGenerationContext.cs +++ b/Discord.API/SourceGenerationContext.cs @@ -10,7 +10,7 @@ using System.Text.Json; IgnoreReadOnlyProperties = false, IncludeFields = true, PropertyNamingPolicy = JsonKnownNamingPolicy.SnakeCaseLower, - Converters = [typeof(GatewayPacketConverter), typeof(GuildDataConverter)], + Converters = [typeof(GatewayPacketConverter), typeof(UnavailableGuildDataConverter)], NumberHandling = JsonNumberHandling.AllowReadingFromString )] [JsonSerializable(typeof(GatewayPacket))]