From 96994906746fc36af9e3f5b54ab6694a4cc347bc Mon Sep 17 00:00:00 2001 From: ambdroid <61042504+ambdroid@users.noreply.github.com> Date: Tue, 1 Oct 2024 08:38:35 -0400 Subject: [PATCH] feat(bot): add poll proxying --- .../Types/Requests/ExecuteWebhookRequest.cs | 10 ++++++++ Myriad/Types/Message.cs | 15 ++++++++++++ PluralKit.Bot/Proxy/ProxyService.cs | 8 +++++-- .../Services/WebhookExecutorService.cs | 24 +++++++++++++++++++ 4 files changed, 55 insertions(+), 2 deletions(-) diff --git a/Myriad/Rest/Types/Requests/ExecuteWebhookRequest.cs b/Myriad/Rest/Types/Requests/ExecuteWebhookRequest.cs index 9378650e..93601076 100644 --- a/Myriad/Rest/Types/Requests/ExecuteWebhookRequest.cs +++ b/Myriad/Rest/Types/Requests/ExecuteWebhookRequest.cs @@ -13,4 +13,14 @@ public record ExecuteWebhookRequest public AllowedMentions? AllowedMentions { get; init; } public bool? Tts { get; init; } public Message.MessageFlags? Flags { get; set; } + public WebhookPoll? Poll { get; set; } + + public record WebhookPoll + { + public Message.PollMedia Question { get; init; } + public Message.PollAnswer[] Answers { get; init; } + public int? Duration { get; init; } + public bool AllowMultiselect { get; init; } + public int LayoutType { get; init; } + } } \ No newline at end of file diff --git a/Myriad/Types/Message.cs b/Myriad/Types/Message.cs index b12ed142..70013ecc 100644 --- a/Myriad/Types/Message.cs +++ b/Myriad/Types/Message.cs @@ -70,6 +70,8 @@ public record Message [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)] public Optional ReferencedMessage { get; init; } + public MessagePoll? Poll { get; init; } + // public MessageComponent[]? Components { get; init; } public record Reference(ulong? GuildId, ulong? ChannelId, ulong? MessageId); @@ -96,4 +98,17 @@ public record Message public bool Me { get; init; } public Emoji Emoji { get; init; } } + + public record PollMedia(string? Text, Emoji? Emoji); + + public record PollAnswer(PollMedia PollMedia); + + public record MessagePoll + { + public PollMedia Question { get; init; } + public PollAnswer[] Answers { get; init; } + public string? Expiry { get; init; } + public bool AllowMultiselect { get; init; } + public int LayoutType { get; init; } + } } \ No newline at end of file diff --git a/PluralKit.Bot/Proxy/ProxyService.cs b/PluralKit.Bot/Proxy/ProxyService.cs index b8a533ef..94e3b2af 100644 --- a/PluralKit.Bot/Proxy/ProxyService.cs +++ b/PluralKit.Bot/Proxy/ProxyService.cs @@ -189,9 +189,9 @@ public class ProxyService throw new ProxyChecksFailedException( "Your system has proxying disabled in this server. Type `pk;proxy on` to enable it."); - // Make sure we have either an attachment or message content + // Make sure we have an attachment, message content, or poll var isMessageBlank = msg.Content == null || msg.Content.Trim().Length == 0; - if (isMessageBlank && msg.Attachments.Length == 0) + if (isMessageBlank && msg.Attachments.Length == 0 && msg.Poll == null) throw new ProxyChecksFailedException("Message cannot be blank."); if (msg.Activity != null) @@ -242,6 +242,7 @@ public class ProxyService GuildId = trigger.GuildId!.Value, ChannelId = rootChannel.Id, ThreadId = threadId, + MessageId = trigger.Id, Name = await FixSameName(messageChannel.Id, ctx, match.Member), AvatarUrl = AvatarUtils.TryRewriteCdnUrl(match.Member.ProxyAvatar(ctx)), Content = content, @@ -252,6 +253,7 @@ public class ProxyService AllowEveryone = allowEveryone, Flags = trigger.Flags.HasFlag(Message.MessageFlags.VoiceMessage) ? Message.MessageFlags.VoiceMessage : null, Tts = tts, + Poll = trigger.Poll, }); await HandleProxyExecutedActions(ctx, autoproxySettings, trigger, proxyMessage, match); } @@ -310,6 +312,7 @@ public class ProxyService GuildId = guild.Id, ChannelId = rootChannel.Id, ThreadId = threadId, + MessageId = originalMsg.Id, Name = match.Member.ProxyName(ctx), AvatarUrl = AvatarUtils.TryRewriteCdnUrl(match.Member.ProxyAvatar(ctx)), Content = match.ProxyContent!, @@ -320,6 +323,7 @@ public class ProxyService AllowEveryone = allowEveryone, Flags = originalMsg.Flags.HasFlag(Message.MessageFlags.VoiceMessage) ? Message.MessageFlags.VoiceMessage : null, Tts = tts, + Poll = originalMsg.Poll, }); diff --git a/PluralKit.Bot/Services/WebhookExecutorService.cs b/PluralKit.Bot/Services/WebhookExecutorService.cs index fa38d22f..e45ca67c 100644 --- a/PluralKit.Bot/Services/WebhookExecutorService.cs +++ b/PluralKit.Bot/Services/WebhookExecutorService.cs @@ -4,6 +4,8 @@ using App.Metrics; using Humanizer; +using NodaTime.Text; + using Myriad.Cache; using Myriad.Extensions; using Myriad.Rest; @@ -35,6 +37,7 @@ public record ProxyRequest public ulong GuildId { get; init; } public ulong ChannelId { get; init; } public ulong? ThreadId { get; init; } + public ulong MessageId { get; init; } public string Name { get; init; } public string? AvatarUrl { get; init; } public string? Content { get; init; } @@ -45,6 +48,7 @@ public record ProxyRequest public bool AllowEveryone { get; init; } public Message.MessageFlags? Flags { get; init; } public bool Tts { get; init; } + public Message.MessagePoll? Poll { get; init; } } public class WebhookExecutorService @@ -154,6 +158,26 @@ public class WebhookExecutorService }).ToArray(); } + if (req.Poll is Message.MessagePoll poll) + { + int? duration = null; + if (poll.Expiry is string expiry) + { + var then = OffsetDateTimePattern.ExtendedIso.Parse(expiry).Value.ToInstant(); + var now = DiscordUtils.SnowflakeToInstant(req.MessageId); + // in theory .TotalHours should be exact, but just in case + duration = (int)Math.Round((then - now).TotalMinutes / 60.0); + } + webhookReq.Poll = new ExecuteWebhookRequest.WebhookPoll + { + Question = poll.Question, + Answers = poll.Answers, + Duration = duration, + AllowMultiselect = poll.AllowMultiselect, + LayoutType = poll.LayoutType + }; + } + Message webhookMessage; using (_metrics.Measure.Timer.Time(BotMetrics.WebhookResponseTime)) {