Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
58 commits
Select commit Hold shift + click to select a range
1b0bbb4
Upgrade to .NET 9.0 and refactor codebase
Jul 6, 2025
33defb8
Refactored InstarBot.Tests.Integration to move away from SpecFlow
Jul 2, 2025
c0299a5
Refactored parts of AutoMemberSystem
Jul 2, 2025
531a874
Re-add Community Manager Team
Jul 6, 2025
46e348c
Fixed some code quality and test adapter issues
Jul 6, 2025
c7d29a4
Fixed some more code quality issues.
PaxAndromeda Jul 6, 2025
72ecdb2
Added new functionality:
PaxAndromeda Nov 23, 2025
c769bc4
Added centralized strings management and more integration tests.
PaxAndromeda Nov 25, 2025
dc622b9
Added birthday system implementation.
PaxAndromeda Dec 12, 2025
f9d824b
Introduced new testing framework to make tests more predictable and e…
PaxAndromeda Dec 18, 2025
2c5b823
Added notification system, updated AMH commands, refactored some code
PaxAndromeda Dec 27, 2025
ebde043
Upgrade to .NET 9.0 and refactor codebase
Jul 6, 2025
465a261
Refactored InstarBot.Tests.Integration to move away from SpecFlow
Jul 2, 2025
fa42159
Refactored parts of AutoMemberSystem
Jul 2, 2025
210b20e
Re-add Community Manager Team
Jul 6, 2025
c1ef7d9
Fixed some code quality and test adapter issues
Jul 6, 2025
d563ac6
Fixed some more code quality issues.
PaxAndromeda Jul 6, 2025
bbf4909
Added new functionality:
PaxAndromeda Nov 23, 2025
291940c
Added centralized strings management and more integration tests.
PaxAndromeda Nov 25, 2025
0691eba
Added birthday system implementation.
PaxAndromeda Dec 12, 2025
69dff17
Introduced new testing framework to make tests more predictable and e…
PaxAndromeda Dec 18, 2025
7ed82c4
Added notification system, updated AMH commands, refactored some code
PaxAndromeda Dec 27, 2025
eba0336
Fixed some minor code quality issues.
PaxAndromeda Dec 27, 2025
445e684
Merge branch 'develop' of https://github.com/PaxAndromeda/Instar into…
PaxAndromeda Dec 27, 2025
cd49d8e
Synchronizing dotnet-linux.yml workflow from master → develop
Dec 28, 2025
cbebfba
Updated Github action to run on hotfix-integ-hanging and develop bran…
Dec 28, 2025
477faaa
Added extra diagnostics logging to PreloadIntroductionPosters
Dec 28, 2025
3a92759
Updated test GetMessagesAsync method
Dec 28, 2025
d7f2cc0
Revert "Added extra diagnostics logging to PreloadIntroductionPosters"
Dec 28, 2025
00ee316
Removed hotfix branch from dotnet-linux.yml
Dec 28, 2025
a911774
Merge branch 'hotfix-integ-hanging' into develop
Dec 28, 2025
af4198c
Update appspec.yml for .NET 10
Dec 28, 2025
beae044
Minor bugfix with cloudwatch metrics + Discord stop
Dec 28, 2025
ab6d881
Fixed some metrics related bugs
Dec 29, 2025
dc5a55f
Bugfix: Missing user ID mention in eligibility embed
Dec 29, 2025
4a39b36
Bugfix: All template variables in Strings.resx must be replaced with…
PaxAndromeda Dec 29, 2025
80ebb4d
Bugfix: Successful setbirthday response will return requested date/time.
PaxAndromeda Dec 29, 2025
fc2bc4f
Updated command line options to permit log level setting at startup
PaxAndromeda Dec 29, 2025
d16bdf4
Sync master -> develop
PaxAndromeda Dec 30, 2025
9e4f993
Bugfix: only grant birthdays once for each runtime
PaxAndromeda Jan 1, 2026
40368de
Bugfix: Auto kick spambot roles upon user join, not user update
PaxAndromeda Jan 1, 2026
e32c80c
Sync 'master' to 'develop'
PaxAndromeda Feb 1, 2026
3289657
Added additional logging to help diagnose test failure on Linux.
PaxAndromeda Feb 9, 2026
70f2f9a
Moving the log line to a spot where it can actually run
PaxAndromeda Feb 9, 2026
83025ca
Added Xunit serilog sink for better log tracing. Also updated AWS SDK
PaxAndromeda Feb 9, 2026
4ce6694
Updated Xunit2 to Xunit3
PaxAndromeda Feb 9, 2026
b060221
Add back console logging
PaxAndromeda Feb 9, 2026
e7dd60e
Removed unnecessary SetupLogging calls
PaxAndromeda Feb 9, 2026
d7f988f
Fixed bug with birthday role being removed while still a user's birthday
PaxAndromeda Feb 9, 2026
4e2bb7b
Works on my machine
PaxAndromeda Feb 9, 2026
09d1510
More logs
PaxAndromeda Feb 9, 2026
b534528
Fixed DateTime parsing issue in test
PaxAndromeda Feb 9, 2026
6388274
Removed extra logging
PaxAndromeda Feb 9, 2026
909a1ed
NotificationService will no longer send a notification if the referen…
PaxAndromeda Feb 9, 2026
ddaf299
Birthday system will no longer attempt to grant roles to a user who j…
PaxAndromeda Feb 9, 2026
0c34ec2
Added more comprehensive user update support
PaxAndromeda Feb 9, 2026
a3c1311
Added configuration for allowed punishment reasons
PaxAndromeda Feb 9, 2026
81f22f9
Minor bugfix
PaxAndromeda Feb 9, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Commands/ApplicationStart/StartInstar.sh
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ startInstar() {

local INSTAR_CONF="/Instar/bin/Config/$INSTAR_CONF_FILE"

/Instar/bin/InstarBot --config-path "$INSTAR_CONF" > /dev/null 2> /dev/null < /dev/null &
/Instar/bin/InstarBot --config-path "$INSTAR_CONF" --level Debug > /dev/null 2> /dev/null < /dev/null &
}

