From 80c572f5946de42a7c377fc686ad22edf268f05d Mon Sep 17 00:00:00 2001 From: Ske Date: Sun, 31 Jan 2021 16:02:34 +0100 Subject: [PATCH] Fix various bugs and regressions --- Myriad/Rest/Ratelimit/Bucket.cs | 5 +- Myriad/Types/GuildMember.cs | 2 +- PluralKit.Bot/Bot.cs | 10 ++- PluralKit.Bot/CommandSystem/Context.cs | 4 +- PluralKit.Bot/Commands/ImportExport.cs | 1 - PluralKit.Bot/Commands/Misc.cs | 3 +- PluralKit.Bot/Commands/SystemFront.cs | 16 +++-- PluralKit.Bot/Handlers/MessageCreated.cs | 2 +- PluralKit.Bot/Proxy/ProxyService.cs | 61 ++++++++----------- PluralKit.Bot/Services/LogChannelService.cs | 2 - .../Services/WebhookExecutorService.cs | 11 +++- 11 files changed, 60 insertions(+), 57 deletions(-) diff --git a/Myriad/Rest/Ratelimit/Bucket.cs b/Myriad/Rest/Ratelimit/Bucket.cs index 7f49ec33..918b11b2 100644 --- a/Myriad/Rest/Ratelimit/Bucket.cs +++ b/Myriad/Rest/Ratelimit/Bucket.cs @@ -73,11 +73,14 @@ namespace Myriad.Rest.Ratelimit try { _semaphore.Wait(); + + _logger.Verbose("{BucketKey}/{BucketMajor}: Received rate limit headers: {@RateLimitHeaders}", + Key, Major, headers); if (headers.ResetAfter != null) { var headerNextReset = DateTimeOffset.UtcNow + headers.ResetAfter.Value; // todo: server time - if (headerNextReset > _nextReset) + if (_nextReset == null || headerNextReset > _nextReset) { _logger.Debug("{BucketKey}/{BucketMajor}: Received reset time {NextReset} from server (after: {NextResetAfter}, remaining: {Remaining}, local remaining: {LocalRemaining})", Key, Major, headerNextReset, headers.ResetAfter.Value, headers.Remaining, Remaining); diff --git a/Myriad/Types/GuildMember.cs b/Myriad/Types/GuildMember.cs index da25fd65..c08508ff 100644 --- a/Myriad/Types/GuildMember.cs +++ b/Myriad/Types/GuildMember.cs @@ -7,7 +7,7 @@ public record GuildMemberPartial { - public string Nick { get; init; } + public string? Nick { get; init; } public ulong[] Roles { get; init; } public string JoinedAt { get; init; } } diff --git a/PluralKit.Bot/Bot.cs b/PluralKit.Bot/Bot.cs index 17c8bfad..550c8d48 100644 --- a/PluralKit.Bot/Bot.cs +++ b/PluralKit.Bot/Bot.cs @@ -14,6 +14,7 @@ using Myriad.Cache; using Myriad.Extensions; using Myriad.Gateway; using Myriad.Rest; +using Myriad.Rest.Exceptions; using Myriad.Types; using NodaTime; @@ -244,9 +245,12 @@ namespace PluralKit.Bot // Once we've sent it to Sentry, report it to the user (if we have permission to) var reportChannel = handler.ErrorChannelFor(evt); - // TODO: ID lookup - // if (reportChannel != null && reportChannel.BotHasAllPermissions(Permissions.SendMessages | Permissions.EmbedLinks)) - // await _errorMessageService.SendErrorMessage(reportChannel, sentryEvent.EventId.ToString()); + if (reportChannel != null) + { + var botPerms = PermissionsIn(reportChannel.Value); + if (botPerms.HasFlag(PermissionSet.SendMessages | PermissionSet.EmbedLinks)) + await _errorMessageService.SendErrorMessage(reportChannel.Value, sentryEvent.EventId.ToString()); + } } } diff --git a/PluralKit.Bot/CommandSystem/Context.cs b/PluralKit.Bot/CommandSystem/Context.cs index d0135ced..16ac3abd 100644 --- a/PluralKit.Bot/CommandSystem/Context.cs +++ b/PluralKit.Bot/CommandSystem/Context.cs @@ -101,9 +101,9 @@ namespace PluralKit.Bot { Content = text, Embed = embed, - AllowedMentions = mentions + // Default to an empty allowed mentions object instead of null (which means no mentions allowed) + AllowedMentions = mentions ?? new AllowedMentions() }); - // TODO: mentions should default to empty and not null? if (embed != null) { diff --git a/PluralKit.Bot/Commands/ImportExport.cs b/PluralKit.Bot/Commands/ImportExport.cs index fda3afe7..bbc3973a 100644 --- a/PluralKit.Bot/Commands/ImportExport.cs +++ b/PluralKit.Bot/Commands/ImportExport.cs @@ -144,7 +144,6 @@ namespace PluralKit.Bot try { var dm = await ctx.RestNew.CreateDm(ctx.AuthorNew.Id); - // TODO: send file var msg = await ctx.RestNew.CreateMessage(dm.Id, new MessageRequest {Content = $"{Emojis.Success} Here you go!"}, diff --git a/PluralKit.Bot/Commands/Misc.cs b/PluralKit.Bot/Commands/Misc.cs index 92ea99e4..b663747d 100644 --- a/PluralKit.Bot/Commands/Misc.cs +++ b/PluralKit.Bot/Commands/Misc.cs @@ -84,8 +84,7 @@ namespace PluralKit.Bot { var totalSwitches = _metrics.Snapshot.GetForContext("Application").Gauges.FirstOrDefault(m => m.MultidimensionalName == CoreMetrics.SwitchCount.Name)?.Value ?? 0; var totalMessages = _metrics.Snapshot.GetForContext("Application").Gauges.FirstOrDefault(m => m.MultidimensionalName == CoreMetrics.MessageCount.Name)?.Value ?? 0; - // TODO: shard stuff - var shardId = ctx.ShardNew.ShardInfo?.ShardId ?? -1; + var shardId = ctx.ShardNew.ShardInfo.ShardId; var shardTotal = ctx.Cluster.Shards.Count; var shardUpTotal = _shards.Shards.Where(x => x.Connected).Count(); var shardInfo = _shards.GetShardInfo(ctx.ShardNew); diff --git a/PluralKit.Bot/Commands/SystemFront.cs b/PluralKit.Bot/Commands/SystemFront.cs index 47a01d03..3f8cbc0b 100644 --- a/PluralKit.Bot/Commands/SystemFront.cs +++ b/PluralKit.Bot/Commands/SystemFront.cs @@ -1,5 +1,6 @@ using System; using System.Linq; +using System.Text; using System.Threading.Tasks; using NodaTime; @@ -70,6 +71,7 @@ namespace PluralKit.Bot embedTitle, async (builder, switches) => { + var sb = new StringBuilder(); foreach (var entry in switches) { var lastSw = entry.LastTime; @@ -98,17 +100,13 @@ namespace PluralKit.Bot stringToAdd = $"**{membersStr}** ({sw.Timestamp.FormatZoned(system.Zone)}, {switchSince.FormatDuration()} ago)\n"; } - - try // Unfortunately the only way to test DiscordEmbedBuilder.Description max length is this - { - // TODO: what is this?? - // builder.Description += stringToAdd; - } - catch (ArgumentException) - { + + if (sb.Length + stringToAdd.Length >= 1024) break; - }// TODO: Make sure this works + sb.Append(stringToAdd); } + + builder.Description(sb.ToString()); } ); } diff --git a/PluralKit.Bot/Handlers/MessageCreated.cs b/PluralKit.Bot/Handlers/MessageCreated.cs index cd5a0f00..b5fc477a 100644 --- a/PluralKit.Bot/Handlers/MessageCreated.cs +++ b/PluralKit.Bot/Handlers/MessageCreated.cs @@ -58,7 +58,7 @@ namespace PluralKit.Bot public async Task Handle(Shard shard, MessageCreateEvent evt) { if (evt.Author.Id == shard.User?.Id) return; - if (evt.Type != Message.MessageType.Default) return; + if (evt.Type != Message.MessageType.Default && evt.Type != Message.MessageType.Reply) return; if (IsDuplicateMessage(evt)) return; var guild = evt.GuildId != null ? _cache.GetGuild(evt.GuildId.Value) : null; diff --git a/PluralKit.Bot/Proxy/ProxyService.cs b/PluralKit.Bot/Proxy/ProxyService.cs index 0a362ab4..32781447 100644 --- a/PluralKit.Bot/Proxy/ProxyService.cs +++ b/PluralKit.Bot/Proxy/ProxyService.cs @@ -88,7 +88,8 @@ namespace PluralKit.Bot if (ctx.SystemId == null) return false; // Make sure channel is a guild text channel and this is a normal message - if ((channel.Type != Channel.ChannelType.GuildText && channel.Type != Channel.ChannelType.GuildNews) || msg.Type != Message.MessageType.Default) return false; + if (channel.Type != Channel.ChannelType.GuildText && channel.Type != Channel.ChannelType.GuildNews) return false; + if (msg.Type != Message.MessageType.Default && msg.Type != Message.MessageType.Reply) return false; // Make sure author is a normal user if (msg.Author.System == true || msg.Author.Bot || msg.WebhookId != null) return false; @@ -109,12 +110,13 @@ namespace PluralKit.Bot { // Create reply embed var embeds = new List(); - if (trigger.MessageReference?.ChannelId == trigger.ChannelId) + if (trigger.Type == Message.MessageType.Reply && trigger.MessageReference?.ChannelId == trigger.ChannelId) { - var repliedTo = await FetchReplyOriginalMessage(trigger.MessageReference); + var repliedTo = trigger.ReferencedMessage.Value; if (repliedTo != null) { - var embed = CreateReplyEmbed(repliedTo); + var nickname = await FetchReferencedMessageAuthorNickname(trigger, repliedTo); + var embed = CreateReplyEmbed(trigger, repliedTo, nickname); if (embed != null) embeds.Add(embed); } @@ -130,7 +132,7 @@ namespace PluralKit.Bot { GuildId = trigger.GuildId!.Value, ChannelId = trigger.ChannelId, - Name = FixSingleCharacterName(match.Member.ProxyName(ctx)), + Name = match.Member.ProxyName(ctx), AvatarUrl = match.Member.ProxyAvatar(ctx), Content = content, Attachments = trigger.Attachments, @@ -140,39 +142,39 @@ namespace PluralKit.Bot await HandleProxyExecutedActions(shard, conn, ctx, trigger, proxyMessage, match); } - private async Task FetchReplyOriginalMessage(Message.Reference reference) + private async Task FetchReferencedMessageAuthorNickname(Message trigger, Message referenced) { + if (referenced.WebhookId != null) + return null; + try { - var msg = await _rest.GetMessage(reference.ChannelId!.Value, reference.MessageId!.Value); - if (msg == null) - _logger.Warning("Attempted to fetch reply message {ChannelId}/{MessageId} but it was not found", - reference.ChannelId, reference.MessageId); - return msg; + var member = await _rest.GetGuildMember(trigger.GuildId!.Value, referenced.Author.Id); + return member?.Nick; } - catch (UnauthorizedException) + catch (ForbiddenException) { - _logger.Warning("Attempted to fetch reply message {ChannelId}/{MessageId} but bot was not allowed to", - reference.ChannelId, reference.MessageId); + _logger.Warning("Failed to fetch member {UserId} in guild {GuildId} when getting reply nickname, falling back to username", + referenced.Author.Id, trigger.GuildId!.Value); + return null; } - - return null; } - private Embed CreateReplyEmbed(Message original) + private Embed CreateReplyEmbed(Message trigger, Message repliedTo, string? nickname) { - var jumpLink = $"https://discord.com/channels/{original.GuildId}/{original.ChannelId}/{original.Id}"; + // repliedTo doesn't have a GuildId field :/ + var jumpLink = $"https://discord.com/channels/{trigger.GuildId}/{repliedTo.ChannelId}/{repliedTo.Id}"; var content = new StringBuilder(); - var hasContent = !string.IsNullOrWhiteSpace(original.Content); + var hasContent = !string.IsNullOrWhiteSpace(repliedTo.Content); if (hasContent) { - var msg = original.Content; + var msg = repliedTo.Content; if (msg.Length > 100) { - msg = original.Content.Substring(0, 100); - var spoilersInOriginalString = Regex.Matches(original.Content, @"\|\|").Count; + msg = repliedTo.Content.Substring(0, 100); + var spoilersInOriginalString = Regex.Matches(repliedTo.Content, @"\|\|").Count; var spoilersInTruncatedString = Regex.Matches(msg, @"\|\|").Count; if (spoilersInTruncatedString % 2 == 1 && spoilersInOriginalString % 2 == 0) msg += "||"; @@ -181,7 +183,7 @@ namespace PluralKit.Bot content.Append($"**[Reply to:]({jumpLink})** "); content.Append(msg); - if (original.Attachments.Length > 0) + if (repliedTo.Attachments.Length > 0) content.Append($" {Emojis.Paperclip}"); } else @@ -189,11 +191,8 @@ namespace PluralKit.Bot content.Append($"*[(click to see attachment)]({jumpLink})*"); } - // TODO: get the nickname somehow - var username = original.Author.Username; - // var username = original.Member?.Nick ?? original.Author.Username; - - var avatarUrl = $"https://cdn.discordapp.com/avatars/{original.Author.Id}/{original.Author.Avatar}.png"; + var username = nickname ?? repliedTo.Author.Username; + var avatarUrl = $"https://cdn.discordapp.com/avatars/{repliedTo.Author.Id}/{repliedTo.Author.Avatar}.png"; return new Embed { @@ -288,12 +287,6 @@ namespace PluralKit.Bot return true; } - private string FixSingleCharacterName(string proxyName) - { - if (proxyName.Length == 1) return proxyName += "\u17b5"; - else return proxyName; - } - private void CheckProxyNameBoundsOrError(string proxyName) { if (proxyName.Length > Limits.MaxProxyNameLength) throw Errors.ProxyNameTooLong(proxyName); diff --git a/PluralKit.Bot/Services/LogChannelService.cs b/PluralKit.Bot/Services/LogChannelService.cs index d08e42a7..6501181f 100644 --- a/PluralKit.Bot/Services/LogChannelService.cs +++ b/PluralKit.Bot/Services/LogChannelService.cs @@ -53,8 +53,6 @@ namespace PluralKit.Bot { } // Send embed! - - // TODO: fix? await using var conn = await _db.Obtain(); var embed = _embed.CreateLoggedMessageEmbed(await _repo.GetSystem(conn, ctx.SystemId.Value), await _repo.GetMember(conn, proxy.Member.Id), hookMessage, trigger.Id, trigger.Author, proxy.Content, diff --git a/PluralKit.Bot/Services/WebhookExecutorService.cs b/PluralKit.Bot/Services/WebhookExecutorService.cs index 005f2b45..9017bc30 100644 --- a/PluralKit.Bot/Services/WebhookExecutorService.cs +++ b/PluralKit.Bot/Services/WebhookExecutorService.cs @@ -87,7 +87,7 @@ namespace PluralKit.Bot var webhookReq = new ExecuteWebhookRequest { - Username = FixClyde(req.Name).Truncate(80), + Username = FixProxyName(req.Name).Truncate(80), Content = content, AllowedMentions = allowedMentions, AvatarUrl = !string.IsNullOrWhiteSpace(req.AvatarUrl) ? req.AvatarUrl : null, @@ -185,6 +185,8 @@ namespace PluralKit.Bot return chunks; } + private string FixProxyName(string name) => FixSingleCharacterName(FixClyde(name)); + private string FixClyde(string name) { static string Replacement(Match m) => m.Groups[1].Value + "\u200A" + m.Groups[2].Value; @@ -193,5 +195,12 @@ namespace PluralKit.Bot // since Discord blocks webhooks containing the word "Clyde"... for some reason. /shrug return Regex.Replace(name, "(c)(lyde)", Replacement, RegexOptions.IgnoreCase); } + + private string FixSingleCharacterName(string proxyName) + { + if (proxyName.Length == 1) + return proxyName + "\u17b5"; + return proxyName; + } } } \ No newline at end of file