From 5a52abed77ad2d85d07f5f2680596dea7933a07d Mon Sep 17 00:00:00 2001 From: Ske Date: Sun, 31 Jan 2021 14:50:10 +0100 Subject: [PATCH] Convert Sentry enrichers --- Myriad/Gateway/Events/MessageUpdateEvent.cs | 1 + PluralKit.Bot/Utils/DiscordUtils.cs | 53 +------------ PluralKit.Bot/Utils/SentryUtils.cs | 83 +++++++++++---------- 3 files changed, 45 insertions(+), 92 deletions(-) diff --git a/Myriad/Gateway/Events/MessageUpdateEvent.cs b/Myriad/Gateway/Events/MessageUpdateEvent.cs index 0bd1293b..09ef4316 100644 --- a/Myriad/Gateway/Events/MessageUpdateEvent.cs +++ b/Myriad/Gateway/Events/MessageUpdateEvent.cs @@ -9,6 +9,7 @@ namespace Myriad.Gateway public Optional Author { get; init; } public Optional Member { get; init; } public Optional Attachments { get; init; } + public Optional GuildId { get; init; } // TODO: lots of partials } } \ No newline at end of file diff --git a/PluralKit.Bot/Utils/DiscordUtils.cs b/PluralKit.Bot/Utils/DiscordUtils.cs index 69bf51e6..28b21ae0 100644 --- a/PluralKit.Bot/Utils/DiscordUtils.cs +++ b/PluralKit.Bot/Utils/DiscordUtils.cs @@ -30,9 +30,7 @@ namespace PluralKit.Bot public const uint Green = 0x00cc78; public const uint Red = 0xef4b3d; public const uint Gray = 0x979c9f; - - public static Permissions DM_PERMISSIONS = (Permissions) 0b00000_1000110_1011100110000_000000; - + private static readonly Regex USER_MENTION = new Regex("<@!?(\\d{17,19})>"); private static readonly Regex ROLE_MENTION = new Regex("<@&(\\d{17,19})>"); private static readonly Regex EVERYONE_HERE_MENTION = new Regex("@(everyone|here)"); @@ -44,60 +42,11 @@ namespace PluralKit.Bot // corresponding to: https://github.com/Khan/simple-markdown/blob/master/src/index.js#L1489 // I added ? at the start/end; they need to be handled specially later... private static readonly Regex UNBROKEN_LINK_REGEX = new Regex("?"); - - private static readonly FieldInfo _roleIdsField = - typeof(DiscordMember).GetField("_role_ids", BindingFlags.NonPublic | BindingFlags.Instance); public static string NameAndMention(this User user) { return $"{user.Username}#{user.Discriminator} ({user.Mention()})"; } - - // We funnel all "permissions from DiscordMember" calls through here - // This way we can ensure we do the read permission correction everywhere - private static Permissions PermissionsInGuild(DiscordChannel channel, DiscordMember member) - { - ValidateCachedRoles(member); - var permissions = channel.PermissionsFor(member); - - // This method doesn't account for channels without read permissions - // If we don't have read permissions in the channel, we don't have *any* permissions - if ((permissions & Permissions.AccessChannels) != Permissions.AccessChannels) - return Permissions.None; - - return permissions; - } - - // Workaround for DSP internal error - private static void ValidateCachedRoles(DiscordMember member) - { - var roleIdCache = _roleIdsField.GetValue(member) as List; - var currentRoleIds = member.Roles.Where(x => x != null).Select(x => x.Id); - var invalidRoleIds = roleIdCache.Where(x => !currentRoleIds.Contains(x)).ToList(); - roleIdCache.RemoveAll(x => invalidRoleIds.Contains(x)); - } - - - // Same as PermissionsIn, but always synchronous. DiscordUser must be a DiscordMember if channel is in guild. - public static Permissions PermissionsInSync(this DiscordChannel channel, DiscordUser user) - { - if (channel.Guild != null && !(user is DiscordMember)) - throw new ArgumentException("Function was passed a guild channel but a non-member DiscordUser"); - - if (user is DiscordMember m) return PermissionsInGuild(channel, m); - if (channel.Type == ChannelType.Private) return DM_PERMISSIONS; - return Permissions.None; - } - - public static Permissions BotPermissions(this DiscordChannel channel) - { - // TODO: can we get a CurrentMember somehow without a guild context? - // at least, without somehow getting a DiscordClient reference as an arg(which I don't want to do) - if (channel.Guild != null) - return PermissionsInSync(channel, channel.Guild.CurrentMember); - if (channel.Type == ChannelType.Private) return DM_PERMISSIONS; - return Permissions.None; - } public static Instant SnowflakeToInstant(ulong snowflake) => Instant.FromUtc(2015, 1, 1, 0, 0, 0) + Duration.FromMilliseconds(snowflake >> 22); diff --git a/PluralKit.Bot/Utils/SentryUtils.cs b/PluralKit.Bot/Utils/SentryUtils.cs index 0d9cfb19..ed1bf2f5 100644 --- a/PluralKit.Bot/Utils/SentryUtils.cs +++ b/PluralKit.Bot/Utils/SentryUtils.cs @@ -1,9 +1,6 @@ using System.Collections.Generic; -using System.Linq; - -using DSharpPlus; -using DSharpPlus.EventArgs; +using Myriad.Extensions; using Myriad.Gateway; using Sentry; @@ -15,82 +12,88 @@ namespace PluralKit.Bot void Enrich(Scope scope, Shard shard, T evt); } - public class SentryEnricher //: - // TODO!!! - // ISentryEnricher, - // ISentryEnricher, - // ISentryEnricher, - // ISentryEnricher, - // ISentryEnricher + public class SentryEnricher: + ISentryEnricher, + ISentryEnricher, + ISentryEnricher, + ISentryEnricher, + ISentryEnricher { + private readonly Bot _bot; + + public SentryEnricher(Bot bot) + { + _bot = bot; + } + // TODO: should this class take the Scope by dependency injection instead? // Would allow us to create a centralized "chain of handlers" where this class could just be registered as an entry in - public void Enrich(Scope scope, Shard shard, MessageCreateEventArgs evt) + public void Enrich(Scope scope, Shard shard, MessageCreateEvent evt) { - scope.AddBreadcrumb(evt.Message.Content, "event.message", data: new Dictionary + scope.AddBreadcrumb(evt.Content, "event.message", data: new Dictionary { {"user", evt.Author.Id.ToString()}, - {"channel", evt.Channel.Id.ToString()}, - {"guild", evt.Channel.GuildId.ToString()}, - {"message", evt.Message.Id.ToString()}, + {"channel", evt.ChannelId.ToString()}, + {"guild", evt.GuildId.ToString()}, + {"message", evt.Id.ToString()}, }); - scope.SetTag("shard", shard.ShardInfo?.ShardId.ToString()); + scope.SetTag("shard", shard.ShardInfo.ShardId.ToString()); // Also report information about the bot's permissions in the channel // We get a lot of permission errors so this'll be useful for determining problems - var perms = evt.Channel.BotPermissions(); + var perms = _bot.PermissionsIn(evt.ChannelId); scope.AddBreadcrumb(perms.ToPermissionString(), "permissions"); } - public void Enrich(Scope scope, Shard shard, MessageDeleteEventArgs evt) + public void Enrich(Scope scope, Shard shard, MessageDeleteEvent evt) { scope.AddBreadcrumb("", "event.messageDelete", data: new Dictionary() { - {"channel", evt.Channel.Id.ToString()}, - {"guild", evt.Channel.GuildId.ToString()}, - {"message", evt.Message.Id.ToString()}, + {"channel", evt.ChannelId.ToString()}, + {"guild", evt.GuildId.ToString()}, + {"message", evt.Id.ToString()}, }); - scope.SetTag("shard", shard.ShardInfo?.ShardId.ToString()); + scope.SetTag("shard", shard.ShardInfo.ShardId.ToString()); } - public void Enrich(Scope scope, Shard shard, MessageUpdateEventArgs evt) + public void Enrich(Scope scope, Shard shard, MessageUpdateEvent evt) { - scope.AddBreadcrumb(evt.Message.Content ?? "", "event.messageEdit", + scope.AddBreadcrumb(evt.Content.Value ?? "", "event.messageEdit", data: new Dictionary() { - {"channel", evt.Channel.Id.ToString()}, - {"guild", evt.Channel.GuildId.ToString()}, - {"message", evt.Message.Id.ToString()} + {"channel", evt.ChannelId.ToString()}, + {"guild", evt.GuildId.Value.ToString()}, + {"message", evt.Id.ToString()} }); - scope.SetTag("shard", shard.ShardInfo?.ShardId.ToString()); + scope.SetTag("shard", shard.ShardInfo.ShardId.ToString()); } - public void Enrich(Scope scope, Shard shard, MessageBulkDeleteEventArgs evt) + public void Enrich(Scope scope, Shard shard, MessageDeleteBulkEvent evt) { scope.AddBreadcrumb("", "event.messageDelete", data: new Dictionary() { - {"channel", evt.Channel.Id.ToString()}, - {"guild", evt.Channel.Id.ToString()}, - {"messages", string.Join(",", evt.Messages.Select(m => m.Id))}, + {"channel", evt.ChannelId.ToString()}, + {"guild", evt.GuildId.ToString()}, + {"messages", string.Join(",", evt.Ids)}, }); - scope.SetTag("shard", shard.ShardInfo?.ShardId.ToString()); + scope.SetTag("shard", shard.ShardInfo.ShardId.ToString()); } - public void Enrich(Scope scope, Shard shard, MessageReactionAddEventArgs evt) + public void Enrich(Scope scope, Shard shard, MessageReactionAddEvent evt) { scope.AddBreadcrumb("", "event.reaction", data: new Dictionary() { - {"user", evt.User.Id.ToString()}, - {"channel", (evt.Channel?.Id ?? 0).ToString()}, - {"guild", (evt.Channel?.GuildId ?? 0).ToString()}, - {"message", evt.Message.Id.ToString()}, + {"user", evt.UserId.ToString()}, + {"channel", evt.ChannelId.ToString()}, + {"guild", (evt.GuildId ?? 0).ToString()}, + {"message", evt.MessageId.ToString()}, {"reaction", evt.Emoji.Name} }); - scope.SetTag("shard", shard.ShardInfo?.ShardId.ToString()); + scope.SetTag("shard", shard.ShardInfo.ShardId.ToString()); } } } \ No newline at end of file