startInstar
1 change: 1 addition & 0 deletions InstarBot.Tests.Common/EmbedVerifier.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using System.Collections.Immutable;
using Discord;
using Serilog;
using Xunit;

namespace InstarBot.Tests;

Expand Down
6 changes: 3 additions & 3 deletions InstarBot.Tests.Common/InstarBot.Tests.Common.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -7,20 +7,20 @@
<RootNamespace>InstarBot.Tests</RootNamespace>
<IsTestProject>false</IsTestProject>
<PublishWithAspNetCoreTargetManifest>false</PublishWithAspNetCoreTargetManifest>
<OutputType>Exe</OutputType>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="AWSSDK.Core" Version="4.0.3.12" />
<PackageReference Include="FluentAssertions" Version="8.8.0" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="18.0.1" />
<PackageReference Include="Moq" Version="4.20.72" />
<PackageReference Include="MSTest.TestAdapter" Version="4.0.2" />
<PackageReference Include="MSTest.TestFramework" Version="4.0.2" />
<PackageReference Include="System.Linq.Async" Version="7.0.0" />
<PackageReference Include="xunit" Version="2.9.3" />
<PackageReference Include="xunit.runner.visualstudio" Version="3.1.5">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="xunit.v3" Version="3.2.2" />
</ItemGroup>

<ItemGroup>
Expand Down
1 change: 0 additions & 1 deletion InstarBot.Tests.Integration/Assembly.cs

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -4,20 +4,20 @@
<TargetFramework>net10.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
<OutputType>Exe</OutputType>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Ardalis.GuardClauses" Version="5.0.0" />
<PackageReference Include="AWSSDK.Core" Version="4.0.3.12" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="18.0.1" />
<PackageReference Include="Moq" Version="4.20.72" />
<PackageReference Include="MSTest.TestAdapter" Version="4.0.2" />
<PackageReference Include="MSTest.TestFramework" Version="4.0.2" />
<PackageReference Include="xunit" Version="2.9.3" />
<PackageReference Include="xunit.runner.visualstudio" Version="3.1.5">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="FluentAssertions" Version="8.8.0" />
<PackageReference Include="xunit.v3" Version="3.2.2" />
</ItemGroup>

