From d373ff49ba236ac1521876fdca7e59947ade2efc Mon Sep 17 00:00:00 2001 From: Toutsu Date: Tue, 19 May 2026 11:22:44 +0300 Subject: [PATCH] feat(discord): add DiscordPlatformMessenger IPlatformMessenger implementation Co-Authored-By: Claude Opus 4.7 --- .../Discord/DiscordPlatformMessenger.cs | 71 +++++++++++++++++++ .../Discord/DiscordPlatformMessengerTests.cs | 21 ++++++ 2 files changed, 92 insertions(+) create mode 100644 src/GmRelay.DiscordBot/Infrastructure/Discord/DiscordPlatformMessenger.cs create mode 100644 tests/GmRelay.Bot.Tests/Discord/DiscordPlatformMessengerTests.cs diff --git a/src/GmRelay.DiscordBot/Infrastructure/Discord/DiscordPlatformMessenger.cs b/src/GmRelay.DiscordBot/Infrastructure/Discord/DiscordPlatformMessenger.cs new file mode 100644 index 0000000..bc435bc --- /dev/null +++ b/src/GmRelay.DiscordBot/Infrastructure/Discord/DiscordPlatformMessenger.cs @@ -0,0 +1,71 @@ +using GmRelay.DiscordBot.Rendering; +using GmRelay.Shared.Platform; +using GmRelay.Shared.Rendering; +using NetCord; +using NetCord.Rest; + +namespace GmRelay.DiscordBot.Infrastructure.Discord; + +public sealed class DiscordPlatformMessenger(RestClient restClient) : IPlatformMessenger +{ + public async Task SendScheduleAsync(PlatformScheduleMessage message, CancellationToken ct) + { + var (embeds, actionRows) = DiscordSessionBatchRenderer.Render(message.View); + + var channelId = ulong.Parse(message.Group.ExternalChannelId + ?? message.Group.ExternalGroupId); + + var msg = await restClient.SendMessageAsync( + channelId, + new MessageProperties() + .WithEmbeds(embeds) + .WithComponents(actionRows)); + + return new PlatformMessageRef( + PlatformKind.Discord, + message.Group.ExternalGroupId, + null, + msg.Id.ToString()); + } + + public async Task UpdateScheduleAsync(PlatformScheduleMessage message, CancellationToken ct) + { + if (message.ExistingMessage is null) + return; + + var (embeds, actionRows) = DiscordSessionBatchRenderer.Render(message.View); + + var channelId = ulong.Parse(message.Group.ExternalChannelId + ?? message.Group.ExternalGroupId); + var messageId = ulong.Parse(message.ExistingMessage.ExternalMessageId); + + await restClient.ModifyMessageAsync( + channelId, + messageId, + options => + { + options.Embeds = embeds; + options.Components = actionRows; + }); + } + + public Task SendGroupMessageAsync(PlatformGroup group, string htmlText, CancellationToken ct) + { + return Task.CompletedTask; + } + + public Task SendPrivateMessageAsync(PlatformPrivateMessage message, CancellationToken ct) + { + return Task.CompletedTask; + } + + public Task AnswerInteractionAsync(PlatformInteractionReply reply, CancellationToken ct) + { + return Task.CompletedTask; + } + + public Task SendCalendarFileAsync(PlatformCalendarFile file, CancellationToken ct) + { + return Task.CompletedTask; + } +} diff --git a/tests/GmRelay.Bot.Tests/Discord/DiscordPlatformMessengerTests.cs b/tests/GmRelay.Bot.Tests/Discord/DiscordPlatformMessengerTests.cs new file mode 100644 index 0000000..a59eaee --- /dev/null +++ b/tests/GmRelay.Bot.Tests/Discord/DiscordPlatformMessengerTests.cs @@ -0,0 +1,21 @@ +using GmRelay.DiscordBot.Infrastructure.Discord; +using GmRelay.Shared.Platform; +using GmRelay.Shared.Rendering; + +namespace GmRelay.Bot.Tests.Discord; + +public sealed class DiscordPlatformMessengerTests +{ + [Fact] + public void Constructor_ShouldAcceptRestClient() + { + var constructor = typeof(DiscordPlatformMessenger).GetConstructor(new[] { typeof(NetCord.Rest.RestClient) }); + Assert.NotNull(constructor); + } + + [Fact] + public void DiscordPlatformMessenger_ShouldImplementIPlatformMessenger() + { + Assert.True(typeof(IPlatformMessenger).IsAssignableFrom(typeof(DiscordPlatformMessenger))); + } +}