diff --git a/Remora.Discord.Commands/Parsers/SnowflakeParser.cs b/Remora.Discord.Commands/Parsers/SnowflakeParser.cs index 2ee38a331c..b30a3a7521 100644 --- a/Remora.Discord.Commands/Parsers/SnowflakeParser.cs +++ b/Remora.Discord.Commands/Parsers/SnowflakeParser.cs @@ -20,6 +20,7 @@ // along with this program. If not, see . // +using System.Text.RegularExpressions; using System.Threading; using System.Threading.Tasks; using JetBrains.Annotations; @@ -38,9 +39,26 @@ namespace Remora.Discord.Commands.Parsers; [PublicAPI] public class SnowflakeParser : AbstractTypeParser { + private static readonly Regex _channelLinkRegex = new + ( + @"^https://(canary\.|ptb\.)?discord\.com/channels/(?@me|[0-9]*)/(?[0-9]*)(/(?[0-9]*))?/?$", + RegexOptions.Compiled | RegexOptions.CultureInvariant + ); + /// public override ValueTask> TryParseAsync(string value, CancellationToken ct = default) { + var channelLinkMatch = _channelLinkRegex.Match(value); + if (channelLinkMatch.Success) + { + value = channelLinkMatch.Groups["message_id"].Value; + + if (string.IsNullOrEmpty(value)) + { + value = channelLinkMatch.Groups["channel_id"].Value; + } + } + return new ( !DiscordSnowflake.TryParse(value.Unmention(), out var snowflake) diff --git a/Tests/Remora.Discord.Commands.Tests/Parsers/SnowflakeParserTests.cs b/Tests/Remora.Discord.Commands.Tests/Parsers/SnowflakeParserTests.cs index d2a0db6db8..5b089ae699 100644 --- a/Tests/Remora.Discord.Commands.Tests/Parsers/SnowflakeParserTests.cs +++ b/Tests/Remora.Discord.Commands.Tests/Parsers/SnowflakeParserTests.cs @@ -66,6 +66,24 @@ public async Task CanParseSnowflakeByNumber() Assert.Equal(snowflakeValue, tryParse.Entity.Value); } + /// + /// Tests whether the parser can parse snowflake value given by url. + /// + /// Mention that should be parsed correctly. + /// A representing the asynchronous unit test. + [InlineData("https://discord.com/channels/690919691404967977/765178263517397033")] + [InlineData("https://discord.com/channels/690919691404967977/1389600463250260019/765178263517397033")] + [InlineData("https://canary.discord.com/channels/690919691404967977/1389600463250260019/765178263517397033")] + [InlineData("https://ptb.discord.com/channels/690919691404967977/1389600463250260019/765178263517397033")] + [Theory] + public async Task CanParseSnowflakeByUrl(string value) + { + ulong snowflakeValue = 765178263517397033; + var tryParse = await _parser.TryParseAsync(value); + ResultAssert.Successful(tryParse); + Assert.Equal(snowflakeValue, tryParse.Entity.Value); + } + /// /// Tests whether the parser can parse snowflake value given by mentions. ///