<ItemGroup>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,7 @@ await tds.CreateNotificationAsync(new Notification

// There is a potential asynchronous delay here, so let's keep waiting for this condition for 5 seconds.
await Task.WhenAny(
Task.Delay(5000),
Task.Delay(5000, TestContext.Current.CancellationToken),
Task.Factory.StartNew(async () =>
{
while (true)
Expand All @@ -160,7 +160,7 @@ await Task.WhenAny(
// only poll once every 50ms
await Task.Delay(50);
}
}));
}, TestContext.Current.CancellationToken));
}

[Fact]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ public static class PageCommandTests
{
private const string TestReason = "Test reason for paging";

private static async Task<TestOrchestrator> SetupOrchestrator(PageCommandTestContext context)
private static async Task<TestOrchestrator> SetupOrchestrator(PageCommandTestContext context)
{
var orchestrator = TestOrchestrator.Default;

Expand Down
14 changes: 7 additions & 7 deletions InstarBot.Tests.Integration/Interactions/PingCommandTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,13 @@ namespace InstarBot.Tests.Integration.Interactions;

public static class PingCommandTests
{
/// <summary>
/// Tests that the ping command emits an ephemeral "Pong!" response.
/// </summary>
/// <remarks>This test verifies that calling the ping command results in the
/// expected ephemeral "Pong!" response.</remarks>
/// <returns></returns>
[Fact(DisplayName = "User should be able to issue the Ping command.")]
/// <summary>
/// Tests that the ping command emits an ephemeral "Pong!" response.
/// </summary>
/// <remarks>This test verifies that calling the ping command results in the
/// expected ephemeral "Pong!" response.</remarks>
/// <returns></returns>
[Fact(DisplayName = "User should be able to issue the Ping command.")]
public static async Task PingCommand_Send_ShouldEmitEphemeralPong()
{
// Arrange
Expand Down
9 changes: 5 additions & 4 deletions InstarBot.Tests.Integration/Services/BirthdaySystemTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
using Moq;
using PaxAndromeda.Instar;
using PaxAndromeda.Instar.Services;
using Serilog;
using Xunit;
using Metric = PaxAndromeda.Instar.Metrics.Metric;

Expand Down Expand Up @@ -68,7 +69,7 @@ public static async Task BirthdaySystem_WhenUserBirthday_ShouldGrantRole()
var channel = await orchestrator.Discord.GetChannel(orchestrator.Configuration.BirthdayConfig.BirthdayAnnounceChannel) as TestChannel;
channel.Should().NotBeNull();

var messages = await channel.GetMessagesAsync().SelectMany(n => n).ToListAsync();
var messages = await channel.GetMessagesAsync().SelectMany(n => n).ToListAsync(TestContext.Current.CancellationToken);
messages.Count.Should().BeGreaterThan(0);
TestUtilities.MatchesFormat(Strings.Birthday_Announcement, messages[0].Content);

Expand Down Expand Up @@ -153,7 +154,7 @@ public static async Task BirthdaySystem_WhenNoBirthdays_ShouldDoNothing()
var channel = await orchestrator.Discord.GetChannel(orchestrator.Configuration.BirthdayConfig.BirthdayAnnounceChannel) as TestChannel;
channel.Should().NotBeNull();

var messages = await channel.GetMessagesAsync().SelectMany(n => n).ToListAsync();
var messages = await channel.GetMessagesAsync().SelectMany(n => n).ToListAsync(TestContext.Current.CancellationToken);
messages.Count.Should().Be(0);
}

Expand Down Expand Up @@ -210,8 +211,8 @@ public static async Task BirthdaySystem_WithBirthdayRoleButNoBirthdayRecord_Shou
public static async Task BirthdaySystem_WithUserBirthdayStill_ShouldKeepBirthdayRoles()
{
// Arrange
var birthday = DateTime.Parse("2000-02-13T12:00:00Z");
var currentTime = DateTime.Parse("2025-02-14T00:00:00Z");
var birthday = DateTimeOffset.Parse("2000-02-13T00:00:00-08:00");
var currentTime = DateTimeOffset.Parse("2025-02-14T00:00:00Z");

var orchestrator = await SetupOrchestrator(currentTime, birthday);
var system = orchestrator.GetService<IBirthdaySystem>();
Expand Down
7 changes: 7 additions & 0 deletions InstarBot.Tests.Orchestrator/InstarBot.Test.Framework.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,15 @@
<TargetFramework>net10.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<OutputType>Exe</OutputType>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="AWSSDK.Core" Version="4.0.3.12" />
<PackageReference Include="Serilog.Sinks.XUnit3" Version="1.2.0" />
<PackageReference Include="xunit.v3" Version="3.2.2" />
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\InstarBot.Tests.Common\InstarBot.Tests.Common.csproj" />
</ItemGroup>
Expand Down
5 changes: 4 additions & 1 deletion InstarBot.Tests.Orchestrator/TestOrchestrator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@
using Serilog.Events;
using System.Diagnostics.CodeAnalysis;
using System.Runtime.InteropServices;
using Serilog.Sinks.XUnit3;
using Xunit;
using InvalidOperationException = Amazon.CloudWatchLogs.Model.InvalidOperationException;

namespace InstarBot.Test.Framework
Expand Down Expand Up @@ -109,12 +111,13 @@ private void InitializeActor()
tdbs.CreateUserAsync(InstarUserData.CreateFrom(user)).Wait();
}

private static void SetupLogging()
public static void SetupLogging()
{
Log.Logger = new LoggerConfiguration()
.Enrich.FromLogContext()
.MinimumLevel.Is(LogEventLevel.Verbose)
.WriteTo.Console()
.WriteTo.XUnit3TestOutput()
.CreateLogger();
Log.Warning("Logging is enabled for this unit test.");
}
Expand Down
3 changes: 0 additions & 3 deletions InstarBot.Tests.Unit/Assembly.cs

This file was deleted.

10 changes: 5 additions & 5 deletions InstarBot.Tests.Unit/AsyncAutoResetEventTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ public void WaitAsync_CompletesImmediately_WhenInitiallySignaled()
var ev = new AsyncAutoResetEvent(true);

// Act
var task = ev.WaitAsync();
var task = ev.WaitAsync(TestContext.Current.CancellationToken);

// Assert
task.IsCompleted.Should().BeTrue();
Expand All @@ -26,8 +26,8 @@ public void Set_ReleasesSingleWaiter()
{
var ev = new AsyncAutoResetEvent(false);

var waiter1 = ev.WaitAsync();
var waiter2 = ev.WaitAsync();
var waiter1 = ev.WaitAsync(TestContext.Current.CancellationToken);
var waiter2 = ev.WaitAsync(TestContext.Current.CancellationToken);

// First Set should release only one waiter.
ev.Set();
Expand All @@ -49,13 +49,13 @@ public void Set_MarksEventSignaled_WhenNoWaiters()
// No waiters now — Set should mark the event signaled so the next WaitAsync completes immediately.
ev.Set();

var immediate = ev.WaitAsync();
var immediate = ev.WaitAsync(TestContext.Current.CancellationToken);

// WaitAsync should complete immediately after Set() when there were no waiters
immediate.IsCompleted.Should().BeTrue();

// That consumption should reset the event; a subsequent waiter should block.
var next = ev.WaitAsync();
var next = ev.WaitAsync(TestContext.Current.CancellationToken);

next.IsCompleted.Should().BeFalse();
}
Expand Down
2 changes: 1 addition & 1 deletion InstarBot.Tests.Unit/BirthdayTests.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using System;
using System;
using FluentAssertions;
using Moq;
using PaxAndromeda.Instar;
Expand Down
6 changes: 3 additions & 3 deletions InstarBot.Tests.Unit/InstarBot.Tests.Unit.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -7,16 +7,15 @@
<IsPackable>false</IsPackable>

<RootNamespace>InstarBot.Tests</RootNamespace>
<OutputType>Exe</OutputType>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Ardalis.GuardClauses" Version="5.0.0" />
<PackageReference Include="AWSSDK.Core" Version="4.0.3.12" />
<PackageReference Include="FluentAssertions" Version="8.8.0" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="18.0.1" />
<PackageReference Include="Moq" Version="4.20.72" />
<PackageReference Include="MSTest.TestAdapter" Version="4.0.2" />
<PackageReference Include="MSTest.TestFramework" Version="4.0.2" />
<PackageReference Include="xunit" Version="2.9.3" />
<PackageReference Include="xunit.runner.visualstudio" Version="3.1.5">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
Expand All @@ -25,6 +24,7 @@
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
<PackageReference Include="xunit.v3" Version="3.2.2" />
</ItemGroup>

<ItemGroup>
Expand Down
5 changes: 3 additions & 2 deletions InstarBot/Birthday.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System.Diagnostics.CodeAnalysis;
using System.Diagnostics.CodeAnalysis;
using Serilog;

namespace PaxAndromeda.Instar;

Expand Down Expand Up @@ -94,7 +95,7 @@ public bool IsToday
var currentLocalTime = dtNow.ToOffset(utcOffset);

var localTimeToday = new DateTimeOffset(currentLocalTime.Date, currentLocalTime.Offset);
var localTimeTomorrow = localTimeToday.Date.AddDays(1);
var localTimeTomorrow = localTimeToday.AddDays(1);

return Observed >= localTimeToday && Observed < localTimeTomorrow;
}
Expand Down
2 changes: 1 addition & 1 deletion InstarBot/Commands/SetBirthdayCommand.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using System.Diagnostics.CodeAnalysis;
using System.Diagnostics.CodeAnalysis;
using Discord;
using Discord.Interactions;
using Discord.WebSocket;
Expand Down
3 changes: 2 additions & 1 deletion InstarBot/ConfigModels/AutoMemberConfig.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@ public sealed class AutoMemberConfig
public int MinimumMessages { get; init; }
public int MinimumMessageTime { get; init; }
public List<RoleGroup> RequiredRoles { get; init; } = null!;
public bool EnableGaiusCheck { get; init; }
public bool EnableGaiusCheck { get; init; }
public List<string> AllowedPunishmentReasons { get; init; } = [];
}

[UsedImplicitly]
Expand Down
1 change: 1 addition & 0 deletions InstarBot/InstarBot.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
<PackageReference Include="Ardalis.GuardClauses" Version="5.0.0" />
<PackageReference Include="AWSSDK.AppConfigData" Version="4.0.2.6" />
<PackageReference Include="AWSSDK.CloudWatch" Version="4.0.5.4" />
<PackageReference Include="AWSSDK.Core" Version="4.0.3.12" />
<PackageReference Include="AWSSDK.DynamoDBv2" Version="4.0.10" />
<PackageReference Include="AWSSDK.SimpleSystemsManagement" Version="4.0.6.3" />
<PackageReference Include="CommandLineParser" Version="2.9.1" />
Expand Down
8 changes: 4 additions & 4 deletions InstarBot/Modals/UserUpdatedEventArgs.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,18 @@

namespace PaxAndromeda.Instar.Modals;

public class UserUpdatedEventArgs(Snowflake id, IGuildUser before, IGuildUser after)
public class UserUpdatedEventArgs(Snowflake id, IUser before, IUser after)
{
public Snowflake ID { get; } = id;

public IGuildUser Before { get; } = before;
public IUser Before { get; } = before;

public IGuildUser After { get; } = after;
public IUser After { get; } = after;

// TODO: add additional parts to this for the data we care about

/// <summary>
/// A flag indicating whether data we care about (e.g. nicknames, usernames) has changed.
/// </summary>
public bool HasUpdated => Before.Username != After.Username || Before.Nickname != After.Nickname;
public bool HasUpdated => Before.Username != After.Username || (Before is IGuildUser gBefore && After is IGuildUser gAfter && gBefore.Nickname != gAfter.Nickname);
}
Loading