New type definitions
This commit is contained in:
parent
2b18bd8ae4
commit
da9be4735e
@ -16,6 +16,156 @@ public class JsonTests
|
|||||||
_testOutputHelper = 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<GuildCreatePacket>(gateway_packet);
|
||||||
|
Assert.IsType<GuildData>((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<GatewayPacket>(src, SourceGenerationContext.Default.GatewayPacket);
|
||||||
|
|
||||||
|
Assert.IsType<GuildCreatePacket>(packet);
|
||||||
|
Assert.IsType<UnavailableGuildData>(((GuildCreatePacket)packet).Data);
|
||||||
|
Assert.True(packet is GuildCreatePacket
|
||||||
|
{
|
||||||
|
Data: UnavailableGuildData
|
||||||
|
{
|
||||||
|
Id: 922243411795390566,
|
||||||
|
Unavailable: true
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void InvalidSessionDeserialize()
|
public void InvalidSessionDeserialize()
|
||||||
{
|
{
|
||||||
|
|||||||
20
Discord.API/DataTypes/GuildData.cs
Normal file
20
Discord.API/DataTypes/GuildData.cs
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
namespace Discord.API;
|
||||||
|
|
||||||
|
public 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; }
|
||||||
|
}
|
||||||
51
Discord.API/DataTypes/GuildDataConverter.cs
Normal file
51
Discord.API/DataTypes/GuildDataConverter.cs
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
using System.Text.Json;
|
||||||
|
using System.Text.Json.Serialization;
|
||||||
|
|
||||||
|
namespace Discord.API;
|
||||||
|
|
||||||
|
internal class GuildDataConverter : JsonConverter<UnavailableGuildData>
|
||||||
|
{
|
||||||
|
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() ?? "")
|
||||||
|
};
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
14
Discord.API/DataTypes/GuildMemberData.cs
Normal file
14
Discord.API/DataTypes/GuildMemberData.cs
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
using System.Text.Json.Serialization;
|
||||||
|
|
||||||
|
namespace Discord.API;
|
||||||
|
|
||||||
|
public class GuildMemberData
|
||||||
|
{
|
||||||
|
public UserData? User { get; init; }
|
||||||
|
public string? Nick { get; init; }
|
||||||
|
public ulong[]? Roles { get; init; }
|
||||||
|
public DateTime? JoinedAt { get; init; }
|
||||||
|
public bool? Deaf { get; init; }
|
||||||
|
public bool? Mute { get; init; }
|
||||||
|
//TODO: More fields
|
||||||
|
}
|
||||||
15
Discord.API/DataTypes/RoleData.cs
Normal file
15
Discord.API/DataTypes/RoleData.cs
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
using System.Text.Json.Serialization;
|
||||||
|
|
||||||
|
namespace Discord.API;
|
||||||
|
|
||||||
|
public class RoleData
|
||||||
|
{
|
||||||
|
[JsonRequired]
|
||||||
|
public ulong Id { get; init; }
|
||||||
|
public string? Name { get; init; }
|
||||||
|
public uint? Color { get; init; }
|
||||||
|
public bool? Hoist { get; init; }
|
||||||
|
public int? Position { get; init; }
|
||||||
|
public bool? Managed { get; init; }
|
||||||
|
public bool? Mentionable { get; init; }
|
||||||
|
}
|
||||||
@ -2,8 +2,10 @@ using System.Text.Json.Serialization;
|
|||||||
|
|
||||||
namespace Discord.API;
|
namespace Discord.API;
|
||||||
|
|
||||||
public sealed class UnavailableGuildData
|
[JsonPolymorphic(UnknownDerivedTypeHandling = JsonUnknownDerivedTypeHandling.FallBackToNearestAncestor)]
|
||||||
|
[JsonDerivedType(typeof(GuildData))]
|
||||||
|
public class UnavailableGuildData
|
||||||
{
|
{
|
||||||
public required ulong Id { get; init; }
|
public required ulong Id { get; init; }
|
||||||
public bool Unavailable { get; init; }
|
public virtual bool Unavailable => true;
|
||||||
}
|
}
|
||||||
21
Discord.API/DataTypes/VoiceStateData.cs
Normal file
21
Discord.API/DataTypes/VoiceStateData.cs
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
using System.Text.Json.Serialization;
|
||||||
|
|
||||||
|
namespace Discord.API;
|
||||||
|
|
||||||
|
public class VoiceStateData
|
||||||
|
{
|
||||||
|
public ulong? GuildId { get; init; }
|
||||||
|
public ulong? ChannelId { get; init; }
|
||||||
|
[JsonRequired]
|
||||||
|
public required ulong UserId { get; init; }
|
||||||
|
public GuildMemberData? Member { get; init; }
|
||||||
|
public string? SessionId { get; init; }
|
||||||
|
public bool? Mute { get; init; }
|
||||||
|
public bool? Deaf { get; init; }
|
||||||
|
public bool? SelfMute { get; init; }
|
||||||
|
public bool? SelfDeaf { get; init; }
|
||||||
|
public bool? SelfStream { get; init; }
|
||||||
|
public bool? SelfVideo { get; init; }
|
||||||
|
public bool? Suppress { get; init; }
|
||||||
|
public DateTime? RequestToSpeakTimestamp { get; init; }
|
||||||
|
}
|
||||||
@ -4,7 +4,7 @@
|
|||||||
<TargetFramework>net8.0</TargetFramework>
|
<TargetFramework>net8.0</TargetFramework>
|
||||||
<ImplicitUsings>enable</ImplicitUsings>
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
<Nullable>enable</Nullable>
|
<Nullable>enable</Nullable>
|
||||||
<RootNamespace>api</RootNamespace>
|
<RootNamespace>Discord.API</RootNamespace>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
|
|||||||
@ -8,6 +8,7 @@ namespace Discord.API;
|
|||||||
[JsonDerivedType(typeof(ChannelUpdatePacket))]
|
[JsonDerivedType(typeof(ChannelUpdatePacket))]
|
||||||
[JsonDerivedType(typeof(ChannelDeletePacket))]
|
[JsonDerivedType(typeof(ChannelDeletePacket))]
|
||||||
[JsonDerivedType(typeof(ReadyPacket))]
|
[JsonDerivedType(typeof(ReadyPacket))]
|
||||||
|
[JsonDerivedType(typeof(GuildCreatePacket))]
|
||||||
internal abstract class DispatchPacket : GatewayPacket
|
internal abstract class DispatchPacket : GatewayPacket
|
||||||
{
|
{
|
||||||
public override Opcode Op => Opcode.Dispatch;
|
public override Opcode Op => Opcode.Dispatch;
|
||||||
|
|||||||
@ -0,0 +1,11 @@
|
|||||||
|
using System.Text.Json.Serialization;
|
||||||
|
|
||||||
|
namespace Discord.API;
|
||||||
|
|
||||||
|
internal class GuildCreatePacket : DispatchPacket
|
||||||
|
{
|
||||||
|
public override string Event => "GUILD_CREATE";
|
||||||
|
[JsonRequired]
|
||||||
|
[JsonPropertyName("d")]
|
||||||
|
public required UnavailableGuildData Data { get; init; }
|
||||||
|
}
|
||||||
@ -52,6 +52,8 @@ internal class GatewayPacketConverter : JsonConverter<GatewayPacket>
|
|||||||
SourceGenerationContext.Default.ChannelUpdatePacket),
|
SourceGenerationContext.Default.ChannelUpdatePacket),
|
||||||
"CHANNEL_DELETE" => json_doc.Deserialize(
|
"CHANNEL_DELETE" => json_doc.Deserialize(
|
||||||
SourceGenerationContext.Default.ChannelDeletePacket),
|
SourceGenerationContext.Default.ChannelDeletePacket),
|
||||||
|
"GUILD_CREATE" => json_doc.Deserialize(
|
||||||
|
SourceGenerationContext.Default.GuildCreatePacket),
|
||||||
_ => throw new NotSupportedException($"Packet {event_name} is not supported in json deserialization")
|
_ => throw new NotSupportedException($"Packet {event_name} is not supported in json deserialization")
|
||||||
};
|
};
|
||||||
default:
|
default:
|
||||||
|
|||||||
@ -10,7 +10,7 @@ using System.Text.Json;
|
|||||||
IgnoreReadOnlyProperties = false,
|
IgnoreReadOnlyProperties = false,
|
||||||
IncludeFields = true,
|
IncludeFields = true,
|
||||||
PropertyNamingPolicy = JsonKnownNamingPolicy.SnakeCaseLower,
|
PropertyNamingPolicy = JsonKnownNamingPolicy.SnakeCaseLower,
|
||||||
Converters = [typeof(GatewayPacketConverter)],
|
Converters = [typeof(GatewayPacketConverter), typeof(GuildDataConverter)],
|
||||||
NumberHandling = JsonNumberHandling.AllowReadingFromString
|
NumberHandling = JsonNumberHandling.AllowReadingFromString
|
||||||
)]
|
)]
|
||||||
[JsonSerializable(typeof(GatewayPacket))]
|
[JsonSerializable(typeof(GatewayPacket))]
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user