From b0be937768ea1acf5a5373b14d479ff0ea205b1e Mon Sep 17 00:00:00 2001 From: Milkshake Date: Wed, 4 Sep 2024 15:03:30 -0400 Subject: [PATCH] Fix automatic warnings on AutoMod-blocked messages for forum channels (#225) * AutoMod auto-warn: use fallback channel for blocks in GuildForum channels * Use 'is' instead of '==' * Fetch forum channel auto-warn fallback on startup Also adds handling for when this config value is missing --- Events/MessageEvent.cs | 153 ++++++++++++++++++++++------------------- Program.cs | 5 ++ Structs.cs | 3 + config.json | 3 +- 4 files changed, 94 insertions(+), 70 deletions(-) diff --git a/Events/MessageEvent.cs b/Events/MessageEvent.cs index 8acc4e6..8ef2b88 100644 --- a/Events/MessageEvent.cs +++ b/Events/MessageEvent.cs @@ -106,8 +106,17 @@ static async Task DeleteAndWarnAsync(DiscordMessage message, string reason, Disc static async Task DeleteAndWarnAsync(MockDiscordMessage message, string reason, DiscordClient client, bool wasAutoModBlock = false) { + var channel = message.Channel; + if (!wasAutoModBlock) _ = message.DeleteAsync(); + else + if (channel.Type is DiscordChannelType.GuildForum) + if (Program.cfgjson.ForumChannelAutoWarnFallbackChannel == 0) + Program.discord.Logger.LogWarning("A warning in forum channel {channelId} was attempted, but may fail due to the fallback channel not being set. Please set 'forumChannelAutoWarnFallbackChannel' in config.json to avoid this.", channel.Id); + else + channel = Program.ForumChannelAutoWarnFallbackChannel; + try { _ = InvestigationsHelpers.SendInfringingMessaageAsync("mod", message, reason, null, wasAutoModBlock: wasAutoModBlock); @@ -116,8 +125,8 @@ static async Task DeleteAndWarnAsync(MockDiscordMessage message, string reason, { // still warn anyway } - DiscordMessage msg = await message.Channel.SendMessageAsync($"{Program.cfgjson.Emoji.Denied} {message.Author.Mention} was automatically warned: **{reason.Replace("`", "\\`").Replace("*", "\\*")}**"); - var warning = await WarningHelpers.GiveWarningAsync(message.Author, client.CurrentUser, reason, contextMessage: msg, message.Channel, " automatically "); + DiscordMessage msg = await channel.SendMessageAsync($"{Program.cfgjson.Emoji.Denied} {message.Author.Mention} was automatically warned: **{reason.Replace("`", "\\`").Replace("*", "\\*")}**"); + var warning = await WarningHelpers.GiveWarningAsync(message.Author, client.CurrentUser, reason, contextMessage: msg, channel, " automatically "); await InvestigationsHelpers.SendInfringingMessaageAsync("investigations", message, reason, warning.ContextLink, wasAutoModBlock: wasAutoModBlock); } @@ -139,9 +148,15 @@ public static async Task MessageHandlerAsync(DiscordClient client, MockDiscordMe return; if (wasAutoModBlock) - Program.discord.Logger.LogDebug("Processing AutoMod-blocked message in {channelId} by user {userId}", message.Channel.Id, message.Author.Id); + { + Program.discord.Logger.LogDebug("Processing AutoMod-blocked message in {channelId} by user {userId}", channel.Id, message.Author.Id); + if (channel.Type == DiscordChannelType.GuildForum && Program.cfgjson.ForumChannelAutoWarnFallbackChannel != 0) + channel = Program.ForumChannelAutoWarnFallbackChannel; + } else - Program.discord.Logger.LogDebug("Processing message {messageId} in {channelId} by user {userId}", message.Id, message.Channel.Id, message.Author.Id); + { + Program.discord.Logger.LogDebug("Processing message {messageId} in {channelId} by user {userId}", message.Id, channel.Id, message.Author.Id); + } if (!limitFilters) { @@ -170,12 +185,12 @@ public static async Task MessageHandlerAsync(DiscordClient client, MockDiscordMe if (!isAnEdit && message.Author.Id == Program.cfgjson.ModmailUserId && message.Content == "@here" && message.Embeds[0].Footer.Text.Contains("User ID:")) { - Program.discord.Logger.LogDebug(Program.CliptokEventID, "Processing modmail message {message} in {channel}", message.Id, message.Channel); + Program.discord.Logger.LogDebug(Program.CliptokEventID, "Processing modmail message {message} in {channel}", message.Id, channel); var idString = modmaiL_rx.Match(message.Embeds[0].Footer.Text).Groups[1].Captures[0].Value; DiscordMember modmailMember = default; try { - modmailMember = await message.Channel.Guild.GetMemberAsync(Convert.ToUInt64(idString)); + modmailMember = await channel.Guild.GetMemberAsync(Convert.ToUInt64(idString)); } catch (DSharpPlus.Exceptions.NotFoundException) { @@ -184,10 +199,10 @@ public static async Task MessageHandlerAsync(DiscordClient client, MockDiscordMe DiscordMessageBuilder memberWarnInfo = new(); - DiscordRole muted = await message.Channel.Guild.GetRoleAsync(Program.cfgjson.MutedRole); + DiscordRole muted = await channel.Guild.GetRoleAsync(Program.cfgjson.MutedRole); if (modmailMember.Roles.Contains(muted)) { - memberWarnInfo.AddEmbed(await WarningHelpers.GenerateWarningsEmbedAsync(modmailMember)).AddEmbed(await MuteHelpers.MuteStatusEmbed(modmailMember, message.Channel.Guild)); + memberWarnInfo.AddEmbed(await WarningHelpers.GenerateWarningsEmbedAsync(modmailMember)).AddEmbed(await MuteHelpers.MuteStatusEmbed(modmailMember, channel.Guild)); } // Add notes to message if any exist & are set to show on modmail @@ -216,7 +231,7 @@ public static async Task MessageHandlerAsync(DiscordClient client, MockDiscordMe // If message was built (if user is muted OR if user has notes to show on modmail), send it if (memberWarnInfo.Embeds.Count != 0) - await message.Channel.SendMessageAsync(memberWarnInfo); + await channel.SendMessageAsync(memberWarnInfo); // If any notes were shown & set to show only once, delete them now foreach (var note in notesToNotify.Where(note => note.Value.ShowOnce)) @@ -231,7 +246,7 @@ public static async Task MessageHandlerAsync(DiscordClient client, MockDiscordMe } // handle #giveaways - if (!isAnEdit && message.Author.Id == Program.cfgjson.GiveawayBot && message.Channel.Id == Program.cfgjson.GiveawaysChannel && message.Content == Program.cfgjson.GiveawayTriggerMessage) + if (!isAnEdit && message.Author.Id == Program.cfgjson.GiveawayBot && channel.Id == Program.cfgjson.GiveawaysChannel && message.Content == Program.cfgjson.GiveawayTriggerMessage) { string giveawayTitle = message.Embeds[0].Title; @@ -245,7 +260,7 @@ public static async Task MessageHandlerAsync(DiscordClient client, MockDiscordMe } // Skip DMs, external guilds, and messages from bots, beyond this point. - if (message.Channel.IsPrivate || message.Channel.Guild.Id != Program.cfgjson.ServerID || message.Author.IsBot) + if (channel.IsPrivate || channel.Guild.Id != Program.cfgjson.ServerID || message.Author.IsBot) return; if (!limitFilters) @@ -258,7 +273,7 @@ public static async Task MessageHandlerAsync(DiscordClient client, MockDiscordMe DiscordMember member; try { - member = await message.Channel.Guild.GetMemberAsync(message.Author.Id); + member = await channel.Guild.GetMemberAsync(message.Author.Id); } catch (DSharpPlus.Exceptions.NotFoundException) { @@ -278,7 +293,7 @@ public static async Task MessageHandlerAsync(DiscordClient client, MockDiscordMe !member.Roles.Any(role => role.Id == Program.cfgjson.TqsRoleId)) { await message.DeleteAsync(); - var msg = await message.Channel.SendMessageAsync($"{Program.cfgjson.Emoji.Error} {message.Author.Mention}, you can't send messages in this thread!\nTry creating a post on {message.Channel.Parent.Mention} instead."); + var msg = await channel.SendMessageAsync($"{Program.cfgjson.Emoji.Error} {message.Author.Mention}, you can't send messages in this thread!\nTry creating a post on {channel.Parent.Mention} instead."); await Task.Delay(5000); await msg.DeleteAsync(); return; @@ -289,11 +304,11 @@ public static async Task MessageHandlerAsync(DiscordClient client, MockDiscordMe { if (wasAutoModBlock) { - Program.discord.Logger.LogDebug("AutoMod-blocked message in {channelId} by user {userId} triggered mass-mention filter", message.Channel.Id, message.Author.Id); + Program.discord.Logger.LogDebug("AutoMod-blocked message in {channelId} by user {userId} triggered mass-mention filter", channel.Id, message.Author.Id); } else { - Program.discord.Logger.LogDebug("Message {messageId} in {channelId} by user {userId} triggered mass-mention filter", message.Id, message.Channel.Id, message.Author.Id); + Program.discord.Logger.LogDebug("Message {messageId} in {channelId} by user {userId} triggered mass-mention filter", message.Id, channel.Id, message.Author.Id); _ = message.DeleteAsync(); } @@ -310,7 +325,7 @@ public static async Task MessageHandlerAsync(DiscordClient client, MockDiscordMe // Matching word list foreach (var listItem in Program.cfgjson.WordListList) { - if (listItem.ExcludedChannels.Contains(message.Channel.Id) || listItem.Passive) + if (listItem.ExcludedChannels.Contains(channel.Id) || listItem.Passive) { continue; } @@ -320,9 +335,9 @@ public static async Task MessageHandlerAsync(DiscordClient client, MockDiscordMe if (success) { if (wasAutoModBlock) - Program.discord.Logger.LogDebug("AutoMod-blocked message in {channelId} by user {userId} triggered word list filter", message.Channel.Id, message.Author.Id); + Program.discord.Logger.LogDebug("AutoMod-blocked message in {channelId} by user {userId} triggered word list filter", channel.Id, message.Author.Id); else - Program.discord.Logger.LogDebug("Message {messageId} in {channelId} by user {userId} triggered word list filter", message.Id, message.Channel.Id, message.Author.Id); + Program.discord.Logger.LogDebug("Message {messageId} in {channelId} by user {userId} triggered word list filter", message.Id, channel.Id, message.Author.Id); string reason = listItem.Reason; try @@ -340,16 +355,16 @@ public static async Task MessageHandlerAsync(DiscordClient client, MockDiscordMe { if (!wasAutoModBlock) _ = message.DeleteAsync(); - await BanHelpers.BanFromServerAsync(message.Author.Id, reason, client.CurrentUser.Id, message.Channel.Guild, 0, message.Channel, default, true); + await BanHelpers.BanFromServerAsync(message.Author.Id, reason, client.CurrentUser.Id, channel.Guild, 0, channel, default, true); return; } - //var tmp = message.Channel.Type; + //var tmp = channel.Type; match = true; - DiscordMessage msg = await message.Channel.SendMessageAsync($"{Program.cfgjson.Emoji.Denied} {message.Author.Mention} was automatically warned: **{reason.Replace("`", "\\`").Replace("*", "\\*")}**"); - var warning = await WarningHelpers.GiveWarningAsync(message.Author, client.CurrentUser, reason, contextMessage: msg, message.Channel, " automatically "); + DiscordMessage msg = await channel.SendMessageAsync($"{Program.cfgjson.Emoji.Denied} {message.Author.Mention} was automatically warned: **{reason.Replace("`", "\\`").Replace("*", "\\*")}**"); + var warning = await WarningHelpers.GiveWarningAsync(message.Author, client.CurrentUser, reason, contextMessage: msg, channel, " automatically "); await InvestigationsHelpers.SendInfringingMessaageAsync("investigations", message, reason, warning.ContextLink, extraField: ("Match", flaggedWord, true), wasAutoModBlock: wasAutoModBlock); return; } @@ -370,11 +385,11 @@ public static async Task MessageHandlerAsync(DiscordClient client, MockDiscordMe { if (wasAutoModBlock) { - Program.discord.Logger.LogDebug("AutoMod-blocked message in {channelId} by user {userId} triggered unapproved invite filter", message.Channel.Id, message.Author.Id); + Program.discord.Logger.LogDebug("AutoMod-blocked message in {channelId} by user {userId} triggered unapproved invite filter", channel.Id, message.Author.Id); } else { - Program.discord.Logger.LogDebug("Message {messageId} in {channelId} by user {userId} triggered unapproved invite filter", message.Id, message.Channel.Id, message.Author.Id); + Program.discord.Logger.LogDebug("Message {messageId} in {channelId} by user {userId} triggered unapproved invite filter", message.Id, channel.Id, message.Author.Id); _ = message.DeleteAsync(); } @@ -388,8 +403,8 @@ public static async Task MessageHandlerAsync(DiscordClient client, MockDiscordMe // still warn anyway } - DiscordMessage msg = await message.Channel.SendMessageAsync($"{Program.cfgjson.Emoji.Denied} {message.Author.Mention} was automatically warned: **{reason.Replace("`", "\\`").Replace("*", "\\*")}**"); - var warning = await WarningHelpers.GiveWarningAsync(message.Author, client.CurrentUser, reason, contextMessage: msg, message.Channel, " automatically "); + DiscordMessage msg = await channel.SendMessageAsync($"{Program.cfgjson.Emoji.Denied} {message.Author.Mention} was automatically warned: **{reason.Replace("`", "\\`").Replace("*", "\\*")}**"); + var warning = await WarningHelpers.GiveWarningAsync(message.Author, client.CurrentUser, reason, contextMessage: msg, channel, " automatically "); await InvestigationsHelpers.SendInfringingMessaageAsync("investigations", message, reason, warning.ContextLink, wasAutoModBlock: wasAutoModBlock); match = true; return; @@ -446,7 +461,7 @@ public static async Task MessageHandlerAsync(DiscordClient client, MockDiscordMe } } - if (invite != default && invite.Guild is not null && (Program.cfgjson.InviteIDExclusion.Contains(invite.Guild.Id) || invite.Guild.Id == message.Channel.Guild.Id)) + if (invite != default && invite.Guild is not null && (Program.cfgjson.InviteIDExclusion.Contains(invite.Guild.Id) || invite.Guild.Id == channel.Guild.Id)) continue; if (maliciousCache == default && invite != default && invite.Guild is not null) @@ -458,8 +473,8 @@ public static async Task MessageHandlerAsync(DiscordClient client, MockDiscordMe _ = message.DeleteAsync(); string reason = "Sent a malicious Discord invite"; - DiscordMessage msg = await message.Channel.SendMessageAsync($"{Program.cfgjson.Emoji.Denied} {message.Author.Mention} was automatically warned: **{reason.Replace("`", "\\`").Replace("*", "\\*")}**"); - var warning = await WarningHelpers.GiveWarningAsync(message.Author, client.CurrentUser, reason, contextMessage: msg, message.Channel, " automatically "); + DiscordMessage msg = await channel.SendMessageAsync($"{Program.cfgjson.Emoji.Denied} {message.Author.Mention} was automatically warned: **{reason.Replace("`", "\\`").Replace("*", "\\*")}**"); + var warning = await WarningHelpers.GiveWarningAsync(message.Author, client.CurrentUser, reason, contextMessage: msg, channel, " automatically "); string responseToSend = $"```json\n{JsonConvert.SerializeObject(maliciousCache)}\n```"; @@ -510,7 +525,7 @@ public static async Task MessageHandlerAsync(DiscordClient client, MockDiscordMe return; // Mass emoji - if (!Program.cfgjson.UnrestrictedEmojiChannels.Contains(message.ChannelId) && message.Content.Length >= Program.cfgjson.MassEmojiThreshold) + if (!Program.cfgjson.UnrestrictedEmojiChannels.Contains(channel.Id) && message.Content.Length >= Program.cfgjson.MassEmojiThreshold) { char[] tempArray = message.Content.Replace("🏻", "").Replace("🏼", "").Replace("🏽", "").Replace("🏾", "").Replace("🏿", "").ToCharArray(); int pos = 0; @@ -535,11 +550,11 @@ public static async Task MessageHandlerAsync(DiscordClient client, MockDiscordMe { if (wasAutoModBlock) { - Program.discord.Logger.LogDebug("AutoMod-blocked message in {channelId} by user {userId} triggered mass emoji filter", message.Channel.Id, message.Author.Id); + Program.discord.Logger.LogDebug("AutoMod-blocked message in {channelId} by user {userId} triggered mass emoji filter", channel.Id, message.Author.Id); } else { - Program.discord.Logger.LogDebug("Message {messageId} in {channelId} by user {userId} triggered mass emoji filter", message.Id, message.Channel.Id, message.Author.Id); + Program.discord.Logger.LogDebug("Message {messageId} in {channelId} by user {userId} triggered mass emoji filter", message.Id, channel.Id, message.Author.Id); _ = message.DeleteAsync(); } @@ -550,12 +565,12 @@ public static async Task MessageHandlerAsync(DiscordClient client, MockDiscordMe await Program.db.HashSetAsync("emojiPardoned", member.Id.ToString(), false); DiscordMessage msgOut; if (Program.cfgjson.UnrestrictedEmojiChannels.Count > 0) - msgOut = await message.Channel.SendMessageAsync($"{Program.cfgjson.Emoji.Information} {message.Author.Mention}, if you want to play around with lots of emoji, please use <#{Program.cfgjson.UnrestrictedEmojiChannels[0]}> to avoid punishment."); + msgOut = await channel.SendMessageAsync($"{Program.cfgjson.Emoji.Information} {message.Author.Mention}, if you want to play around with lots of emoji, please use <#{Program.cfgjson.UnrestrictedEmojiChannels[0]}> to avoid punishment."); else if (wasAutoModBlock) - msgOut = await message.Channel.SendMessageAsync($"{Program.cfgjson.Emoji.Information} {message.Author.Mention} Your message contained too many emoji."); + msgOut = await channel.SendMessageAsync($"{Program.cfgjson.Emoji.Information} {message.Author.Mention} Your message contained too many emoji."); else - msgOut = await message.Channel.SendMessageAsync($"{Program.cfgjson.Emoji.Information} {message.Author.Mention} Your message was automatically deleted for mass emoji."); + msgOut = await channel.SendMessageAsync($"{Program.cfgjson.Emoji.Information} {message.Author.Mention} Your message was automatically deleted for mass emoji."); await InvestigationsHelpers.SendInfringingMessaageAsync("investigations", message, reason, DiscordHelpers.MessageLink(msgOut), wasAutoModBlock: wasAutoModBlock); return; @@ -568,15 +583,15 @@ public static async Task MessageHandlerAsync(DiscordClient client, MockDiscordMe await Program.db.HashSetAsync("emojiPardoned", member.Id.ToString(), true); } - DiscordMessage msg = await message.Channel.SendMessageAsync(output); - var warning = await WarningHelpers.GiveWarningAsync(message.Author, client.CurrentUser, reason, contextMessage: msg, message.Channel, " automatically "); + DiscordMessage msg = await channel.SendMessageAsync(output); + var warning = await WarningHelpers.GiveWarningAsync(message.Author, client.CurrentUser, reason, contextMessage: msg, channel, " automatically "); await InvestigationsHelpers.SendInfringingMessaageAsync("investigations", message, reason, warning.ContextLink, wasAutoModBlock: wasAutoModBlock); return; } if (!limitFilters) { - if (message.Channel.Id == Program.cfgjson.TechSupportChannel && + if (channel.Id == Program.cfgjson.TechSupportChannel && message.Content.Contains($"<@&{Program.cfgjson.CommunityTechSupportRoleID}>")) { if (supportRatelimit.ContainsKey(message.Author.Id)) @@ -593,7 +608,7 @@ public static async Task MessageHandlerAsync(DiscordClient client, MockDiscordMe .WithTimestamp(DateTime.Now) .WithAuthor(DiscordHelpers.UniqueUsername(message.Author), null, $"https://cdn.discordapp.com/avatars/{message.Author.Id}/{message.Author.AvatarHash}.png?size=128"); - var lastMsgs = await message.Channel.GetMessagesBeforeAsync(message.Id, 50).ToListAsync(); + var lastMsgs = await channel.GetMessagesBeforeAsync(message.Id, 50).ToListAsync(); var msgMatch = lastMsgs.FirstOrDefault(m => m.Author.Id == message.Author.Id); if (msgMatch is not null) @@ -616,7 +631,7 @@ public static async Task MessageHandlerAsync(DiscordClient client, MockDiscordMe embed.ImageUrl = message.Attachments[0].Url; } - embed.AddField("Message Link", $"https://discord.com/channels/{message.Channel.Guild.Id}/{message.Channel.Id}/{message.Id}"); + embed.AddField("Message Link", $"https://discord.com/channels/{channel.Guild.Id}/{channel.Id}/{message.Id}"); var logOut = await LogChannelHelper.LogMessageAsync("support", new DiscordMessageBuilder().AddEmbed(embed)); _ = logOut.CreateReactionAsync(DiscordEmoji.FromName(client, ":CliptokAcknowledge:", true)); } @@ -635,17 +650,17 @@ public static async Task MessageHandlerAsync(DiscordClient client, MockDiscordMe { if (wasAutoModBlock) { - Program.discord.Logger.LogDebug("AutoMod-blocked message in {channelId} by user {userId} triggered phishing message filter", message.Channel.Id, message.Author.Id); + Program.discord.Logger.LogDebug("AutoMod-blocked message in {channelId} by user {userId} triggered phishing message filter", channel.Id, message.Author.Id); } else { - Program.discord.Logger.LogDebug("Message {messageId} in {channelId} by user {userId} triggered phishing message filter", message.Id, message.Channel.Id, message.Author.Id); + Program.discord.Logger.LogDebug("Message {messageId} in {channelId} by user {userId} triggered phishing message filter", message.Id, channel.Id, message.Author.Id); _ = message.DeleteAsync(); } string reason = "Sending phishing URL(s)"; - DiscordMessage msg = await message.Channel.SendMessageAsync($"{Program.cfgjson.Emoji.Denied} {message.Author.Mention} was automatically warned: **{reason.Replace("`", "\\`").Replace("*", "\\*")}**"); - var warning = await WarningHelpers.GiveWarningAsync(message.Author, client.CurrentUser, reason, contextMessage: msg, message.Channel, " automatically "); + DiscordMessage msg = await channel.SendMessageAsync($"{Program.cfgjson.Emoji.Denied} {message.Author.Mention} was automatically warned: **{reason.Replace("`", "\\`").Replace("*", "\\*")}**"); + var warning = await WarningHelpers.GiveWarningAsync(message.Author, client.CurrentUser, reason, contextMessage: msg, channel, " automatically "); string responseToSend = await StringHelpers.CodeOrHasteBinAsync(responseText, "json", 1000, true); @@ -657,21 +672,21 @@ public static async Task MessageHandlerAsync(DiscordClient client, MockDiscordMe } // attempted to ping @everyone/@here - if (Program.cfgjson.EveryoneFilter && !member.Roles.Any(role => Program.cfgjson.EveryoneExcludedRoles.Contains(role.Id)) && !Program.cfgjson.EveryoneExcludedChannels.Contains(message.Channel.Id) && (message.Content.Contains("@everyone") || message.Content.Contains("@here"))) + if (Program.cfgjson.EveryoneFilter && !member.Roles.Any(role => Program.cfgjson.EveryoneExcludedRoles.Contains(role.Id)) && !Program.cfgjson.EveryoneExcludedChannels.Contains(channel.Id) && (message.Content.Contains("@everyone") || message.Content.Contains("@here"))) { if (wasAutoModBlock) { - Program.discord.Logger.LogDebug("AutoMod-blocked message in {channelId} by user {userId} triggered everyone/here mention filter", message.Channel.Id, message.Author.Id); + Program.discord.Logger.LogDebug("AutoMod-blocked message in {channelId} by user {userId} triggered everyone/here mention filter", channel.Id, message.Author.Id); } else { - Program.discord.Logger.LogDebug("Message {messageId} in {channelId} by user {userId} triggered everyone/here mention filter", message.Id, message.Channel.Id, message.Author.Id); + Program.discord.Logger.LogDebug("Message {messageId} in {channelId} by user {userId} triggered everyone/here mention filter", message.Id, channel.Id, message.Author.Id); _ = message.DeleteAsync(); } string reason = "Attempted to ping everyone/here"; - DiscordMessage msg = await message.Channel.SendMessageAsync($"{Program.cfgjson.Emoji.Denied} {message.Author.Mention} was automatically warned: **{reason.Replace("`", "\\`").Replace("*", "\\*")}**"); - var warning = await WarningHelpers.GiveWarningAsync(message.Author, client.CurrentUser, reason, contextMessage: msg, message.Channel, " automatically "); + DiscordMessage msg = await channel.SendMessageAsync($"{Program.cfgjson.Emoji.Denied} {message.Author.Mention} was automatically warned: **{reason.Replace("`", "\\`").Replace("*", "\\*")}**"); + var warning = await WarningHelpers.GiveWarningAsync(message.Author, client.CurrentUser, reason, contextMessage: msg, channel, " automatically "); await InvestigationsHelpers.SendInfringingMessaageAsync("investigations", message, reason, warning.ContextLink, wasAutoModBlock: wasAutoModBlock); return; } @@ -681,11 +696,11 @@ public static async Task MessageHandlerAsync(DiscordClient client, MockDiscordMe { if (wasAutoModBlock) { - Program.discord.Logger.LogDebug("AutoMod-blocked message in {channelId} by user {userId} triggered mass mention filter", message.Channel.Id, message.Author.Id); + Program.discord.Logger.LogDebug("AutoMod-blocked message in {channelId} by user {userId} triggered mass mention filter", channel.Id, message.Author.Id); } else { - Program.discord.Logger.LogDebug("Message {messageId} in {channelId} by user {userId} triggered mass mention filter", message.Id, message.Channel.Id, message.Author.Id); + Program.discord.Logger.LogDebug("Message {messageId} in {channelId} by user {userId} triggered mass mention filter", message.Id, channel.Id, message.Author.Id); } string reason = "Mass mentions"; @@ -700,8 +715,8 @@ public static async Task MessageHandlerAsync(DiscordClient client, MockDiscordMe // still warn anyway } - DiscordMessage msg = await message.Channel.SendMessageAsync($"{Program.cfgjson.Emoji.Denied} {message.Author.Mention} was automatically warned: **{reason.Replace("`", "\\`").Replace("*", "\\*")}**"); - var warning = await WarningHelpers.GiveWarningAsync(message.Author, client.CurrentUser, reason, contextMessage: msg, message.Channel, " automatically "); + DiscordMessage msg = await channel.SendMessageAsync($"{Program.cfgjson.Emoji.Denied} {message.Author.Mention} was automatically warned: **{reason.Replace("`", "\\`").Replace("*", "\\*")}**"); + var warning = await WarningHelpers.GiveWarningAsync(message.Author, client.CurrentUser, reason, contextMessage: msg, channel, " automatically "); await InvestigationsHelpers.SendInfringingMessaageAsync("investigations", message, reason, warning.ContextLink, wasAutoModBlock: wasAutoModBlock); return; } @@ -716,11 +731,11 @@ public static async Task MessageHandlerAsync(DiscordClient client, MockDiscordMe { if (wasAutoModBlock) { - Program.discord.Logger.LogDebug("AutoMod-blocked message in {channelId} by user {userId} triggered line limit filter", message.Channel.Id, message.Author.Id); + Program.discord.Logger.LogDebug("AutoMod-blocked message in {channelId} by user {userId} triggered line limit filter", channel.Id, message.Author.Id); } else { - Program.discord.Logger.LogDebug("Message {messageId} in {channelId} by user {userId} triggered line limit filter", message.Id, message.Channel.Id, message.Author.Id); + Program.discord.Logger.LogDebug("Message {messageId} in {channelId} by user {userId} triggered line limit filter", message.Id, channel.Id, message.Author.Id); _ = message.DeleteAsync(); } @@ -742,12 +757,12 @@ public static async Task MessageHandlerAsync(DiscordClient client, MockDiscordMe if (!wasAutoModBlock) { messageBuilder.AddComponents(new DiscordButtonComponent(DiscordButtonStyle.Secondary, "line-limit-deleted-message-callback", "View message content", false, null)); - msg = await message.Channel.SendMessageAsync(messageBuilder); + msg = await channel.SendMessageAsync(messageBuilder); await Program.db.HashSetAsync("deletedMessageReferences", msg.Id, message.Content); } else { - msg = await message.Channel.SendMessageAsync(messageBuilder); + msg = await channel.SendMessageAsync(messageBuilder); } await InvestigationsHelpers.SendInfringingMessaageAsync("investigations", message, reason, DiscordHelpers.MessageLink(msg), wasAutoModBlock: wasAutoModBlock); return; @@ -762,15 +777,15 @@ public static async Task MessageHandlerAsync(DiscordClient client, MockDiscordMe if (!wasAutoModBlock) { messageBuilder.AddComponents(new DiscordButtonComponent(DiscordButtonStyle.Secondary, "line-limit-deleted-message-callback", "View message content", false, null)); - msg = await message.Channel.SendMessageAsync(messageBuilder); + msg = await channel.SendMessageAsync(messageBuilder); await Program.db.HashSetAsync("deletedMessageReferences", msg.Id, message.Content); } else { - msg = await message.Channel.SendMessageAsync(messageBuilder); + msg = await channel.SendMessageAsync(messageBuilder); } - var warning = await WarningHelpers.GiveWarningAsync(message.Author, client.CurrentUser, reason, contextMessage: msg, message.Channel, " automatically "); + var warning = await WarningHelpers.GiveWarningAsync(message.Author, client.CurrentUser, reason, contextMessage: msg, channel, " automatically "); await InvestigationsHelpers.SendInfringingMessaageAsync("investigations", message, reason, warning.ContextLink, wasAutoModBlock: wasAutoModBlock); return; @@ -782,9 +797,9 @@ public static async Task MessageHandlerAsync(DiscordClient client, MockDiscordMe if (!limitFilters) { // feedback hub forum - if ((await GetPermLevelAsync(member)) < ServerPermLevel.TrialModerator && !isAnEdit && message.Channel.IsThread && message.Channel.ParentId == Program.cfgjson.FeedbackHubForum && !Program.db.SetContains("processedFeedbackHubThreads", message.Channel.Id)) + if ((await GetPermLevelAsync(member)) < ServerPermLevel.TrialModerator && !isAnEdit && channel.IsThread && channel.ParentId == Program.cfgjson.FeedbackHubForum && !Program.db.SetContains("processedFeedbackHubThreads", channel.Id)) { - var thread = (DiscordThreadChannel)message.Channel; + var thread = (DiscordThreadChannel)channel; Program.db.SetAdd("processedFeedbackHubThreads", thread.Id); // we need to make sure this is the first message in the channel @@ -793,7 +808,7 @@ public static async Task MessageHandlerAsync(DiscordClient client, MockDiscordMe // lock thread if there is no possible feedback hub link if (!message.Content.Contains("aka.ms/") && !message.Content.Contains("feedback-hub:")) { - await message.BaseMessage.RespondAsync($"{Program.cfgjson.Emoji.Error} Your {message.Channel.Parent.Mention} submission must include a Feedback Hub link!\nThis post will be automatically deleted shortly."); + await message.BaseMessage.RespondAsync($"{Program.cfgjson.Emoji.Error} Your {channel.Parent.Mention} submission must include a Feedback Hub link!\nThis post will be automatically deleted shortly."); await thread.ModifyAsync(thread => { thread.IsArchived = true; @@ -802,11 +817,11 @@ await thread.ModifyAsync(thread => await Task.Delay(30000); await LogChannelHelper.LogMessageAsync("messages", new DiscordMessageBuilder() - .WithContent($"{Program.cfgjson.Emoji.Deleted} Deleted non-feedback post from {message.Author.Mention} in {message.Channel.Parent.Mention}:") + .WithContent($"{Program.cfgjson.Emoji.Deleted} Deleted non-feedback post from {message.Author.Mention} in {channel.Parent.Mention}:") .AddEmbed(new DiscordEmbedBuilder() .WithAuthor( - $"{DiscordHelpers.UniqueUsername(message.Author)} in #{message.Channel.Parent.Name}", - null, await LykosAvatarMethods.UserOrMemberAvatarURL(message.Author, message.Channel.Guild)) + $"{DiscordHelpers.UniqueUsername(message.Author)} in #{channel.Parent.Name}", + null, await LykosAvatarMethods.UserOrMemberAvatarURL(message.Author, channel.Guild)) .WithTitle(thread.Name) .WithDescription(message.Content) .WithColor(DiscordColor.Red) @@ -845,7 +860,7 @@ await LogChannelHelper.LogMessageAsync("messages", logChannel = await Program.discord.GetChannelAsync((ulong)listItem.ChannelId); } - string content = $"{Program.cfgjson.Emoji.Warning} Detected potentially suspicious message by {message.Author.Mention} in {message.Channel.Mention}:"; + string content = $"{Program.cfgjson.Emoji.Warning} Detected potentially suspicious message by {message.Author.Mention} in {channel.Mention}:"; (string name, string value, bool inline) extraField = new("Match", flaggedWord, true); @@ -894,9 +909,9 @@ await InvestigationsHelpers.SendInfringingMessaageAsync( } if (wasAutoModBlock) - Program.discord.Logger.LogDebug("AutoMod-blocked message in {channelId} by user {userId} triggered no filters!", message.Channel.Id, message.Author.Id); + Program.discord.Logger.LogDebug("AutoMod-blocked message in {channelId} by user {userId} triggered no filters!", channel.Id, message.Author.Id); else - Program.discord.Logger.LogDebug("Message {messageId} in {channelId} by user {userId} triggered no filters!", message.Id, message.Channel.Id, message.Author.Id); + Program.discord.Logger.LogDebug("Message {messageId} in {channelId} by user {userId} triggered no filters!", message.Id, channel.Id, message.Author.Id); } public static int CountNewlines(string input) diff --git a/Program.cs b/Program.cs index a4cb726..340b987 100644 --- a/Program.cs +++ b/Program.cs @@ -63,6 +63,8 @@ class Program : BaseCommandModule static public readonly HttpClient httpClient = new(); public static List serverApiList = new(); + + public static DiscordChannel ForumChannelAutoWarnFallbackChannel; public static void UpdateLists() { @@ -239,6 +241,9 @@ static async Task Main(string[] _) await discord.ConnectAsync(); await ReadyEvent.OnStartup(discord); + + if (cfgjson.ForumChannelAutoWarnFallbackChannel != 0) + ForumChannelAutoWarnFallbackChannel = await discord.GetChannelAsync(cfgjson.ForumChannelAutoWarnFallbackChannel); // Only wait 3 seconds before the first set of tasks. await Task.Delay(3000); diff --git a/Structs.cs b/Structs.cs index b5cb871..abf477d 100644 --- a/Structs.cs +++ b/Structs.cs @@ -298,6 +298,9 @@ public class ConfigJson [JsonProperty("voiceChannelPurge")] public bool VoiceChannelPurge { get; private set; } = true; + + [JsonProperty("forumChannelAutoWarnFallbackChannel")] + public ulong ForumChannelAutoWarnFallbackChannel { get; private set; } = 0; } public enum Level { Information, Warning, Error, Debug, Verbose } diff --git a/config.json b/config.json index 0a47d3b..f19cb84 100644 --- a/config.json +++ b/config.json @@ -323,5 +323,6 @@ "logLevel": "Debug", "lokiURL": "http://100.79.19.82:3100", "lokiServiceName": "cliptok", - "voiceChannelPurge": true + "voiceChannelPurge": true, + "forumChannelAutoWarnFallbackChannel": 150662382874525696 }