diff --git a/pom.xml b/pom.xml index d222788a..97bd8993 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ org.egg.papertrail paper-trail-bot - 2.4.0 + 2.5.0 PaperTrail A simple bot for logging all user actions diff --git a/src/main/java/org/papertrail/commons/constant/ProjectInfo.java b/src/main/java/org/papertrail/commons/constant/ProjectInfo.java index 9b8cf5fe..86a7addd 100644 --- a/src/main/java/org/papertrail/commons/constant/ProjectInfo.java +++ b/src/main/java/org/papertrail/commons/constant/ProjectInfo.java @@ -7,6 +7,6 @@ private ProjectInfo() { } public static final String APPNAME = "PaperTrail"; - public static final String VERSION = "v2.4.0"; + public static final String VERSION = "v2.5.0"; public static final String PROJECT_ISSUE_LINK="https://github.com/eggy03/PaperTrailBot/issues"; } diff --git a/src/main/java/org/papertrail/commons/utilities/BooleanFormatter.java b/src/main/java/org/papertrail/commons/utilities/BooleanFormatter.java index 5ea33f5c..a73c3fa0 100644 --- a/src/main/java/org/papertrail/commons/utilities/BooleanFormatter.java +++ b/src/main/java/org/papertrail/commons/utilities/BooleanFormatter.java @@ -27,4 +27,15 @@ public static String formatToYesOrNo (Object value) { return "No"; } + + @NotNull + public static String formatToEnabledOrDisabled (Object value) { + if(value==null) + return "N/A"; + + if(Boolean.TRUE.equals(value)) + return "Enabled"; + + return "Disabled"; + } } diff --git a/src/main/java/org/papertrail/commons/utilities/OnboardingUtils.java b/src/main/java/org/papertrail/commons/utilities/OnboardingUtils.java new file mode 100644 index 00000000..ad2cad96 --- /dev/null +++ b/src/main/java/org/papertrail/commons/utilities/OnboardingUtils.java @@ -0,0 +1,49 @@ +package org.papertrail.commons.utilities; + +import lombok.experimental.UtilityClass; +import net.dv8tion.jda.api.entities.Guild; +import net.dv8tion.jda.api.entities.channel.middleman.GuildChannel; +import org.jetbrains.annotations.NotNull; + +import java.util.List; + +@UtilityClass +public class OnboardingUtils { + + @NotNull + public static String formatMode(Object value) { + if(value==null) return "N/A"; + + return switch (String.valueOf(value)) { + case "1" -> "Advanced Mode"; + case "0" -> "Regular Mode"; + default -> "N/A"; + }; + } + + @NotNull + public static String formatStatus(Object value) { + if(value==null) + return "N/A"; + + if(Boolean.TRUE.equals(value)) + return "Enabled"; + + return "Disabled"; + } + + @NotNull + public static String resolveChannelsFromList(Guild guild, Object value) { + if(value == null) return "No Resolvable Channel IDs"; + + StringBuilder sb = new StringBuilder(); + if(value instanceof List channelIdList) { + channelIdList.forEach(channelId -> { + GuildChannel channel = guild.getGuildChannelById((String) channelId); + sb.append(channel!=null ? channel.getAsMention() : channelId).append(" "); + }); + } + + return sb.toString(); + } +} diff --git a/src/main/java/org/papertrail/commons/utilities/RoleObjectParser.java b/src/main/java/org/papertrail/commons/utilities/RoleObjectParser.java index 101bac1f..91d132ee 100644 --- a/src/main/java/org/papertrail/commons/utilities/RoleObjectParser.java +++ b/src/main/java/org/papertrail/commons/utilities/RoleObjectParser.java @@ -22,8 +22,7 @@ public static String parseRole(GenericGuildEvent event, Object roleObject) { if (o instanceof Map roleMap && roleMap.containsKey("id")) { String roleId = (String) roleMap.get("id"); Role role = event.getGuild().getRoleById(roleId); - roleString.append(role!=null ? role.getAsMention() : roleMap.get("name")) - .append(System.lineSeparator()); + roleString.append(role!=null ? role.getAsMention() : roleMap.get("name")).append(" "); } } return roleString.toString(); diff --git a/src/main/java/org/papertrail/listeners/audit/event/AuditLogEventListener.java b/src/main/java/org/papertrail/listeners/audit/event/AuditLogEventListener.java index e07c0c5b..cb1f8577 100644 --- a/src/main/java/org/papertrail/listeners/audit/event/AuditLogEventListener.java +++ b/src/main/java/org/papertrail/listeners/audit/event/AuditLogEventListener.java @@ -39,6 +39,10 @@ import org.papertrail.listeners.audit.helper.MemberVoiceMoveEventHelper; import org.papertrail.listeners.audit.helper.MessagePinEventHelper; import org.papertrail.listeners.audit.helper.MessageUnpinEventHelper; +import org.papertrail.listeners.audit.helper.OnboardingPromptCreateEventHelper; +import org.papertrail.listeners.audit.helper.OnboardingPromptDeleteEventHelper; +import org.papertrail.listeners.audit.helper.OnboardingPromptUpdateEventHelper; +import org.papertrail.listeners.audit.helper.OnboardingUpdateEventHelper; import org.papertrail.listeners.audit.helper.RoleCreateEventHelper; import org.papertrail.listeners.audit.helper.RoleDeleteEventHelper; import org.papertrail.listeners.audit.helper.RoleUpdateEventHelper; @@ -91,18 +95,12 @@ private void auditLogParser(GuildAuditLogEntryCreateEvent event, String channelI ActionType action = ale.getType(); switch (action) { - case AUTO_MODERATION_FLAG_TO_CHANNEL -> - AutoModerationFlagToChannelEventHelper.format(event, ale, channelIdToSendTo); - case AUTO_MODERATION_MEMBER_TIMEOUT -> - AutoModerationMemberTimeoutEventHelper.format(event, ale, channelIdToSendTo); - case AUTO_MODERATION_RULE_BLOCK_MESSAGE -> - AutoModerationRuleBlockMessageEventHelper.format(event, ale, channelIdToSendTo); - case AUTO_MODERATION_RULE_CREATE -> - AutoModerationRuleCreateEventHelper.format(event, ale, channelIdToSendTo); - case AUTO_MODERATION_RULE_UPDATE -> - AutoModerationRuleUpdateEventHelper.format(event, ale, channelIdToSendTo); - case AUTO_MODERATION_RULE_DELETE -> - AutoModerationRuleDeleteEventHelper.format(event, ale, channelIdToSendTo); + case AUTO_MODERATION_FLAG_TO_CHANNEL -> AutoModerationFlagToChannelEventHelper.format(event, ale, channelIdToSendTo); + case AUTO_MODERATION_MEMBER_TIMEOUT -> AutoModerationMemberTimeoutEventHelper.format(event, ale, channelIdToSendTo); + case AUTO_MODERATION_RULE_BLOCK_MESSAGE -> AutoModerationRuleBlockMessageEventHelper.format(event, ale, channelIdToSendTo); + case AUTO_MODERATION_RULE_CREATE -> AutoModerationRuleCreateEventHelper.format(event, ale, channelIdToSendTo); + case AUTO_MODERATION_RULE_UPDATE -> AutoModerationRuleUpdateEventHelper.format(event, ale, channelIdToSendTo); + case AUTO_MODERATION_RULE_DELETE -> AutoModerationRuleDeleteEventHelper.format(event, ale, channelIdToSendTo); case KICK -> KickEventHelper.format(event, ale, channelIdToSendTo); case BAN -> BanEventHelper.format(event, ale, channelIdToSendTo); @@ -160,20 +158,26 @@ private void auditLogParser(GuildAuditLogEntryCreateEvent event, String channelI case THREAD_UPDATE -> ThreadUpdateEventHelper.format(event, ale, channelIdToSendTo); case THREAD_DELETE -> ThreadDeleteEventHelper.format(event, ale, channelIdToSendTo); - case VOICE_CHANNEL_STATUS_DELETE -> - VoiceChannelStatusDeleteEventHelper.format(event, ale, channelIdToSendTo); - case VOICE_CHANNEL_STATUS_UPDATE -> - VoiceChannelStatusUpdateEventHelper.format(event, ale, channelIdToSendTo); + case VOICE_CHANNEL_STATUS_DELETE -> VoiceChannelStatusDeleteEventHelper.format(event, ale, channelIdToSendTo); + case VOICE_CHANNEL_STATUS_UPDATE -> VoiceChannelStatusUpdateEventHelper.format(event, ale, channelIdToSendTo); case WEBHOOK_CREATE -> WebhookCreateEventHelper.format(event, ale, channelIdToSendTo); case WEBHOOK_UPDATE -> WebhookUpdateEventHelper.format(event, ale, channelIdToSendTo); case WEBHOOK_REMOVE -> WebhookRemoveEventHelper.format(event, ale, channelIdToSendTo); - case APPLICATION_COMMAND_PRIVILEGES_UPDATE, - PRUNE, - INTEGRATION_UPDATE, - INVITE_UPDATE, - UNKNOWN -> GenericAuditLogEventHelper.format(event, ale, channelIdToSendTo); + case SOUNDBOARD_SOUND_CREATE -> SoundboardSoundCreateEventHelper.format(event, ale, channelIdToSendTo); + case SOUNDBOARD_SOUND_UPDATE -> SoundboardSoundUpdateEventHelper.format(event, ale, channelIdToSendTo); + case SOUNDBOARD_SOUND_DELETE -> SoundboardSoundDeleteEventHelper.format(event, ale, channelIdToSendTo); + + case ONBOARDING_UPDATE -> OnboardingUpdateEventHelper.format(event, channelIdToSendTo); + case ONBOARDING_PROMPT_CREATE -> OnboardingPromptCreateEventHelper.format(event, channelIdToSendTo); + case ONBOARDING_PROMPT_UPDATE -> OnboardingPromptUpdateEventHelper.format(event, channelIdToSendTo); + case ONBOARDING_PROMPT_DELETE -> OnboardingPromptDeleteEventHelper.format(event, channelIdToSendTo); + + case HOME_SETTINGS_CREATE, HOME_SETTINGS_UPDATE -> { + // might come back later and implement it + // but for now, don't send these events + } // these seemingly don't trigger properly, or are unreliable case MESSAGE_BULK_DELETE, @@ -181,13 +185,14 @@ private void auditLogParser(GuildAuditLogEntryCreateEvent event, String channelI MESSAGE_DELETE, MESSAGE_UPDATE -> GenericAuditLogEventHelper.format(event, ale, channelIdToSendTo); - case SOUNDBOARD_SOUND_CREATE -> SoundboardSoundCreateEventHelper.format(event, ale, channelIdToSendTo); - case SOUNDBOARD_SOUND_UPDATE -> SoundboardSoundUpdateEventHelper.format(event, ale, channelIdToSendTo); - case SOUNDBOARD_SOUND_DELETE -> SoundboardSoundDeleteEventHelper.format(event, ale, channelIdToSendTo); + // except UNKNOWN, the rest have never been seen to be triggered + case APPLICATION_COMMAND_PRIVILEGES_UPDATE, PRUNE, INTEGRATION_UPDATE, + INVITE_UPDATE, ONBOARDING_CREATE, + UNKNOWN -> GenericAuditLogEventHelper.format(event, ale, channelIdToSendTo); default -> { GenericAuditLogEventHelper.format(event, ale, channelIdToSendTo); - log.warn("The following event has either no enum value defined in JDA and is not covered by the UNKNOWN type or is not implemented by me yet {}", ale.getType().name()); + log.warn("The following event is either not covered by JDA's UNKNOWN type or is not implemented by me yet {}", ale.getType().name()); } } } diff --git a/src/main/java/org/papertrail/listeners/audit/helper/OnboardingPromptCreateEventHelper.java b/src/main/java/org/papertrail/listeners/audit/helper/OnboardingPromptCreateEventHelper.java new file mode 100644 index 00000000..d6779a16 --- /dev/null +++ b/src/main/java/org/papertrail/listeners/audit/helper/OnboardingPromptCreateEventHelper.java @@ -0,0 +1,79 @@ +package org.papertrail.listeners.audit.helper; + +import lombok.experimental.UtilityClass; +import net.dv8tion.jda.api.EmbedBuilder; +import net.dv8tion.jda.api.audit.AuditLogEntry; +import net.dv8tion.jda.api.entities.MessageEmbed; +import net.dv8tion.jda.api.entities.User; +import net.dv8tion.jda.api.entities.channel.concrete.TextChannel; +import net.dv8tion.jda.api.events.guild.GuildAuditLogEntryCreateEvent; +import org.papertrail.commons.utilities.BooleanFormatter; + +import java.awt.Color; + +@UtilityClass +public class OnboardingPromptCreateEventHelper { + + public static void format(GuildAuditLogEntryCreateEvent event, String channelIdToSendTo) { + + AuditLogEntry ale = event.getEntry(); + + EmbedBuilder eb = new EmbedBuilder(); + eb.setTitle("Audit Log Entry | Onboarding Prompt Create Event"); + + User executor = ale.getJDA().getUserById(ale.getUserId()); + String mentionableExecutor = (executor != null ? executor.getAsMention() : ale.getTargetId()); + + eb.setDescription("👤 " + mentionableExecutor + "has created an Onboarding Prompt"); + eb.setColor(Color.GREEN); + + eb.addField("Action Type", String.valueOf(ale.getType()), true); + eb.addField("Target Type", String.valueOf(ale.getTargetType()), true); + + ale.getChanges().forEach((changeKey, changeValue) -> { + + Object oldValue = changeValue.getOldValue(); + Object newValue = changeValue.getNewValue(); + + switch (changeKey){ + case "single_select": + eb.addField("Single Selection Mode", BooleanFormatter.formatToYesOrNo(newValue), false); + break; + + case "required": + eb.addField("Required", BooleanFormatter.formatToYesOrNo(newValue), false); + break; + + case "type", "id": + break; + + case "title": + eb.addField("Question Title", String.valueOf(newValue), false); + break; + + case "options": + eb.addField("Question Options", "Review the options in Onboarding Settings", false); + break; + + case "in_onboarding": + eb.addField("Is a Pre-Join Question", BooleanFormatter.formatToYesOrNo(newValue), false); + break; + + default: + eb.addField(changeKey, "OLD_VALUE: "+oldValue, false); + eb.addField(changeKey, "NEW_VALUE: "+newValue, false); + } + + }); + + eb.setFooter("Audit Log Entry ID: "+ale.getId()); + eb.setTimestamp(ale.getTimeCreated()); + + MessageEmbed mb = eb.build(); + + TextChannel sendingChannel = event.getGuild().getTextChannelById(channelIdToSendTo); + if(sendingChannel!=null && sendingChannel.canTalk()) { + sendingChannel.sendMessageEmbeds(mb).queue(); + } + } +} diff --git a/src/main/java/org/papertrail/listeners/audit/helper/OnboardingPromptDeleteEventHelper.java b/src/main/java/org/papertrail/listeners/audit/helper/OnboardingPromptDeleteEventHelper.java new file mode 100644 index 00000000..43b1dffc --- /dev/null +++ b/src/main/java/org/papertrail/listeners/audit/helper/OnboardingPromptDeleteEventHelper.java @@ -0,0 +1,76 @@ +package org.papertrail.listeners.audit.helper; + +import lombok.experimental.UtilityClass; +import net.dv8tion.jda.api.EmbedBuilder; +import net.dv8tion.jda.api.audit.AuditLogEntry; +import net.dv8tion.jda.api.entities.MessageEmbed; +import net.dv8tion.jda.api.entities.User; +import net.dv8tion.jda.api.entities.channel.concrete.TextChannel; +import net.dv8tion.jda.api.events.guild.GuildAuditLogEntryCreateEvent; +import org.papertrail.commons.utilities.BooleanFormatter; + +import java.awt.Color; + +@UtilityClass +public class OnboardingPromptDeleteEventHelper { + + public static void format(GuildAuditLogEntryCreateEvent event, String channelIdToSendTo) { + + AuditLogEntry ale = event.getEntry(); + + EmbedBuilder eb = new EmbedBuilder(); + eb.setTitle("Audit Log Entry | Onboarding Prompt Delete Event"); + + User executor = ale.getJDA().getUserById(ale.getUserId()); + String mentionableExecutor = (executor != null ? executor.getAsMention() : ale.getTargetId()); + + eb.setDescription("👤 " + mentionableExecutor + "has made deleted an Onboarding Prompt"); + eb.setColor(Color.RED); + + eb.addField("Action Type", String.valueOf(ale.getType()), true); + eb.addField("Target Type", String.valueOf(ale.getTargetType()), true); + + ale.getChanges().forEach((changeKey, changeValue) -> { + + Object oldValue = changeValue.getOldValue(); + Object newValue = changeValue.getNewValue(); + + switch (changeKey){ + case "single_select": + eb.addField("Single Selection Mode", BooleanFormatter.formatToYesOrNo(oldValue), false); + break; + + case "required": + eb.addField("Was Required", BooleanFormatter.formatToYesOrNo(oldValue), false); + break; + + case "type", "id", "options": + break; + + case "title": + eb.addField("Question Title", String.valueOf(oldValue), false); + break; + + case "in_onboarding": + eb.addField("Was a Pre-Join Question", BooleanFormatter.formatToYesOrNo(oldValue), false); + break; + + default: + eb.addField(changeKey, "OLD_VALUE: "+oldValue, false); + eb.addField(changeKey, "NEW_VALUE: "+newValue, false); + } + + }); + + eb.setFooter("Audit Log Entry ID: "+ale.getId()); + eb.setTimestamp(ale.getTimeCreated()); + + MessageEmbed mb = eb.build(); + + TextChannel sendingChannel = event.getGuild().getTextChannelById(channelIdToSendTo); + if(sendingChannel!=null && sendingChannel.canTalk()) { + sendingChannel.sendMessageEmbeds(mb).queue(); + } + } + +} diff --git a/src/main/java/org/papertrail/listeners/audit/helper/OnboardingPromptUpdateEventHelper.java b/src/main/java/org/papertrail/listeners/audit/helper/OnboardingPromptUpdateEventHelper.java new file mode 100644 index 00000000..bf21d7ec --- /dev/null +++ b/src/main/java/org/papertrail/listeners/audit/helper/OnboardingPromptUpdateEventHelper.java @@ -0,0 +1,83 @@ +package org.papertrail.listeners.audit.helper; + +import lombok.experimental.UtilityClass; +import net.dv8tion.jda.api.EmbedBuilder; +import net.dv8tion.jda.api.audit.AuditLogEntry; +import net.dv8tion.jda.api.entities.MessageEmbed; +import net.dv8tion.jda.api.entities.User; +import net.dv8tion.jda.api.entities.channel.concrete.TextChannel; +import net.dv8tion.jda.api.events.guild.GuildAuditLogEntryCreateEvent; +import org.papertrail.commons.utilities.BooleanFormatter; + +import java.awt.Color; + +@UtilityClass +public class OnboardingPromptUpdateEventHelper { + + public static void format(GuildAuditLogEntryCreateEvent event, String channelIdToSendTo) { + + AuditLogEntry ale = event.getEntry(); + + EmbedBuilder eb = new EmbedBuilder(); + eb.setTitle("Audit Log Entry | Onboarding Prompt Update Event"); + + User executor = ale.getJDA().getUserById(ale.getUserId()); + String mentionableExecutor = (executor != null ? executor.getAsMention() : ale.getTargetId()); + + eb.setDescription("👤 " + mentionableExecutor + "has made changes to an existing Onboarding Prompt"); + eb.setColor(Color.YELLOW); + + eb.addField("Action Type", String.valueOf(ale.getType()), true); + eb.addField("Target Type", String.valueOf(ale.getTargetType()), true); + + ale.getChanges().forEach((changeKey, changeValue) -> { + + Object oldValue = changeValue.getOldValue(); + Object newValue = changeValue.getNewValue(); + + switch (changeKey){ + case "single_select": + eb.addField("Old Single Selection Mode", BooleanFormatter.formatToYesOrNo(oldValue), false); + eb.addField("New Single Selection Mode", BooleanFormatter.formatToYesOrNo(newValue), false); + break; + + case "required": + eb.addField("Was Required", BooleanFormatter.formatToYesOrNo(oldValue), false); + eb.addField("Is Required", BooleanFormatter.formatToYesOrNo(newValue), false); + break; + + case "type", "id": + break; + + case "title": + eb.addField("Old Question Title", String.valueOf(oldValue), false); + eb.addField("New Question Title", String.valueOf(newValue), false); + break; + + case "options": + eb.addField("Question Options", "Review the changed options in Onboarding Settings", false); + break; + + case "in_onboarding": + eb.addField("Was a Pre-Join Question", BooleanFormatter.formatToYesOrNo(oldValue), false); + eb.addField("Is a Pre-Join Question", BooleanFormatter.formatToYesOrNo(newValue), false); + break; + + default: + eb.addField(changeKey, "OLD_VALUE: "+oldValue, false); + eb.addField(changeKey, "NEW_VALUE: "+newValue, false); + } + + }); + + eb.setFooter("Audit Log Entry ID: "+ale.getId()); + eb.setTimestamp(ale.getTimeCreated()); + + MessageEmbed mb = eb.build(); + + TextChannel sendingChannel = event.getGuild().getTextChannelById(channelIdToSendTo); + if(sendingChannel!=null && sendingChannel.canTalk()) { + sendingChannel.sendMessageEmbeds(mb).queue(); + } + } +} diff --git a/src/main/java/org/papertrail/listeners/audit/helper/OnboardingUpdateEventHelper.java b/src/main/java/org/papertrail/listeners/audit/helper/OnboardingUpdateEventHelper.java new file mode 100644 index 00000000..5374e42a --- /dev/null +++ b/src/main/java/org/papertrail/listeners/audit/helper/OnboardingUpdateEventHelper.java @@ -0,0 +1,76 @@ +package org.papertrail.listeners.audit.helper; + +import lombok.experimental.UtilityClass; +import net.dv8tion.jda.api.EmbedBuilder; +import net.dv8tion.jda.api.audit.AuditLogEntry; +import net.dv8tion.jda.api.entities.Guild; +import net.dv8tion.jda.api.entities.MessageEmbed; +import net.dv8tion.jda.api.entities.User; +import net.dv8tion.jda.api.entities.channel.concrete.TextChannel; +import net.dv8tion.jda.api.events.guild.GuildAuditLogEntryCreateEvent; +import org.papertrail.commons.utilities.OnboardingUtils; + +import java.awt.Color; + +@UtilityClass +public class OnboardingUpdateEventHelper { + + public static void format(GuildAuditLogEntryCreateEvent event, String channelIdToSendTo) { + + AuditLogEntry ale = event.getEntry(); + + EmbedBuilder eb = new EmbedBuilder(); + eb.setTitle("Audit Log Entry | Onboarding Update Event"); + + User executor = ale.getJDA().getUserById(ale.getUserId()); + String mentionableExecutor = (executor != null ? executor.getAsMention() : ale.getTargetId()); + + Guild guild = event.getGuild(); + + eb.setDescription("👤 " + mentionableExecutor + "has made changes to Onboarding"); + eb.setColor(Color.MAGENTA); + + eb.addField("Action Type", String.valueOf(ale.getType()), true); + eb.addField("Target Type", String.valueOf(ale.getTargetType()), true); + + ale.getChanges().forEach((changeKey, changeValue) -> { + Object oldValue = changeValue.getOldValue(); + Object newValue = changeValue.getNewValue(); + + switch (changeKey){ + case "enabled": + eb.addField("Old Onboarding Status", OnboardingUtils.formatStatus(oldValue), false); + eb.addField("New Onboarding Status", OnboardingUtils.formatStatus(newValue), true); + break; + + case "mode": + eb.addField("Old Onboarding Mode", OnboardingUtils.formatMode(oldValue), false); + eb.addField("New Onboarding Mode", OnboardingUtils.formatMode(newValue), true); + break; + + case "default_channel_ids": + eb.addField("Old Default Channels", OnboardingUtils.resolveChannelsFromList(guild, oldValue), false); + eb.addField("New Default Channels", OnboardingUtils.resolveChannelsFromList(guild, newValue), false); + break; + + case "prompts": // unknown as to exactly why this is triggered + eb.addField("Prompt Updates", "Overall Pre-join/Post-join questions may have been updated.\n Review changes manually.", false); + break; + + default: + eb.addField(changeKey, "from: "+oldValue+" to: "+newValue, false); + } + + }); + + eb.setFooter("Audit Log Entry ID: "+ale.getId()); + eb.setTimestamp(ale.getTimeCreated()); + + MessageEmbed mb = eb.build(); + + TextChannel sendingChannel = event.getGuild().getTextChannelById(channelIdToSendTo); + if(sendingChannel!=null && sendingChannel.canTalk()) { + sendingChannel.sendMessageEmbeds(mb).queue(); + } + } +}