diff --git a/Modules/EmojisModule.cs b/Modules/EmojisModule.cs index 76b7ad9..939a36d 100644 --- a/Modules/EmojisModule.cs +++ b/Modules/EmojisModule.cs @@ -8,6 +8,7 @@ using Morpheus.Services; using Morpheus.Utilities; using System.IO.Compression; +using System.Globalization; namespace Morpheus.Modules; @@ -294,9 +295,14 @@ private async Task HandleServerSelectInteraction(SocketInteraction interaction) return; } + if (!TryParseSelectionId(comp.Data.Values.FirstOrDefault(), out ulong selectedGuildId)) + { + await comp.RespondAsync("Invalid server selection.", ephemeral: true); + return; + } + await comp.DeferAsync(); - ulong selectedGuildId = ulong.Parse(comp.Data.Values.First()); var sourceGuild = client.GetGuild(selectedGuildId); if (sourceGuild == null) @@ -349,9 +355,14 @@ private async Task HandleEmojiSelectInteraction(SocketInteraction interaction) return; } + if (!TryParseSelectionId(comp.Data.Values.FirstOrDefault(), out ulong emojiId)) + { + await comp.RespondAsync("Invalid emoji selection.", ephemeral: true); + return; + } + await comp.DeferAsync(); - ulong emojiId = ulong.Parse(comp.Data.Values.First()); var sourceGuild = client.GetGuild(session.SourceGuildId); var targetGuild = client.GetGuild(session.TargetGuildId); @@ -824,6 +835,13 @@ await comp.ModifyOriginalResponseAsync(msg => _ => 50 }; + internal static bool TryParseSelectionId(string? value, out ulong id) + { + id = 0; + return !string.IsNullOrEmpty(value) && + ulong.TryParse(value, NumberStyles.None, CultureInfo.InvariantCulture, out id); + } + // ─── Cleanup expired sessions ──────────────────────────────────────── private static void CleanupExpiredSessions() diff --git a/Morpheus.Tests/EmojisModuleTests.cs b/Morpheus.Tests/EmojisModuleTests.cs index 1c9ac19..28ee573 100644 --- a/Morpheus.Tests/EmojisModuleTests.cs +++ b/Morpheus.Tests/EmojisModuleTests.cs @@ -22,6 +22,29 @@ public void TryGetReferencedMessageId_ReturnsReferenceIdWhenPresent() Assert.Equal(42UL, messageId); } + [Theory] + [InlineData("123456789", 123456789UL)] + [InlineData("18446744073709551615", ulong.MaxValue)] + public void TryParseSelectionId_AcceptsUnsignedDecimalIds(string value, ulong expected) + { + bool parsed = EmojisModule.TryParseSelectionId(value, out ulong id); + + Assert.True(parsed); + Assert.Equal(expected, id); + } + + [Theory] + [InlineData(null)] + [InlineData("")] + [InlineData(" ")] + [InlineData("not-an-id")] + [InlineData("-1")] + [InlineData("18446744073709551616")] + public void TryParseSelectionId_RejectsMalformedIds(string? value) + { + Assert.False(EmojisModule.TryParseSelectionId(value, out _)); + } + [Fact] public void GetEmojiArchivePath_UsesGuildIdUnderTempDirectory() {