using System.Text.Json; using Newtonsoft.Json; using Xunit.Abstractions; using JsonSerializer = System.Text.Json.JsonSerializer; namespace Discord.API.Tests; using Xunit; using Discord.API; public class JsonTests { private readonly ITestOutputHelper _testOutputHelper; public JsonTests(ITestOutputHelper testOutputHelper) { _testOutputHelper = testOutputHelper; } [Fact] public void GuildCreateDeserialize() { string src = """ { "op": 0, "t": "GUILD_CREATE", "s": 3, "d":{ "id": "197038439483310086", "name": "Discord Testers", "icon": "f64c482b807da4f539cff778d174971c", "description": "The official place to report Discord Bugs!", "splash": null, "discovery_splash": null, "features": [ "ANIMATED_ICON", "VERIFIED", "NEWS", "VANITY_URL", "DISCOVERABLE", "MORE_EMOJI", "INVITE_SPLASH", "BANNER", "COMMUNITY" ], "emojis": [], "banner": "9b6439a7de04f1d26af92f84ac9e1e4a", "owner_id": "73193882359173120", "application_id": null, "region": null, "afk_channel_id": null, "afk_timeout": 300, "system_channel_id": null, "widget_enabled": true, "widget_channel_id": null, "verification_level": 3, "roles": [], "default_message_notifications": 1, "mfa_level": 1, "explicit_content_filter": 2, "max_presences": 40000, "max_members": 250000, "vanity_url_code": "discord-testers", "premium_tier": 3, "premium_subscription_count": 33, "system_channel_flags": 0, "preferred_locale": "en-US", "rules_channel_id": "441688182833020939", "public_updates_channel_id": "281283303326089216", "safety_alerts_channel_id": "281283303326089216", "joined_at": "2024-06-27T11:59:36Z", "large": false, "member_count": 69, "voice_states": [ { "channel_id": "157733188964188161", "user_id": "80351110224678912", "session_id": "90326bd25d71d39b9ef95b299e3872ff", "deaf": false, "mute": false, "self_deaf": false, "self_mute": true, "suppress": false, "request_to_speak_timestamp": "2021-03-31T18:45:31.297561+00:00" } ], "members":[ { "user": { "id": "80351110224678912", "username": "Nelly", "discriminator": "1337", "avatar": "8342729096ea3675442027381ff50dfe", "verified": true, "email": "nelly@discord.com", "flags": 64, "banner": "06c16474723fe537c283b8efa61a30c8", "accent_color": 16711680, "premium_type": 1, "public_flags": 64, "avatar_decoration_data": { "sku_id": "1144058844004233369", "asset": "a_fed43ab12698df65902ba06727e20c0e" } }, "nick": "NOT API SUPPORT", "avatar": null, "roles": [], "joined_at": "2015-04-26T06:26:56.936000+00:00", "deaf": false, "mute": false } ], "channels":[ { "id": "41771983423143937", "guild_id": "197038439483310086", "name": "general", "type": 0, "position": 6, "permission_overwrites": [], "rate_limit_per_user": 2, "nsfw": true, "topic": "24/7 chat about how to gank Mike #2", "last_message_id": "155117677105512449", "parent_id": "399942396007890945", "default_auto_archive_duration": 60 } ] } } """; GatewayPacket? gateway_packet = JsonSerializer.Deserialize(src, SourceGenerationContext.Default.GatewayPacket); Assert.IsType(gateway_packet); Assert.IsType((gateway_packet as GuildCreatePacket)!.Data); } [Fact] public void UnavailableGuildCreateDeserialize() { string src = """ { "op": 0, "t": "GUILD_CREATE", "s": 3, "d":{ "id": "922243411795390566", "unavailable": true } } """; GatewayPacket? packet = JsonSerializer.Deserialize(src, SourceGenerationContext.Default.GatewayPacket); Assert.IsType(packet); Assert.IsType(((GuildCreatePacket)packet).Data); Assert.True(packet is GuildCreatePacket { Data: UnavailableGuildData { Id: 922243411795390566, Unavailable: true } }); } [Fact] public void InvalidSessionDeserialize() { string src = """ { "op": 9 } """; GatewayPacket? gateway_packet = JsonSerializer.Deserialize(src, SourceGenerationContext.Default.GatewayPacket); Assert.IsType(gateway_packet); } [Fact] public void ReconnectPacketDeserialize() { string src = """ { "op": 7, "d": null } """; GatewayPacket? gateway_packet = JsonSerializer.Deserialize(src, SourceGenerationContext.Default.GatewayPacket); Assert.IsType(gateway_packet); } [Fact] public void ResumePacketSerialize() { ResumePacket gateway_packet = new() { Data = new() { Token = "tokenlol", Sequence = 10, SessionId = "sessionlol69" } }; string serialized = JsonSerializer.Serialize(gateway_packet, SourceGenerationContext.Default.GatewayPacket); _testOutputHelper.WriteLine($"Serilazed Resume packet: {serialized}"); //TODO: Verify the string } [Fact] public void HelloPacketDeserialize() { string src = """ { "op": 10, "d": { "heartbeat_interval": 45000 } } """; GatewayPacket? gateway_packet = JsonSerializer.Deserialize(src, SourceGenerationContext.Default.GatewayPacket); Assert.IsType(gateway_packet); Assert.True(gateway_packet is HelloPacket { Op: GatewayPacket.Opcode.Hello, Data.HeartbeatInterval: 45000 }); } [Fact] public void HeartbeatAckDeserialize() { string src = """ {"op":11} """; GatewayPacket? gateway_packet = JsonSerializer.Deserialize(src, SourceGenerationContext.Default.GatewayPacket); Assert.IsType(gateway_packet); Assert.Equal(GatewayPacket.Opcode.HeartbeatAck, gateway_packet.Op); } [Fact] public void HeartbeatPacketSerialize() { HeartbeatPacket heartbeat_packet = new() { Sequence = 69 }; string serialized = JsonSerializer.Serialize(heartbeat_packet, SourceGenerationContext.Default.GatewayPacket); JsonDocument json_doc = JsonDocument.Parse(serialized); Assert.True(json_doc.RootElement.TryGetProperty("op", out var opcode) && opcode.ValueKind == JsonValueKind.Number && opcode.TryGetInt32(out int op) && op == (int)GatewayPacket.Opcode.Heartbeat); Assert.True(json_doc.RootElement.TryGetProperty("d", out var sequence) && sequence.ValueKind == JsonValueKind.Number && sequence.TryGetUInt64(out ulong seq) && seq == 69); } [Fact] public void IdentifyPacketSerialize() { IdentifyPacket identify_packet = new() { Data = new() { Token = "token_lol", Intents = 6969, Shard = [1, 2], LargeThreshold = 42 } }; string serialized = JsonSerializer.Serialize(identify_packet, SourceGenerationContext.Default.GatewayPacket); _testOutputHelper.WriteLine($"Serialized Identify packet: {serialized}"); //TODO: Test the output string } [Fact] public void ReadyPacketDeserialize() { const string src = """ { "op":0, "t":"READY", "s":1, "d":{ "v":10, "user":{ "id":"1234", "username":"abrakadabra", "discriminator":"1111", "global_name":"glblname" }, "guilds":[ { "id":"5678", "unavailable":true } ], "session_id":"abcd", "resume_gateway_url":"dfgh", "application":{ "id":"3333", "flags":5555 } } } """; GatewayPacket? packet = JsonSerializer.Deserialize(src, SourceGenerationContext.Default.GatewayPacket); Assert.NotNull(packet); Assert.IsType(packet); Assert.True(packet is ReadyPacket { Op: GatewayPacket.Opcode.Dispatch, Event: "READY", Sequence: 1, Data: { User: { Id:1234, Username: "abrakadabra", Discriminator: "1111", GlobalName: "glblname" }, Version: 10, SessionId: "abcd", ResumeGatewayUrl: "dfgh", Guilds:[ { Id: 5678, Unavailable: true } ], Application: { Id: 3333, Flags: 5555 } } }); } [Fact] public void ChannelCreateDeserialize() { string src = """ { "op":0, "t":"CHANNEL_CREATE", "s":1, "d":{ "id": "922243411795390570", "type": 2, "guild_id": "5678", "position": 3, "name": "voice csennel", "topic": "A very interesting topic", "nsfw": true, "last_message_id":"6969", "bitrate":420, "parent_id": "5555" } } """; var gateway_packet = JsonSerializer.Deserialize(src, SourceGenerationContext.Default.GatewayPacket); Assert.IsType(gateway_packet); Assert.True(gateway_packet is ChannelCreatePacket { Op: GatewayPacket.Opcode.Dispatch, Event: "CHANNEL_CREATE", Sequence: 1, Data: { Id: 922243411795390570, Name: "voice csennel", GuildId: 5678, Type: 2, Position: 3, Topic: "A very interesting topic", Nsfw: true, Bitrate: 420, ParentId: 5555, LastMessageId: 6969 } }); } [Fact] public void ChannelUpdateDeserialize() { string src = """ { "op":0, "t":"CHANNEL_UPDATE", "s":1, "d":{ "id": "922243411795390570", "type": 2, "guild_id": "5678", "position": 3, "name": "voice csennel", "topic": "A very interesting topic", "nsfw": true, "last_message_id":"6969", "bitrate":420, "parent_id": "5555" } } """; var gateway_packet = JsonSerializer.Deserialize(src, SourceGenerationContext.Default.GatewayPacket); Assert.IsType(gateway_packet); Assert.True(gateway_packet is ChannelUpdatePacket { Op: GatewayPacket.Opcode.Dispatch, Event: "CHANNEL_UPDATE", Sequence: 1, Data: { Id: 922243411795390570, Name: "voice csennel", GuildId: 5678, Type: 2, Position: 3, Topic: "A very interesting topic", Nsfw: true, Bitrate: 420, ParentId: 5555, LastMessageId: 6969 } }); } }