From 3f4ab165ce61fef8992aff08c7070cd9e7fe95b1 Mon Sep 17 00:00:00 2001
From: Stevan Freeborn <65925598+StevanFreeborn@users.noreply.github.com>
Date: Wed, 7 May 2025 23:54:46 -0500
Subject: [PATCH] chore: begin porting code from playground
---
src/Directory.Build.props | 14 +++++++
src/StevesBot.Worker.Tests/.editorconfig | 4 ++
.../StevesBot.Worker.Tests.csproj | 36 ++++++++++++++----
.../Unit/DiscordClientExceptionTests.cs | 37 +++++++++++++++++++
.../Unit/DiscordClientOptionsTests.cs | 37 +++++++++++++++++++
src/StevesBot.Worker.Tests/UnitTest1.cs | 10 -----
src/StevesBot.Worker.Tests/Usings.cs | 1 +
src/StevesBot.Worker/.editorconfig | 2 +
.../Discord/DiscordClientException.cs | 16 ++++++++
.../Discord/DiscordClientOptions.cs | 8 ++++
.../Discord/Events/DiscordEvent.cs | 16 ++++++++
.../Discord/Events/DiscordEventConverter.cs | 24 ++++++++++++
.../Discord/Events/DiscordOpCodes.cs | 6 +++
.../Discord/Events/HelloDiscordEvent.cs | 13 +++++++
src/StevesBot.Worker/Program.cs | 2 +-
src/StevesBot.Worker/StevesBot.Worker.csproj | 8 ++--
src/StevesBot.Worker/Usings.cs | 2 +
src/StevesBot.Worker/Worker.cs | 5 ++-
src/StevesBot.Worker/appsettings.Example.json | 13 +++++++
19 files changed, 230 insertions(+), 24 deletions(-)
create mode 100644 src/Directory.Build.props
create mode 100644 src/StevesBot.Worker.Tests/.editorconfig
create mode 100644 src/StevesBot.Worker.Tests/Unit/DiscordClientExceptionTests.cs
create mode 100644 src/StevesBot.Worker.Tests/Unit/DiscordClientOptionsTests.cs
delete mode 100644 src/StevesBot.Worker.Tests/UnitTest1.cs
create mode 100644 src/StevesBot.Worker.Tests/Usings.cs
create mode 100644 src/StevesBot.Worker/.editorconfig
create mode 100644 src/StevesBot.Worker/Discord/DiscordClientException.cs
create mode 100644 src/StevesBot.Worker/Discord/DiscordClientOptions.cs
create mode 100644 src/StevesBot.Worker/Discord/Events/DiscordEvent.cs
create mode 100644 src/StevesBot.Worker/Discord/Events/DiscordEventConverter.cs
create mode 100644 src/StevesBot.Worker/Discord/Events/DiscordOpCodes.cs
create mode 100644 src/StevesBot.Worker/Discord/Events/HelloDiscordEvent.cs
create mode 100644 src/StevesBot.Worker/Usings.cs
create mode 100644 src/StevesBot.Worker/appsettings.Example.json
diff --git a/src/Directory.Build.props b/src/Directory.Build.props
new file mode 100644
index 0000000..807df2c
--- /dev/null
+++ b/src/Directory.Build.props
@@ -0,0 +1,14 @@
+
+
+
+ net9.0
+ enable
+ enable
+ latest
+ All
+ true
+ true
+ true
+
+
+
diff --git a/src/StevesBot.Worker.Tests/.editorconfig b/src/StevesBot.Worker.Tests/.editorconfig
new file mode 100644
index 0000000..a84e56b
--- /dev/null
+++ b/src/StevesBot.Worker.Tests/.editorconfig
@@ -0,0 +1,4 @@
+[*.cs]
+dotnet_diagnostic.CA1515.severity = none
+dotnet_diagnostic.CA1707.severity = none
+dotnet_diagnostic.CA2201.severity = none
diff --git a/src/StevesBot.Worker.Tests/StevesBot.Worker.Tests.csproj b/src/StevesBot.Worker.Tests/StevesBot.Worker.Tests.csproj
index 38c5bc8..3602d53 100644
--- a/src/StevesBot.Worker.Tests/StevesBot.Worker.Tests.csproj
+++ b/src/StevesBot.Worker.Tests/StevesBot.Worker.Tests.csproj
@@ -1,21 +1,41 @@
-
+
- net9.0
- enable
- enable
false
-
-
-
-
+
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+ all
+
+
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+ all
+
+
+
+
+
+
+
+
+ true
+ ./TestResults/Coverage/
+ cobertura
+ [StevesBot.Worker]*
+ **/Program.cs,**/Worker.cs
+
+
+
+
+
+
+
diff --git a/src/StevesBot.Worker.Tests/Unit/DiscordClientExceptionTests.cs b/src/StevesBot.Worker.Tests/Unit/DiscordClientExceptionTests.cs
new file mode 100644
index 0000000..6be76d7
--- /dev/null
+++ b/src/StevesBot.Worker.Tests/Unit/DiscordClientExceptionTests.cs
@@ -0,0 +1,37 @@
+namespace StevesBot.Worker.Tests.Unit;
+
+public class DiscordClientExceptionTests
+{
+ [Fact]
+ public void Constructor_WhenCalledWithoutParameters_ItShouldCreateInstance()
+ {
+ var exception = new DiscordClientException();
+
+ exception.Should().NotBeNull();
+ exception.Should().BeOfType();
+ }
+
+ [Fact]
+ public void Constructor_WhenCalledWithMessage_ItShouldCreateInstance()
+ {
+ var message = "Test message";
+ var exception = new DiscordClientException(message);
+
+ exception.Should().NotBeNull();
+ exception.Should().BeOfType();
+ exception.Message.Should().Be(message);
+ }
+
+ [Fact]
+ public void Constructor_WhenCalledWithMessageAndInnerException_ItShouldCreateInstance()
+ {
+ var message = "Test message";
+ var innerException = new Exception("Inner exception");
+ var exception = new DiscordClientException(message, innerException);
+
+ exception.Should().NotBeNull();
+ exception.Should().BeOfType();
+ exception.Message.Should().Be(message);
+ exception.InnerException.Should().Be(innerException);
+ }
+}
\ No newline at end of file
diff --git a/src/StevesBot.Worker.Tests/Unit/DiscordClientOptionsTests.cs b/src/StevesBot.Worker.Tests/Unit/DiscordClientOptionsTests.cs
new file mode 100644
index 0000000..cd2f5c5
--- /dev/null
+++ b/src/StevesBot.Worker.Tests/Unit/DiscordClientOptionsTests.cs
@@ -0,0 +1,37 @@
+namespace StevesBot.Worker.Tests.Unit;
+
+public class DiscordClientOptionsTests
+{
+ [Fact]
+ public void Constructor_WhenCalledWithoutParameters_ItShouldCreateInstance()
+ {
+ var options = new DiscordClientOptions();
+
+ options.Should().NotBeNull();
+ options.Should().BeOfType();
+ options.ApiUrl.Should().Be(string.Empty);
+ options.AppToken.Should().Be(string.Empty);
+ options.Intents.Should().Be(0);
+ }
+
+ [Fact]
+ public void Constructor_WhenCalledWithParameters_ItShouldCreateInstance()
+ {
+ var apiUrl = "https://api.example.com";
+ var appToken = "test-token";
+ var intents = 123;
+
+ var options = new DiscordClientOptions
+ {
+ ApiUrl = apiUrl,
+ AppToken = appToken,
+ Intents = intents
+ };
+
+ options.Should().NotBeNull();
+ options.Should().BeOfType();
+ options.ApiUrl.Should().Be(apiUrl);
+ options.AppToken.Should().Be(appToken);
+ options.Intents.Should().Be(intents);
+ }
+}
\ No newline at end of file
diff --git a/src/StevesBot.Worker.Tests/UnitTest1.cs b/src/StevesBot.Worker.Tests/UnitTest1.cs
deleted file mode 100644
index f017831..0000000
--- a/src/StevesBot.Worker.Tests/UnitTest1.cs
+++ /dev/null
@@ -1,10 +0,0 @@
-namespace StevesBot.Worker.Tests;
-
-public class UnitTest1
-{
- [Fact]
- public void Test1()
- {
-
- }
-}
\ No newline at end of file
diff --git a/src/StevesBot.Worker.Tests/Usings.cs b/src/StevesBot.Worker.Tests/Usings.cs
new file mode 100644
index 0000000..a1cf763
--- /dev/null
+++ b/src/StevesBot.Worker.Tests/Usings.cs
@@ -0,0 +1 @@
+global using StevesBot.Worker.Discord;
\ No newline at end of file
diff --git a/src/StevesBot.Worker/.editorconfig b/src/StevesBot.Worker/.editorconfig
new file mode 100644
index 0000000..2dc531e
--- /dev/null
+++ b/src/StevesBot.Worker/.editorconfig
@@ -0,0 +1,2 @@
+[*.cs]
+dotnet_diagnostic.CA2007.severity = none
diff --git a/src/StevesBot.Worker/Discord/DiscordClientException.cs b/src/StevesBot.Worker/Discord/DiscordClientException.cs
new file mode 100644
index 0000000..791cd04
--- /dev/null
+++ b/src/StevesBot.Worker/Discord/DiscordClientException.cs
@@ -0,0 +1,16 @@
+namespace StevesBot.Worker.Discord;
+
+internal class DiscordClientException : Exception
+{
+ public DiscordClientException()
+ {
+ }
+
+ public DiscordClientException(string message) : base(message)
+ {
+ }
+
+ public DiscordClientException(string message, Exception innerException) : base(message, innerException)
+ {
+ }
+}
\ No newline at end of file
diff --git a/src/StevesBot.Worker/Discord/DiscordClientOptions.cs b/src/StevesBot.Worker/Discord/DiscordClientOptions.cs
new file mode 100644
index 0000000..885d548
--- /dev/null
+++ b/src/StevesBot.Worker/Discord/DiscordClientOptions.cs
@@ -0,0 +1,8 @@
+namespace StevesBot.Worker.Discord;
+
+internal class DiscordClientOptions
+{
+ public string ApiUrl { get; init; } = string.Empty;
+ public string AppToken { get; init; } = string.Empty;
+ public int Intents { get; init; }
+}
diff --git a/src/StevesBot.Worker/Discord/Events/DiscordEvent.cs b/src/StevesBot.Worker/Discord/Events/DiscordEvent.cs
new file mode 100644
index 0000000..7ac4ff8
--- /dev/null
+++ b/src/StevesBot.Worker/Discord/Events/DiscordEvent.cs
@@ -0,0 +1,16 @@
+namespace StevesBot.Worker.Discord.Events;
+
+internal record DiscordEvent
+{
+ [JsonPropertyName("op")]
+ public int Op { get; init; }
+
+ [JsonPropertyName("s")]
+ public int? Sequence { get; init; }
+
+ [JsonPropertyName("t")]
+ public string? Type { get; init; }
+
+ [JsonPropertyName("d")]
+ public object? Data { get; init; }
+}
\ No newline at end of file
diff --git a/src/StevesBot.Worker/Discord/Events/DiscordEventConverter.cs b/src/StevesBot.Worker/Discord/Events/DiscordEventConverter.cs
new file mode 100644
index 0000000..8426030
--- /dev/null
+++ b/src/StevesBot.Worker/Discord/Events/DiscordEventConverter.cs
@@ -0,0 +1,24 @@
+namespace StevesBot.Worker.Discord.Events;
+
+internal class DiscordEventConverter : JsonConverter
+{
+ private const string OpPropertyName = "op";
+
+ public override DiscordEvent? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
+ {
+ using var jsonDoc = JsonDocument.ParseValue(ref reader);
+ var root = jsonDoc.RootElement;
+ var op = root.GetProperty(OpPropertyName).GetInt32();
+
+ return op switch
+ {
+ DiscordOpCodes.Hello => JsonSerializer.Deserialize(root.GetRawText(), options),
+ _ => JsonSerializer.Deserialize(root.GetRawText(), options)
+ };
+ }
+
+ public override void Write(Utf8JsonWriter writer, DiscordEvent value, JsonSerializerOptions options)
+ {
+ throw new NotImplementedException();
+ }
+}
\ No newline at end of file
diff --git a/src/StevesBot.Worker/Discord/Events/DiscordOpCodes.cs b/src/StevesBot.Worker/Discord/Events/DiscordOpCodes.cs
new file mode 100644
index 0000000..7eefb1d
--- /dev/null
+++ b/src/StevesBot.Worker/Discord/Events/DiscordOpCodes.cs
@@ -0,0 +1,6 @@
+namespace StevesBot.Worker.Discord.Events;
+
+internal static class DiscordOpCodes
+{
+ public const int Hello = 10;
+}
\ No newline at end of file
diff --git a/src/StevesBot.Worker/Discord/Events/HelloDiscordEvent.cs b/src/StevesBot.Worker/Discord/Events/HelloDiscordEvent.cs
new file mode 100644
index 0000000..689442f
--- /dev/null
+++ b/src/StevesBot.Worker/Discord/Events/HelloDiscordEvent.cs
@@ -0,0 +1,13 @@
+namespace StevesBot.Worker.Discord.Events;
+
+internal record HelloDiscordEvent : DiscordEvent
+{
+ [JsonPropertyName("d")]
+ public new HelloData? Data { get; init; }
+}
+
+internal record HelloData
+{
+ [JsonPropertyName("heartbeat_interval")]
+ public int HeartbeatInterval { get; init; }
+}
diff --git a/src/StevesBot.Worker/Program.cs b/src/StevesBot.Worker/Program.cs
index 0a8bb16..8e9cef5 100644
--- a/src/StevesBot.Worker/Program.cs
+++ b/src/StevesBot.Worker/Program.cs
@@ -4,4 +4,4 @@ var builder = Host.CreateApplicationBuilder(args);
builder.Services.AddHostedService();
var host = builder.Build();
-host.Run();
\ No newline at end of file
+await host.RunAsync();
\ No newline at end of file
diff --git a/src/StevesBot.Worker/StevesBot.Worker.csproj b/src/StevesBot.Worker/StevesBot.Worker.csproj
index 14e07c3..1bb4602 100644
--- a/src/StevesBot.Worker/StevesBot.Worker.csproj
+++ b/src/StevesBot.Worker/StevesBot.Worker.csproj
@@ -1,13 +1,15 @@
- net9.0
- enable
- enable
dotnet-StevesBot.Worker-0b7a94ae-5cbd-406d-8422-1c791715ef7d
+
+
+
+
+
diff --git a/src/StevesBot.Worker/Usings.cs b/src/StevesBot.Worker/Usings.cs
new file mode 100644
index 0000000..a344eb9
--- /dev/null
+++ b/src/StevesBot.Worker/Usings.cs
@@ -0,0 +1,2 @@
+global using System.Text.Json;
+global using System.Text.Json.Serialization;
\ No newline at end of file
diff --git a/src/StevesBot.Worker/Worker.cs b/src/StevesBot.Worker/Worker.cs
index 19cef50..610b3a1 100644
--- a/src/StevesBot.Worker/Worker.cs
+++ b/src/StevesBot.Worker/Worker.cs
@@ -1,6 +1,6 @@
namespace StevesBot.Worker;
-public class Worker : BackgroundService
+internal class Worker : BackgroundService
{
private readonly ILogger _logger;
@@ -15,8 +15,9 @@ public class Worker : BackgroundService
{
if (_logger.IsEnabled(LogLevel.Information))
{
- _logger.LogInformation("Worker running at: {time}", DateTimeOffset.Now);
+ _logger.LogInformation("Worker running at: {Time}", DateTimeOffset.Now);
}
+
await Task.Delay(1000, stoppingToken);
}
}
diff --git a/src/StevesBot.Worker/appsettings.Example.json b/src/StevesBot.Worker/appsettings.Example.json
new file mode 100644
index 0000000..db47611
--- /dev/null
+++ b/src/StevesBot.Worker/appsettings.Example.json
@@ -0,0 +1,13 @@
+{
+ "Logging": {
+ "LogLevel": {
+ "Default": "Information",
+ "Microsoft.Hosting.Lifetime": "Information"
+ }
+ },
+ "DiscordClientOptions": {
+ "ApiUrl": "ApiUrl",
+ "AppToken": "AppToken",
+ "Intents": 0
+ }
+}