From b4540af9dbd24dce3b13617ffbacd01c06ae22dd Mon Sep 17 00:00:00 2001 From: Laci0503 Date: Mon, 24 Jun 2024 01:30:33 +0200 Subject: [PATCH] Experimenting with source generators --- .gitignore | 2 ++ Discord.API/DataTypes/ChannelData.cs | 20 +++++++++++ .../DataTypes/PartialApplicationData.cs | 12 +++++++ Discord.API/DataTypes/UnavailableGuildData.cs | 11 ++++++ Discord.API/DataTypes/UserData.cs | 16 +++++++++ Discord.API/Discord.API.csproj | 36 +++++++++++++++++++ .../DispatchPacket/ChannelCreatePacket.cs | 12 +++++++ .../DispatchPacket/ChannelDeletePacket.cs | 12 +++++++ .../DispatchPacket/ChannelUpdatePacket.cs | 12 +++++++ .../DispatchPacket/DispatchPacket.cs | 16 +++++++++ .../DispatchPacket/ReadyPacket.cs | 33 +++++++++++++++++ .../GatewayPacketTypes/GatewayPacket.cs | 26 ++++++++++++++ .../GatewayPacketTypes/IdentifyPacket.cs | 36 +++++++++++++++++++ Discord.API/IDiscordApi.cs | 20 +++++++++++ Discord.API/LifeTime.cs | 13 +++++++ Discord.API/SingleEventLifeTime.cs | 13 +++++++ Discord.API/SourceGenerationContext.cs | 13 +++++++ Discord.API/StaticProperties.cs | 8 +++++ discord_api.sln | 20 +++++++++++ example_bot/Program.cs | 2 ++ example_bot/example_bot.csproj | 10 ++++++ model/Class1.cs | 6 ++++ model/model.csproj | 9 +++++ 23 files changed, 358 insertions(+) create mode 100644 Discord.API/DataTypes/ChannelData.cs create mode 100644 Discord.API/DataTypes/PartialApplicationData.cs create mode 100644 Discord.API/DataTypes/UnavailableGuildData.cs create mode 100644 Discord.API/DataTypes/UserData.cs create mode 100644 Discord.API/Discord.API.csproj create mode 100644 Discord.API/GatewayPacketTypes/DispatchPacket/ChannelCreatePacket.cs create mode 100644 Discord.API/GatewayPacketTypes/DispatchPacket/ChannelDeletePacket.cs create mode 100644 Discord.API/GatewayPacketTypes/DispatchPacket/ChannelUpdatePacket.cs create mode 100644 Discord.API/GatewayPacketTypes/DispatchPacket/DispatchPacket.cs create mode 100644 Discord.API/GatewayPacketTypes/DispatchPacket/ReadyPacket.cs create mode 100644 Discord.API/GatewayPacketTypes/GatewayPacket.cs create mode 100644 Discord.API/GatewayPacketTypes/IdentifyPacket.cs create mode 100644 Discord.API/IDiscordApi.cs create mode 100644 Discord.API/LifeTime.cs create mode 100644 Discord.API/SingleEventLifeTime.cs create mode 100644 Discord.API/SourceGenerationContext.cs create mode 100644 Discord.API/StaticProperties.cs create mode 100644 example_bot/Program.cs create mode 100644 example_bot/example_bot.csproj create mode 100644 model/Class1.cs create mode 100644 model/model.csproj diff --git a/.gitignore b/.gitignore index 104b544..95477a8 100644 --- a/.gitignore +++ b/.gitignore @@ -3,6 +3,8 @@ ## ## Get latest from `dotnet new gitignore` +Generated/ + # dotenv files .env diff --git a/Discord.API/DataTypes/ChannelData.cs b/Discord.API/DataTypes/ChannelData.cs new file mode 100644 index 0000000..6b74c0b --- /dev/null +++ b/Discord.API/DataTypes/ChannelData.cs @@ -0,0 +1,20 @@ +using System.Text.Json.Serialization; + +namespace Discord.API; + +public class ChannelData +{ + [JsonRequired] + public ulong Id; + [JsonRequired] + public int Type; + public ulong? GuildId; + public int? Position; + public string? Name; + public string? Topic; + public bool? Nsfw; + public ulong? LastMessageId; + public int? Bitrate; + public ulong? ParentId; + //TODO: Missing fields +} \ No newline at end of file diff --git a/Discord.API/DataTypes/PartialApplicationData.cs b/Discord.API/DataTypes/PartialApplicationData.cs new file mode 100644 index 0000000..2ca685d --- /dev/null +++ b/Discord.API/DataTypes/PartialApplicationData.cs @@ -0,0 +1,12 @@ +using System.Text.Json.Serialization; + +namespace Discord.API; + +public sealed class PartialApplicationData +{ + [JsonRequired] + public ulong Id; + + [JsonRequired] + public ulong Flags; +} \ No newline at end of file diff --git a/Discord.API/DataTypes/UnavailableGuildData.cs b/Discord.API/DataTypes/UnavailableGuildData.cs new file mode 100644 index 0000000..dd698a2 --- /dev/null +++ b/Discord.API/DataTypes/UnavailableGuildData.cs @@ -0,0 +1,11 @@ +using System.Text.Json.Serialization; + +namespace Discord.API; + +public sealed class UnavailableGuildData +{ + [JsonRequired] + public ulong Id; + [JsonRequired] + public bool Unavailable; +} \ No newline at end of file diff --git a/Discord.API/DataTypes/UserData.cs b/Discord.API/DataTypes/UserData.cs new file mode 100644 index 0000000..e5ba94f --- /dev/null +++ b/Discord.API/DataTypes/UserData.cs @@ -0,0 +1,16 @@ +using System.Text.Json.Serialization; +#pragma warning disable CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable. + +namespace Discord.API; + +public sealed class UserData +{ + [JsonRequired] + public ulong Id; + [JsonRequired] + public string Username; + [JsonRequired] + public string Discriminator; + public string? GlobalName; + //TODO More fields +} \ No newline at end of file diff --git a/Discord.API/Discord.API.csproj b/Discord.API/Discord.API.csproj new file mode 100644 index 0000000..4aabd55 --- /dev/null +++ b/Discord.API/Discord.API.csproj @@ -0,0 +1,36 @@ + + + + net8.0 + enable + enable + api + + + + false + + + + true + Generated + + + + + + + + + + + + + + + + + + + + diff --git a/Discord.API/GatewayPacketTypes/DispatchPacket/ChannelCreatePacket.cs b/Discord.API/GatewayPacketTypes/DispatchPacket/ChannelCreatePacket.cs new file mode 100644 index 0000000..5a5e9fb --- /dev/null +++ b/Discord.API/GatewayPacketTypes/DispatchPacket/ChannelCreatePacket.cs @@ -0,0 +1,12 @@ +using System.Text.Json.Serialization; +#pragma warning disable CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable. + +namespace Discord.API; + +[JsonDerivedType(typeof(DispatchPacket), "CHANNEL_CREATE")] +public class ChannelCreatePacket : DispatchPacket +{ + [JsonRequired] + [JsonPropertyName("d")] + public ChannelData Data; +} \ No newline at end of file diff --git a/Discord.API/GatewayPacketTypes/DispatchPacket/ChannelDeletePacket.cs b/Discord.API/GatewayPacketTypes/DispatchPacket/ChannelDeletePacket.cs new file mode 100644 index 0000000..2084237 --- /dev/null +++ b/Discord.API/GatewayPacketTypes/DispatchPacket/ChannelDeletePacket.cs @@ -0,0 +1,12 @@ +using System.Text.Json.Serialization; +#pragma warning disable CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable. + +namespace Discord.API; + +[JsonDerivedType(typeof(DispatchPacket), "CHANNEL_DELETE")] +public class ChannelDeletePacket : DispatchPacket +{ + [JsonRequired] + [JsonPropertyName("d")] + public ChannelData Data; +} \ No newline at end of file diff --git a/Discord.API/GatewayPacketTypes/DispatchPacket/ChannelUpdatePacket.cs b/Discord.API/GatewayPacketTypes/DispatchPacket/ChannelUpdatePacket.cs new file mode 100644 index 0000000..2f70826 --- /dev/null +++ b/Discord.API/GatewayPacketTypes/DispatchPacket/ChannelUpdatePacket.cs @@ -0,0 +1,12 @@ +using System.Text.Json.Serialization; +#pragma warning disable CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable. + +namespace Discord.API; + +[JsonDerivedType(typeof(DispatchPacket), "CHANNEL_UPDATE")] +public class ChannelUpdatePacket : DispatchPacket +{ + [JsonRequired] + [JsonPropertyName("d")] + public ChannelData Data; +} \ No newline at end of file diff --git a/Discord.API/GatewayPacketTypes/DispatchPacket/DispatchPacket.cs b/Discord.API/GatewayPacketTypes/DispatchPacket/DispatchPacket.cs new file mode 100644 index 0000000..1e03bc7 --- /dev/null +++ b/Discord.API/GatewayPacketTypes/DispatchPacket/DispatchPacket.cs @@ -0,0 +1,16 @@ +using System.Text.Json.Serialization; +#pragma warning disable CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable. + +namespace Discord.API; + +[JsonDerivedType(typeof(GatewayPacket), (int)Opcode.Dispatch)] +[JsonPolymorphic(IgnoreUnrecognizedTypeDiscriminators = true, TypeDiscriminatorPropertyName = "t", UnknownDerivedTypeHandling = JsonUnknownDerivedTypeHandling.FallBackToBaseType)] +public class DispatchPacket : GatewayPacket +{ + [JsonPropertyName("t")] + [JsonRequired] + public string Event; + + [JsonPropertyName("s")] + public ulong? Sequence; +} \ No newline at end of file diff --git a/Discord.API/GatewayPacketTypes/DispatchPacket/ReadyPacket.cs b/Discord.API/GatewayPacketTypes/DispatchPacket/ReadyPacket.cs new file mode 100644 index 0000000..66d84a6 --- /dev/null +++ b/Discord.API/GatewayPacketTypes/DispatchPacket/ReadyPacket.cs @@ -0,0 +1,33 @@ +using System.Text.Json.Serialization; +#pragma warning disable CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable. + +namespace Discord.API; + +[JsonDerivedType(typeof(DispatchPacket), "READY")] +public class ReadyPacket : DispatchPacket +{ + public sealed class ReadyData + { + [JsonPropertyName("v")] + public int Version; + + [JsonRequired] + public UserData User; + + [JsonRequired] + public UnavailableGuildData Guilds; + + [JsonRequired] + public string SessionId; + + [JsonRequired] + public string ResumeUrl; + + [JsonRequired] + public PartialApplicationData Application; + } + + [JsonRequired] + [JsonPropertyName("d")] + public ReadyData Data; +} \ No newline at end of file diff --git a/Discord.API/GatewayPacketTypes/GatewayPacket.cs b/Discord.API/GatewayPacketTypes/GatewayPacket.cs new file mode 100644 index 0000000..b7b0d40 --- /dev/null +++ b/Discord.API/GatewayPacketTypes/GatewayPacket.cs @@ -0,0 +1,26 @@ +using System.Text.Json.Serialization; + +namespace Discord.API; + +[JsonPolymorphic(IgnoreUnrecognizedTypeDiscriminators = false, TypeDiscriminatorPropertyName = "op", UnknownDerivedTypeHandling = JsonUnknownDerivedTypeHandling.FallBackToBaseType)] +public class GatewayPacket +{ + public enum Opcode + { + Dispatch = 0, + Heartbeat = 1, + Identify = 2, + PresenceUpdate = 3, + VoiceStateUpdate = 4, + Resume = 6, + Reconnect = 7, + RequestGuildMembers = 8, + InvalidSession = 9, + Hello = 10, + HeartbeatAck = 11 + } + + [JsonRequired] + [JsonPropertyName("op")] + public Opcode Op; +} \ No newline at end of file diff --git a/Discord.API/GatewayPacketTypes/IdentifyPacket.cs b/Discord.API/GatewayPacketTypes/IdentifyPacket.cs new file mode 100644 index 0000000..4dd2c03 --- /dev/null +++ b/Discord.API/GatewayPacketTypes/IdentifyPacket.cs @@ -0,0 +1,36 @@ +using System.Text.Json.Serialization; + +namespace Discord.API; + +//[JsonDerivedType(typeof(GatewayPacket), (int)Opcode.Identify)] +public class IdentifyPacket : GatewayPacket +{ + public sealed class IdentifyData + { + public class PropertiesClass + { + public string Os => Environment.OSVersion.ToString(); + public string Browser => StaticProperties.LibraryName; + public string Device => StaticProperties.LibraryName; + private PropertiesClass() { } + public static PropertiesClass Instance { get; } = new PropertiesClass(); + } + + [JsonInclude] + [JsonRequired] + [JsonPropertyName("token")] + public required string Token { get; set; } + [JsonInclude] + public PropertiesClass Properties => PropertiesClass.Instance; + [JsonInclude] + public bool Compress => false; + public int LargeThreshold = 250; + public int[]? Shard = null; + //presence + public ulong Intents { get; init; } + + } + + [JsonPropertyName("d")] + public IdentifyData Data; +} \ No newline at end of file diff --git a/Discord.API/IDiscordApi.cs b/Discord.API/IDiscordApi.cs new file mode 100644 index 0000000..8929dd2 --- /dev/null +++ b/Discord.API/IDiscordApi.cs @@ -0,0 +1,20 @@ +namespace Discord.API; + +public interface IDiscordApi +{ + public void OpenConnection(); + public void Close(); + + public delegate void DiscordEventHandler(IDiscordApi sender, T data, LifeTime lifetime); + + /*public event DiscordEventHandler? OnReady; + public event DiscordEventHandler? OnChannelCreate; + public event DiscordEventHandler? OnChannelUpdate; + public event DiscordEventHandler? OnChannelDelete; + + public event DiscordEventHandler? OnGuildCreate; + public event DiscordEventHandler? OnGuildUpdate; + public event DiscordEventHandler? OnGuildDelete;*/ + + +} \ No newline at end of file diff --git a/Discord.API/LifeTime.cs b/Discord.API/LifeTime.cs new file mode 100644 index 0000000..f62e3e1 --- /dev/null +++ b/Discord.API/LifeTime.cs @@ -0,0 +1,13 @@ +namespace Discord.API; + +public class LifeTime +{ + public virtual bool IsValid => true; + public virtual bool IsInfinite => true; + + protected LifeTime() + {} + + internal static LifeTime Infinite { get; } = new LifeTime(); + internal static SingleEventLifeTime SingleEvent => new SingleEventLifeTime(); +} \ No newline at end of file diff --git a/Discord.API/SingleEventLifeTime.cs b/Discord.API/SingleEventLifeTime.cs new file mode 100644 index 0000000..2a5884f --- /dev/null +++ b/Discord.API/SingleEventLifeTime.cs @@ -0,0 +1,13 @@ +namespace Discord.API; + +public class SingleEventLifeTime : LifeTime +{ + private bool _valid = true; + public override bool IsValid => _valid; + public override bool IsInfinite => false; + + internal void Terminate() + { + _valid = false; + } +} \ No newline at end of file diff --git a/Discord.API/SourceGenerationContext.cs b/Discord.API/SourceGenerationContext.cs new file mode 100644 index 0000000..e48343e --- /dev/null +++ b/Discord.API/SourceGenerationContext.cs @@ -0,0 +1,13 @@ +using System.Text.Json.Serialization; +using System.Text.Json.Serialization.Metadata; + +namespace Discord.API; + +using System.Text.Json; + +[JsonSourceGenerationOptions(IgnoreReadOnlyFields = false, IgnoreReadOnlyProperties = false, IncludeFields = true, PropertyNamingPolicy = JsonKnownNamingPolicy.SnakeCaseLower)] +[JsonSerializable(typeof(GatewayPacket))] +[JsonSerializable(typeof(IdentifyPacket))] +internal partial class SourceGenerationContext : JsonSerializerContext +{ +} \ No newline at end of file diff --git a/Discord.API/StaticProperties.cs b/Discord.API/StaticProperties.cs new file mode 100644 index 0000000..12c9715 --- /dev/null +++ b/Discord.API/StaticProperties.cs @@ -0,0 +1,8 @@ +namespace Discord.API; + +public class StaticProperties +{ + public static string LibraryName => "Custom C# Discord Library"; + public static string LibraryVersion => "0.1 alpha"; + public static string LibraryWebsite => "https://laci0503.duckdns.org/laci0503/DiscordApi"; +} \ No newline at end of file diff --git a/discord_api.sln b/discord_api.sln index bb32f59..f120141 100644 --- a/discord_api.sln +++ b/discord_api.sln @@ -3,6 +3,12 @@ Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio Version 17 VisualStudioVersion = 17.0.31903.59 MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "model", "model\model.csproj", "{2FA8D012-CC43-4FBC-9520-CF627AB4BBEA}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Discord.API", "Discord.API\Discord.API.csproj", "{5C77661B-670F-400B-AF77-E3EC062B673D}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "example_bot", "example_bot\example_bot.csproj", "{331F5928-8E65-4782-8311-BC1E80F1C002}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -11,4 +17,18 @@ Global GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {2FA8D012-CC43-4FBC-9520-CF627AB4BBEA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {2FA8D012-CC43-4FBC-9520-CF627AB4BBEA}.Debug|Any CPU.Build.0 = Debug|Any CPU + {2FA8D012-CC43-4FBC-9520-CF627AB4BBEA}.Release|Any CPU.ActiveCfg = Release|Any CPU + {2FA8D012-CC43-4FBC-9520-CF627AB4BBEA}.Release|Any CPU.Build.0 = Release|Any CPU + {5C77661B-670F-400B-AF77-E3EC062B673D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {5C77661B-670F-400B-AF77-E3EC062B673D}.Debug|Any CPU.Build.0 = Debug|Any CPU + {5C77661B-670F-400B-AF77-E3EC062B673D}.Release|Any CPU.ActiveCfg = Release|Any CPU + {5C77661B-670F-400B-AF77-E3EC062B673D}.Release|Any CPU.Build.0 = Release|Any CPU + {331F5928-8E65-4782-8311-BC1E80F1C002}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {331F5928-8E65-4782-8311-BC1E80F1C002}.Debug|Any CPU.Build.0 = Debug|Any CPU + {331F5928-8E65-4782-8311-BC1E80F1C002}.Release|Any CPU.ActiveCfg = Release|Any CPU + {331F5928-8E65-4782-8311-BC1E80F1C002}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection EndGlobal diff --git a/example_bot/Program.cs b/example_bot/Program.cs new file mode 100644 index 0000000..3751555 --- /dev/null +++ b/example_bot/Program.cs @@ -0,0 +1,2 @@ +// See https://aka.ms/new-console-template for more information +Console.WriteLine("Hello, World!"); diff --git a/example_bot/example_bot.csproj b/example_bot/example_bot.csproj new file mode 100644 index 0000000..2150e37 --- /dev/null +++ b/example_bot/example_bot.csproj @@ -0,0 +1,10 @@ + + + + Exe + net8.0 + enable + enable + + + diff --git a/model/Class1.cs b/model/Class1.cs new file mode 100644 index 0000000..9bef5b7 --- /dev/null +++ b/model/Class1.cs @@ -0,0 +1,6 @@ +namespace model; + +public class Class1 +{ + +} diff --git a/model/model.csproj b/model/model.csproj new file mode 100644 index 0000000..fa71b7a --- /dev/null +++ b/model/model.csproj @@ -0,0 +1,9 @@ + + + + net8.0 + enable + enable + + +