diff --git a/extra/admin-api/Models/Spacebar.Models.Gateway/GuildMemberListUpdate.cs b/extra/admin-api/Models/Spacebar.Models.Gateway/GuildMemberListUpdate.cs index d1692cc79..f9d11b3ac 100644 --- a/extra/admin-api/Models/Spacebar.Models.Gateway/GuildMemberListUpdate.cs +++ b/extra/admin-api/Models/Spacebar.Models.Gateway/GuildMemberListUpdate.cs @@ -103,7 +103,7 @@ public class GuildMemberListSyncItemJsonConverter : JsonConverter(ref reader, options); if (n.ContainsKey("group")) return n.Deserialize(); - if (n.ContainsKey("member")) return n.Deserialize(); + if (n.ContainsKey("member")) return n.Deserialize(); throw new InvalidOperationException("Could not determine sync item type for keys " + string.Join(", ", n.Select(x => x.Key))); } diff --git a/extra/admin-api/Models/Spacebar.Models.Generic/Member.cs b/extra/admin-api/Models/Spacebar.Models.Generic/Member.cs index bb01fc47d..6cb1c6bbe 100644 --- a/extra/admin-api/Models/Spacebar.Models.Generic/Member.cs +++ b/extra/admin-api/Models/Spacebar.Models.Generic/Member.cs @@ -51,8 +51,131 @@ public class MemberJsonConverter : JsonConverter { public override Member? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { - throw new NotImplementedException(); // TODO + if (reader.TokenType == JsonTokenType.Null) + return null; + + using var document = JsonDocument.ParseValue(ref reader); + var jsonObject = document.RootElement; + if (jsonObject.ValueKind != JsonValueKind.Object) + throw new JsonException("Expected member payload to be a JSON object."); + + var hasPresence = jsonObject.TryGetProperty("presence", out _); + Member member = hasPresence + ? new MemberWithPresence { User = null! } + : new Member { User = null! }; + var hasUser = false; + + foreach (var property in jsonObject.EnumerateObject()) + { + switch (property.Name) + { + case "user": + member.User = property.Value.Deserialize(options) ?? throw new JsonException("The required member user field is invalid."); + hasUser = true; + + break; + case "nick": + member.Nick = property.Value.ValueKind == JsonValueKind.Null ? null : property.Value.GetString(); + break; + case "avatar": + member.Avatar = property.Value.ValueKind == JsonValueKind.Null ? null : property.Value.GetString(); + break; + case "avatar_decoration_data": + member.AvatarDecorationData = property.Value.ValueKind == JsonValueKind.Null ? null : JsonNode.Parse(property.Value.GetRawText()) as JsonObject; + break; + case "collectibles": + member.Collectibles = property.Value.ValueKind == JsonValueKind.Null ? null : JsonNode.Parse(property.Value.GetRawText()) as JsonObject; + break; + case "display_name_styles": + if (property.Value.ValueKind != JsonValueKind.Null) + member.DisplayNameStyles = property.Value.Deserialize(options); + break; + case "banner": + member.Banner = property.Value.ValueKind == JsonValueKind.Null ? null : property.Value.GetString(); + break; + case "bio": + member.Bio = property.Value.ValueKind == JsonValueKind.Null ? null : property.Value.GetString(); + break; + case "roles": + if (property.Value.ValueKind == JsonValueKind.Null) + { + member.Roles = null; + break; + } + + if (property.Value.ValueKind != JsonValueKind.Array) + throw new JsonException("Expected roles to be an array."); + + member.Roles = new List(); + foreach (var role in property.Value.EnumerateArray()) + { + switch (role.ValueKind) + { + case JsonValueKind.Number: + member.Roles.Add(role.GetInt64()); + break; + case JsonValueKind.String: + if (!long.TryParse(role.GetString(), out var roleId)) + throw new JsonException("Invalid role id."); + member.Roles.Add(roleId); + break; + default: + throw new JsonException("Invalid role id value kind."); + } + } + + break; + case "presence": + if (member is MemberWithPresence memberWithPresence && property.Value.ValueKind != JsonValueKind.Null) + memberWithPresence.Presence = property.Value.Deserialize(options); + break; + } + } + + if (!hasUser) + throw new JsonException("The required member user field is missing."); + + return member; } - public override void Write(Utf8JsonWriter writer, Member value, JsonSerializerOptions options) => JsonSerializer.Serialize(writer, value, value.GetType(), options); + public override void Write(Utf8JsonWriter writer, Member value, JsonSerializerOptions options) + { + writer.WriteStartObject(); + { + writer.WritePropertyName("user"); + JsonSerializer.Serialize(writer, value.User); + + if (value.Nick != null) writer.WriteString("nick", value.Nick); + if (value.Avatar != null) writer.WriteString("avatar", value.Avatar); + + if (value.AvatarDecorationData != null) + { + writer.WritePropertyName("avatar_decoration_data"); + JsonSerializer.Serialize(writer, value.AvatarDecorationData); + } + + if (value.Collectibles != null) + { + writer.WritePropertyName("collectibles"); + JsonSerializer.Serialize(writer, value.Collectibles); + } + + writer.WritePropertyName("display_name_styles"); + if (value.DisplayNameStyles != null) + { + JsonSerializer.Serialize(writer, value.DisplayNameStyles); + } + else writer.WriteNullValue(); + + if (value.Banner != null) writer.WriteString("banner", value.Banner); + if (value.Bio != null) writer.WriteString("bio", value.Bio); + + if (value.Roles != null) + { + writer.WritePropertyName("roles"); + JsonSerializer.Serialize(writer, value.Roles); + } + } + writer.WriteEndObject(); + } } \ No newline at end of file