diff --git a/.github/workflows/publish-container-image.yml b/.github/workflows/publish-container-image.yml index 3bddad85..1e5e65aa 100644 --- a/.github/workflows/publish-container-image.yml +++ b/.github/workflows/publish-container-image.yml @@ -19,10 +19,10 @@ jobs: steps: - name: Checkout code - uses: actions/checkout@v4 + uses: actions/checkout@v6 - name: Log in to GHCR - uses: docker/login-action@v3 + uses: docker/login-action@v4 with: registry: ${{ env.REGISTRY }} username: ${{ github.actor }} diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index ebe3a024..77d3ebdf 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,5 +1,7 @@ -This project does not accept pull requests. +This project does not accept pull requests. I haven't been getting enough time to set up a contribution guideline. +I will start accepting PRs once a guideline is in effect. -If you would like to modify or extend the bot, please feel free to fork the repository and maintain your own version. +Meanwhile, please feel free to fork the repository and maintain your own version. In case of any doubt or question +regarding the codebase, you can open an issue in GitHub. -Bug reports and suggestions are welcome through the Issues tab. I may review and address them as time permits. \ No newline at end of file +Bug reports and suggestions are also welcome through the Issues tab. I may review and address them as time permits. \ No newline at end of file diff --git a/Dockerfile b/Dockerfile index ecaade86..1a33fab7 100644 --- a/Dockerfile +++ b/Dockerfile @@ -23,6 +23,6 @@ WORKDIR /app VOLUME /tmp # Copy the JAR from the build stage -COPY --from=build --chown=papertrail:papertrail /app/target/papertrailbot-jar-with-dependencies.jar papertrailbot.jar +COPY --from=build --chown=papertrail:papertrail /app/target/quarkus-app bot USER papertrail -ENTRYPOINT ["java","-jar","papertrailbot.jar"] \ No newline at end of file +ENTRYPOINT ["java","-jar","bot/quarkus-run.jar"] \ No newline at end of file diff --git a/README.md b/README.md index a09d1d08..2e83dfa5 100644 --- a/README.md +++ b/README.md @@ -13,7 +13,9 @@ * [Self-Host (Manual Configuration)](#self-host-manual-configuration) * [Sharding (Advanced Configuration)](#sharding-advanced-configuration) * [Synchronizing Rate Limits (Advanced Configuration)](#synchronizing-rate-limits-advanced-configuration) +* [Health Checks and Custom Port Configuration](#health-checks-and-custom-port-configuration) * [License](#license) +* [AI Usage Declaration and Policy](#ai-usage-declaration-and-policy) * [Help](#help) # Overview @@ -97,10 +99,10 @@ Don't forget to copy the `bot token` as it will be required in the next step ### Step 2.2: Get Required Secrets -| Variable | Description | -|-----------|--------------------------------------------------------------------| -| `TOKEN` | Discord application bot token (from the Developer Portal) | -| `API_URL` | Internal URL of the PaperTrail API (e.g., `http://localhost:8080`) | +| Variable | Description | Default Value | Optional | +|-----------|--------------------------------------------------------------------|------------------|----------| +| `TOKEN` | Discord application bot token (from the Developer Portal) | No Default Value | No | +| `API_URL` | Internal URL of the PaperTrail API (e.g., `http://localhost:8080`) | No Default Value | No | Example `.env` file: @@ -172,11 +174,11 @@ Discord allows you to have up to 2500 guilds per shard but the recommended confi You will need the following additional environment variables for custom shard configuration. -| Variable | Description | -|----------------|-------------------------------------------------------------------------------| -| `TOTAL_SHARDS` | Total number of shards used by the bot across all running processes/instances | -| `MIN_SHARD_ID` | The first shard ID handled by this specific bot instance | -| `MAX_SHARD_ID` | The last shard ID handled by this specific bot instance | +| Variable | Description | Default Value | Optional | +|----------------|-------------------------------------------------------------------------------|---------------|----------| +| `TOTAL_SHARDS` | Total number of shards used by the bot across all running processes/instances | 1 | Yes | +| `MIN_SHARD_ID` | The first shard ID handled by this specific bot instance | 0 | Yes | +| `MAX_SHARD_ID` | The last shard ID handled by this specific bot instance | 0 | Yes | Shard IDs start at 0. @@ -277,9 +279,9 @@ This will set the discord token to `"my token"` and map the bound port to port ` Add the following environment variable to your bot: -| Variable | Description | -|-------------|----------------------------------------------------------------------------------------------------------------------------| -| `PROXY_URL` | Base URL for the HTTP proxy that will receive Discord API requests instead of discord.com (Example: http://localhost:3000) | +| Variable | Description | Default Value | Optional | +|---------------------------|----------------------------------------------------------------------------------------------------------------------------|---------------|----------| +| `TWILIGHT_HTTP_PROXY_URL` | Base URL for the HTTP proxy that will receive Discord API requests instead of discord.com (Example: http://localhost:3000) | Blank | Yes | When configured, all Discord API requests made by the bot will be routed through the proxy. @@ -300,12 +302,58 @@ as the instance-level. While this should not create functional conflicts, it may lead to under-utilization of the rate limits provided by Discord and can reduce the overall throughput of your bot cluster. +# Health Checks and Custom Port Configuration + +## Health Checks + +Since v4, it is possible to get health information by probing any of the following health endpoints: + +| Endpoint | Description | +|---------------------|-------------------------------------------------------------------------------------------------------| +| `/q/health` | Aggregated health status containing all registered checks. | +| `/q/health/live` | Liveness probe. Verifies that the bot process is healthy and that all shards are operating normally. | +| `/q/health/ready` | Readiness probe. Verifies that all shards are fully connected to Discord and ready to receive events. | +| `/q/health/started` | Startup probe. Indicates whether the application has completed its startup sequence. | + +### Liveness Check + +The liveness check reports **UP** when all shards belonging to this instance are in one of the following states: + +* `CONNECTED` +* `ATTEMPTING_TO_RECONNECT` +* `RECONNECT_QUEUED` +* `WAITING_TO_RECONNECT` + +### Readiness Check + +The readiness check reports **UP** only when every shard belonging to this instance is fully `CONNECTED` to Discord. + +## Custom Port Configuration + +By, default PaperTrail runs on port 8080. If port 8080 is occupied by a different service, or you wish to +run the application on a different port, you can manually set the `PORT` environment variable. + +| Variable | Description | Default Value | Optional | +|----------|-------------------------------------------------------|---------------|----------| +| `PORT` | Port Number on which the instance of the bot will run | 8080 | Yes | + # License This project is licensed under the [AGPLv3](/LICENSE) license. -Read this -easy-to-understand [Medium](https://medium.com/swlh/understanding-the-agpl-the-most-misunderstood-license-86fd1fe91275) -article about AGPLv3 and it's scope. + +# AI Usage Declaration and Policy + +No AI or LLM agents have been used to generate any part of the project's source code. +This policy applies to all existing source code and future code contributions. + +After two years of development and manual testing, the application has reached a fairly stable and maintainable state. +To preserve code quality, maintainability, format, and stability, +AI-generated source code is **not accepted** for inclusion in this repository and the repositories related to the +application. + +Limited use of AI for non-code tasks, such as commit message generation, spelling correction, +or documentation proofreading, may be permitted at the maintainer's discretion. +Such usage does not constitute authorship of the project's source code. # Help diff --git a/pom.xml b/pom.xml index 7e038075..66576fba 100644 --- a/pom.xml +++ b/pom.xml @@ -1,66 +1,87 @@ - + - 4.0.0 - io.github.eggy03 papertrailbot - 3.7.3 + 4.0.0 PaperTrail Bot A simple bot for logging all server and member actions + quarkus + + 25 UTF-8 UTF-8 - 25 + + + quarkus-bom + io.quarkus.platform + 3.35.4 + true 6.4.1 - 2.0.4 - 2.7.0 - 3.2.0 + 2.0.5 3.20.0 33.5.0-jre + 26.1.0 1.18.46 - 3.8.0 - 3.15.0 - - - io.github.eggy03.papertrail.bot.main.Start + 3.15.0 + 3.5.5 + + + + ${quarkus.platform.group-id} + ${quarkus.platform.artifact-id} + ${quarkus.platform.version} + pom + import + + + + + + - net.dv8tion - JDA - ${jda.version} + io.quarkus + quarkus-arc + - org.tinylog - slf4j-tinylog - ${tinylog.version} + io.quarkus + quarkus-smallrye-health + + - org.tinylog - tinylog-api - ${tinylog.version} + net.dv8tion + JDA + ${jda.version} + + - org.tinylog - tinylog-impl - ${tinylog.version} + org.projectlombok + lombok + ${lombok.version} + provided - io.github.cdimascio - dotenv-java - ${dotenv.version} + org.jetbrains + annotations + ${jetbrains.annotations.version} + org.apache.commons commons-lang3 @@ -79,49 +100,22 @@ ${papertrail.sdk.version} - - org.projectlombok - lombok - ${lombok.version} - provided - ${project.artifactId} - - org.apache.maven.plugins - maven-assembly-plugin - ${maven.assembly.plugin.version} - - - - true - ${app.main.class} - - - - jar-with-dependencies - - - - - assemble-all - package - - single - - - + ${quarkus.platform.group-id} + quarkus-maven-plugin + ${quarkus.platform.version} + true - - org.apache.maven.plugins maven-compiler-plugin - ${maven-compiler-plugin.version} + ${compiler-plugin.version} + true org.projectlombok @@ -131,7 +125,54 @@ + + maven-surefire-plugin + ${surefire-plugin.version} + + @{argLine} + + org.jboss.logmanager.LogManager + ${maven.home} + + + + + maven-failsafe-plugin + ${surefire-plugin.version} + + + + integration-test + verify + + + + + @{argLine} + + ${project.build.directory}/${project.artifactId}-runner + org.jboss.logmanager.LogManager + ${maven.home} + + + + + + native + + + native + + + + false + false + true + + + + diff --git a/src/main/java/io/github/eggy03/papertrail/bot/BootstrapService.java b/src/main/java/io/github/eggy03/papertrail/bot/BootstrapService.java new file mode 100644 index 00000000..3c5cb93c --- /dev/null +++ b/src/main/java/io/github/eggy03/papertrail/bot/BootstrapService.java @@ -0,0 +1,129 @@ +package io.github.eggy03.papertrail.bot; + +import io.quarkus.runtime.Startup; +import jakarta.annotation.PostConstruct; +import jakarta.annotation.PreDestroy; +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.enterprise.inject.Instance; +import jakarta.enterprise.inject.Produces; +import jakarta.inject.Inject; +import lombok.NonNull; +import lombok.extern.slf4j.Slf4j; +import net.dv8tion.jda.api.OnlineStatus; +import net.dv8tion.jda.api.hooks.ListenerAdapter; +import net.dv8tion.jda.api.requests.GatewayIntent; +import net.dv8tion.jda.api.requests.RestConfig; +import net.dv8tion.jda.api.sharding.DefaultShardManagerBuilder; +import net.dv8tion.jda.api.sharding.ShardManager; +import net.dv8tion.jda.api.utils.ChunkingFilter; +import net.dv8tion.jda.api.utils.MemberCachePolicy; +import net.dv8tion.jda.api.utils.cache.CacheFlag; +import org.eclipse.microprofile.config.inject.ConfigProperty; + +@Slf4j +@ApplicationScoped +@Startup +public final class BootstrapService { + + private final @NonNull String discordToken; + private final @NonNull Integer minShardId; + private final @NonNull Integer maxShardId; + private final @NonNull Integer totalShards; + private final @NonNull String twilightHttpProxyUrl; + private final @NonNull Instance listeners; + + private ShardManager shardManager; + + @Inject + public BootstrapService( + @ConfigProperty(name = "discord.token") @NonNull String discordToken, + @ConfigProperty(name = "min.shard.id") @NonNull Integer minShardId, + @ConfigProperty(name = "max.shard.id") @NonNull Integer maxShardId, + @ConfigProperty(name = "total.shards") @NonNull Integer totalShards, + @ConfigProperty(name = "twilight.http.proxy.url") @NonNull String twilightHttpProxyUrl, + @NonNull Instance listeners + ) { + this.discordToken = discordToken; + this.minShardId = minShardId; + this.maxShardId = maxShardId; + this.totalShards = totalShards; + this.twilightHttpProxyUrl = twilightHttpProxyUrl; + this.listeners = listeners; + } + + @PostConstruct + void login() { + + DefaultShardManagerBuilder builder = DefaultShardManagerBuilder.createDefault(discordToken); + + builder.enableIntents(GatewayIntent.SCHEDULED_EVENTS, + GatewayIntent.AUTO_MODERATION_EXECUTION, + GatewayIntent.AUTO_MODERATION_CONFIGURATION, + GatewayIntent.MESSAGE_CONTENT, + GatewayIntent.GUILD_MEMBERS, + GatewayIntent.GUILD_EXPRESSIONS, + GatewayIntent.GUILD_PRESENCES, + GatewayIntent.GUILD_MODERATION + ); + + //cache all members + builder.setMemberCachePolicy(MemberCachePolicy.ALL); + // cache all activities + builder.enableCache(CacheFlag.ACTIVITY, + CacheFlag.CLIENT_STATUS, + CacheFlag.EMOJI, + CacheFlag.STICKER, + CacheFlag.ONLINE_STATUS, + CacheFlag.MEMBER_OVERRIDES, + CacheFlag.ROLE_TAGS, + CacheFlag.SCHEDULED_EVENTS + ); + // chunk all guilds + builder.setChunkingFilter(ChunkingFilter.ALL); + + // set status + builder.setStatus(OnlineStatus.ONLINE); + + // add listeners + listeners.forEach(builder::addEventListeners); + + // add shards + builder.setShardsTotal(totalShards); + builder.setShards(minShardId, maxShardId); + + // add custom twilight http proxy url if present + // note the current implementation only changes the proxy + // JDA's internal rate limit logic still applies on top of the proxy + // you need to provide a custom RestRateLimiter config + if (!twilightHttpProxyUrl.isBlank()) { // don't use isEmpty cause default value is a whitespace + builder.setRestConfig(new RestConfig().setBaseUrl(twilightHttpProxyUrl)); + } + + // build shard manager and login + shardManager = builder.build(); + + } + + @PreDestroy + void shutdown() { + if (shardManager == null) + return; + + for (int i = minShardId; i <= maxShardId; i++) { + log.info("Shutting Down Shard: {}", i); + shardManager.shutdown(i); + } + + } + + @Produces + @ApplicationScoped + ShardManager shardManager() { + + if (shardManager == null) + throw new IllegalStateException("ShardManager requested before it was available"); + + return shardManager; + } + +} diff --git a/src/main/java/io/github/eggy03/papertrail/bot/Start.java b/src/main/java/io/github/eggy03/papertrail/bot/Start.java new file mode 100644 index 00000000..14b3fe6e --- /dev/null +++ b/src/main/java/io/github/eggy03/papertrail/bot/Start.java @@ -0,0 +1,11 @@ +package io.github.eggy03.papertrail.bot; + +import io.quarkus.runtime.Quarkus; +import io.quarkus.runtime.annotations.QuarkusMain; + +@QuarkusMain +public final class Start { + static void main(String... args) { + Quarkus.run(args); + } +} diff --git a/src/main/java/io/github/eggy03/papertrail/bot/bean/PaperTrailSdkBeanProvider.java b/src/main/java/io/github/eggy03/papertrail/bot/bean/PaperTrailSdkBeanProvider.java new file mode 100644 index 00000000..2e427761 --- /dev/null +++ b/src/main/java/io/github/eggy03/papertrail/bot/bean/PaperTrailSdkBeanProvider.java @@ -0,0 +1,43 @@ +package io.github.eggy03.papertrail.bot.bean; + +import io.github.eggy03.papertrail.sdk.client.AuditLogRegistrationClient; +import io.github.eggy03.papertrail.sdk.client.MessageLogContentClient; +import io.github.eggy03.papertrail.sdk.client.MessageLogRegistrationClient; +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.enterprise.inject.Produces; +import jakarta.inject.Inject; +import lombok.NonNull; +import org.eclipse.microprofile.config.inject.ConfigProperty; +import org.jetbrains.annotations.Contract; + +@ApplicationScoped +public final class PaperTrailSdkBeanProvider { + + private final @NonNull String apiUrl; + + @Inject + public PaperTrailSdkBeanProvider(@ConfigProperty(name = "api.url") @NonNull String apiUrl) { + this.apiUrl = apiUrl; + } + + @Contract(" -> new") + @Produces + @ApplicationScoped + public @NonNull AuditLogRegistrationClient auditLogRegistrationClient() { + return new AuditLogRegistrationClient(apiUrl); + } + + @Contract(" -> new") + @Produces + @ApplicationScoped + public @NonNull MessageLogRegistrationClient messageLogRegistrationClient() { + return new MessageLogRegistrationClient(apiUrl); + } + + @Contract(" -> new") + @Produces + @ApplicationScoped + public @NonNull MessageLogContentClient messageLogContentClient() { + return new MessageLogContentClient(apiUrl); + } +} diff --git a/src/main/java/io/github/eggy03/papertrail/bot/constant/ProjectInfo.java b/src/main/java/io/github/eggy03/papertrail/bot/constant/ProjectInfo.java index ad5e68c4..c0711941 100644 --- a/src/main/java/io/github/eggy03/papertrail/bot/constant/ProjectInfo.java +++ b/src/main/java/io/github/eggy03/papertrail/bot/constant/ProjectInfo.java @@ -4,13 +4,13 @@ import lombok.experimental.UtilityClass; @UtilityClass -public class ProjectInfo { +public final class ProjectInfo { @NonNull public static final String APPNAME = "PaperTrail"; @NonNull - public static final String VERSION = "v3.7.3"; + public static final String VERSION = "v4.0.0"; @NonNull public static final String PROJECT_ISSUE_LINK = "https://github.com/eggy03/PaperTrailBot/issues"; diff --git a/src/main/java/io/github/eggy03/papertrail/bot/controller/LivenessCheckController.java b/src/main/java/io/github/eggy03/papertrail/bot/controller/LivenessCheckController.java new file mode 100644 index 00000000..800d5871 --- /dev/null +++ b/src/main/java/io/github/eggy03/papertrail/bot/controller/LivenessCheckController.java @@ -0,0 +1,56 @@ +package io.github.eggy03.papertrail.bot.controller; + +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.inject.Inject; +import lombok.NonNull; +import net.dv8tion.jda.api.JDA; +import net.dv8tion.jda.api.sharding.ShardManager; +import org.eclipse.microprofile.health.HealthCheck; +import org.eclipse.microprofile.health.HealthCheckResponse; +import org.eclipse.microprofile.health.Liveness; + +import java.util.Objects; +import java.util.Set; +import java.util.stream.Collectors; + +@Liveness +@ApplicationScoped +public class LivenessCheckController implements HealthCheck { + + private static final Set HEALTHY_STATUSES = Set.of( + JDA.Status.CONNECTED, + JDA.Status.ATTEMPTING_TO_RECONNECT, + JDA.Status.RECONNECT_QUEUED, + JDA.Status.WAITING_TO_RECONNECT + ); + + private final @NonNull ShardManager shardManager; + + @Inject + public LivenessCheckController(@NonNull ShardManager shardManager) { + this.shardManager = shardManager; + } + + @Override + public HealthCheckResponse call() { + + if (HEALTHY_STATUSES.containsAll(shardManager.getStatuses().values())) { + return HealthCheckResponse.named("Liveness Check") + .withData("Shard Statuses", "All Shards are operating normally") + .up() + .build(); + } else { + String shardStatuses = shardManager.getStatuses() + .values() + .stream() + .map(Objects::toString) + .collect(Collectors.joining(", ")); + + return HealthCheckResponse.named("Liveness Check") + .withData("Shard Statuses", shardStatuses) + .down() + .build(); + } + + } +} diff --git a/src/main/java/io/github/eggy03/papertrail/bot/controller/ReadinessCheckController.java b/src/main/java/io/github/eggy03/papertrail/bot/controller/ReadinessCheckController.java new file mode 100644 index 00000000..5a77f3e0 --- /dev/null +++ b/src/main/java/io/github/eggy03/papertrail/bot/controller/ReadinessCheckController.java @@ -0,0 +1,48 @@ +package io.github.eggy03.papertrail.bot.controller; + +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.inject.Inject; +import lombok.NonNull; +import net.dv8tion.jda.api.JDA; +import net.dv8tion.jda.api.sharding.ShardManager; +import org.eclipse.microprofile.health.HealthCheck; +import org.eclipse.microprofile.health.HealthCheckResponse; +import org.eclipse.microprofile.health.Readiness; + +import java.util.Objects; +import java.util.stream.Collectors; + +@Readiness +@ApplicationScoped +public class ReadinessCheckController implements HealthCheck { + + private final @NonNull ShardManager shardManager; + + @Inject + public ReadinessCheckController(@NonNull ShardManager shardManager) { + this.shardManager = shardManager; + } + + @Override + public HealthCheckResponse call() { + + if (shardManager.getStatuses().values().stream().allMatch(status -> status == JDA.Status.CONNECTED)) { + return HealthCheckResponse.named("Readiness Check") + .withData("Shard Statuses", "All Shards are connected") + .up() + .build(); + } else { + String shardStatuses = shardManager.getStatuses() + .values() + .stream() + .map(Objects::toString) + .collect(Collectors.joining(", ")); + + return HealthCheckResponse.named("Readiness Check") + .withData("Shard Statuses", shardStatuses) + .down() + .build(); + } + + } +} diff --git a/src/main/java/io/github/eggy03/papertrail/bot/handlers/auditlog/AutoModEventHandler.java b/src/main/java/io/github/eggy03/papertrail/bot/handlers/auditlog/AutoModEventHandler.java new file mode 100644 index 00000000..df1c516d --- /dev/null +++ b/src/main/java/io/github/eggy03/papertrail/bot/handlers/auditlog/AutoModEventHandler.java @@ -0,0 +1,250 @@ +package io.github.eggy03.papertrail.bot.handlers.auditlog; + +import io.github.eggy03.papertrail.bot.listeners.auditlog.GuildAuditLogEntryCreateEventHandler; +import io.github.eggy03.papertrail.bot.utils.BooleanUtils; +import io.github.eggy03.papertrail.bot.utils.auditlog.AutoModUtils; +import io.github.eggy03.papertrail.sdk.client.AuditLogRegistrationClient; +import io.github.eggy03.papertrail.sdk.entity.AuditLogRegistrationEntity; +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.inject.Inject; +import lombok.NonNull; +import lombok.extern.slf4j.Slf4j; +import net.dv8tion.jda.api.EmbedBuilder; +import net.dv8tion.jda.api.audit.AuditLogEntry; +import net.dv8tion.jda.api.entities.User; +import net.dv8tion.jda.api.entities.automod.AutoModRule; +import net.dv8tion.jda.api.entities.channel.concrete.TextChannel; +import net.dv8tion.jda.api.events.guild.GuildAuditLogEntryCreateEvent; +import net.dv8tion.jda.api.utils.MarkdownUtil; +import org.apache.commons.lang3.StringUtils; + +import java.awt.Color; + +@ApplicationScoped +@Slf4j +@SuppressWarnings("java:S1192") +public final class AutoModEventHandler extends GuildAuditLogEntryCreateEventHandler { + + private final @NonNull AuditLogRegistrationClient client; + + @Inject + public AutoModEventHandler(@NonNull AuditLogRegistrationClient client) { + this.client = client; + } + + @NonNull + private String getRegisteredGuildChannel(@NonNull String guildId) { + return client.getRegisteredGuild(guildId) + .map(AuditLogRegistrationEntity::getChannelId).orElse(StringUtils.EMPTY); + + } + + private void performChecksThenBuildAndSendEmbed(@NonNull GuildAuditLogEntryCreateEvent event, @NonNull EmbedBuilder embedBuilder, @NonNull String channelIdToSendTo) { + if (!embedBuilder.isValidLength() || embedBuilder.isEmpty()) { + log.warn("Embed is empty or too long (current length: {}).", embedBuilder.length()); + return; + } + + TextChannel sendingChannel = event.getGuild().getTextChannelById(channelIdToSendTo); + if (sendingChannel != null && sendingChannel.canTalk()) { + sendingChannel.sendMessageEmbeds(embedBuilder.build()).queue(); + } + } + + @Override + public void onAutoModerationFlagToChannel(@NonNull GuildAuditLogEntryCreateEvent event) { + + String channelIdToSendTo = getRegisteredGuildChannel(event.getGuild().getId()); + if (channelIdToSendTo.isBlank()) return; + + AuditLogEntry ale = event.getEntry(); + + EmbedBuilder eb = new EmbedBuilder(); + eb.setTitle("Audit Log Entry | Auto-Mod Event"); + + User targetUser = ale.getJDA().getUserById(ale.getTargetId()); + String targetMention = (targetUser != null ? targetUser.getAsMention() : ale.getTargetId()); + + eb.setDescription(MarkdownUtil.quoteBlock("Event: AutoMod Message Flag\nTarget Member: " + targetMention)); + eb.setColor(Color.YELLOW); + + eb.addField( + MarkdownUtil.underline("Additional Info"), + MarkdownUtil.codeblock("Flagged message will be available in the channel set to receive AutoMod events."), + false + ); + + eb.setFooter("Audit Log Entry ID: " + ale.getId()); + eb.setTimestamp(ale.getTimeCreated()); + + performChecksThenBuildAndSendEmbed(event, eb, channelIdToSendTo); + + } + + @Override + public void onAutoModerationMemberTimeout(@NonNull GuildAuditLogEntryCreateEvent event) { + + String channelIdToSendTo = getRegisteredGuildChannel(event.getGuild().getId()); + if (channelIdToSendTo.isBlank()) return; + + AuditLogEntry ale = event.getEntry(); + + EmbedBuilder eb = new EmbedBuilder(); + eb.setTitle("Audit Log Entry | Auto-mod Event"); + + User targetUser = ale.getJDA().getUserById(ale.getTargetId()); + String targetMention = (targetUser != null ? targetUser.getAsMention() : ale.getTargetId()); + + eb.setDescription(MarkdownUtil.quoteBlock("Event: AutoMod Member Timeout\nTarget Member: " + targetMention)); + eb.setColor(Color.MAGENTA); + + eb.addField( + MarkdownUtil.underline("Additional Info"), + MarkdownUtil.codeblock("Timeout Rule and Reason will be available in the channel set to receive AutoMod events."), + false + ); + + eb.setFooter("Audit Log Entry ID: " + ale.getId()); + eb.setTimestamp(ale.getTimeCreated()); + + performChecksThenBuildAndSendEmbed(event, eb, channelIdToSendTo); + } + + @Override + public void onAutoModerationRuleBlockMessage(@NonNull GuildAuditLogEntryCreateEvent event) { + + String channelIdToSendTo = getRegisteredGuildChannel(event.getGuild().getId()); + if (channelIdToSendTo.isBlank()) return; + + AuditLogEntry ale = event.getEntry(); + + EmbedBuilder eb = new EmbedBuilder(); + eb.setTitle("Audit Log Entry | Auto-mod Event"); + + User targetUser = ale.getJDA().getUserById(ale.getTargetId()); + String targetMention = (targetUser != null ? targetUser.getAsMention() : ale.getTargetId()); + + eb.setDescription(MarkdownUtil.quoteBlock("Event: AutoMod Message Block\nTarget Member: " + targetMention)); + eb.setColor(Color.ORANGE); + + eb.addField( + MarkdownUtil.underline("Additional Info"), + MarkdownUtil.codeblock("Blocked message will be available in the channel set to receive AutoMod events."), + false + ); + + eb.setFooter("Audit Log Entry ID: " + ale.getId()); + eb.setTimestamp(ale.getTimeCreated()); + + performChecksThenBuildAndSendEmbed(event, eb, channelIdToSendTo); + + } + + @Override + public void onAutoModerationRuleCreate(@NonNull GuildAuditLogEntryCreateEvent event) { + + String channelIdToSendTo = getRegisteredGuildChannel(event.getGuild().getId()); + if (channelIdToSendTo.isBlank()) return; + + AuditLogEntry ale = event.getEntry(); + + EmbedBuilder eb = new EmbedBuilder(); + eb.setTitle("Audit Log Entry | AutoMod Rule Create"); + + User executor = ale.getJDA().getUserById(ale.getUserIdLong()); + String mentionableExecutor = (executor != null ? executor.getAsMention() : ale.getUserId()); + + eb.setDescription(MarkdownUtil.quoteBlock("Rule Created By: " + mentionableExecutor + "\nRule Created For: AutoMod")); + eb.setColor(Color.GREEN); + + ale.getChanges().forEach((changeKey, changeValue) -> { + + Object newValue = changeValue.getNewValue(); + + switch (changeKey) { + + case "enabled" -> + eb.addField(MarkdownUtil.underline("Enabled"), "╰┈➤" + BooleanUtils.formatToYesOrNo(newValue), false); + + case "trigger_type" -> + eb.addField(MarkdownUtil.underline("Trigger Type"), "╰┈➤" + AutoModUtils.autoModTriggerTypeResolver(newValue), false); + + case "event_type" -> + eb.addField(MarkdownUtil.underline("Event Type"), "╰┈➤" + AutoModUtils.autoModEventTypeResolver(newValue), false); + + case "name" -> eb.addField(MarkdownUtil.underline("AutoMod Rule Name "), "╰┈➤" + newValue, false); + + default -> { + // ignore everything else + } + } + }); + + eb.addField("Additional Info", MarkdownUtil.codeblock("For more info on trigger metadata, actions, exempt roles and channels, visit Safety Setup in your server"), false); + eb.setFooter("Audit Log Entry ID: " + ale.getId()); + eb.setTimestamp(ale.getTimeCreated()); + + performChecksThenBuildAndSendEmbed(event, eb, channelIdToSendTo); + } + + @Override + public void onAutoModerationRuleUpdate(@NonNull GuildAuditLogEntryCreateEvent event) { + + String channelIdToSendTo = getRegisteredGuildChannel(event.getGuild().getId()); + if (channelIdToSendTo.isBlank()) return; + + AuditLogEntry ale = event.getEntry(); + + EmbedBuilder eb = new EmbedBuilder(); + eb.setTitle("Audit Log Entry | AutoMod Rule Update"); + + User executor = ale.getJDA().getUserById(ale.getUserIdLong()); + String mentionableExecutor = (executor != null ? executor.getAsMention() : ale.getUserId()); + + eb.setDescription(MarkdownUtil.quoteBlock("Rule Updated By: " + mentionableExecutor + "\nRule Updated For: AutoMod")); + eb.setColor(Color.YELLOW); + + // add name of the rule which got updated + AutoModRule rule = ale.getGuild().retrieveAutoModRuleById(ale.getTargetId()).complete(); + eb.addField(MarkdownUtil.underline("AutoMod Rule Name"), "╰┈➤" + rule.getName(), false); + + eb.addField(MarkdownUtil.underline("Additional Info"), MarkdownUtil.codeblock("For more info on trigger metadata, actions, exempt roles and channel changes, visit Safety Setup in your server"), false); + + eb.setFooter("Audit Log Entry ID: " + ale.getId()); + eb.setTimestamp(ale.getTimeCreated()); + + performChecksThenBuildAndSendEmbed(event, eb, channelIdToSendTo); + } + + @Override + public void onAutoModerationRuleDelete(@NonNull GuildAuditLogEntryCreateEvent event) { + + String channelIdToSendTo = getRegisteredGuildChannel(event.getGuild().getId()); + if (channelIdToSendTo.isBlank()) return; + + AuditLogEntry ale = event.getEntry(); + + EmbedBuilder eb = new EmbedBuilder(); + eb.setTitle("Audit Log Entry | AutoMod Rule Delete"); + + User executor = ale.getJDA().getUserById(ale.getUserIdLong()); + String mentionableExecutor = (executor != null ? executor.getAsMention() : ale.getUserId()); + + eb.setDescription(MarkdownUtil.quoteBlock("Rule Deleted By: " + mentionableExecutor + "\nRule Deleted For: AutoMod")); + eb.setColor(Color.RED); + + ale.getChanges().forEach((changeKey, changeValue) -> { + + Object oldValue = changeValue.getOldValue(); + + if (changeKey.equals("name")) { + eb.addField(MarkdownUtil.underline("AutoMod Rule Name"), "╰┈➤" + oldValue, false); + } + }); + + eb.setFooter("Audit Log Entry ID: " + ale.getId()); + eb.setTimestamp(ale.getTimeCreated()); + + performChecksThenBuildAndSendEmbed(event, eb, channelIdToSendTo); + } +} diff --git a/src/main/java/io/github/eggy03/papertrail/bot/listeners/auditlog/helper/channel/ChannelUpdateEventHelper.java b/src/main/java/io/github/eggy03/papertrail/bot/handlers/auditlog/ChannelEventHandler.java similarity index 51% rename from src/main/java/io/github/eggy03/papertrail/bot/listeners/auditlog/helper/channel/ChannelUpdateEventHelper.java rename to src/main/java/io/github/eggy03/papertrail/bot/handlers/auditlog/ChannelEventHandler.java index 36129740..ac64e562 100644 --- a/src/main/java/io/github/eggy03/papertrail/bot/listeners/auditlog/helper/channel/ChannelUpdateEventHelper.java +++ b/src/main/java/io/github/eggy03/papertrail/bot/handlers/auditlog/ChannelEventHandler.java @@ -1,10 +1,14 @@ -package io.github.eggy03.papertrail.bot.listeners.auditlog.helper.channel; +package io.github.eggy03.papertrail.bot.handlers.auditlog; -import io.github.eggy03.papertrail.bot.listeners.auditlog.helper.channel.utils.ChannelUtils; +import io.github.eggy03.papertrail.bot.listeners.auditlog.GuildAuditLogEntryCreateEventHandler; import io.github.eggy03.papertrail.bot.utils.BooleanUtils; import io.github.eggy03.papertrail.bot.utils.DurationUtils; +import io.github.eggy03.papertrail.bot.utils.auditlog.ChannelUtils; +import io.github.eggy03.papertrail.sdk.client.AuditLogRegistrationClient; +import io.github.eggy03.papertrail.sdk.entity.AuditLogRegistrationEntity; +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.inject.Inject; import lombok.NonNull; -import lombok.experimental.UtilityClass; import lombok.extern.slf4j.Slf4j; import net.dv8tion.jda.api.EmbedBuilder; import net.dv8tion.jda.api.audit.AuditLogEntry; @@ -13,14 +17,105 @@ import net.dv8tion.jda.api.entities.channel.middleman.GuildChannel; import net.dv8tion.jda.api.events.guild.GuildAuditLogEntryCreateEvent; import net.dv8tion.jda.api.utils.MarkdownUtil; +import org.apache.commons.lang3.StringUtils; import java.awt.Color; -@UtilityClass +@ApplicationScoped @Slf4j -public class ChannelUpdateEventHelper { +@SuppressWarnings("java:S1192") +public final class ChannelEventHandler extends GuildAuditLogEntryCreateEventHandler { - public static void format(@NonNull GuildAuditLogEntryCreateEvent event, @NonNull String channelIdToSendTo) { + private final @NonNull AuditLogRegistrationClient client; + + @Inject + public ChannelEventHandler(@NonNull AuditLogRegistrationClient client) { + this.client = client; + } + + @NonNull + private String getRegisteredGuildChannel(@NonNull String guildId) { + return client.getRegisteredGuild(guildId) + .map(AuditLogRegistrationEntity::getChannelId).orElse(StringUtils.EMPTY); + + } + + private void performChecksThenBuildAndSendEmbed(@NonNull GuildAuditLogEntryCreateEvent event, @NonNull EmbedBuilder embedBuilder, @NonNull String channelIdToSendTo) { + if (!embedBuilder.isValidLength() || embedBuilder.isEmpty()) { + log.warn("Embed is empty or too long (current length: {}).", embedBuilder.length()); + return; + } + + TextChannel sendingChannel = event.getGuild().getTextChannelById(channelIdToSendTo); + if (sendingChannel != null && sendingChannel.canTalk()) { + sendingChannel.sendMessageEmbeds(embedBuilder.build()).queue(); + } + } + + @Override + public void onChannelCreate(@NonNull GuildAuditLogEntryCreateEvent event) { + String channelIdToSendTo = getRegisteredGuildChannel(event.getGuild().getId()); + if (channelIdToSendTo.isBlank()) return; + + AuditLogEntry ale = event.getEntry(); + + User executor = ale.getJDA().getUserById(ale.getUserIdLong()); + String mentionableExecutor = (executor != null ? executor.getAsMention() : ale.getUserId()); + + GuildChannel targetChannel = ale.getGuild().getGuildChannelById(ale.getTargetId()); + String targetChannelMention = (targetChannel != null ? targetChannel.getAsMention() : ale.getTargetId()); + + EmbedBuilder eb = new EmbedBuilder(); + eb.setTitle("Audit Log Entry | Channel Create Event"); + + eb.setDescription(MarkdownUtil.quoteBlock("Channel Created By: " + mentionableExecutor + "\nTarget Channel: " + targetChannelMention)); + eb.setColor(Color.GREEN); + + ale.getChanges().forEach((changeKey, changeValue) -> { + + Object oldValue = changeValue.getOldValue(); + Object newValue = changeValue.getNewValue(); + + switch (changeKey) { + case "user_limit" -> + eb.addField(MarkdownUtil.underline("User Limit"), "╰┈➤" + ChannelUtils.resolveVoiceChannelUserLimit(newValue), false); + + case "rate_limit_per_user" -> + eb.addField(MarkdownUtil.underline("Slow Mode"), "╰┈➤" + DurationUtils.formatSeconds(newValue), false); + + case "type" -> + eb.addField(MarkdownUtil.underline("Channel Type"), "╰┈➤" + ChannelUtils.resolveChannelType(newValue), false); + + case "nsfw" -> + eb.addField(MarkdownUtil.underline("Is NSFW"), "╰┈➤" + BooleanUtils.formatToYesOrNo(newValue), false); + + case "name" -> eb.addField(MarkdownUtil.underline("Channel Name"), "╰┈➤" + newValue, false); + + case "bitrate" -> + eb.addField(MarkdownUtil.underline("Voice Channel Bitrate"), "╰┈➤" + ChannelUtils.resolveVoiceChannelBitrate(newValue), false); + + case "permission_overwrites", "flags", "template", "available_tags" -> { + // the first two are for all types of channels and may stay empty during creation events + // the second two are forum only cases which stay empty during creation + } + + default -> { + eb.addField("Unimplemented Change Key", changeKey, false); + log.info("Unimplemented Change Key for Channel Create: {}\nOLD_VALUE: {}\nNEW_VALUE: {}", changeKey, oldValue, newValue); + } + } + }); + + eb.setFooter("Audit Log Entry ID: " + ale.getId()); + eb.setTimestamp(ale.getTimeCreated()); + + performChecksThenBuildAndSendEmbed(event, eb, channelIdToSendTo); + } + + @Override + public void onChannelUpdate(@NonNull GuildAuditLogEntryCreateEvent event) { + String channelIdToSendTo = getRegisteredGuildChannel(event.getGuild().getId()); + if (channelIdToSendTo.isBlank()) return; AuditLogEntry ale = event.getEntry(); @@ -118,7 +213,7 @@ public static void format(@NonNull GuildAuditLogEntryCreateEvent event, @NonNull default -> { eb.addField("Unimplemented Change Key", changeKey, false); - log.info("Unimplemented Change Key: {}\nOLD_VALUE: {}\nNEW_VALUE: {}", changeKey, oldValue, newValue); + log.info("Unimplemented Change Key for Channel Update: {}\nOLD_VALUE: {}\nNEW_VALUE: {}", changeKey, oldValue, newValue); } } @@ -127,14 +222,44 @@ public static void format(@NonNull GuildAuditLogEntryCreateEvent event, @NonNull eb.setFooter("Audit Log Entry ID: " + ale.getId()); eb.setTimestamp(ale.getTimeCreated()); - if (!eb.isValidLength() || eb.isEmpty()) { - log.warn("Embed is empty or too long (current length: {}).", eb.length()); - return; - } + performChecksThenBuildAndSendEmbed(event, eb, channelIdToSendTo); + } - TextChannel sendingChannel = event.getGuild().getTextChannelById(channelIdToSendTo); - if (sendingChannel != null && sendingChannel.canTalk()) { - sendingChannel.sendMessageEmbeds(eb.build()).queue(); - } + @Override + public void onChannelDelete(@NonNull GuildAuditLogEntryCreateEvent event) { + String channelIdToSendTo = getRegisteredGuildChannel(event.getGuild().getId()); + if (channelIdToSendTo.isBlank()) return; + + AuditLogEntry ale = event.getEntry(); + + User executor = ale.getJDA().getUserById(ale.getUserIdLong()); + String mentionableExecutor = (executor != null ? executor.getAsMention() : ale.getUserId()); + + EmbedBuilder eb = new EmbedBuilder(); + eb.setTitle("Audit Log Entry | Channel Delete Event"); + + eb.setDescription(MarkdownUtil.quoteBlock("Channel Deleted By: " + mentionableExecutor + "\nTarget Channel ID: " + ale.getTargetId())); + eb.setColor(Color.RED); + + ale.getChanges().forEach((changeKey, changeValue) -> { + + Object oldValue = changeValue.getOldValue(); + + switch (changeKey) { + case "name" -> eb.addField(MarkdownUtil.underline("Name"), "╰┈➤" + oldValue, false); + + case "type" -> + eb.addField(MarkdownUtil.underline("Type"), "╰┈➤" + ChannelUtils.resolveChannelType(oldValue), false); + + default -> { + // omit all other fields + } + } + }); + + eb.setFooter("Audit Log Entry ID: " + ale.getId()); + eb.setTimestamp(ale.getTimeCreated()); + + performChecksThenBuildAndSendEmbed(event, eb, channelIdToSendTo); } } diff --git a/src/main/java/io/github/eggy03/papertrail/bot/handlers/auditlog/ChannelOverrideEventHandler.java b/src/main/java/io/github/eggy03/papertrail/bot/handlers/auditlog/ChannelOverrideEventHandler.java new file mode 100644 index 00000000..38a04e00 --- /dev/null +++ b/src/main/java/io/github/eggy03/papertrail/bot/handlers/auditlog/ChannelOverrideEventHandler.java @@ -0,0 +1,235 @@ +package io.github.eggy03.papertrail.bot.handlers.auditlog; + +import io.github.eggy03.papertrail.bot.listeners.auditlog.GuildAuditLogEntryCreateEventHandler; +import io.github.eggy03.papertrail.bot.utils.auditlog.ChannelUtils; +import io.github.eggy03.papertrail.sdk.client.AuditLogRegistrationClient; +import io.github.eggy03.papertrail.sdk.entity.AuditLogRegistrationEntity; +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.inject.Inject; +import lombok.NonNull; +import lombok.extern.slf4j.Slf4j; +import net.dv8tion.jda.api.EmbedBuilder; +import net.dv8tion.jda.api.audit.AuditLogEntry; +import net.dv8tion.jda.api.entities.Member; +import net.dv8tion.jda.api.entities.Role; +import net.dv8tion.jda.api.entities.User; +import net.dv8tion.jda.api.entities.channel.concrete.TextChannel; +import net.dv8tion.jda.api.entities.channel.middleman.GuildChannel; +import net.dv8tion.jda.api.events.guild.GuildAuditLogEntryCreateEvent; +import net.dv8tion.jda.api.utils.MarkdownUtil; +import org.apache.commons.lang3.StringUtils; + +import java.awt.Color; + +@ApplicationScoped +@Slf4j +@SuppressWarnings("java:S1192") +public final class ChannelOverrideEventHandler extends GuildAuditLogEntryCreateEventHandler { + + private final @NonNull AuditLogRegistrationClient client; + + @Inject + public ChannelOverrideEventHandler(@NonNull AuditLogRegistrationClient client) { + this.client = client; + } + + @NonNull + private String getRegisteredGuildChannel(@NonNull String guildId) { + return client.getRegisteredGuild(guildId) + .map(AuditLogRegistrationEntity::getChannelId).orElse(StringUtils.EMPTY); + + } + + private void performChecksThenBuildAndSendEmbed(@NonNull GuildAuditLogEntryCreateEvent event, @NonNull EmbedBuilder embedBuilder, @NonNull String channelIdToSendTo) { + if (!embedBuilder.isValidLength() || embedBuilder.isEmpty()) { + log.warn("Embed is empty or too long (current length: {}).", embedBuilder.length()); + return; + } + + TextChannel sendingChannel = event.getGuild().getTextChannelById(channelIdToSendTo); + if (sendingChannel != null && sendingChannel.canTalk()) { + sendingChannel.sendMessageEmbeds(embedBuilder.build()).queue(); + } + } + + @Override + public void onChannelOverrideCreate(@NonNull GuildAuditLogEntryCreateEvent event) { + String channelIdToSendTo = getRegisteredGuildChannel(event.getGuild().getId()); + if (channelIdToSendTo.isBlank()) return; + + AuditLogEntry ale = event.getEntry(); + + User executor = ale.getJDA().getUserById(ale.getUserIdLong()); + String mentionableExecutor = (executor != null ? executor.getAsMention() : ale.getUserId()); + + GuildChannel targetChannel = event.getGuild().getGuildChannelById(ale.getTargetId()); + String targetChannelMention = (targetChannel != null ? targetChannel.getAsMention() : ale.getTargetId()); + + EmbedBuilder eb = new EmbedBuilder(); + eb.setTitle("Audit Log Entry | Channel Override Create"); + eb.setDescription(MarkdownUtil.quoteBlock("Override Created By: " + mentionableExecutor + "\nTarget Channel: " + targetChannelMention)); + eb.setColor(Color.GREEN); + + ale.getChanges().forEach((changeKey, changeValue) -> { + Object oldValue = changeValue.getOldValue(); + Object newValue = changeValue.getNewValue(); + + switch (changeKey) { + + case "type" -> + eb.addField(MarkdownUtil.underline("Override Type"), "╰┈➤" + ChannelUtils.resolveChannelOverrideTargetType(newValue), false); + + case "deny" -> + eb.addField(MarkdownUtil.underline("Denied Permissions"), ChannelUtils.resolveChannelOverridePermissions(newValue, "❌"), false); + case "allow" -> + eb.addField(MarkdownUtil.underline("Allowed Permissions"), ChannelUtils.resolveChannelOverridePermissions(newValue, "✅"), false); + + // id exposes the member/role id which for which the channel permissions are overridden + // only one member/role permission id is fetched per loop + case "id" -> + eb.addField(MarkdownUtil.underline("Target Member/Role"), "╰┈➤" + ChannelUtils.autoResolveMemberOrRole(newValue, event), false); + + default -> { + eb.addField("Unimplemented Change Key", changeKey, false); + log.info("Unimplemented Change Key for Channel Override Create: {}\nOLD_VALUE: {}\nNEW_VALUE: {}", changeKey, oldValue, newValue); + } + } + }); + + eb.setFooter("Audit Log Entry ID: " + ale.getId()); + eb.setTimestamp(ale.getTimeCreated()); + + + performChecksThenBuildAndSendEmbed(event, eb, channelIdToSendTo); + } + + @Override + public void onChannelOverrideUpdate(@NonNull GuildAuditLogEntryCreateEvent event) { + String channelIdToSendTo = getRegisteredGuildChannel(event.getGuild().getId()); + if (channelIdToSendTo.isBlank()) return; + + AuditLogEntry ale = event.getEntry(); + + User executor = ale.getJDA().getUserById(ale.getUserIdLong()); + String mentionableExecutor = (executor != null ? executor.getAsMention() : ale.getUserId()); + + GuildChannel targetChannel = event.getGuild().getGuildChannelById(ale.getTargetId()); + String targetChannelMention = (targetChannel != null ? targetChannel.getAsMention() : ale.getTargetId()); + + EmbedBuilder eb = new EmbedBuilder(); + eb.setTitle("Audit Log Entry | Channel Override Update"); + eb.setDescription(MarkdownUtil.quoteBlock("Override Updated By: " + mentionableExecutor + "\nTarget Channel: " + targetChannelMention)); + eb.setColor(Color.YELLOW); + + eb.addField(MarkdownUtil.underline("Override Type"), "╰┈➤" + ChannelUtils.resolveChannelOverrideTargetType(ale.getOptionByName("type")), false); + eb.addField(MarkdownUtil.underline("Permissions Overridden For"), "╰┈➤" + getTargetRoleOrMember(ale, event), false); + + ale.getChanges().forEach((changeKey, changeValue) -> { + + Object oldValue = changeValue.getOldValue(); + Object newValue = changeValue.getNewValue(); + + switch (changeKey) { + + case "deny" -> + eb.addField(MarkdownUtil.underline("Denied Permissions"), ChannelUtils.resolveChannelOverridePermissions(newValue, "❌"), false); + case "allow" -> + eb.addField(MarkdownUtil.underline("Allowed Permissions"), ChannelUtils.resolveChannelOverridePermissions(newValue, "✅"), false); + + default -> { + eb.addField("Unimplemented Change Key", changeKey, false); + log.info("Unimplemented Change Key for Channel Override Update: {}\nOLD_VALUE: {}\nNEW_VALUE: {}", changeKey, oldValue, newValue); + } + + } + }); + + eb.setFooter("Audit Log Entry ID: " + ale.getId()); + eb.setTimestamp(ale.getTimeCreated()); + + performChecksThenBuildAndSendEmbed(event, eb, channelIdToSendTo); + } + + @Override + public void onChannelOverrideDelete(@NonNull GuildAuditLogEntryCreateEvent event) { + String channelIdToSendTo = getRegisteredGuildChannel(event.getGuild().getId()); + if (channelIdToSendTo.isBlank()) return; + + AuditLogEntry ale = event.getEntry(); + + User executor = ale.getJDA().getUserById(ale.getUserIdLong()); + String mentionableExecutor = (executor != null ? executor.getAsMention() : ale.getUserId()); + + GuildChannel targetChannel = event.getGuild().getGuildChannelById(ale.getTargetId()); + String targetChannelMention = (targetChannel != null ? targetChannel.getAsMention() : ale.getTargetId()); + + EmbedBuilder eb = new EmbedBuilder(); + eb.setTitle("Audit Log Entry | Channel Override Delete"); + + eb.setDescription(MarkdownUtil.quoteBlock("Override Deleted By: " + mentionableExecutor + "\nTarget Channel: " + targetChannelMention)); + eb.setColor(Color.RED); + + ale.getChanges().forEach((changeKey, changeValue) -> { + Object oldValue = changeValue.getOldValue(); + Object newValue = changeValue.getNewValue(); + + switch (changeKey) { + + case "type" -> + eb.addField(MarkdownUtil.underline("Override Type"), "╰┈➤" + ChannelUtils.resolveChannelOverrideTargetType(oldValue), false); + + case "deny" -> + eb.addField(MarkdownUtil.underline("Denied Permissions"), ChannelUtils.resolveChannelOverridePermissions(oldValue, "❌"), false); + case "allow" -> + eb.addField(MarkdownUtil.underline("Allowed Permissions"), ChannelUtils.resolveChannelOverridePermissions(oldValue, "✅"), false); + + // id exposes the member/role id which for which the channel permissions are overridden + // only one member/role permission id is fetched per loop + case "id" -> + eb.addField(MarkdownUtil.underline("Target Member/Role"), "╰┈➤" + ChannelUtils.autoResolveMemberOrRole(oldValue, event), false); + + default -> { + eb.addField("Unimplemented Change Key", changeKey, false); + log.info("Unimplemented Change Key for Channel Override Delete: {}\nOLD_VALUE: {}\nNEW_VALUE: {}", changeKey, oldValue, newValue); + } + } + }); + + eb.setFooter("Audit Log Entry ID: " + ale.getId()); + eb.setTimestamp(ale.getTimeCreated()); + + performChecksThenBuildAndSendEmbed(event, eb, channelIdToSendTo); + } + + // ALE changes do not expose the id and type keys in case of override updates + // therefore, this hacky method is required + // IDK why channel override updates don't show this info + @NonNull + private String getTargetRoleOrMember(@NonNull AuditLogEntry ale, @NonNull GuildAuditLogEntryCreateEvent event) { + + String overriddenId = ale.getOptionByName("id"); // id of the member or role + String overriddenType = ale.getOptionByName("type"); // type that determines if the ID is that of a role or a member + + if (overriddenId == null) + return "Member or Role ID is null"; + + return switch (overriddenType) { + + case "0" -> { + // It’s a role + Role role = event.getGuild().getRoleById(overriddenId); + yield role != null ? role.getAsMention() : overriddenId; + } + + case "1" -> { + // It's a member + Member member = event.getGuild().getMemberById(overriddenId); + yield member != null ? member.getAsMention() : overriddenId; + } + + case null -> "Override Type is null"; + default -> "Unimplemented Override Type: " + overriddenType; + + }; + } +} diff --git a/src/main/java/io/github/eggy03/papertrail/bot/handlers/auditlog/EmojiEventHandler.java b/src/main/java/io/github/eggy03/papertrail/bot/handlers/auditlog/EmojiEventHandler.java new file mode 100644 index 00000000..0d84cf02 --- /dev/null +++ b/src/main/java/io/github/eggy03/papertrail/bot/handlers/auditlog/EmojiEventHandler.java @@ -0,0 +1,156 @@ +package io.github.eggy03.papertrail.bot.handlers.auditlog; + +import io.github.eggy03.papertrail.bot.listeners.auditlog.GuildAuditLogEntryCreateEventHandler; +import io.github.eggy03.papertrail.sdk.client.AuditLogRegistrationClient; +import io.github.eggy03.papertrail.sdk.entity.AuditLogRegistrationEntity; +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.inject.Inject; +import lombok.NonNull; +import lombok.extern.slf4j.Slf4j; +import net.dv8tion.jda.api.EmbedBuilder; +import net.dv8tion.jda.api.audit.AuditLogEntry; +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 net.dv8tion.jda.api.utils.MarkdownUtil; +import org.apache.commons.lang3.StringUtils; + +import java.awt.Color; + +@ApplicationScoped +@Slf4j +@SuppressWarnings("java:S1192") +public final class EmojiEventHandler extends GuildAuditLogEntryCreateEventHandler { + + private final @NonNull AuditLogRegistrationClient client; + + @Inject + public EmojiEventHandler(@NonNull AuditLogRegistrationClient client) { + this.client = client; + } + + @NonNull + private String getRegisteredGuildChannel(@NonNull String guildId) { + return client.getRegisteredGuild(guildId) + .map(AuditLogRegistrationEntity::getChannelId).orElse(StringUtils.EMPTY); + + } + + private void performChecksThenBuildAndSendEmbed(@NonNull GuildAuditLogEntryCreateEvent event, @NonNull EmbedBuilder embedBuilder, @NonNull String channelIdToSendTo) { + if (!embedBuilder.isValidLength() || embedBuilder.isEmpty()) { + log.warn("Embed is empty or too long (current length: {}).", embedBuilder.length()); + return; + } + + TextChannel sendingChannel = event.getGuild().getTextChannelById(channelIdToSendTo); + if (sendingChannel != null && sendingChannel.canTalk()) { + sendingChannel.sendMessageEmbeds(embedBuilder.build()).queue(); + } + } + + @Override + public void onEmojiCreate(@NonNull GuildAuditLogEntryCreateEvent event) { + String channelIdToSendTo = getRegisteredGuildChannel(event.getGuild().getId()); + if (channelIdToSendTo.isBlank()) return; + + AuditLogEntry ale = event.getEntry(); + + User executor = ale.getJDA().getUserById(ale.getUserIdLong()); + String mentionableExecutor = (executor != null ? executor.getAsMention() : ale.getUserId()); + + EmbedBuilder eb = new EmbedBuilder(); + eb.setTitle("Audit Log Entry | Emoji Create Event"); + eb.setDescription(MarkdownUtil.quoteBlock("Emoji Created By: " + mentionableExecutor)); + eb.setColor(Color.GREEN); + + ale.getChanges().forEach((changeKey, changeValue) -> { + + Object oldValue = changeValue.getOldValue(); + Object newValue = changeValue.getNewValue(); + + if (changeKey.equals("name")) { + eb.addField(MarkdownUtil.underline("Emoji Name"), "╰┈➤" + newValue, false); + eb.addField(MarkdownUtil.underline("Emoji"), "╰┈➤" + "<:" + newValue + ":" + ale.getTargetId() + ">", false); // ale's TargetID retrieves the ID of the created emoji + } else { + eb.addField("Unimplemented Change Key", changeKey, false); + log.info("Unimplemented Change Key on Emoji Create: {}\nOLD_VALUE: {}\nNEW_VALUE: {}", changeKey, oldValue, newValue); + } + }); + + eb.setFooter("Audit Log Entry ID: " + ale.getId()); + eb.setTimestamp(ale.getTimeCreated()); + + performChecksThenBuildAndSendEmbed(event, eb, channelIdToSendTo); + } + + @Override + public void onEmojiUpdate(@NonNull GuildAuditLogEntryCreateEvent event) { + String channelIdToSendTo = getRegisteredGuildChannel(event.getGuild().getId()); + if (channelIdToSendTo.isBlank()) return; + + AuditLogEntry ale = event.getEntry(); + + User executor = ale.getJDA().getUserById(ale.getUserIdLong()); + String mentionableExecutor = (executor != null ? executor.getAsMention() : ale.getUserId()); + + + EmbedBuilder eb = new EmbedBuilder(); + eb.setTitle("Audit Log Entry | Emoji Update Event"); + eb.setDescription(MarkdownUtil.quoteBlock("Emoji Updated By: " + mentionableExecutor)); + eb.setColor(Color.YELLOW); + + ale.getChanges().forEach((changeKey, changeValue) -> { + + Object oldValue = changeValue.getOldValue(); + Object newValue = changeValue.getNewValue(); + + if (changeKey.equals("name")) { + eb.addField(MarkdownUtil.underline("Emoji Name Updated"), "╰┈➤" + "From " + oldValue + " to " + newValue, false); + eb.addField(MarkdownUtil.underline("Target Emoji"), "╰┈➤" + "<:" + newValue + ":" + ale.getTargetId() + ">", false); + } else { + eb.addField("Unimplemented Change Key", changeKey, false); + log.info("Unimplemented Change Key on Emoji Update: {}\nOLD_VALUE: {}\nNEW_VALUE: {}", changeKey, oldValue, newValue); + } + }); + + eb.setFooter("Audit Log Entry ID: " + ale.getId()); + eb.setTimestamp(ale.getTimeCreated()); + + performChecksThenBuildAndSendEmbed(event, eb, channelIdToSendTo); + } + + @Override + public void onEmojiDelete(@NonNull GuildAuditLogEntryCreateEvent event) { + String channelIdToSendTo = getRegisteredGuildChannel(event.getGuild().getId()); + if (channelIdToSendTo.isBlank()) return; + + AuditLogEntry ale = event.getEntry(); + + User executor = ale.getJDA().getUserById(ale.getUserIdLong()); + String mentionableExecutor = (executor != null ? executor.getAsMention() : ale.getUserId()); + + EmbedBuilder eb = new EmbedBuilder(); + eb.setTitle("Audit Log Entry | Emoji Delete Event"); + eb.setDescription(MarkdownUtil.quoteBlock("Emoji Deleted By: " + mentionableExecutor)); + eb.setColor(Color.RED); + + ale.getChanges().forEach((changeKey, changeValue) -> { + + Object oldValue = changeValue.getOldValue(); + Object newValue = changeValue.getNewValue(); + + if (changeKey.equals("name")) { + eb.addField(MarkdownUtil.underline("Emoji Name"), "╰┈➤" + oldValue, false); + } else { + eb.addField("Unimplemented Change Key", changeKey, false); + log.info("Unimplemented Change Key on Emoji Delete: {}\nOLD_VALUE: {}\nNEW_VALUE: {}", changeKey, oldValue, newValue); + } + }); + eb.addField("Deleted Emoji ID", "╰┈➤" + ale.getTargetId(), false); + + eb.setFooter("Audit Log Entry ID: " + ale.getId()); + eb.setTimestamp(ale.getTimeCreated()); + + performChecksThenBuildAndSendEmbed(event, eb, channelIdToSendTo); + } +} diff --git a/src/main/java/io/github/eggy03/papertrail/bot/listeners/auditlog/helper/guild/GuildUpdateEventHelper.java b/src/main/java/io/github/eggy03/papertrail/bot/handlers/auditlog/GuildUpdateEventHandler.java similarity index 60% rename from src/main/java/io/github/eggy03/papertrail/bot/listeners/auditlog/helper/guild/GuildUpdateEventHelper.java rename to src/main/java/io/github/eggy03/papertrail/bot/handlers/auditlog/GuildUpdateEventHandler.java index f8a16928..7973f829 100644 --- a/src/main/java/io/github/eggy03/papertrail/bot/listeners/auditlog/helper/guild/GuildUpdateEventHelper.java +++ b/src/main/java/io/github/eggy03/papertrail/bot/handlers/auditlog/GuildUpdateEventHandler.java @@ -1,10 +1,14 @@ -package io.github.eggy03.papertrail.bot.listeners.auditlog.helper.guild; +package io.github.eggy03.papertrail.bot.handlers.auditlog; -import io.github.eggy03.papertrail.bot.listeners.auditlog.helper.guild.utils.GuildUtils; +import io.github.eggy03.papertrail.bot.listeners.auditlog.GuildAuditLogEntryCreateEventHandler; import io.github.eggy03.papertrail.bot.utils.BooleanUtils; import io.github.eggy03.papertrail.bot.utils.DurationUtils; +import io.github.eggy03.papertrail.bot.utils.auditlog.GuildUtils; +import io.github.eggy03.papertrail.sdk.client.AuditLogRegistrationClient; +import io.github.eggy03.papertrail.sdk.entity.AuditLogRegistrationEntity; +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.inject.Inject; import lombok.NonNull; -import lombok.experimental.UtilityClass; import lombok.extern.slf4j.Slf4j; import net.dv8tion.jda.api.EmbedBuilder; import net.dv8tion.jda.api.audit.AuditLogEntry; @@ -12,14 +16,45 @@ import net.dv8tion.jda.api.entities.channel.concrete.TextChannel; import net.dv8tion.jda.api.events.guild.GuildAuditLogEntryCreateEvent; import net.dv8tion.jda.api.utils.MarkdownUtil; +import org.apache.commons.lang3.StringUtils; import java.awt.Color; -@UtilityClass +@ApplicationScoped @Slf4j -public class GuildUpdateEventHelper { +@SuppressWarnings("java:S1192") +public final class GuildUpdateEventHandler extends GuildAuditLogEntryCreateEventHandler { - public static void format(@NonNull GuildAuditLogEntryCreateEvent event, @NonNull String channelIdToSendTo) { + private final @NonNull AuditLogRegistrationClient client; + + @Inject + public GuildUpdateEventHandler(@NonNull AuditLogRegistrationClient client) { + this.client = client; + } + + @NonNull + private String getRegisteredGuildChannel(@NonNull String guildId) { + return client.getRegisteredGuild(guildId) + .map(AuditLogRegistrationEntity::getChannelId).orElse(StringUtils.EMPTY); + + } + + private void performChecksThenBuildAndSendEmbed(@NonNull GuildAuditLogEntryCreateEvent event, @NonNull EmbedBuilder embedBuilder, @NonNull String channelIdToSendTo) { + if (!embedBuilder.isValidLength() || embedBuilder.isEmpty()) { + log.warn("Embed is empty or too long (current length: {}).", embedBuilder.length()); + return; + } + + TextChannel sendingChannel = event.getGuild().getTextChannelById(channelIdToSendTo); + if (sendingChannel != null && sendingChannel.canTalk()) { + sendingChannel.sendMessageEmbeds(embedBuilder.build()).queue(); + } + } + + @Override + public void onGuildUpdate(@NonNull GuildAuditLogEntryCreateEvent event) { + String channelIdToSendTo = getRegisteredGuildChannel(event.getGuild().getId()); + if (channelIdToSendTo.isBlank()) return; AuditLogEntry ale = event.getEntry(); @@ -99,7 +134,7 @@ public static void format(@NonNull GuildAuditLogEntryCreateEvent event, @NonNull default -> { eb.addField("Unimplemented Change Key", changeKey, false); - log.info("Unimplemented Change Key: {}\nOLD_VALUE: {}\nNEW_VALUE: {}", changeKey, oldValue, newValue); + log.info("Unimplemented Change Key for Guild Update: {}\nOLD_VALUE: {}\nNEW_VALUE: {}", changeKey, oldValue, newValue); } } }); @@ -107,14 +142,40 @@ public static void format(@NonNull GuildAuditLogEntryCreateEvent event, @NonNull eb.setFooter("Audit Log Entry ID: " + ale.getId()); eb.setTimestamp(ale.getTimeCreated()); - if (!eb.isValidLength() || eb.isEmpty()) { - log.warn("Embed is empty or too long (current length: {}).", eb.length()); - return; - } + performChecksThenBuildAndSendEmbed(event, eb, channelIdToSendTo); + } - TextChannel sendingChannel = event.getGuild().getTextChannelById(channelIdToSendTo); - if (sendingChannel != null && sendingChannel.canTalk()) { - sendingChannel.sendMessageEmbeds(eb.build()).queue(); - } + @Override + public void onGuildProfileUpdate(@NonNull GuildAuditLogEntryCreateEvent event) { + String channelIdToSendTo = getRegisteredGuildChannel(event.getGuild().getId()); + if (channelIdToSendTo.isBlank()) return; + + AuditLogEntry ale = event.getEntry(); + + User executor = ale.getJDA().getUserById(ale.getUserIdLong()); + String mentionableExecutor = (executor != null ? executor.getAsMention() : ale.getUserId()); + + EmbedBuilder eb = new EmbedBuilder(); + eb.setTitle("Audit Log Entry | Guild Profile Update Event"); + eb.setDescription(MarkdownUtil.quoteBlock("Guild Profile Updated By: " + mentionableExecutor + "\nTarget Guild: " + event.getGuild().getName())); + eb.setColor(Color.PINK); + + ale.getChanges().keySet().forEach(key -> { + switch (key) { + case "traits" -> + eb.addField(MarkdownUtil.underline("Server Traits"), "╰┈➤Server Traits have been updated", false); + case "visibility" -> + eb.addField(MarkdownUtil.underline("Visibility"), "╰┈➤Profile Visibility has been changed", false); + case "brand_color_primary" -> + eb.addField(MarkdownUtil.underline("Banner Color"), "╰┈➤Banner Color has been updated", false); + case "game_application_ids" -> + eb.addField(MarkdownUtil.underline("Games"), "╰┈➤Games have been updated", false); + default -> eb.addField(MarkdownUtil.underline(key), "╰┈➤" + key + " has/have been updated", false); + } + }); + eb.setFooter("Audit Log Entry ID: " + ale.getId()); + eb.setTimestamp(ale.getTimeCreated()); + + performChecksThenBuildAndSendEmbed(event, eb, channelIdToSendTo); } } diff --git a/src/main/java/io/github/eggy03/papertrail/bot/handlers/auditlog/HomeSettingsEventHandler.java b/src/main/java/io/github/eggy03/papertrail/bot/handlers/auditlog/HomeSettingsEventHandler.java new file mode 100644 index 00000000..6b3aab0c --- /dev/null +++ b/src/main/java/io/github/eggy03/papertrail/bot/handlers/auditlog/HomeSettingsEventHandler.java @@ -0,0 +1,110 @@ +package io.github.eggy03.papertrail.bot.handlers.auditlog; + +import io.github.eggy03.papertrail.bot.listeners.auditlog.GuildAuditLogEntryCreateEventHandler; +import io.github.eggy03.papertrail.sdk.client.AuditLogRegistrationClient; +import io.github.eggy03.papertrail.sdk.entity.AuditLogRegistrationEntity; +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.inject.Inject; +import lombok.NonNull; +import lombok.extern.slf4j.Slf4j; +import net.dv8tion.jda.api.EmbedBuilder; +import net.dv8tion.jda.api.audit.AuditLogEntry; +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 net.dv8tion.jda.api.utils.MarkdownUtil; +import org.apache.commons.lang3.StringUtils; + +import java.awt.Color; + +@ApplicationScoped +@Slf4j +@SuppressWarnings("java:S1192") +public final class HomeSettingsEventHandler extends GuildAuditLogEntryCreateEventHandler { + + private final @NonNull AuditLogRegistrationClient client; + + @Inject + public HomeSettingsEventHandler(@NonNull AuditLogRegistrationClient client) { + this.client = client; + } + + @NonNull + private String getRegisteredGuildChannel(@NonNull String guildId) { + return client.getRegisteredGuild(guildId) + .map(AuditLogRegistrationEntity::getChannelId).orElse(StringUtils.EMPTY); + + } + + private void performChecksThenBuildAndSendEmbed(@NonNull GuildAuditLogEntryCreateEvent event, @NonNull EmbedBuilder embedBuilder, @NonNull String channelIdToSendTo) { + if (!embedBuilder.isValidLength() || embedBuilder.isEmpty()) { + log.warn("Embed is empty or too long (current length: {}).", embedBuilder.length()); + return; + } + + TextChannel sendingChannel = event.getGuild().getTextChannelById(channelIdToSendTo); + if (sendingChannel != null && sendingChannel.canTalk()) { + sendingChannel.sendMessageEmbeds(embedBuilder.build()).queue(); + } + } + + @Override + public void onHomeSettingsCreate(@NonNull GuildAuditLogEntryCreateEvent event) { + String channelIdToSendTo = getRegisteredGuildChannel(event.getGuild().getId()); + if (channelIdToSendTo.isBlank()) return; + + AuditLogEntry ale = event.getEntry(); + + User executor = ale.getJDA().getUserById(ale.getUserIdLong()); + String mentionableExecutor = (executor != null ? executor.getAsMention() : ale.getUserId()); + + EmbedBuilder eb = new EmbedBuilder(); + eb.setTitle("Audit Log Entry | Server Guide Create Event"); + eb.setDescription(MarkdownUtil.quoteBlock("Server Guide Created By: " + mentionableExecutor)); + eb.setColor(Color.GREEN); + + eb.addField( + MarkdownUtil.underline("More Info"), + MarkdownUtil.codeblock("To view the created guide, either visit the Server Guide section or the Onboarding section of your guild."), + false + ); + + eb.setFooter("Audit Log Entry ID: " + ale.getId()); + eb.setTimestamp(ale.getTimeCreated()); + + performChecksThenBuildAndSendEmbed(event, eb, channelIdToSendTo); + } + + @Override + public void onHomeSettingsUpdate(@NonNull GuildAuditLogEntryCreateEvent event) { + String channelIdToSendTo = getRegisteredGuildChannel(event.getGuild().getId()); + if (channelIdToSendTo.isBlank()) return; + + AuditLogEntry ale = event.getEntry(); + + User executor = ale.getJDA().getUserById(ale.getUserIdLong()); + String mentionableExecutor = (executor != null ? executor.getAsMention() : ale.getUserId()); + + EmbedBuilder eb = new EmbedBuilder(); + eb.setTitle("Audit Log Entry | Server Guide Update Event"); + eb.setDescription(MarkdownUtil.quoteBlock("Server Guide Updated By: " + mentionableExecutor)); + eb.setColor(Color.YELLOW); + + ale.getChanges().keySet().forEach(key -> { + switch (key) { + case "welcome_message" -> + eb.addField(MarkdownUtil.underline("Welcome Message"), "╰┈➤Welcome Message has been updated", false); + case "resource_channels" -> + eb.addField(MarkdownUtil.underline("Resources"), "╰┈➤Resources have been updated", false); + case "new_member_actions" -> + eb.addField(MarkdownUtil.underline("New Member Join To-Do"), "╰┈➤Interactive Actions have been updated", false); + default -> eb.addField(MarkdownUtil.underline(key), "╰┈➤" + key + " has/have been updated", false); + } + }); + + eb.setFooter("Audit Log Entry ID: " + ale.getId()); + eb.setTimestamp(ale.getTimeCreated()); + + performChecksThenBuildAndSendEmbed(event, eb, channelIdToSendTo); + } +} diff --git a/src/main/java/io/github/eggy03/papertrail/bot/handlers/auditlog/IntegrationEventHandler.java b/src/main/java/io/github/eggy03/papertrail/bot/handlers/auditlog/IntegrationEventHandler.java new file mode 100644 index 00000000..22377af0 --- /dev/null +++ b/src/main/java/io/github/eggy03/papertrail/bot/handlers/auditlog/IntegrationEventHandler.java @@ -0,0 +1,171 @@ +package io.github.eggy03.papertrail.bot.handlers.auditlog; + +import io.github.eggy03.papertrail.bot.listeners.auditlog.GuildAuditLogEntryCreateEventHandler; +import io.github.eggy03.papertrail.sdk.client.AuditLogRegistrationClient; +import io.github.eggy03.papertrail.sdk.entity.AuditLogRegistrationEntity; +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.inject.Inject; +import lombok.NonNull; +import lombok.extern.slf4j.Slf4j; +import net.dv8tion.jda.api.EmbedBuilder; +import net.dv8tion.jda.api.audit.AuditLogEntry; +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 net.dv8tion.jda.api.utils.MarkdownUtil; +import org.apache.commons.lang3.StringUtils; + +import java.awt.Color; + +@ApplicationScoped +@Slf4j +@SuppressWarnings("java:S1192") +public final class IntegrationEventHandler extends GuildAuditLogEntryCreateEventHandler { + + private final @NonNull AuditLogRegistrationClient client; + + @Inject + public IntegrationEventHandler(@NonNull AuditLogRegistrationClient client) { + this.client = client; + } + + @NonNull + private String getRegisteredGuildChannel(@NonNull String guildId) { + return client.getRegisteredGuild(guildId) + .map(AuditLogRegistrationEntity::getChannelId).orElse(StringUtils.EMPTY); + + } + + private void performChecksThenBuildAndSendEmbed(@NonNull GuildAuditLogEntryCreateEvent event, @NonNull EmbedBuilder embedBuilder, @NonNull String channelIdToSendTo) { + if (!embedBuilder.isValidLength() || embedBuilder.isEmpty()) { + log.warn("Embed is empty or too long (current length: {}).", embedBuilder.length()); + return; + } + + TextChannel sendingChannel = event.getGuild().getTextChannelById(channelIdToSendTo); + if (sendingChannel != null && sendingChannel.canTalk()) { + sendingChannel.sendMessageEmbeds(embedBuilder.build()).queue(); + } + } + + @Override + public void onIntegrationCreate(@NonNull GuildAuditLogEntryCreateEvent event) { + String channelIdToSendTo = getRegisteredGuildChannel(event.getGuild().getId()); + if (channelIdToSendTo.isBlank()) return; + + AuditLogEntry ale = event.getEntry(); + + User executor = ale.getJDA().getUserById(ale.getUserIdLong()); + String mentionableExecutor = (executor != null ? executor.getAsMention() : ale.getUserId()); + + EmbedBuilder eb = new EmbedBuilder(); + eb.setTitle("Audit Log Entry | Integration Create Event"); + eb.setDescription(MarkdownUtil.quoteBlock("Integration Created By: " + mentionableExecutor)); + eb.setColor(Color.PINK); + + ale.getChanges().forEach((changeKey, changeValue) -> { + + Object oldValue = changeValue.getOldValue(); + Object newValue = changeValue.getNewValue(); + + switch (changeKey) { + case "type" -> eb.addField(MarkdownUtil.underline("Integration Type"), "╰┈➤" + newValue, false); + case "name" -> eb.addField(MarkdownUtil.underline("Integration Name"), "╰┈➤" + newValue, false); + + default -> { + eb.addField("Unimplemented Change Key", changeKey, false); + log.info("Unimplemented Change Key on Integration Create: {}\nOLD_VALUE: {}\nNEW_VALUE: {}", changeKey, oldValue, newValue); + } + } + }); + + eb.setFooter("Audit Log Entry ID: " + ale.getId()); + eb.setTimestamp(ale.getTimeCreated()); + + performChecksThenBuildAndSendEmbed(event, eb, channelIdToSendTo); + } + + @Override + public void onIntegrationUpdate(@NonNull GuildAuditLogEntryCreateEvent event) { + + log.warn("Integration Update Event Detected. Implement this sometime later\n{}", event.getEntry().getChanges()); + + String channelIdToSendTo = getRegisteredGuildChannel(event.getGuild().getId()); + if (channelIdToSendTo.isBlank()) return; + + AuditLogEntry ale = event.getEntry(); + + EmbedBuilder eb = new EmbedBuilder(); + eb.setTitle("Audit Log Entry | Integration Update Event"); + eb.setColor(Color.LIGHT_GRAY); + + String implementationNotice = "We do not have sufficient data to log the changes in an INTEGRATION_UPDATE Event." + .concat(" A proper implementation might happen in future releases if such an event is fired consistently."); + + eb.addField("Implementation Notice", MarkdownUtil.codeblock(implementationNotice), false); + + eb.setFooter("Audit Log Entry ID: " + ale.getId()); + eb.setTimestamp(ale.getTimeCreated()); + + performChecksThenBuildAndSendEmbed(event, eb, channelIdToSendTo); + } + + @Override + public void onIntegrationDelete(@NonNull GuildAuditLogEntryCreateEvent event) { + String channelIdToSendTo = getRegisteredGuildChannel(event.getGuild().getId()); + if (channelIdToSendTo.isBlank()) return; + + AuditLogEntry ale = event.getEntry(); + + User executor = ale.getJDA().getUserById(ale.getUserIdLong()); + String mentionableExecutor = (executor != null ? executor.getAsMention() : ale.getUserId()); + + EmbedBuilder eb = new EmbedBuilder(); + eb.setTitle("Audit Log Entry | Integration Delete Event"); + eb.setDescription(MarkdownUtil.quoteBlock("Integration Deleted By: " + mentionableExecutor)); + eb.setColor(Color.MAGENTA); + + ale.getChanges().forEach((changeKey, changeValue) -> { + Object oldValue = changeValue.getOldValue(); + Object newValue = changeValue.getNewValue(); + + switch (changeKey) { + case "type" -> eb.addField(MarkdownUtil.underline("Integration Type"), "╰┈➤" + oldValue, false); + case "name" -> eb.addField(MarkdownUtil.underline("Integration Name"), "╰┈➤" + oldValue, false); + + default -> { + eb.addField("Unimplemented Change Key", changeKey, false); + log.info("Unimplemented Change Key on Integration Delete: {}\nOLD_VALUE: {}\nNEW_VALUE: {}", changeKey, oldValue, newValue); + } + } + }); + + eb.setFooter("Audit Log Entry ID: " + ale.getId()); + eb.setTimestamp(ale.getTimeCreated()); + + performChecksThenBuildAndSendEmbed(event, eb, channelIdToSendTo); + } + + @Override + public void onApplicationCommandPrivilegesUpdate(@NonNull GuildAuditLogEntryCreateEvent event) { + String channelIdToSendTo = getRegisteredGuildChannel(event.getGuild().getId()); + if (channelIdToSendTo.isBlank()) return; + + AuditLogEntry ale = event.getEntry(); + + User executor = ale.getJDA().getUserById(ale.getUserIdLong()); + String mentionableExecutor = (executor != null ? executor.getAsMention() : ale.getUserId()); + + EmbedBuilder eb = new EmbedBuilder(); + eb.setTitle("Audit Log Entry | Application Command Privilege Update"); + eb.setDescription(MarkdownUtil.quoteBlock("Application Command Privilege Updated By: " + mentionableExecutor)); + eb.setColor(Color.PINK); + + eb.addField(MarkdownUtil.underline("More Info"), MarkdownUtil.codeblock("To know more about what changes were made, visit the Integrations section"), false); + + eb.setFooter("Audit Log Entry ID: " + ale.getId()); + eb.setTimestamp(ale.getTimeCreated()); + + performChecksThenBuildAndSendEmbed(event, eb, channelIdToSendTo); + } +} diff --git a/src/main/java/io/github/eggy03/papertrail/bot/handlers/auditlog/InviteEventHandler.java b/src/main/java/io/github/eggy03/papertrail/bot/handlers/auditlog/InviteEventHandler.java new file mode 100644 index 00000000..bff8ad06 --- /dev/null +++ b/src/main/java/io/github/eggy03/papertrail/bot/handlers/auditlog/InviteEventHandler.java @@ -0,0 +1,194 @@ +package io.github.eggy03.papertrail.bot.handlers.auditlog; + +import io.github.eggy03.papertrail.bot.listeners.auditlog.GuildAuditLogEntryCreateEventHandler; +import io.github.eggy03.papertrail.bot.utils.BooleanUtils; +import io.github.eggy03.papertrail.bot.utils.DurationUtils; +import io.github.eggy03.papertrail.bot.utils.auditlog.InviteUtils; +import io.github.eggy03.papertrail.sdk.client.AuditLogRegistrationClient; +import io.github.eggy03.papertrail.sdk.entity.AuditLogRegistrationEntity; +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.inject.Inject; +import lombok.NonNull; +import lombok.extern.slf4j.Slf4j; +import net.dv8tion.jda.api.EmbedBuilder; +import net.dv8tion.jda.api.audit.AuditLogEntry; +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 net.dv8tion.jda.api.utils.MarkdownUtil; +import org.apache.commons.lang3.StringUtils; + +import java.awt.Color; + +@ApplicationScoped +@Slf4j +@SuppressWarnings("java:S1192") +public final class InviteEventHandler extends GuildAuditLogEntryCreateEventHandler { + + private final @NonNull AuditLogRegistrationClient client; + + @Inject + public InviteEventHandler(@NonNull AuditLogRegistrationClient client) { + this.client = client; + } + + @NonNull + private String getRegisteredGuildChannel(@NonNull String guildId) { + return client.getRegisteredGuild(guildId) + .map(AuditLogRegistrationEntity::getChannelId).orElse(StringUtils.EMPTY); + + } + + private void performChecksThenBuildAndSendEmbed(@NonNull GuildAuditLogEntryCreateEvent event, @NonNull EmbedBuilder embedBuilder, @NonNull String channelIdToSendTo) { + if (!embedBuilder.isValidLength() || embedBuilder.isEmpty()) { + log.warn("Embed is empty or too long (current length: {}).", embedBuilder.length()); + return; + } + + TextChannel sendingChannel = event.getGuild().getTextChannelById(channelIdToSendTo); + if (sendingChannel != null && sendingChannel.canTalk()) { + sendingChannel.sendMessageEmbeds(embedBuilder.build()).queue(); + } + } + + @Override + public void onInviteCreate(@NonNull GuildAuditLogEntryCreateEvent event) { + String channelIdToSendTo = getRegisteredGuildChannel(event.getGuild().getId()); + if (channelIdToSendTo.isBlank()) return; + + AuditLogEntry ale = event.getEntry(); + + User executor = ale.getJDA().getUserById(ale.getUserIdLong()); + String mentionableExecutor = (executor != null ? executor.getAsMention() : ale.getUserId()); + + EmbedBuilder eb = new EmbedBuilder(); + eb.setTitle("Audit Log Entry | Invite Create Event"); + + eb.setDescription(MarkdownUtil.quoteBlock("Invite Created By: " + mentionableExecutor)); + eb.setColor(Color.CYAN); + + ale.getChanges().forEach((changeKey, changeValue) -> { + + Object oldValue = changeValue.getOldValue(); + Object newValue = changeValue.getNewValue(); + + switch (changeKey) { + + case "code" -> eb.addField(MarkdownUtil.underline("Invite Code"), "╰┈➤" + newValue, false); + + case "inviter_id" -> + eb.addField(MarkdownUtil.underline("Invite Created By"), "╰┈➤" + InviteUtils.resolveInviter(newValue, event), false); + + case "temporary" -> + eb.addField(MarkdownUtil.underline("Is Temporary"), "╰┈➤" + BooleanUtils.formatToYesOrNo(newValue), false); + + case "max_uses" -> + eb.addField(MarkdownUtil.underline("Max Uses"), "╰┈➤" + InviteUtils.resolveMaxUses(newValue), false); + + case "uses", "flags" -> { + // ignore + } + + case "role_ids" -> + eb.addField(MarkdownUtil.underline("Roles Attached"), "╰┈➤" + InviteUtils.resolveInviteRoleList(event, newValue), false); + + case "max_age" -> + eb.addField(MarkdownUtil.underline("Expires After"), "╰┈➤" + DurationUtils.formatSeconds(newValue), false); + + case "channel_id" -> + eb.addField(MarkdownUtil.underline("Invite Channel"), "╰┈➤" + InviteUtils.resolveInviteChannel(newValue, event), false); + + default -> { + eb.addField("Unimplemented Change Key", changeKey, false); + log.info("Unimplemented Change Key on Invite Create: {}\nOLD_VALUE: {}\nNEW_VALUE: {}", changeKey, oldValue, newValue); + } + } + }); + + eb.setFooter("Audit Log Entry ID: " + ale.getId()); + eb.setTimestamp(ale.getTimeCreated()); + + performChecksThenBuildAndSendEmbed(event, eb, channelIdToSendTo); + } + + @Override + public void onInviteUpdate(@NonNull GuildAuditLogEntryCreateEvent event) { + log.warn("Invite Update Event Detected. Implement this sometime later\n{}", event.getEntry().getChanges()); + + String channelIdToSendTo = getRegisteredGuildChannel(event.getGuild().getId()); + if (channelIdToSendTo.isBlank()) return; + + AuditLogEntry ale = event.getEntry(); + + EmbedBuilder eb = new EmbedBuilder(); + eb.setTitle("Audit Log Entry | Invite Update Event"); + eb.setColor(Color.LIGHT_GRAY); + + String implementationNotice = "We do not have sufficient data to log the changes in an INVITE_UPDATE Event" + .concat(" because invites seem to be immutable at the moment, which causes this event to not be fired.") + .concat(" A proper implementation might happen in future releases if such an event is fired consistently."); + + eb.addField("Implementation Notice", MarkdownUtil.codeblock(implementationNotice), false); + + eb.setFooter("Audit Log Entry ID: " + ale.getId()); + eb.setTimestamp(ale.getTimeCreated()); + + performChecksThenBuildAndSendEmbed(event, eb, channelIdToSendTo); + } + + @Override + public void onInviteDelete(@NonNull GuildAuditLogEntryCreateEvent event) { + String channelIdToSendTo = getRegisteredGuildChannel(event.getGuild().getId()); + if (channelIdToSendTo.isBlank()) return; + + AuditLogEntry ale = event.getEntry(); + + EmbedBuilder eb = new EmbedBuilder(); + eb.setTitle("Audit Log Entry | Invite Delete Event"); + + User executor = ale.getJDA().getUserById(ale.getUserIdLong()); + String mentionableExecutor = (executor != null ? executor.getAsMention() : ale.getUserId()); + + eb.setDescription(MarkdownUtil.quoteBlock("Invite Deleted By: " + mentionableExecutor)); + eb.setColor(Color.BLUE); + + ale.getChanges().forEach((changeKey, changeValue) -> { + Object oldValue = changeValue.getOldValue(); + Object newValue = changeValue.getNewValue(); + + switch (changeKey) { + + case "code" -> eb.addField(MarkdownUtil.underline("Deleted Invite Code"), "╰┈➤" + oldValue, false); + + case "inviter_id" -> + eb.addField(MarkdownUtil.underline("Invite Deleted By"), "╰┈➤" + InviteUtils.resolveInviter(oldValue, event), false); + + case "temporary" -> + eb.addField(MarkdownUtil.underline("Was Temporary"), "╰┈➤" + BooleanUtils.formatToYesOrNo(oldValue), false); + + case "max_uses", "flags", "max_age" -> { + // ignore + } + + case "role_ids" -> + eb.addField(MarkdownUtil.underline("Roles Attached"), "╰┈➤" + InviteUtils.resolveInviteRoleList(event, oldValue), false); + + case "uses" -> eb.addField(MarkdownUtil.underline("Use Count"), "╰┈➤" + oldValue, false); + + case "channel_id" -> + eb.addField(MarkdownUtil.underline("Invite Channel"), "╰┈➤" + InviteUtils.resolveInviteChannel(oldValue, event), false); + + default -> { + eb.addField("Unimplemented Change Key", changeKey, false); + log.info("Unimplemented Change Key on Invite Delete: {}\nOLD_VALUE: {}\nNEW_VALUE: {}", changeKey, oldValue, newValue); + } + + } + }); + + eb.setFooter("Audit Log Entry ID: " + ale.getId()); + eb.setTimestamp(ale.getTimeCreated()); + + performChecksThenBuildAndSendEmbed(event, eb, channelIdToSendTo); + } +} diff --git a/src/main/java/io/github/eggy03/papertrail/bot/handlers/auditlog/MemberStatusEventHandler.java b/src/main/java/io/github/eggy03/papertrail/bot/handlers/auditlog/MemberStatusEventHandler.java new file mode 100644 index 00000000..f261e62d --- /dev/null +++ b/src/main/java/io/github/eggy03/papertrail/bot/handlers/auditlog/MemberStatusEventHandler.java @@ -0,0 +1,208 @@ +package io.github.eggy03.papertrail.bot.handlers.auditlog; + +import io.github.eggy03.papertrail.bot.listeners.auditlog.GuildAuditLogEntryCreateEventHandler; +import io.github.eggy03.papertrail.bot.utils.BooleanUtils; +import io.github.eggy03.papertrail.bot.utils.DurationUtils; +import io.github.eggy03.papertrail.bot.utils.auditlog.MemberUtils; +import io.github.eggy03.papertrail.sdk.client.AuditLogRegistrationClient; +import io.github.eggy03.papertrail.sdk.entity.AuditLogRegistrationEntity; +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.inject.Inject; +import lombok.NonNull; +import lombok.extern.slf4j.Slf4j; +import net.dv8tion.jda.api.EmbedBuilder; +import net.dv8tion.jda.api.audit.AuditLogEntry; +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 net.dv8tion.jda.api.utils.MarkdownUtil; +import org.apache.commons.lang3.StringUtils; + +import java.awt.Color; + +@ApplicationScoped +@Slf4j +@SuppressWarnings("java:S1192") +public final class MemberStatusEventHandler extends GuildAuditLogEntryCreateEventHandler { + + private final @NonNull AuditLogRegistrationClient client; + + @Inject + public MemberStatusEventHandler(@NonNull AuditLogRegistrationClient client) { + this.client = client; + } + + @NonNull + private String getRegisteredGuildChannel(@NonNull String guildId) { + return client.getRegisteredGuild(guildId) + .map(AuditLogRegistrationEntity::getChannelId).orElse(StringUtils.EMPTY); + + } + + private void performChecksThenBuildAndSendEmbed(@NonNull GuildAuditLogEntryCreateEvent event, @NonNull EmbedBuilder embedBuilder, @NonNull String channelIdToSendTo) { + if (!embedBuilder.isValidLength() || embedBuilder.isEmpty()) { + log.warn("Embed is empty or too long (current length: {}).", embedBuilder.length()); + return; + } + + TextChannel sendingChannel = event.getGuild().getTextChannelById(channelIdToSendTo); + if (sendingChannel != null && sendingChannel.canTalk()) { + sendingChannel.sendMessageEmbeds(embedBuilder.build()).queue(); + } + } + + @Override + public void onMemberUpdate(@NonNull GuildAuditLogEntryCreateEvent event) { + String channelIdToSendTo = getRegisteredGuildChannel(event.getGuild().getId()); + if (channelIdToSendTo.isBlank()) return; + + AuditLogEntry ale = event.getEntry(); + + User executor = ale.getJDA().getUserById(ale.getUserIdLong()); + String mentionableExecutor = (executor != null ? executor.getAsMention() : ale.getUserId()); + + User targetUser = ale.getJDA().getUserById(ale.getTargetIdLong()); + String mentionableTargetUser = (targetUser != null ? targetUser.getAsMention() : ale.getTargetId()); + + EmbedBuilder eb = new EmbedBuilder(); + eb.setTitle("Audit Log Entry | Member Update Event"); + eb.setDescription(MarkdownUtil.quoteBlock("Executor: " + mentionableExecutor + "\nTarget: " + mentionableTargetUser)); + eb.setColor(Color.CYAN); + + if (targetUser != null) + eb.setThumbnail(targetUser.getEffectiveAvatarUrl()); + + ale.getChanges().forEach((changeKey, changeValue) -> { + Object oldValue = changeValue.getOldValue(); + Object newValue = changeValue.getNewValue(); + + switch (changeKey) { + + case "communication_disabled_until" -> { + if (newValue == null) { + eb.setColor(Color.GREEN); + eb.addField(MarkdownUtil.underline("Timeout Lifted"), "╰┈➤ Timeout has been removed", false); + } else { + eb.setColor(Color.YELLOW); + eb.addField(MarkdownUtil.underline("Timeout Received"), "╰┈➤ Member has received a timeout", false); + eb.addField(MarkdownUtil.underline("Timeout Ends On"), "╰┈➤" + DurationUtils.isoToLocalTimeCounter(newValue), false); + eb.addField(MarkdownUtil.underline("Timeout Reason"), "╰┈➤" + (ale.getReason() != null ? ale.getReason() : "No Reason Provided"), false); + } + } + case "nick" -> + eb.addField(MarkdownUtil.underline("Nickname Update"), MemberUtils.resolveNickNameChanges(oldValue, newValue), false); + + case "mute" -> + eb.addField(MarkdownUtil.underline("Is Muted in VC"), "╰┈➤" + BooleanUtils.formatToYesOrNo(newValue), false); + + case "deaf" -> + eb.addField(MarkdownUtil.underline("Is Deafened in VC"), "╰┈➤" + BooleanUtils.formatToYesOrNo(newValue), false); + + case "bypasses_verification" -> + eb.addField(MarkdownUtil.underline("Bypass Verification"), "╰┈➤" + BooleanUtils.formatToEnabledOrDisabled(newValue), false); + + default -> { + eb.addField("Unimplemented Change Key", changeKey, false); + log.info("Unimplemented Change Key on Member Update: {}\nOLD_VALUE: {}\nNEW_VALUE: {}", changeKey, oldValue, newValue); + } + } + }); + + eb.setFooter("Audit Log Entry ID: " + ale.getId()); + eb.setTimestamp(ale.getTimeCreated()); + + performChecksThenBuildAndSendEmbed(event, eb, channelIdToSendTo); + } + + @Override + public void onMemberRoleUpdate(@NonNull GuildAuditLogEntryCreateEvent event) { + String channelIdToSendTo = getRegisteredGuildChannel(event.getGuild().getId()); + if (channelIdToSendTo.isBlank()) return; + + AuditLogEntry ale = event.getEntry(); + + User executor = ale.getJDA().getUserById(ale.getUserIdLong()); + String mentionableExecutor = (executor != null ? executor.getAsMention() : ale.getUserId()); + + User targetUser = ale.getJDA().getUserById(ale.getTargetIdLong()); + String mentionableTargetUser = (targetUser != null ? targetUser.getAsMention() : ale.getTargetId()); + + EmbedBuilder eb = new EmbedBuilder(); + eb.setTitle("Audit Log Entry | Member Role Update"); + eb.setDescription(MarkdownUtil.quoteBlock("Executor: " + mentionableExecutor + "\nTarget: " + mentionableTargetUser)); + eb.setColor(Color.YELLOW); + + if (targetUser != null) + eb.setThumbnail(targetUser.getEffectiveAvatarUrl()); + + ale.getChanges().forEach((changeKey, changeValue) -> { + Object oldValue = changeValue.getOldValue(); + Object newValue = changeValue.getNewValue(); + + switch (changeKey) { + case "$add" -> + eb.addField(MarkdownUtil.underline("✅ Role(s) Added"), "╰┈➤" + MemberUtils.parseRoleListMap(event, newValue), false); + + case "$remove" -> + eb.addField(MarkdownUtil.underline("❌ Role(s) Removed"), "╰┈➤" + MemberUtils.parseRoleListMap(event, newValue), false); + + default -> { + eb.addField("Unimplemented Change Key", changeKey, false); + log.info("Unimplemented Change Key on Member Role Update: {}\nOLD_VALUE: {}\nNEW_VALUE: {}", changeKey, oldValue, newValue); + } + } + }); + + eb.setFooter("Audit Log Entry ID: " + ale.getId()); + eb.setTimestamp(ale.getTimeCreated()); + + performChecksThenBuildAndSendEmbed(event, eb, channelIdToSendTo); + } + + // the audit log does not expose much information regarding member vc move and kick events + // therefore GuildVoiceEventListener has been created to know about channels the target has been moved or kicked from + @Override + public void onMemberVoiceKick(@NonNull GuildAuditLogEntryCreateEvent event) { + + String channelIdToSendTo = getRegisteredGuildChannel(event.getGuild().getId()); + if (channelIdToSendTo.isBlank()) return; + + AuditLogEntry ale = event.getEntry(); + + User executor = ale.getJDA().getUserById(ale.getUserId()); + String mentionableExecutor = (executor != null ? executor.getAsMention() : ale.getUserId()); + + EmbedBuilder eb = new EmbedBuilder(); + eb.setTitle("Audit Log Entry | Member Voice Kick Event"); + eb.setDescription(MarkdownUtil.quoteBlock("Member Kicked From a Voice Channel\n By: " + mentionableExecutor)); + eb.setColor(Color.RED); + + eb.setFooter("Audit Log Entry ID: " + ale.getId()); + eb.setTimestamp(ale.getTimeCreated()); + + performChecksThenBuildAndSendEmbed(event, eb, channelIdToSendTo); + } + + // the audit log does not expose much information regarding member vc move and kick events + // therefore GuildVoiceEventListener has been created to know about channels the target has been moved or kicked from + @Override + public void onMemberVoiceMove(@NonNull GuildAuditLogEntryCreateEvent event) { + String channelIdToSendTo = getRegisteredGuildChannel(event.getGuild().getId()); + if (channelIdToSendTo.isBlank()) return; + + AuditLogEntry ale = event.getEntry(); + + User executor = ale.getJDA().getUserById(ale.getUserId()); + String mentionableExecutor = (executor != null ? executor.getAsMention() : ale.getUserId()); + + EmbedBuilder eb = new EmbedBuilder(); + eb.setTitle("Audit Log Entry | Member Voice Move Event"); + eb.setDescription(MarkdownUtil.quoteBlock("Member Moved To A Different Voice Channel\n By: " + mentionableExecutor)); + eb.setColor(Color.YELLOW); + + eb.setFooter("Audit Log Entry ID: " + ale.getId()); + eb.setTimestamp(ale.getTimeCreated()); + + performChecksThenBuildAndSendEmbed(event, eb, channelIdToSendTo); + } +} diff --git a/src/main/java/io/github/eggy03/papertrail/bot/handlers/auditlog/MessageEventHandler.java b/src/main/java/io/github/eggy03/papertrail/bot/handlers/auditlog/MessageEventHandler.java new file mode 100644 index 00000000..8d054783 --- /dev/null +++ b/src/main/java/io/github/eggy03/papertrail/bot/handlers/auditlog/MessageEventHandler.java @@ -0,0 +1,104 @@ +package io.github.eggy03.papertrail.bot.handlers.auditlog; + +import io.github.eggy03.papertrail.bot.listeners.auditlog.GuildAuditLogEntryCreateEventHandler; +import io.github.eggy03.papertrail.sdk.client.AuditLogRegistrationClient; +import io.github.eggy03.papertrail.sdk.entity.AuditLogRegistrationEntity; +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.inject.Inject; +import lombok.NonNull; +import lombok.extern.slf4j.Slf4j; +import net.dv8tion.jda.api.EmbedBuilder; +import net.dv8tion.jda.api.audit.AuditLogEntry; +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 net.dv8tion.jda.api.utils.MarkdownUtil; +import org.apache.commons.lang3.StringUtils; + +import java.awt.Color; + +@ApplicationScoped +@Slf4j +@SuppressWarnings("java:S1192") +public final class MessageEventHandler extends GuildAuditLogEntryCreateEventHandler { + + private final @NonNull AuditLogRegistrationClient client; + + @Inject + public MessageEventHandler(@NonNull AuditLogRegistrationClient client) { + this.client = client; + } + + @NonNull + private String getRegisteredGuildChannel(@NonNull String guildId) { + return client.getRegisteredGuild(guildId) + .map(AuditLogRegistrationEntity::getChannelId).orElse(StringUtils.EMPTY); + + } + + private void performChecksThenBuildAndSendEmbed(@NonNull GuildAuditLogEntryCreateEvent event, @NonNull EmbedBuilder embedBuilder, @NonNull String channelIdToSendTo) { + if (!embedBuilder.isValidLength() || embedBuilder.isEmpty()) { + log.warn("Embed is empty or too long (current length: {}).", embedBuilder.length()); + return; + } + + TextChannel sendingChannel = event.getGuild().getTextChannelById(channelIdToSendTo); + if (sendingChannel != null && sendingChannel.canTalk()) { + sendingChannel.sendMessageEmbeds(embedBuilder.build()).queue(); + } + } + + // for the following four events, audit log does not expose much information + // a custom implementation to log edits and deletes of messages is found in GuildMessageEventListener + @Override + public void onMessageCreate(@NonNull GuildAuditLogEntryCreateEvent event) { + // do nothing (these never trigger) + } + + @Override + public void onMessageUpdate(@NonNull GuildAuditLogEntryCreateEvent event) { + // do nothing (these never trigger) + } + + @Override + public void onMessageDelete(@NonNull GuildAuditLogEntryCreateEvent event) { + String channelIdToSendTo = getRegisteredGuildChannel(event.getGuild().getId()); + if (channelIdToSendTo.isBlank()) return; + + AuditLogEntry ale = event.getEntry(); + + User executor = ale.getJDA().getUserById(ale.getUserIdLong()); + String mentionableExecutor = executor != null ? executor.getAsMention() : ale.getUserId(); + + EmbedBuilder eb = new EmbedBuilder(); + eb.setTitle("Audit Log Entry | Message Delete Event"); + eb.setDescription(MarkdownUtil.quoteBlock("Executor: " + mentionableExecutor)); + eb.setColor(Color.LIGHT_GRAY); + + eb.setFooter("Audit Log Entry ID: " + ale.getId()); + eb.setTimestamp(ale.getTimeCreated()); + + performChecksThenBuildAndSendEmbed(event, eb, channelIdToSendTo); + } + + @Override + public void onMessageBulkDelete(@NonNull GuildAuditLogEntryCreateEvent event) { + String channelIdToSendTo = getRegisteredGuildChannel(event.getGuild().getId()); + if (channelIdToSendTo.isBlank()) return; + + AuditLogEntry ale = event.getEntry(); + + User executor = ale.getJDA().getUserById(ale.getUserIdLong()); + String mentionableExecutor = executor != null ? executor.getAsMention() : ale.getUserId(); + + EmbedBuilder eb = new EmbedBuilder(); + eb.setTitle("Audit Log Entry | Bulk Message Delete Event"); + eb.setDescription(MarkdownUtil.quoteBlock("Executor: " + mentionableExecutor)); + eb.setColor(Color.LIGHT_GRAY); + + eb.setFooter("Audit Log Entry ID: " + ale.getId()); + eb.setTimestamp(ale.getTimeCreated()); + + performChecksThenBuildAndSendEmbed(event, eb, channelIdToSendTo); + } +} diff --git a/src/main/java/io/github/eggy03/papertrail/bot/handlers/auditlog/MessagePinEventHandler.java b/src/main/java/io/github/eggy03/papertrail/bot/handlers/auditlog/MessagePinEventHandler.java new file mode 100644 index 00000000..4b8d85f7 --- /dev/null +++ b/src/main/java/io/github/eggy03/papertrail/bot/handlers/auditlog/MessagePinEventHandler.java @@ -0,0 +1,113 @@ +package io.github.eggy03.papertrail.bot.handlers.auditlog; + +import io.github.eggy03.papertrail.bot.listeners.auditlog.GuildAuditLogEntryCreateEventHandler; +import io.github.eggy03.papertrail.bot.utils.auditlog.MessageUtils; +import io.github.eggy03.papertrail.sdk.client.AuditLogRegistrationClient; +import io.github.eggy03.papertrail.sdk.entity.AuditLogRegistrationEntity; +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.inject.Inject; +import lombok.NonNull; +import lombok.extern.slf4j.Slf4j; +import net.dv8tion.jda.api.EmbedBuilder; +import net.dv8tion.jda.api.audit.AuditLogEntry; +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 net.dv8tion.jda.api.utils.MarkdownUtil; +import org.apache.commons.lang3.StringUtils; + +import java.awt.Color; + +@ApplicationScoped +@Slf4j +@SuppressWarnings("java:S1192") +public final class MessagePinEventHandler extends GuildAuditLogEntryCreateEventHandler { + + private final @NonNull AuditLogRegistrationClient client; + + @Inject + public MessagePinEventHandler(@NonNull AuditLogRegistrationClient client) { + this.client = client; + } + + @NonNull + private String getRegisteredGuildChannel(@NonNull String guildId) { + return client.getRegisteredGuild(guildId) + .map(AuditLogRegistrationEntity::getChannelId).orElse(StringUtils.EMPTY); + + } + + private void performChecksThenBuildAndSendEmbed(@NonNull GuildAuditLogEntryCreateEvent event, @NonNull EmbedBuilder embedBuilder, @NonNull String channelIdToSendTo) { + if (!embedBuilder.isValidLength() || embedBuilder.isEmpty()) { + log.warn("Embed is empty or too long (current length: {}).", embedBuilder.length()); + return; + } + + TextChannel sendingChannel = event.getGuild().getTextChannelById(channelIdToSendTo); + if (sendingChannel != null && sendingChannel.canTalk()) { + sendingChannel.sendMessageEmbeds(embedBuilder.build()).queue(); + } + } + + @Override + public void onMessagePin(@NonNull GuildAuditLogEntryCreateEvent event) { + String channelIdToSendTo = getRegisteredGuildChannel(event.getGuild().getId()); + if (channelIdToSendTo.isBlank()) return; + + AuditLogEntry ale = event.getEntry(); + + EmbedBuilder eb = new EmbedBuilder(); + eb.setTitle("Audit Log Entry | Message Pin Event"); + + User executor = ale.getJDA().getUserById(ale.getUserId()); + String mentionableExecutor = (executor != null ? executor.getAsMention() : ale.getUserId()); + + User target = ale.getJDA().getUserById(ale.getTargetId()); + String mentionableTarget = (target != null ? target.getAsMention() : ale.getTargetId()); + + eb.setDescription(MarkdownUtil.quoteBlock("Message Pinned By: " + mentionableExecutor + "\nMessage Author: " + mentionableTarget)); + eb.setColor(Color.PINK); + + eb.addField( + MarkdownUtil.underline("Pinned Message Jump URL"), + MessageUtils.resolveMessageJumpUrlFromId(ale.getOptionByName("channel_id"), ale.getOptionByName("message_id"), event), + false + ); + + eb.setFooter("Audit Log Entry ID: " + ale.getId()); + eb.setTimestamp(ale.getTimeCreated()); + + performChecksThenBuildAndSendEmbed(event, eb, channelIdToSendTo); + } + + @Override + public void onMessageUnpin(@NonNull GuildAuditLogEntryCreateEvent event) { + String channelIdToSendTo = getRegisteredGuildChannel(event.getGuild().getId()); + if (channelIdToSendTo.isBlank()) return; + + AuditLogEntry ale = event.getEntry(); + + EmbedBuilder eb = new EmbedBuilder(); + eb.setTitle("Audit Log Entry | Message Unpin Event"); + + User executor = ale.getJDA().getUserById(ale.getUserId()); + String mentionableExecutor = (executor != null ? executor.getAsMention() : ale.getUserId()); + + User target = ale.getJDA().getUserById(ale.getTargetId()); + String mentionableTarget = (target != null ? target.getAsMention() : ale.getTargetId()); + + eb.setDescription(MarkdownUtil.quoteBlock("Message Un-Pinned By: " + mentionableExecutor + "\nMessage Author: " + mentionableTarget)); + eb.setColor(Color.MAGENTA); + + eb.addField( + MarkdownUtil.underline("Un-Pinned Message Jump URL"), + MessageUtils.resolveMessageJumpUrlFromId(ale.getOptionByName("channel_id"), ale.getOptionByName("message_id"), event), + false + ); + + eb.setFooter("Audit Log Entry ID: " + ale.getId()); + eb.setTimestamp(ale.getTimeCreated()); + + performChecksThenBuildAndSendEmbed(event, eb, channelIdToSendTo); + } +} diff --git a/src/main/java/io/github/eggy03/papertrail/bot/handlers/auditlog/ModActionEventHandler.java b/src/main/java/io/github/eggy03/papertrail/bot/handlers/auditlog/ModActionEventHandler.java new file mode 100644 index 00000000..8c09146c --- /dev/null +++ b/src/main/java/io/github/eggy03/papertrail/bot/handlers/auditlog/ModActionEventHandler.java @@ -0,0 +1,192 @@ +package io.github.eggy03.papertrail.bot.handlers.auditlog; + +import io.github.eggy03.papertrail.bot.listeners.auditlog.GuildAuditLogEntryCreateEventHandler; +import io.github.eggy03.papertrail.sdk.client.AuditLogRegistrationClient; +import io.github.eggy03.papertrail.sdk.entity.AuditLogRegistrationEntity; +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.inject.Inject; +import lombok.NonNull; +import lombok.extern.slf4j.Slf4j; +import net.dv8tion.jda.api.EmbedBuilder; +import net.dv8tion.jda.api.audit.AuditLogEntry; +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 net.dv8tion.jda.api.utils.MarkdownUtil; +import org.apache.commons.lang3.StringUtils; + +import java.awt.Color; + +@ApplicationScoped +@Slf4j +@SuppressWarnings("java:S1192") +public final class ModActionEventHandler extends GuildAuditLogEntryCreateEventHandler { + + private final @NonNull AuditLogRegistrationClient client; + + @Inject + public ModActionEventHandler(@NonNull AuditLogRegistrationClient client) { + this.client = client; + } + + @NonNull + private String getRegisteredGuildChannel(@NonNull String guildId) { + return client.getRegisteredGuild(guildId) + .map(AuditLogRegistrationEntity::getChannelId).orElse(StringUtils.EMPTY); + + } + + private void performChecksThenBuildAndSendEmbed(@NonNull GuildAuditLogEntryCreateEvent event, @NonNull EmbedBuilder embedBuilder, @NonNull String channelIdToSendTo) { + if (!embedBuilder.isValidLength() || embedBuilder.isEmpty()) { + log.warn("Embed is empty or too long (current length: {}).", embedBuilder.length()); + return; + } + + TextChannel sendingChannel = event.getGuild().getTextChannelById(channelIdToSendTo); + if (sendingChannel != null && sendingChannel.canTalk()) { + sendingChannel.sendMessageEmbeds(embedBuilder.build()).queue(); + } + } + + @Override + public void onKick(@NonNull GuildAuditLogEntryCreateEvent event) { + String channelIdToSendTo = getRegisteredGuildChannel(event.getGuild().getId()); + if (channelIdToSendTo.isBlank()) return; + + AuditLogEntry ale = event.getEntry(); + + User moderator = ale.getJDA().getUserById(ale.getUserIdLong()); + String mentionableModerator = (moderator != null ? moderator.getAsMention() : ale.getUserId()); + String reasonForKick = ale.getReason() == null ? "No Reason Provided" : ale.getReason(); + + // A REST Action is required here because kicked members are not cached + event.getJDA().retrieveUserById(ale.getTargetId()).queue(kickedUser -> { + + String mentionableKickedUser = kickedUser != null ? kickedUser.getAsMention() : ale.getTargetId(); + + EmbedBuilder eb = new EmbedBuilder(); + eb.setTitle("Audit Log Entry | Kick Event"); + eb.setDescription(MarkdownUtil.quoteBlock("A Member Has Been Kicked By: " + mentionableModerator)); + eb.setColor(Color.ORANGE); + + eb.addField(MarkdownUtil.underline("Kicked Member"), "╰┈➤" + mentionableKickedUser, false); + eb.addField(MarkdownUtil.underline("Reason"), "╰┈➤" + reasonForKick, false); + + eb.setFooter("Audit Log Entry ID: " + ale.getId()); + eb.setTimestamp(ale.getTimeCreated()); + + performChecksThenBuildAndSendEmbed(event, eb, channelIdToSendTo); + + }); + } + + @Override + public void onBan(@NonNull GuildAuditLogEntryCreateEvent event) { + String channelIdToSendTo = getRegisteredGuildChannel(event.getGuild().getId()); + if (channelIdToSendTo.isBlank()) return; + + AuditLogEntry ale = event.getEntry(); + + User moderator = ale.getJDA().getUserById(ale.getUserIdLong()); + String mentionableModerator = (moderator != null ? moderator.getAsMention() : ale.getUserId()); + String reasonForBan = ale.getReason() == null ? "No Reason Provided" : ale.getReason(); + + // A REST Action is required here because banned members are not cached + event.getJDA().retrieveUserById(ale.getTargetId()).queue(bannedUser -> { + + String mentionableBannedUser = bannedUser != null ? bannedUser.getAsMention() : ale.getTargetId(); + + EmbedBuilder eb = new EmbedBuilder(); + eb.setTitle("Audit Log Entry | Ban Event"); + eb.setDescription(MarkdownUtil.quoteBlock("A Member Has Been Banned By: " + mentionableModerator)); + eb.setColor(Color.RED); + + eb.addField(MarkdownUtil.underline("Banned Member"), "╰┈➤" + mentionableBannedUser, false); + eb.addField(MarkdownUtil.underline("Ban Reason"), "╰┈➤" + reasonForBan, false); + + eb.setFooter("Audit Log Entry ID: " + ale.getId()); + eb.setTimestamp(ale.getTimeCreated()); + + performChecksThenBuildAndSendEmbed(event, eb, channelIdToSendTo); + }); + } + + @Override + public void onUnban(@NonNull GuildAuditLogEntryCreateEvent event) { + String channelIdToSendTo = getRegisteredGuildChannel(event.getGuild().getId()); + if (channelIdToSendTo.isBlank()) return; + + AuditLogEntry ale = event.getEntry(); + + User moderator = ale.getJDA().getUserById(ale.getUserIdLong()); + String mentionableModerator = (moderator != null ? moderator.getAsMention() : ale.getUserId()); + + event.getJDA().retrieveUserById(ale.getTargetId()).queue(unbannedUser -> { + + String mentionableUnbannedUser = unbannedUser != null ? unbannedUser.getAsMention() : ale.getTargetId(); + + EmbedBuilder eb = new EmbedBuilder(); + eb.setTitle("Audit Log Entry | Member Unban Event"); + eb.setDescription(MarkdownUtil.quoteBlock("A Member Has Been Un-Banned By: " + mentionableModerator)); + eb.setColor(Color.GREEN); + + eb.addField(MarkdownUtil.underline("Un-banned User"), "╰┈➤" + mentionableUnbannedUser, false); + + eb.setFooter("Audit Log Entry ID: " + ale.getId()); + eb.setTimestamp(ale.getTimeCreated()); + + performChecksThenBuildAndSendEmbed(event, eb, channelIdToSendTo); + }); + } + + @Override + public void onBotAdd(@NonNull GuildAuditLogEntryCreateEvent event) { + String channelIdToSendTo = getRegisteredGuildChannel(event.getGuild().getId()); + if (channelIdToSendTo.isBlank()) return; + + AuditLogEntry ale = event.getEntry(); + + User executor = ale.getJDA().getUserById(ale.getUserIdLong()); + String mentionableExecutor = (executor != null ? executor.getAsMention() : ale.getUserId()); + + User target = ale.getJDA().getUserById(ale.getTargetIdLong()); + String mentionableTarget = (target != null ? target.getAsMention() : ale.getTargetId()); + + EmbedBuilder eb = new EmbedBuilder(); + eb.setTitle("Audit Log Entry | Bot Add Event"); + eb.setDescription(MarkdownUtil.quoteBlock("Bot Added By: " + mentionableExecutor + "\nBot ID: " + ale.getTargetId())); + eb.setColor(Color.CYAN); + + eb.addField(MarkdownUtil.underline("Bot Added"), "╰┈➤" + mentionableTarget, false); + + eb.setFooter("Audit Log Entry ID: " + ale.getId()); + eb.setTimestamp(ale.getTimeCreated()); + + performChecksThenBuildAndSendEmbed(event, eb, channelIdToSendTo); + } + + @Override + public void onPrune(@NonNull GuildAuditLogEntryCreateEvent event) { + // I have never seen a prune event trigger yet + log.warn("Prune Event Detected\n{}", event.getEntry().getChanges()); + + String channelIdToSendTo = getRegisteredGuildChannel(event.getGuild().getId()); + if (channelIdToSendTo.isBlank()) return; + + AuditLogEntry ale = event.getEntry(); + + EmbedBuilder eb = new EmbedBuilder(); + eb.setTitle("Audit Log Entry | Prune Event"); + eb.setColor(Color.LIGHT_GRAY); + + String implementationNotice = "We do not have sufficient payload data to log the changes in a PRUNE Event." + .concat(" A proper implementation might happen in future releases"); + + eb.addField("Implementation Notice", MarkdownUtil.codeblock(implementationNotice), false); + + eb.setFooter("Audit Log Entry ID: " + ale.getId()); + eb.setTimestamp(ale.getTimeCreated()); + + performChecksThenBuildAndSendEmbed(event, eb, channelIdToSendTo); + } +} diff --git a/src/main/java/io/github/eggy03/papertrail/bot/listeners/auditlog/helper/onboarding/OnboardingUpdateEventHelper.java b/src/main/java/io/github/eggy03/papertrail/bot/handlers/auditlog/OnboardingEventHandler.java similarity index 50% rename from src/main/java/io/github/eggy03/papertrail/bot/listeners/auditlog/helper/onboarding/OnboardingUpdateEventHelper.java rename to src/main/java/io/github/eggy03/papertrail/bot/handlers/auditlog/OnboardingEventHandler.java index d6392786..476fc1bc 100644 --- a/src/main/java/io/github/eggy03/papertrail/bot/listeners/auditlog/helper/onboarding/OnboardingUpdateEventHelper.java +++ b/src/main/java/io/github/eggy03/papertrail/bot/handlers/auditlog/OnboardingEventHandler.java @@ -1,9 +1,13 @@ -package io.github.eggy03.papertrail.bot.listeners.auditlog.helper.onboarding; +package io.github.eggy03.papertrail.bot.handlers.auditlog; -import io.github.eggy03.papertrail.bot.listeners.auditlog.helper.onboarding.utils.OnboardingUtils; +import io.github.eggy03.papertrail.bot.listeners.auditlog.GuildAuditLogEntryCreateEventHandler; import io.github.eggy03.papertrail.bot.utils.BooleanUtils; +import io.github.eggy03.papertrail.bot.utils.auditlog.OnboardingUtils; +import io.github.eggy03.papertrail.sdk.client.AuditLogRegistrationClient; +import io.github.eggy03.papertrail.sdk.entity.AuditLogRegistrationEntity; +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.inject.Inject; import lombok.NonNull; -import lombok.experimental.UtilityClass; import lombok.extern.slf4j.Slf4j; import net.dv8tion.jda.api.EmbedBuilder; import net.dv8tion.jda.api.audit.AuditLogEntry; @@ -12,14 +16,70 @@ import net.dv8tion.jda.api.entities.channel.concrete.TextChannel; import net.dv8tion.jda.api.events.guild.GuildAuditLogEntryCreateEvent; import net.dv8tion.jda.api.utils.MarkdownUtil; +import org.apache.commons.lang3.StringUtils; import java.awt.Color; -@UtilityClass +@ApplicationScoped @Slf4j -public class OnboardingUpdateEventHelper { +@SuppressWarnings("java:S1192") +public final class OnboardingEventHandler extends GuildAuditLogEntryCreateEventHandler { - public static void format(@NonNull GuildAuditLogEntryCreateEvent event, @NonNull String channelIdToSendTo) { + private final @NonNull AuditLogRegistrationClient client; + + @Inject + public OnboardingEventHandler(@NonNull AuditLogRegistrationClient client) { + this.client = client; + } + + @NonNull + private String getRegisteredGuildChannel(@NonNull String guildId) { + return client.getRegisteredGuild(guildId) + .map(AuditLogRegistrationEntity::getChannelId).orElse(StringUtils.EMPTY); + + } + + private void performChecksThenBuildAndSendEmbed(@NonNull GuildAuditLogEntryCreateEvent event, @NonNull EmbedBuilder embedBuilder, @NonNull String channelIdToSendTo) { + if (!embedBuilder.isValidLength() || embedBuilder.isEmpty()) { + log.warn("Embed is empty or too long (current length: {}).", embedBuilder.length()); + return; + } + + TextChannel sendingChannel = event.getGuild().getTextChannelById(channelIdToSendTo); + if (sendingChannel != null && sendingChannel.canTalk()) { + sendingChannel.sendMessageEmbeds(embedBuilder.build()).queue(); + } + } + + @Override + public void onOnboardingCreate(@NonNull GuildAuditLogEntryCreateEvent event) { + log.warn("Onboarding Create Event Detected. Implement this sometime later\n{}", event.getEntry().getChanges()); + + String channelIdToSendTo = getRegisteredGuildChannel(event.getGuild().getId()); + if (channelIdToSendTo.isBlank()) return; + + AuditLogEntry ale = event.getEntry(); + + EmbedBuilder eb = new EmbedBuilder(); + eb.setTitle("Audit Log Entry | Onboarding Create Event"); + eb.setColor(Color.LIGHT_GRAY); + + String implementationNotice = "We do not have sufficient data to log the changes in an ONBOARDING_CREATE Event." + .concat(" That is because, even for Onboarding creations, ONBOARDING_UPDATE is fired instead.") + .concat(" A proper implementation might happen in future releases if such an event is fired consistently."); + + eb.addField("Implementation Notice", MarkdownUtil.codeblock(implementationNotice), false); + + eb.setFooter("Audit Log Entry ID: " + ale.getId()); + eb.setTimestamp(ale.getTimeCreated()); + + performChecksThenBuildAndSendEmbed(event, eb, channelIdToSendTo); + } + + @Override + public void onOnboardingUpdate(@NonNull GuildAuditLogEntryCreateEvent event) { + String channelIdToSendTo = getRegisteredGuildChannel(event.getGuild().getId()); + if (channelIdToSendTo.isBlank()) return; AuditLogEntry ale = event.getEntry(); @@ -63,7 +123,7 @@ public static void format(@NonNull GuildAuditLogEntryCreateEvent event, @NonNull default -> { eb.addField("Unimplemented Change Key", changeKey, false); - log.info("Unimplemented Change Key: {}\nOLD_VALUE: {}\nNEW_VALUE: {}", changeKey, oldValue, newValue); + log.info("Unimplemented Change Key on Onboarding Update: {}\nOLD_VALUE: {}\nNEW_VALUE: {}", changeKey, oldValue, newValue); } } @@ -72,14 +132,6 @@ public static void format(@NonNull GuildAuditLogEntryCreateEvent event, @NonNull eb.setFooter("Audit Log Entry ID: " + ale.getId()); eb.setTimestamp(ale.getTimeCreated()); - if (!eb.isValidLength() || eb.isEmpty()) { - log.warn("Embed is empty or too long (current length: {}).", eb.length()); - return; - } - - TextChannel sendingChannel = event.getGuild().getTextChannelById(channelIdToSendTo); - if (sendingChannel != null && sendingChannel.canTalk()) { - sendingChannel.sendMessageEmbeds(eb.build()).queue(); - } + performChecksThenBuildAndSendEmbed(event, eb, channelIdToSendTo); } } diff --git a/src/main/java/io/github/eggy03/papertrail/bot/handlers/auditlog/OnboardingPromptEventHandler.java b/src/main/java/io/github/eggy03/papertrail/bot/handlers/auditlog/OnboardingPromptEventHandler.java new file mode 100644 index 00000000..26297420 --- /dev/null +++ b/src/main/java/io/github/eggy03/papertrail/bot/handlers/auditlog/OnboardingPromptEventHandler.java @@ -0,0 +1,217 @@ +package io.github.eggy03.papertrail.bot.handlers.auditlog; + +import io.github.eggy03.papertrail.bot.listeners.auditlog.GuildAuditLogEntryCreateEventHandler; +import io.github.eggy03.papertrail.bot.utils.BooleanUtils; +import io.github.eggy03.papertrail.sdk.client.AuditLogRegistrationClient; +import io.github.eggy03.papertrail.sdk.entity.AuditLogRegistrationEntity; +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.inject.Inject; +import lombok.NonNull; +import lombok.extern.slf4j.Slf4j; +import net.dv8tion.jda.api.EmbedBuilder; +import net.dv8tion.jda.api.audit.AuditLogEntry; +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 net.dv8tion.jda.api.utils.MarkdownUtil; +import org.apache.commons.lang3.StringUtils; + +import java.awt.Color; + +@ApplicationScoped +@Slf4j +@SuppressWarnings("java:S1192") +public final class OnboardingPromptEventHandler extends GuildAuditLogEntryCreateEventHandler { + + private final @NonNull AuditLogRegistrationClient client; + + @Inject + public OnboardingPromptEventHandler(@NonNull AuditLogRegistrationClient client) { + this.client = client; + } + + @NonNull + private String getRegisteredGuildChannel(@NonNull String guildId) { + return client.getRegisteredGuild(guildId) + .map(AuditLogRegistrationEntity::getChannelId).orElse(StringUtils.EMPTY); + + } + + private void performChecksThenBuildAndSendEmbed(@NonNull GuildAuditLogEntryCreateEvent event, @NonNull EmbedBuilder embedBuilder, @NonNull String channelIdToSendTo) { + if (!embedBuilder.isValidLength() || embedBuilder.isEmpty()) { + log.warn("Embed is empty or too long (current length: {}).", embedBuilder.length()); + return; + } + + TextChannel sendingChannel = event.getGuild().getTextChannelById(channelIdToSendTo); + if (sendingChannel != null && sendingChannel.canTalk()) { + sendingChannel.sendMessageEmbeds(embedBuilder.build()).queue(); + } + } + + @Override + public void onOnboardingPromptCreate(@NonNull GuildAuditLogEntryCreateEvent event) { + String channelIdToSendTo = getRegisteredGuildChannel(event.getGuild().getId()); + if (channelIdToSendTo.isBlank()) return; + + 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(MarkdownUtil.quoteBlock("Onboarding Prompt Created By: " + mentionableExecutor)); + eb.setColor(Color.GREEN); + + ale.getChanges().forEach((changeKey, changeValue) -> { + + Object oldValue = changeValue.getOldValue(); + Object newValue = changeValue.getNewValue(); + + switch (changeKey) { + case "single_select" -> + eb.addField(MarkdownUtil.underline("Single Selection Mode"), BooleanUtils.formatToYesOrNo(newValue), false); + + case "required" -> + eb.addField(MarkdownUtil.underline("Is Required"), BooleanUtils.formatToYesOrNo(newValue), false); + + case "type", "id" -> { + // skip + } + + case "title" -> eb.addField(MarkdownUtil.underline("Question Title"), String.valueOf(newValue), false); + + case "options" -> + eb.addField(MarkdownUtil.underline("Question Options"), "Review the options in Onboarding Settings", false); + + case "in_onboarding" -> + eb.addField(MarkdownUtil.underline("Is a Pre-Join Question"), BooleanUtils.formatToYesOrNo(newValue), false); + + default -> { + eb.addField("Unimplemented Change Key", changeKey, false); + log.info("Unimplemented Change Key on Onboarding Prompt Create: {}\nOLD_VALUE: {}\nNEW_VALUE: {}", changeKey, oldValue, newValue); + } + } + + }); + + eb.setFooter("Audit Log Entry ID: " + ale.getId()); + eb.setTimestamp(ale.getTimeCreated()); + + performChecksThenBuildAndSendEmbed(event, eb, channelIdToSendTo); + } + + @Override + public void onOnboardingPromptUpdate(@NonNull GuildAuditLogEntryCreateEvent event) { + String channelIdToSendTo = getRegisteredGuildChannel(event.getGuild().getId()); + if (channelIdToSendTo.isBlank()) return; + + 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(MarkdownUtil.quoteBlock("Onboarding Prompt Updated By: " + mentionableExecutor)); + eb.setColor(Color.YELLOW); + + ale.getChanges().forEach((changeKey, changeValue) -> { + + Object oldValue = changeValue.getOldValue(); + Object newValue = changeValue.getNewValue(); + + switch (changeKey) { + case "single_select" -> { + eb.addField(MarkdownUtil.underline("Old Single Selection Mode"), BooleanUtils.formatToYesOrNo(oldValue), false); + eb.addField(MarkdownUtil.underline("New Single Selection Mode"), BooleanUtils.formatToYesOrNo(newValue), false); + } + + case "required" -> { + eb.addField(MarkdownUtil.underline("Was Required"), BooleanUtils.formatToYesOrNo(oldValue), false); + eb.addField(MarkdownUtil.underline("Is Required"), BooleanUtils.formatToYesOrNo(newValue), false); + } + + case "type", "id" -> { + // skip + } + + case "title" -> { + eb.addField(MarkdownUtil.underline("Old Question Title"), String.valueOf(oldValue), false); + eb.addField(MarkdownUtil.underline("New Question Title"), String.valueOf(newValue), false); + } + + case "options" -> + eb.addField(MarkdownUtil.underline("Question Options"), "Review the changed options in Onboarding Settings", false); + + case "in_onboarding" -> { + eb.addField(MarkdownUtil.underline("Was a Pre-Join Question"), BooleanUtils.formatToYesOrNo(oldValue), false); + eb.addField(MarkdownUtil.underline("Is a Pre-Join Question"), BooleanUtils.formatToYesOrNo(newValue), false); + } + + default -> { + eb.addField("Unimplemented Change Key", changeKey, false); + log.info("Unimplemented Change Key on Onboarding Prompt Update: {}\nOLD_VALUE: {}\nNEW_VALUE: {}", changeKey, oldValue, newValue); + } + } + }); + + eb.setFooter("Audit Log Entry ID: " + ale.getId()); + eb.setTimestamp(ale.getTimeCreated()); + + performChecksThenBuildAndSendEmbed(event, eb, channelIdToSendTo); + } + + @Override + public void onOnboardingPromptDelete(@NonNull GuildAuditLogEntryCreateEvent event) { + String channelIdToSendTo = getRegisteredGuildChannel(event.getGuild().getId()); + if (channelIdToSendTo.isBlank()) return; + + 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(MarkdownUtil.quoteBlock("Onboarding Prompt Deleted By: " + mentionableExecutor)); + eb.setColor(Color.RED); + + ale.getChanges().forEach((changeKey, changeValue) -> { + + Object oldValue = changeValue.getOldValue(); + Object newValue = changeValue.getNewValue(); + + switch (changeKey) { + + case "single_select" -> + eb.addField(MarkdownUtil.underline("Single Selection Mode"), BooleanUtils.formatToYesOrNo(oldValue), false); + + case "required" -> + eb.addField(MarkdownUtil.underline("Was Required"), BooleanUtils.formatToYesOrNo(oldValue), false); + + case "type", "id", "options" -> { + // skip + } + case "title" -> eb.addField(MarkdownUtil.underline("Question Title"), String.valueOf(oldValue), false); + + case "in_onboarding" -> + eb.addField(MarkdownUtil.underline("Was a Pre-Join Question"), BooleanUtils.formatToYesOrNo(oldValue), false); + + default -> { + eb.addField("Unimplemented Change Key", changeKey, false); + log.info("Unimplemented Change Key on Onboarding Prompt Delete: {}\nOLD_VALUE: {}\nNEW_VALUE: {}", changeKey, oldValue, newValue); + } + } + }); + + eb.setFooter("Audit Log Entry ID: " + ale.getId()); + eb.setTimestamp(ale.getTimeCreated()); + + performChecksThenBuildAndSendEmbed(event, eb, channelIdToSendTo); + } +} diff --git a/src/main/java/io/github/eggy03/papertrail/bot/handlers/auditlog/RoleEventHandler.java b/src/main/java/io/github/eggy03/papertrail/bot/handlers/auditlog/RoleEventHandler.java new file mode 100644 index 00000000..1a6fe691 --- /dev/null +++ b/src/main/java/io/github/eggy03/papertrail/bot/handlers/auditlog/RoleEventHandler.java @@ -0,0 +1,226 @@ +package io.github.eggy03.papertrail.bot.handlers.auditlog; + +import io.github.eggy03.papertrail.bot.listeners.auditlog.GuildAuditLogEntryCreateEventHandler; +import io.github.eggy03.papertrail.bot.utils.BooleanUtils; +import io.github.eggy03.papertrail.bot.utils.auditlog.RoleUtils; +import io.github.eggy03.papertrail.sdk.client.AuditLogRegistrationClient; +import io.github.eggy03.papertrail.sdk.entity.AuditLogRegistrationEntity; +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.inject.Inject; +import lombok.NonNull; +import lombok.extern.slf4j.Slf4j; +import net.dv8tion.jda.api.EmbedBuilder; +import net.dv8tion.jda.api.audit.AuditLogEntry; +import net.dv8tion.jda.api.entities.Role; +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 net.dv8tion.jda.api.utils.MarkdownUtil; +import org.apache.commons.lang3.StringUtils; + +import java.awt.Color; + +@ApplicationScoped +@Slf4j +@SuppressWarnings("java:S1192") +public final class RoleEventHandler extends GuildAuditLogEntryCreateEventHandler { + + private final @NonNull AuditLogRegistrationClient client; + + @Inject + public RoleEventHandler(@NonNull AuditLogRegistrationClient client) { + this.client = client; + } + + @NonNull + private String getRegisteredGuildChannel(@NonNull String guildId) { + return client.getRegisteredGuild(guildId) + .map(AuditLogRegistrationEntity::getChannelId).orElse(StringUtils.EMPTY); + + } + + private void performChecksThenBuildAndSendEmbed(@NonNull GuildAuditLogEntryCreateEvent event, @NonNull EmbedBuilder embedBuilder, @NonNull String channelIdToSendTo) { + if (!embedBuilder.isValidLength() || embedBuilder.isEmpty()) { + log.warn("Embed is empty or too long (current length: {}).", embedBuilder.length()); + return; + } + + TextChannel sendingChannel = event.getGuild().getTextChannelById(channelIdToSendTo); + if (sendingChannel != null && sendingChannel.canTalk()) { + sendingChannel.sendMessageEmbeds(embedBuilder.build()).queue(); + } + } + + @Override + public void onRoleCreate(@NonNull GuildAuditLogEntryCreateEvent event) { + String channelIdToSendTo = getRegisteredGuildChannel(event.getGuild().getId()); + if (channelIdToSendTo.isBlank()) return; + + AuditLogEntry ale = event.getEntry(); + + User executor = ale.getJDA().getUserById(ale.getUserId()); + String mentionableExecutor = (executor != null ? executor.getAsMention() : ale.getUserId()); + + Role targetRole = ale.getJDA().getRoleById(ale.getTargetId()); + String mentionableTargetRole = (targetRole != null ? targetRole.getAsMention() : ale.getTargetId()); + + EmbedBuilder eb = new EmbedBuilder(); + eb.setTitle("Audit Log Entry | Role Create Event"); + eb.setDescription(MarkdownUtil.quoteBlock("Role Created By: " + mentionableExecutor + "\nTarget Role: " + mentionableTargetRole)); + eb.setColor(Color.GREEN); + + ale.getChanges().forEach((changeKey, changeValue) -> { + + Object oldValue = changeValue.getOldValue(); + Object newValue = changeValue.getNewValue(); + + switch (changeKey) { + + case "name" -> eb.addField(MarkdownUtil.underline("Role Name"), "╰┈➤" + newValue, false); + + case "colors", "hoist", "color", "permissions", "mentionable" -> { + /* discord for some reason shows the following to be default/null even + * when you set them during the creation of the role itself + * and delegates them to ROLE_UPDATE event + */ + } + default -> { + eb.addField("Unimplemented Change Key", changeKey, false); + log.info("Unimplemented Change Key on Role Create: {}\nOLD_VALUE: {}\nNEW_VALUE: {}", changeKey, oldValue, newValue); + } + } + }); + + eb.setFooter("Audit Log Entry ID: " + ale.getId()); + eb.setTimestamp(ale.getTimeCreated()); + + performChecksThenBuildAndSendEmbed(event, eb, channelIdToSendTo); + } + + @Override + public void onRoleUpdate(@NonNull GuildAuditLogEntryCreateEvent event) { + String channelIdToSendTo = getRegisteredGuildChannel(event.getGuild().getId()); + if (channelIdToSendTo.isBlank()) return; + + AuditLogEntry ale = event.getEntry(); + + User executor = ale.getJDA().getUserById(ale.getUserId()); + String mentionableExecutor = (executor != null ? executor.getAsMention() : ale.getUserId()); + + Role targetRole = ale.getJDA().getRoleById(ale.getTargetId()); + String mentionableTargetRole = (targetRole != null ? targetRole.getAsMention() : ale.getTargetId()); + + EmbedBuilder eb = new EmbedBuilder(); + eb.setTitle("Audit Log Entry | Role Update Event"); + eb.setDescription(MarkdownUtil.quoteBlock("Role Updated By: " + mentionableExecutor + "\nTarget Role: " + mentionableTargetRole)); + eb.setColor(Color.YELLOW); + + ale.getChanges().forEach((changeKey, changeValue) -> { + + Object oldValue = changeValue.getOldValue(); + Object newValue = changeValue.getNewValue(); + + switch (changeKey) { + + case "name" -> { + eb.addField(MarkdownUtil.underline("Old Role Name"), "╰┈➤" + oldValue, true); + eb.addField(MarkdownUtil.underline("New Role Name"), "╰┈➤" + newValue, true); + eb.addBlankField(true); + } + + case "hoist" -> { + eb.addField(MarkdownUtil.underline("Old Display Separately"), "╰┈➤" + BooleanUtils.formatToYesOrNo(oldValue), true); + eb.addField(MarkdownUtil.underline("New Display Separately"), "╰┈➤" + BooleanUtils.formatToYesOrNo(newValue), true); + eb.addBlankField(true); + } + + case "color" -> { + eb.addField(MarkdownUtil.underline("Old Color"), "╰┈➤" + RoleUtils.formatToHex(oldValue), true); + eb.addField(MarkdownUtil.underline("New Color"), "╰┈➤" + RoleUtils.formatToHex(newValue), true); + eb.addBlankField(true); + } + + case "permissions" -> { + eb.addField(MarkdownUtil.underline("Old Role Permissions"), RoleUtils.resolveRolePermissions(oldValue, "✅"), true); + eb.addField(MarkdownUtil.underline("New Role Permissions"), RoleUtils.resolveRolePermissions(newValue, "✅"), true); + eb.addBlankField(true); + } + + case "mentionable" -> { + eb.addField(MarkdownUtil.underline("Old Mentionable"), "╰┈➤" + BooleanUtils.formatToYesOrNo(oldValue), true); + eb.addField(MarkdownUtil.underline("New Mentionable"), "╰┈➤" + BooleanUtils.formatToYesOrNo(newValue), true); + eb.addBlankField(true); + } + + case "colors" -> { + eb.addField(MarkdownUtil.underline("Old Gradient Color System"), RoleUtils.formatGradientToHex(oldValue), true); + eb.addField(MarkdownUtil.underline("New Gradient Color System"), RoleUtils.formatGradientToHex(newValue), true); + eb.addBlankField(true); + } + + default -> { + eb.addField("Unimplemented Change Key", changeKey, false); + log.info("Unimplemented Change Key on Role Update: {}\nOLD_VALUE: {}\nNEW_VALUE: {}", changeKey, oldValue, newValue); + } + + } + }); + + eb.setFooter("Audit Log Entry ID: " + ale.getId()); + eb.setTimestamp(ale.getTimeCreated()); + + performChecksThenBuildAndSendEmbed(event, eb, channelIdToSendTo); + } + + @Override + public void onRoleDelete(@NonNull GuildAuditLogEntryCreateEvent event) { + String channelIdToSendTo = getRegisteredGuildChannel(event.getGuild().getId()); + if (channelIdToSendTo.isBlank()) return; + + AuditLogEntry ale = event.getEntry(); + + User executor = ale.getJDA().getUserById(ale.getUserId()); + String mentionableExecutor = (executor != null ? executor.getAsMention() : ale.getUserId()); + + EmbedBuilder eb = new EmbedBuilder(); + eb.setTitle("Audit Log Entry | Role Delete Event"); + eb.setDescription(MarkdownUtil.quoteBlock("Role Deleted By: " + mentionableExecutor + "\nTarget Role ID: " + ale.getTargetId())); + eb.setColor(Color.RED); + + ale.getChanges().forEach((changeKey, changeValue) -> { + Object oldValue = changeValue.getOldValue(); + Object newValue = changeValue.getNewValue(); + + switch (changeKey) { + + case "name" -> eb.addField(MarkdownUtil.underline("Role Name"), "╰┈➤" + oldValue, false); + + case "hoist" -> + eb.addField(MarkdownUtil.underline("Display Separately"), "╰┈➤" + BooleanUtils.formatToYesOrNo(oldValue), false); + + case "color" -> + eb.addField(MarkdownUtil.underline("Color"), "╰┈➤" + RoleUtils.formatToHex(oldValue), false); + + case "permissions" -> + eb.addField(MarkdownUtil.underline("Role Permissions"), RoleUtils.resolveRolePermissions(oldValue, "✅"), false); + + case "mentionable" -> + eb.addField(MarkdownUtil.underline("Mentionable"), "╰┈➤" + BooleanUtils.formatToYesOrNo(oldValue), false); + + case "colors" -> + eb.addField(MarkdownUtil.underline("Gradient Color System"), RoleUtils.formatGradientToHex(oldValue), false); + + default -> { + eb.addField("Unimplemented Change Key", changeKey, false); + log.info("Unimplemented Change Key on Role Delete: {}\nOLD_VALUE: {}\nNEW_VALUE: {}", changeKey, oldValue, newValue); + } + } + + }); + + eb.setFooter("Audit Log Entry ID: " + ale.getId()); + eb.setTimestamp(ale.getTimeCreated()); + + performChecksThenBuildAndSendEmbed(event, eb, channelIdToSendTo); + } +} diff --git a/src/main/java/io/github/eggy03/papertrail/bot/handlers/auditlog/ScheduledEventHandler.java b/src/main/java/io/github/eggy03/papertrail/bot/handlers/auditlog/ScheduledEventHandler.java new file mode 100644 index 00000000..aecda5c0 --- /dev/null +++ b/src/main/java/io/github/eggy03/papertrail/bot/handlers/auditlog/ScheduledEventHandler.java @@ -0,0 +1,206 @@ +package io.github.eggy03.papertrail.bot.handlers.auditlog; + +import io.github.eggy03.papertrail.bot.listeners.auditlog.GuildAuditLogEntryCreateEventHandler; +import io.github.eggy03.papertrail.bot.utils.auditlog.ScheduledEventUtils; +import io.github.eggy03.papertrail.sdk.client.AuditLogRegistrationClient; +import io.github.eggy03.papertrail.sdk.entity.AuditLogRegistrationEntity; +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.inject.Inject; +import lombok.NonNull; +import lombok.extern.slf4j.Slf4j; +import net.dv8tion.jda.api.EmbedBuilder; +import net.dv8tion.jda.api.audit.AuditLogEntry; +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 net.dv8tion.jda.api.utils.MarkdownUtil; +import org.apache.commons.lang3.StringUtils; + +import java.awt.Color; + +@ApplicationScoped +@Slf4j +@SuppressWarnings("java:S1192") +public final class ScheduledEventHandler extends GuildAuditLogEntryCreateEventHandler { + + private final @NonNull AuditLogRegistrationClient client; + + @Inject + public ScheduledEventHandler(@NonNull AuditLogRegistrationClient client) { + this.client = client; + } + + @NonNull + private String getRegisteredGuildChannel(@NonNull String guildId) { + return client.getRegisteredGuild(guildId) + .map(AuditLogRegistrationEntity::getChannelId).orElse(StringUtils.EMPTY); + + } + + private void performChecksThenBuildAndSendEmbed(@NonNull GuildAuditLogEntryCreateEvent event, @NonNull EmbedBuilder embedBuilder, @NonNull String channelIdToSendTo) { + if (!embedBuilder.isValidLength() || embedBuilder.isEmpty()) { + log.warn("Embed is empty or too long (current length: {}).", embedBuilder.length()); + return; + } + + TextChannel sendingChannel = event.getGuild().getTextChannelById(channelIdToSendTo); + if (sendingChannel != null && sendingChannel.canTalk()) { + sendingChannel.sendMessageEmbeds(embedBuilder.build()).queue(); + } + } + + @Override + public void onScheduledEventCreate(@NonNull GuildAuditLogEntryCreateEvent event) { + String channelIdToSendTo = getRegisteredGuildChannel(event.getGuild().getId()); + if (channelIdToSendTo.isBlank()) return; + + AuditLogEntry ale = event.getEntry(); + + User executor = ale.getJDA().getUserById(ale.getUserIdLong()); + String mentionableExecutor = (executor != null ? executor.getAsMention() : ale.getUserId()); + + EmbedBuilder eb = new EmbedBuilder(); + eb.setTitle("Audit Log Entry | Scheduled Event Create Event"); + eb.setDescription(MarkdownUtil.quoteBlock("Scheduled Event Created By: " + mentionableExecutor)); + eb.setColor(Color.GREEN); + + ale.getChanges().forEach((changeKey, changeValue) -> { + Object oldValue = changeValue.getOldValue(); + Object newValue = changeValue.getNewValue(); + + switch (changeKey) { + case "entity_type" -> + eb.addField(MarkdownUtil.underline("Event Type"), "╰┈➤" + ScheduledEventUtils.resolveEventType(newValue), false); + case "name" -> eb.addField(MarkdownUtil.underline("Event Name"), "╰┈➤" + newValue, false); + case "description" -> eb.addField(MarkdownUtil.underline("Event Description"), "╰┈➤" + newValue, false); + case "status" -> + eb.addField(MarkdownUtil.underline("Event Status"), "╰┈➤" + ScheduledEventUtils.resolveStatusType(newValue), false); + case "location" -> eb.addField(MarkdownUtil.underline("Event Location"), "╰┈➤" + newValue, false); + case "privacy_level", "image_hash", "channel_id", "recurrence_rule" -> { + // skip + } + default -> { + eb.addField("Unimplemented Change Key", changeKey, false); + log.info("Unimplemented Change Key on Scheduled Event Create: {}\nOLD_VALUE: {}\nNEW_VALUE: {}", changeKey, oldValue, newValue); + } + } + }); + + eb.setFooter("Audit Log Entry ID: " + ale.getId()); + eb.setTimestamp(ale.getTimeCreated()); + + + performChecksThenBuildAndSendEmbed(event, eb, channelIdToSendTo); + } + + @Override + public void onScheduledEventUpdate(@NonNull GuildAuditLogEntryCreateEvent event) { + String channelIdToSendTo = getRegisteredGuildChannel(event.getGuild().getId()); + if (channelIdToSendTo.isBlank()) return; + + AuditLogEntry ale = event.getEntry(); + + User executor = ale.getJDA().getUserById(ale.getUserIdLong()); + String mentionableExecutor = (executor != null ? executor.getAsMention() : ale.getUserId()); + + EmbedBuilder eb = new EmbedBuilder(); + eb.setTitle("Audit Log Entry | Scheduled Event Update Event"); + eb.setDescription(MarkdownUtil.quoteBlock("Scheduled Event Updated By: " + mentionableExecutor)); + eb.setColor(Color.YELLOW); + + ale.getChanges().forEach((changeKey, changeValue) -> { + Object oldValue = changeValue.getOldValue(); + Object newValue = changeValue.getNewValue(); + + switch (changeKey) { + case "entity_type" -> { + eb.addField(MarkdownUtil.underline("Old Event Type"), "╰┈➤" + ScheduledEventUtils.resolveEventType(oldValue), true); + eb.addField(MarkdownUtil.underline("New Event Type"), "╰┈➤" + ScheduledEventUtils.resolveEventType(newValue), true); + eb.addBlankField(true); + } + case "name" -> { + eb.addField(MarkdownUtil.underline("Old Event Name"), "╰┈➤" + oldValue, true); + eb.addField(MarkdownUtil.underline("New Event Name"), "╰┈➤" + newValue, true); + eb.addBlankField(true); + } + case "description" -> { + eb.addField(MarkdownUtil.underline("Old Event Description"), "╰┈➤" + oldValue, true); + eb.addField(MarkdownUtil.underline("New Event Description"), "╰┈➤" + newValue, true); + eb.addBlankField(true); + } + case "status" -> { + eb.addField(MarkdownUtil.underline("Old Event Status"), "╰┈➤" + ScheduledEventUtils.resolveStatusType(oldValue), true); + eb.addField(MarkdownUtil.underline("New Event Status"), "╰┈➤" + ScheduledEventUtils.resolveStatusType(newValue), true); + eb.addBlankField(true); + } + case "location" -> { + eb.addField(MarkdownUtil.underline("Event Location"), "╰┈➤" + oldValue, true); + eb.addField(MarkdownUtil.underline("Event Location"), "╰┈➤" + newValue, true); + eb.addBlankField(true); + } + case "privacy_level" -> + eb.addField(MarkdownUtil.underline("Privacy"), "╰┈➤Event privacy has been updated", false); + case "image_hash" -> + eb.addField(MarkdownUtil.underline("Image"), "╰┈➤Event Image has been updated", false); + case "channel_id" -> + eb.addField(MarkdownUtil.underline("Channel"), "╰┈➤Event Channel has been updated", false); + case "recurrence_rule" -> + eb.addField(MarkdownUtil.underline("Recurrence Rule"), "╰┈➤Recurrence Rule has been updated", false); + + default -> { + eb.addField("Unimplemented Change Key", changeKey, false); + log.info("Unimplemented Change Key on Scheduled Event Update: {}\nOLD_VALUE: {}\nNEW_VALUE: {}", changeKey, oldValue, newValue); + } + } + }); + + eb.setFooter("Audit Log Entry ID: " + ale.getId()); + eb.setTimestamp(ale.getTimeCreated()); + + + performChecksThenBuildAndSendEmbed(event, eb, channelIdToSendTo); + } + + @Override + public void onScheduledEventDelete(@NonNull GuildAuditLogEntryCreateEvent event) { + String channelIdToSendTo = getRegisteredGuildChannel(event.getGuild().getId()); + if (channelIdToSendTo.isBlank()) return; + + AuditLogEntry ale = event.getEntry(); + + User executor = ale.getJDA().getUserById(ale.getUserIdLong()); + String mentionableExecutor = (executor != null ? executor.getAsMention() : ale.getUserId()); + + EmbedBuilder eb = new EmbedBuilder(); + eb.setTitle("Audit Log Entry | Scheduled Event Delete Event"); + eb.setDescription(MarkdownUtil.quoteBlock("Scheduled Event Deleted By: " + mentionableExecutor)); + eb.setColor(Color.RED); + + ale.getChanges().forEach((changeKey, changeValue) -> { + Object oldValue = changeValue.getOldValue(); + Object newValue = changeValue.getNewValue(); + + switch (changeKey) { + case "entity_type" -> + eb.addField(MarkdownUtil.underline("Event Type"), "╰┈➤" + ScheduledEventUtils.resolveEventType(oldValue), false); + case "name" -> eb.addField(MarkdownUtil.underline("Event Name"), "╰┈➤" + oldValue, false); + case "description" -> eb.addField(MarkdownUtil.underline("Event Description"), "╰┈➤" + oldValue, false); + case "status" -> + eb.addField(MarkdownUtil.underline("Event Status"), "╰┈➤" + ScheduledEventUtils.resolveStatusType(oldValue), false); + case "location" -> eb.addField(MarkdownUtil.underline("Event Location"), "╰┈➤" + oldValue, false); + case "privacy_level", "image_hash", "channel_id", "recurrence_rule" -> { + // skip + } + default -> { + eb.addField("Unimplemented Change Key", changeKey, false); + log.info("Unimplemented Change Key on Scheduled Event Delete: {}\nOLD_VALUE: {}\nNEW_VALUE: {}", changeKey, oldValue, newValue); + } + } + }); + + eb.setFooter("Audit Log Entry ID: " + ale.getId()); + eb.setTimestamp(ale.getTimeCreated()); + + performChecksThenBuildAndSendEmbed(event, eb, channelIdToSendTo); + } +} diff --git a/src/main/java/io/github/eggy03/papertrail/bot/handlers/auditlog/SoundboardEventHandler.java b/src/main/java/io/github/eggy03/papertrail/bot/handlers/auditlog/SoundboardEventHandler.java new file mode 100644 index 00000000..e12fee84 --- /dev/null +++ b/src/main/java/io/github/eggy03/papertrail/bot/handlers/auditlog/SoundboardEventHandler.java @@ -0,0 +1,201 @@ +package io.github.eggy03.papertrail.bot.handlers.auditlog; + +import io.github.eggy03.papertrail.bot.listeners.auditlog.GuildAuditLogEntryCreateEventHandler; +import io.github.eggy03.papertrail.bot.utils.auditlog.SoundboardUtils; +import io.github.eggy03.papertrail.sdk.client.AuditLogRegistrationClient; +import io.github.eggy03.papertrail.sdk.entity.AuditLogRegistrationEntity; +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.inject.Inject; +import lombok.NonNull; +import lombok.extern.slf4j.Slf4j; +import net.dv8tion.jda.api.EmbedBuilder; +import net.dv8tion.jda.api.audit.AuditLogEntry; +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 net.dv8tion.jda.api.utils.MarkdownUtil; +import org.apache.commons.lang3.StringUtils; + +import java.awt.Color; + +@ApplicationScoped +@Slf4j +@SuppressWarnings("java:S1192") +public final class SoundboardEventHandler extends GuildAuditLogEntryCreateEventHandler { + + private final @NonNull AuditLogRegistrationClient client; + + @Inject + public SoundboardEventHandler(@NonNull AuditLogRegistrationClient client) { + this.client = client; + } + + @NonNull + private String getRegisteredGuildChannel(@NonNull String guildId) { + return client.getRegisteredGuild(guildId) + .map(AuditLogRegistrationEntity::getChannelId).orElse(StringUtils.EMPTY); + + } + + private void performChecksThenBuildAndSendEmbed(@NonNull GuildAuditLogEntryCreateEvent event, @NonNull EmbedBuilder embedBuilder, @NonNull String channelIdToSendTo) { + if (!embedBuilder.isValidLength() || embedBuilder.isEmpty()) { + log.warn("Embed is empty or too long (current length: {}).", embedBuilder.length()); + return; + } + + TextChannel sendingChannel = event.getGuild().getTextChannelById(channelIdToSendTo); + if (sendingChannel != null && sendingChannel.canTalk()) { + sendingChannel.sendMessageEmbeds(embedBuilder.build()).queue(); + } + } + + @Override + public void onSoundboardSoundCreate(@NonNull GuildAuditLogEntryCreateEvent event) { + String channelIdToSendTo = getRegisteredGuildChannel(event.getGuild().getId()); + if (channelIdToSendTo.isBlank()) return; + + AuditLogEntry ale = event.getEntry(); + + User executor = ale.getJDA().getUserById(ale.getUserIdLong()); + String mentionableExecutor = (executor != null ? executor.getAsMention() : ale.getUserId()); + + EmbedBuilder eb = new EmbedBuilder(); + eb.setTitle("Audit Log Entry | Soundboard Sound Create Event"); + eb.setDescription(MarkdownUtil.quoteBlock("Sound Item Added By: " + mentionableExecutor)); + eb.setColor(Color.GREEN); + + ale.getChanges().forEach((changeKey, changeValue) -> { + + Object oldValue = changeValue.getOldValue(); + Object newValue = changeValue.getNewValue(); + + switch (changeKey) { + + case "user_id", "sound_id", "id", "guild_id", "available" -> { + // skip + } + case "volume" -> + eb.addField(MarkdownUtil.underline("Volume"), "╰┈➤" + SoundboardUtils.resolveVolumePercentage(newValue), false); + + case "emoji_name" -> eb.addField(MarkdownUtil.underline("Related Emoji"), "╰┈➤" + newValue, false); + + case "emoji_id" -> eb.addField(MarkdownUtil.underline("Related Emoji ID"), "╰┈➤" + newValue, false); + + case "name" -> eb.addField(MarkdownUtil.underline("Sound Item Name"), "╰┈➤" + newValue, false); + + default -> { + eb.addField("Unimplemented Change Key", changeKey, false); + log.info("Unimplemented Change Key on Soundboard Sound Create: {}\nOLD_VALUE: {}\nNEW_VALUE: {}", changeKey, oldValue, newValue); + } + } + }); + + eb.setFooter("Audit Log Entry ID: " + ale.getId()); + eb.setTimestamp(ale.getTimeCreated()); + + performChecksThenBuildAndSendEmbed(event, eb, channelIdToSendTo); + } + + @Override + public void onSoundboardSoundUpdate(@NonNull GuildAuditLogEntryCreateEvent event) { + String channelIdToSendTo = getRegisteredGuildChannel(event.getGuild().getId()); + if (channelIdToSendTo.isBlank()) return; + + AuditLogEntry ale = event.getEntry(); + + User executor = ale.getJDA().getUserById(ale.getUserIdLong()); + String mentionableExecutor = (executor != null ? executor.getAsMention() : ale.getUserId()); + + EmbedBuilder eb = new EmbedBuilder(); + eb.setTitle("Audit Log Entry | Soundboard Sound Update Event"); + eb.setDescription(MarkdownUtil.quoteBlock("Sound Item Updated By: " + mentionableExecutor)); + eb.setColor(Color.YELLOW); + + ale.getChanges().forEach((changeKey, changeValue) -> { + Object oldValue = changeValue.getOldValue(); + Object newValue = changeValue.getNewValue(); + + switch (changeKey) { + case "user_id", "sound_id", "id", "guild_id", "available" -> { + // skip + } + case "volume" -> { + eb.addField(MarkdownUtil.underline("Old Volume"), "╰┈➤" + SoundboardUtils.resolveVolumePercentage(oldValue), true); + eb.addField(MarkdownUtil.underline("New Volume"), "╰┈➤" + SoundboardUtils.resolveVolumePercentage(newValue), true); + eb.addBlankField(true); + } + case "emoji_name" -> { + eb.addField(MarkdownUtil.underline("Old Related Emoji"), "╰┈➤" + oldValue, true); + eb.addField(MarkdownUtil.underline("New Related Emoji"), "╰┈➤" + newValue, true); + eb.addBlankField(true); + } + case "emoji_id" -> { + eb.addField(MarkdownUtil.underline("Old Related Emoji ID"), "╰┈➤" + oldValue, true); + eb.addField(MarkdownUtil.underline("New Related Emoji ID"), "╰┈➤" + newValue, true); + eb.addBlankField(true); + } + case "name" -> { + eb.addField(MarkdownUtil.underline("Old Sound Item Name"), "╰┈➤" + oldValue, true); + eb.addField(MarkdownUtil.underline("New Sound Item Name"), "╰┈➤" + newValue, true); + eb.addBlankField(true); + } + default -> { + eb.addField("Unimplemented Change Key", changeKey, false); + log.info("Unimplemented Change Key on Soundboard Sound Update: {}\nOLD_VALUE: {}\nNEW_VALUE: {}", changeKey, oldValue, newValue); + } + } + }); + + eb.setFooter("Audit Log Entry ID: " + ale.getId()); + eb.setTimestamp(ale.getTimeCreated()); + + performChecksThenBuildAndSendEmbed(event, eb, channelIdToSendTo); + } + + @Override + public void onSoundboardSoundDelete(@NonNull GuildAuditLogEntryCreateEvent event) { + String channelIdToSendTo = getRegisteredGuildChannel(event.getGuild().getId()); + if (channelIdToSendTo.isBlank()) return; + + AuditLogEntry ale = event.getEntry(); + + User executor = ale.getJDA().getUserById(ale.getUserIdLong()); + String mentionableExecutor = (executor != null ? executor.getAsMention() : ale.getUserId()); + + EmbedBuilder eb = new EmbedBuilder(); + eb.setTitle("Audit Log Entry | Soundboard Sound Delete Event"); + eb.setDescription(MarkdownUtil.quoteBlock("Sound Item Deleted By: " + mentionableExecutor)); + eb.setColor(Color.RED); + + ale.getChanges().forEach((changeKey, changeValue) -> { + + Object oldValue = changeValue.getOldValue(); + Object newValue = changeValue.getNewValue(); + + switch (changeKey) { + + case "user_id", "sound_id", "id", "guild_id", "available" -> { + // skip + } + case "volume" -> + eb.addField(MarkdownUtil.underline("Volume"), "╰┈➤" + SoundboardUtils.resolveVolumePercentage(oldValue), false); + + case "emoji_name" -> eb.addField(MarkdownUtil.underline("Related Emoji"), "╰┈➤" + oldValue, false); + + case "emoji_id" -> eb.addField(MarkdownUtil.underline("Related Emoji ID"), "╰┈➤" + oldValue, false); + + case "name" -> eb.addField(MarkdownUtil.underline("Sound Item Name"), "╰┈➤" + oldValue, false); + + default -> { + eb.addField("Unimplemented Change Key", changeKey, false); + log.info("Unimplemented Change Key on Soundboard Sound Delete: {}\nOLD_VALUE: {}\nNEW_VALUE: {}", changeKey, oldValue, newValue); + } + } + }); + + eb.setFooter("Audit Log Entry ID: " + ale.getId()); + eb.setTimestamp(ale.getTimeCreated()); + + performChecksThenBuildAndSendEmbed(event, eb, channelIdToSendTo); + } +} diff --git a/src/main/java/io/github/eggy03/papertrail/bot/handlers/auditlog/StageInstanceEventHandler.java b/src/main/java/io/github/eggy03/papertrail/bot/handlers/auditlog/StageInstanceEventHandler.java new file mode 100644 index 00000000..e5196152 --- /dev/null +++ b/src/main/java/io/github/eggy03/papertrail/bot/handlers/auditlog/StageInstanceEventHandler.java @@ -0,0 +1,170 @@ +package io.github.eggy03.papertrail.bot.handlers.auditlog; + +import io.github.eggy03.papertrail.bot.listeners.auditlog.GuildAuditLogEntryCreateEventHandler; +import io.github.eggy03.papertrail.bot.utils.auditlog.StageUtils; +import io.github.eggy03.papertrail.sdk.client.AuditLogRegistrationClient; +import io.github.eggy03.papertrail.sdk.entity.AuditLogRegistrationEntity; +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.inject.Inject; +import lombok.NonNull; +import lombok.extern.slf4j.Slf4j; +import net.dv8tion.jda.api.EmbedBuilder; +import net.dv8tion.jda.api.audit.AuditLogEntry; +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 net.dv8tion.jda.api.utils.MarkdownUtil; +import org.apache.commons.lang3.StringUtils; + +import java.awt.Color; + +@ApplicationScoped +@Slf4j +@SuppressWarnings("java:S1192") +public final class StageInstanceEventHandler extends GuildAuditLogEntryCreateEventHandler { + + private final @NonNull AuditLogRegistrationClient client; + + @Inject + public StageInstanceEventHandler(@NonNull AuditLogRegistrationClient client) { + this.client = client; + } + + @NonNull + private String getRegisteredGuildChannel(@NonNull String guildId) { + return client.getRegisteredGuild(guildId) + .map(AuditLogRegistrationEntity::getChannelId).orElse(StringUtils.EMPTY); + + } + + private void performChecksThenBuildAndSendEmbed(@NonNull GuildAuditLogEntryCreateEvent event, @NonNull EmbedBuilder embedBuilder, @NonNull String channelIdToSendTo) { + if (!embedBuilder.isValidLength() || embedBuilder.isEmpty()) { + log.warn("Embed is empty or too long (current length: {}).", embedBuilder.length()); + return; + } + + TextChannel sendingChannel = event.getGuild().getTextChannelById(channelIdToSendTo); + if (sendingChannel != null && sendingChannel.canTalk()) { + sendingChannel.sendMessageEmbeds(embedBuilder.build()).queue(); + } + } + + @Override + public void onStageInstanceCreate(@NonNull GuildAuditLogEntryCreateEvent event) { + String channelIdToSendTo = getRegisteredGuildChannel(event.getGuild().getId()); + if (channelIdToSendTo.isBlank()) return; + + AuditLogEntry ale = event.getEntry(); + + User executor = ale.getJDA().getUserById(ale.getUserIdLong()); + String mentionableExecutor = (executor != null ? executor.getAsMention() : ale.getUserId()); + + EmbedBuilder eb = new EmbedBuilder(); + eb.setTitle("Audit Log Entry | Stage Instance Create Event"); + eb.setDescription(MarkdownUtil.quoteBlock("Stage Instance Created By: " + mentionableExecutor)); + eb.setColor(Color.GREEN); + + ale.getChanges().forEach((changeKey, changeValue) -> { + Object oldValue = changeValue.getOldValue(); + Object newValue = changeValue.getNewValue(); + + switch (changeKey) { + case "topic" -> eb.addField(MarkdownUtil.underline("Stage Topic"), "╰┈➤" + newValue, false); + + case "privacy_level" -> + eb.addField(MarkdownUtil.underline("Stage Privacy"), "╰┈➤" + StageUtils.resolveStagePrivacyLevel(newValue), false); + + default -> { + eb.addField("Unimplemented Change Key", changeKey, false); + log.info("Unimplemented Change Key on Stage Instance Create: {}\nOLD_VALUE: {}\nNEW_VALUE: {}", changeKey, oldValue, newValue); + } + } + }); + + eb.setFooter("Audit Log Entry ID: " + ale.getId()); + eb.setTimestamp(ale.getTimeCreated()); + + performChecksThenBuildAndSendEmbed(event, eb, channelIdToSendTo); + } + + @Override + public void onStageInstanceUpdate(@NonNull GuildAuditLogEntryCreateEvent event) { + String channelIdToSendTo = getRegisteredGuildChannel(event.getGuild().getId()); + if (channelIdToSendTo.isBlank()) return; + + AuditLogEntry ale = event.getEntry(); + + User executor = ale.getJDA().getUserById(ale.getUserIdLong()); + String mentionableExecutor = (executor != null ? executor.getAsMention() : ale.getUserId()); + + EmbedBuilder eb = new EmbedBuilder(); + eb.setTitle("Audit Log Entry | Stage Instance Update Event"); + eb.setDescription(MarkdownUtil.quoteBlock("Stage Instance Updated By: " + mentionableExecutor)); + eb.setColor(Color.YELLOW); + + ale.getChanges().forEach((changeKey, changeValue) -> { + Object oldValue = changeValue.getOldValue(); + Object newValue = changeValue.getNewValue(); + + switch (changeKey) { + case "topic" -> { + eb.addField(MarkdownUtil.underline("Old Stage Topic"), "╰┈➤" + oldValue, true); + eb.addField(MarkdownUtil.underline("New Stage Topic"), "╰┈➤" + newValue, true); + eb.addBlankField(true); + } + case "privacy_level" -> { + eb.addField(MarkdownUtil.underline("Old Stage Privacy"), "╰┈➤" + StageUtils.resolveStagePrivacyLevel(oldValue), true); + eb.addField(MarkdownUtil.underline("New Stage Privacy"), "╰┈➤" + StageUtils.resolveStagePrivacyLevel(newValue), true); + eb.addBlankField(true); + } + + default -> { + eb.addField("Unimplemented Change Key", changeKey, false); + log.info("Unimplemented Change Key on Stage Instance Update: {}\nOLD_VALUE: {}\nNEW_VALUE: {}", changeKey, oldValue, newValue); + } + } + }); + + eb.setFooter("Audit Log Entry ID: " + ale.getId()); + eb.setTimestamp(ale.getTimeCreated()); + + performChecksThenBuildAndSendEmbed(event, eb, channelIdToSendTo); + } + + @Override + public void onStageInstanceDelete(@NonNull GuildAuditLogEntryCreateEvent event) { + String channelIdToSendTo = getRegisteredGuildChannel(event.getGuild().getId()); + if (channelIdToSendTo.isBlank()) return; + + AuditLogEntry ale = event.getEntry(); + + User executor = ale.getJDA().getUserById(ale.getUserIdLong()); + String mentionableExecutor = (executor != null ? executor.getAsMention() : ale.getUserId()); + + EmbedBuilder eb = new EmbedBuilder(); + eb.setTitle("Audit Log Entry | Stage Instance Delete Event"); + eb.setDescription(MarkdownUtil.quoteBlock("Stage Instance Deleted By: " + mentionableExecutor)); + eb.setColor(Color.RED); + + ale.getChanges().forEach((changeKey, changeValue) -> { + Object oldValue = changeValue.getOldValue(); + Object newValue = changeValue.getNewValue(); + + switch (changeKey) { + case "topic" -> eb.addField(MarkdownUtil.underline("Stage Topic"), "╰┈➤" + oldValue, false); + + case "privacy_level" -> + eb.addField(MarkdownUtil.underline("Stage Privacy"), "╰┈➤" + StageUtils.resolveStagePrivacyLevel(oldValue), false); + + default -> { + eb.addField("Unimplemented Change Key", changeKey, false); + log.info("Unimplemented Change Key on Stage Instance Delete: {}\nOLD_VALUE: {}\nNEW_VALUE: {}", changeKey, oldValue, newValue); + } + } + }); + eb.setFooter("Audit Log Entry ID: " + ale.getId()); + eb.setTimestamp(ale.getTimeCreated()); + + performChecksThenBuildAndSendEmbed(event, eb, channelIdToSendTo); + } +} diff --git a/src/main/java/io/github/eggy03/papertrail/bot/handlers/auditlog/StickerEventHandler.java b/src/main/java/io/github/eggy03/papertrail/bot/handlers/auditlog/StickerEventHandler.java new file mode 100644 index 00000000..262e5979 --- /dev/null +++ b/src/main/java/io/github/eggy03/papertrail/bot/handlers/auditlog/StickerEventHandler.java @@ -0,0 +1,202 @@ +package io.github.eggy03.papertrail.bot.handlers.auditlog; + +import io.github.eggy03.papertrail.bot.listeners.auditlog.GuildAuditLogEntryCreateEventHandler; +import io.github.eggy03.papertrail.bot.utils.auditlog.StickerUtils; +import io.github.eggy03.papertrail.sdk.client.AuditLogRegistrationClient; +import io.github.eggy03.papertrail.sdk.entity.AuditLogRegistrationEntity; +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.inject.Inject; +import lombok.NonNull; +import lombok.extern.slf4j.Slf4j; +import net.dv8tion.jda.api.EmbedBuilder; +import net.dv8tion.jda.api.audit.AuditLogEntry; +import net.dv8tion.jda.api.entities.User; +import net.dv8tion.jda.api.entities.channel.concrete.TextChannel; +import net.dv8tion.jda.api.entities.sticker.GuildSticker; +import net.dv8tion.jda.api.events.guild.GuildAuditLogEntryCreateEvent; +import net.dv8tion.jda.api.utils.MarkdownUtil; +import org.apache.commons.lang3.StringUtils; + +import java.awt.Color; + +@ApplicationScoped +@Slf4j +@SuppressWarnings("java:S1192") +public final class StickerEventHandler extends GuildAuditLogEntryCreateEventHandler { + + private final @NonNull AuditLogRegistrationClient client; + + @Inject + public StickerEventHandler(@NonNull AuditLogRegistrationClient client) { + this.client = client; + } + + @NonNull + private String getRegisteredGuildChannel(@NonNull String guildId) { + return client.getRegisteredGuild(guildId) + .map(AuditLogRegistrationEntity::getChannelId).orElse(StringUtils.EMPTY); + + } + + private void performChecksThenBuildAndSendEmbed(@NonNull GuildAuditLogEntryCreateEvent event, @NonNull EmbedBuilder embedBuilder, @NonNull String channelIdToSendTo) { + if (!embedBuilder.isValidLength() || embedBuilder.isEmpty()) { + log.warn("Embed is empty or too long (current length: {}).", embedBuilder.length()); + return; + } + + TextChannel sendingChannel = event.getGuild().getTextChannelById(channelIdToSendTo); + if (sendingChannel != null && sendingChannel.canTalk()) { + sendingChannel.sendMessageEmbeds(embedBuilder.build()).queue(); + } + } + + @Override + public void onStickerCreate(@NonNull GuildAuditLogEntryCreateEvent event) { + String channelIdToSendTo = getRegisteredGuildChannel(event.getGuild().getId()); + if (channelIdToSendTo.isBlank()) return; + + AuditLogEntry ale = event.getEntry(); + + User executor = ale.getJDA().getUserById(ale.getUserIdLong()); + String mentionableExecutor = (executor != null ? executor.getAsMention() : ale.getUserId()); + + GuildSticker sticker = event.getGuild().getStickerById(ale.getTargetId()); + String mentionableSticker = (sticker != null ? sticker.getName() : ale.getTargetId()); + + EmbedBuilder eb = new EmbedBuilder(); + eb.setTitle("Audit Log Entry | Sticker Create Event"); + eb.setDescription(MarkdownUtil.quoteBlock("Sticker Created By: " + mentionableExecutor + "\nCreated Sticker: " + mentionableSticker)); + eb.setColor(Color.GREEN); + + ale.getChanges().forEach((changeKey, changeValue) -> { + Object oldValue = changeValue.getOldValue(); + Object newValue = changeValue.getNewValue(); + + switch (changeKey) { + case "format_type", "type", "asset", "available", "guild_id" -> { + // skip + } + case "id" -> { + eb.addField(MarkdownUtil.underline("Sticker ID"), "╰┈➤" + newValue, false); + eb.addField(MarkdownUtil.underline("Sticker Link"), "╰┈➤" + StickerUtils.resolveStickerUrl(event, newValue), false); + } + case "tags" -> + eb.addField(MarkdownUtil.underline("Related Emoji"), "╰┈➤" + StickerUtils.resolveRelatedEmoji(event, newValue), false); + case "description" -> eb.addField(MarkdownUtil.underline("Description"), "╰┈➤" + newValue, false); + case "name" -> eb.addField(MarkdownUtil.underline("Sticker Name"), "╰┈➤" + newValue, false); + + default -> { + eb.addField("Unimplemented Change Key", changeKey, false); + log.info("Unimplemented Change Key on Sticker Create: {}\nOLD_VALUE: {}\nNEW_VALUE: {}", changeKey, oldValue, newValue); + } + } + }); + + eb.setFooter("Audit Log Entry ID: " + ale.getId()); + eb.setTimestamp(ale.getTimeCreated()); + + performChecksThenBuildAndSendEmbed(event, eb, channelIdToSendTo); + } + + @Override + public void onStickerUpdate(@NonNull GuildAuditLogEntryCreateEvent event) { + String channelIdToSendTo = getRegisteredGuildChannel(event.getGuild().getId()); + if (channelIdToSendTo.isBlank()) return; + + AuditLogEntry ale = event.getEntry(); + + User executor = ale.getJDA().getUserById(ale.getUserIdLong()); + String mentionableExecutor = (executor != null ? executor.getAsMention() : ale.getUserId()); + + GuildSticker sticker = event.getGuild().getStickerById(ale.getTargetId()); + String mentionableSticker = (sticker != null ? sticker.getName() : ale.getTargetId()); + + EmbedBuilder eb = new EmbedBuilder(); + eb.setTitle("Audit Log Entry | Sticker Update Event"); + eb.setDescription(MarkdownUtil.quoteBlock("Sticker Updated By: " + mentionableExecutor + "\nUpdated Sticker: " + mentionableSticker)); + eb.setColor(Color.YELLOW); + + ale.getChanges().forEach((changeKey, changeValue) -> { + Object oldValue = changeValue.getOldValue(); + Object newValue = changeValue.getNewValue(); + + switch (changeKey) { + case "format_type", "type", "asset", "available", "guild_id", "id" -> { + // skip + } + case "tags" -> { + eb.addField(MarkdownUtil.underline("Old Related Emoji"), "╰┈➤" + StickerUtils.resolveRelatedEmoji(event, oldValue), true); + eb.addField(MarkdownUtil.underline("New Related Emoji"), "╰┈➤" + StickerUtils.resolveRelatedEmoji(event, newValue), true); + eb.addBlankField(true); + } + case "description" -> { + eb.addField(MarkdownUtil.underline("Old Description"), "╰┈➤" + oldValue, true); + eb.addField(MarkdownUtil.underline("New Description"), "╰┈➤" + newValue, true); + eb.addBlankField(true); + } + case "name" -> { + eb.addField(MarkdownUtil.underline("Old Sticker Name"), "╰┈➤" + oldValue, true); + eb.addField(MarkdownUtil.underline("New Sticker Name"), "╰┈➤" + newValue, true); + eb.addBlankField(true); + } + default -> { + eb.addField("Unimplemented Change Key", changeKey, false); + log.info("Unimplemented Change Key on Sticker Update: {}\nOLD_VALUE: {}\nNEW_VALUE: {}", changeKey, oldValue, newValue); + } + } + }); + + eb.setFooter("Audit Log Entry ID: " + ale.getId()); + eb.setTimestamp(ale.getTimeCreated()); + + performChecksThenBuildAndSendEmbed(event, eb, channelIdToSendTo); + } + + @Override + public void onStickerDelete(@NonNull GuildAuditLogEntryCreateEvent event) { + String channelIdToSendTo = getRegisteredGuildChannel(event.getGuild().getId()); + if (channelIdToSendTo.isBlank()) return; + + AuditLogEntry ale = event.getEntry(); + + User executor = ale.getJDA().getUserById(ale.getUserIdLong()); + String mentionableExecutor = (executor != null ? executor.getAsMention() : ale.getUserId()); + + GuildSticker sticker = event.getGuild().getStickerById(ale.getTargetId()); + String mentionableSticker = (sticker != null ? sticker.getName() : ale.getTargetId()); + + EmbedBuilder eb = new EmbedBuilder(); + eb.setTitle("Audit Log Entry | Sticker Delete Event"); + eb.setDescription(MarkdownUtil.quoteBlock("Sticker Deleted By: " + mentionableExecutor + "\nDeleted Sticker ID: " + mentionableSticker)); + eb.setColor(Color.RED); + + ale.getChanges().forEach((changeKey, changeValue) -> { + Object oldValue = changeValue.getOldValue(); + Object newValue = changeValue.getNewValue(); + + switch (changeKey) { + case "format_type", "type", "asset", "available", "guild_id" -> { + // skip + } + case "id" -> { + eb.addField(MarkdownUtil.underline("Sticker ID"), "╰┈➤" + oldValue, false); + eb.addField(MarkdownUtil.underline("Sticker Link"), "╰┈➤" + StickerUtils.resolveStickerUrl(event, oldValue), false); + } + case "tags" -> + eb.addField(MarkdownUtil.underline("Related Emoji"), "╰┈➤" + StickerUtils.resolveRelatedEmoji(event, oldValue), false); + case "description" -> eb.addField(MarkdownUtil.underline("Description"), "╰┈➤" + oldValue, false); + case "name" -> eb.addField(MarkdownUtil.underline("Sticker Name"), "╰┈➤" + oldValue, false); + + default -> { + eb.addField("Unimplemented Change Key", changeKey, false); + log.info("Unimplemented Change Key on Sticker Delete: {}\nOLD_VALUE: {}\nNEW_VALUE: {}", changeKey, oldValue, newValue); + } + } + }); + + eb.setFooter("Audit Log Entry ID: " + ale.getId()); + eb.setTimestamp(ale.getTimeCreated()); + + performChecksThenBuildAndSendEmbed(event, eb, channelIdToSendTo); + } +} diff --git a/src/main/java/io/github/eggy03/papertrail/bot/handlers/auditlog/ThreadEventHandler.java b/src/main/java/io/github/eggy03/papertrail/bot/handlers/auditlog/ThreadEventHandler.java new file mode 100644 index 00000000..4c706b68 --- /dev/null +++ b/src/main/java/io/github/eggy03/papertrail/bot/handlers/auditlog/ThreadEventHandler.java @@ -0,0 +1,248 @@ +package io.github.eggy03.papertrail.bot.handlers.auditlog; + +import io.github.eggy03.papertrail.bot.listeners.auditlog.GuildAuditLogEntryCreateEventHandler; +import io.github.eggy03.papertrail.bot.utils.BooleanUtils; +import io.github.eggy03.papertrail.bot.utils.DurationUtils; +import io.github.eggy03.papertrail.bot.utils.auditlog.ChannelUtils; +import io.github.eggy03.papertrail.bot.utils.auditlog.ThreadUtils; +import io.github.eggy03.papertrail.sdk.client.AuditLogRegistrationClient; +import io.github.eggy03.papertrail.sdk.entity.AuditLogRegistrationEntity; +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.inject.Inject; +import lombok.NonNull; +import lombok.extern.slf4j.Slf4j; +import net.dv8tion.jda.api.EmbedBuilder; +import net.dv8tion.jda.api.audit.AuditLogEntry; +import net.dv8tion.jda.api.entities.User; +import net.dv8tion.jda.api.entities.channel.concrete.TextChannel; +import net.dv8tion.jda.api.entities.channel.concrete.ThreadChannel; +import net.dv8tion.jda.api.events.guild.GuildAuditLogEntryCreateEvent; +import net.dv8tion.jda.api.utils.MarkdownUtil; +import org.apache.commons.lang3.StringUtils; + +import java.awt.Color; + +@ApplicationScoped +@Slf4j +@SuppressWarnings("java:S1192") +public final class ThreadEventHandler extends GuildAuditLogEntryCreateEventHandler { + + private final @NonNull AuditLogRegistrationClient client; + + @Inject + public ThreadEventHandler(@NonNull AuditLogRegistrationClient client) { + this.client = client; + } + + @NonNull + private String getRegisteredGuildChannel(@NonNull String guildId) { + return client.getRegisteredGuild(guildId) + .map(AuditLogRegistrationEntity::getChannelId).orElse(StringUtils.EMPTY); + + } + + private void performChecksThenBuildAndSendEmbed(@NonNull GuildAuditLogEntryCreateEvent event, @NonNull EmbedBuilder embedBuilder, @NonNull String channelIdToSendTo) { + if (!embedBuilder.isValidLength() || embedBuilder.isEmpty()) { + log.warn("Embed is empty or too long (current length: {}).", embedBuilder.length()); + return; + } + + TextChannel sendingChannel = event.getGuild().getTextChannelById(channelIdToSendTo); + if (sendingChannel != null && sendingChannel.canTalk()) { + sendingChannel.sendMessageEmbeds(embedBuilder.build()).queue(); + } + } + + @Override + public void onThreadCreate(@NonNull GuildAuditLogEntryCreateEvent event) { + String channelIdToSendTo = getRegisteredGuildChannel(event.getGuild().getId()); + if (channelIdToSendTo.isBlank()) return; + + AuditLogEntry ale = event.getEntry(); + + User executor = ale.getJDA().getUserById(ale.getUserIdLong()); + String mentionableExecutor = (executor != null ? executor.getAsMention() : ale.getUserId()); + + ThreadChannel targetThread = event.getGuild().getThreadChannelById(ale.getTargetId()); + String mentionableTargetThread = (targetThread != null ? targetThread.getAsMention() : ale.getTargetId()); + + EmbedBuilder eb = new EmbedBuilder(); + eb.setTitle("Audit Log Entry | Thread Create Event"); + eb.setDescription(MarkdownUtil.quoteBlock("Thread Created By: " + mentionableExecutor + "\nTarget Thread: " + mentionableTargetThread)); + eb.setColor(Color.GREEN); + + ale.getChanges().forEach((changeKey, changeValue) -> { + Object oldValue = changeValue.getOldValue(); + Object newValue = changeValue.getNewValue(); + + switch (changeKey) { + + case "locked" -> + eb.addField(MarkdownUtil.underline("Is Locked"), "╰┈➤" + BooleanUtils.formatToYesOrNo(newValue), false); + + case "auto_archive_duration" -> + eb.addField(MarkdownUtil.underline("Auto Archive Duration"), "╰┈➤" + ThreadUtils.resolveAutoArchiveDuration(newValue), false); + + case "rate_limit_per_user" -> + eb.addField(MarkdownUtil.underline("Slow Mode Limit"), "╰┈➤" + DurationUtils.formatSeconds(newValue), false); + + case "type" -> + eb.addField(MarkdownUtil.underline("Thread Type"), "╰┈➤" + ChannelUtils.resolveChannelType(newValue), false); + + case "archived" -> + eb.addField(MarkdownUtil.underline("Archived"), "╰┈➤" + BooleanUtils.formatToYesOrNo(newValue), false); + + case "flags" -> { + // skip + } + case "invitable" -> + eb.addField(MarkdownUtil.underline("Invitable"), "╰┈➤" + BooleanUtils.formatToYesOrNo(newValue), false); + + case "name" -> eb.addField(MarkdownUtil.underline("Thread Name"), "╰┈➤" + newValue, false); + + default -> { + eb.addField("Unimplemented Change Key", changeKey, false); + log.info("Unimplemented Change Key on Thread Create: {}\nOLD_VALUE: {}\nNEW_VALUE: {}", changeKey, oldValue, newValue); + } + } + }); + + eb.setFooter("Audit Log Entry ID: " + ale.getId()); + eb.setTimestamp(ale.getTimeCreated()); + + performChecksThenBuildAndSendEmbed(event, eb, channelIdToSendTo); + } + + @Override + public void onThreadUpdate(@NonNull GuildAuditLogEntryCreateEvent event) { + String channelIdToSendTo = getRegisteredGuildChannel(event.getGuild().getId()); + if (channelIdToSendTo.isBlank()) return; + + AuditLogEntry ale = event.getEntry(); + + User executor = ale.getJDA().getUserById(ale.getUserIdLong()); + String mentionableExecutor = (executor != null ? executor.getAsMention() : ale.getUserId()); + + ThreadChannel targetThread = event.getGuild().getThreadChannelById(ale.getTargetId()); + String mentionableTargetThread = (targetThread != null ? targetThread.getAsMention() : ale.getTargetId()); + + EmbedBuilder eb = new EmbedBuilder(); + eb.setTitle("Audit Log Entry | Thread Update Event"); + eb.setDescription(MarkdownUtil.quoteBlock("Thread Updated By: " + mentionableExecutor + "\nTarget Thread: " + mentionableTargetThread)); + eb.setColor(Color.YELLOW); + + + ale.getChanges().forEach((changeKey, changeValue) -> { + Object oldValue = changeValue.getOldValue(); + Object newValue = changeValue.getNewValue(); + + switch (changeKey) { + + case "locked" -> { + eb.addField(MarkdownUtil.underline("Was Locked"), "╰┈➤" + BooleanUtils.formatToYesOrNo(oldValue), true); + eb.addField(MarkdownUtil.underline("Is Locked"), "╰┈➤" + BooleanUtils.formatToYesOrNo(newValue), true); + eb.addBlankField(true); + } + case "auto_archive_duration" -> { + eb.addField(MarkdownUtil.underline("Old Auto Archive Duration"), "╰┈➤" + ThreadUtils.resolveAutoArchiveDuration(oldValue), true); + eb.addField(MarkdownUtil.underline("New Auto Archive Duration"), "╰┈➤" + ThreadUtils.resolveAutoArchiveDuration(newValue), true); + eb.addBlankField(true); + } + case "rate_limit_per_user" -> { + eb.addField(MarkdownUtil.underline("Old Slow Mode Limit"), "╰┈➤" + DurationUtils.formatSeconds(oldValue), true); + eb.addField(MarkdownUtil.underline("New Slow Mode Limit"), "╰┈➤" + DurationUtils.formatSeconds(newValue), true); + eb.addBlankField(true); + } + case "type" -> { + eb.addField(MarkdownUtil.underline("Old Thread Type"), "╰┈➤" + ChannelUtils.resolveChannelType(oldValue), true); + eb.addField(MarkdownUtil.underline("New Thread Type"), "╰┈➤" + ChannelUtils.resolveChannelType(newValue), true); + eb.addBlankField(true); + } + case "archived" -> { + eb.addField(MarkdownUtil.underline("Old Archive Status"), "╰┈➤" + BooleanUtils.formatToEnabledOrDisabled(oldValue), true); + eb.addField(MarkdownUtil.underline("New Archive Status"), "╰┈➤" + BooleanUtils.formatToEnabledOrDisabled(newValue), true); + eb.addBlankField(true); + } + case "flags" -> eb.addField(MarkdownUtil.underline("Flags"), "╰┈➤Thread flags were updated", false); + + case "invitable" -> { + eb.addField(MarkdownUtil.underline("Was Invitable"), "╰┈➤" + BooleanUtils.formatToYesOrNo(oldValue), true); + eb.addField(MarkdownUtil.underline("Is Invitable"), "╰┈➤" + BooleanUtils.formatToYesOrNo(newValue), true); + eb.addBlankField(true); + } + case "name" -> { + eb.addField(MarkdownUtil.underline("Old Thread Name"), "╰┈➤" + oldValue, true); + eb.addField(MarkdownUtil.underline("New Thread Name"), "╰┈➤" + newValue, true); + eb.addBlankField(true); + } + default -> { + eb.addField("Unimplemented Change Key", changeKey, false); + log.info("Unimplemented Change Key on Thread Update: {}\nOLD_VALUE: {}\nNEW_VALUE: {}", changeKey, oldValue, newValue); + } + } + }); + + eb.setFooter("Audit Log Entry ID: " + ale.getId()); + eb.setTimestamp(ale.getTimeCreated()); + + performChecksThenBuildAndSendEmbed(event, eb, channelIdToSendTo); + } + + @Override + public void onThreadDelete(@NonNull GuildAuditLogEntryCreateEvent event) { + String channelIdToSendTo = getRegisteredGuildChannel(event.getGuild().getId()); + if (channelIdToSendTo.isBlank()) return; + + AuditLogEntry ale = event.getEntry(); + + User executor = ale.getJDA().getUserById(ale.getUserIdLong()); + String mentionableExecutor = (executor != null ? executor.getAsMention() : ale.getUserId()); + + EmbedBuilder eb = new EmbedBuilder(); + eb.setTitle("Audit Log Entry | Thread Delete Event"); + eb.setDescription(MarkdownUtil.quoteBlock("Thread Deleted By: " + mentionableExecutor + "\nTarget Thread ID: " + ale.getTargetId())); + eb.setColor(Color.RED); + + ale.getChanges().forEach((changeKey, changeValue) -> { + Object oldValue = changeValue.getOldValue(); + Object newValue = changeValue.getNewValue(); + + switch (changeKey) { + + case "locked" -> + eb.addField(MarkdownUtil.underline("Was Locked"), "╰┈➤" + BooleanUtils.formatToYesOrNo(oldValue), false); + + case "auto_archive_duration" -> + eb.addField(MarkdownUtil.underline("Auto Archive Duration"), "╰┈➤" + ThreadUtils.resolveAutoArchiveDuration(oldValue), false); + + case "rate_limit_per_user" -> + eb.addField(MarkdownUtil.underline("Slow Mode Limit"), "╰┈➤" + DurationUtils.formatSeconds(oldValue), false); + + case "type" -> + eb.addField(MarkdownUtil.underline("Thread Type"), "╰┈➤" + ChannelUtils.resolveChannelType(oldValue), false); + + case "archived" -> + eb.addField(MarkdownUtil.underline("Archived"), "╰┈➤" + BooleanUtils.formatToYesOrNo(oldValue), false); + + case "flags" -> { + // skip + } + + case "invitable" -> + eb.addField(MarkdownUtil.underline("Invitable"), "╰┈➤" + BooleanUtils.formatToYesOrNo(oldValue), false); + + case "name" -> eb.addField(MarkdownUtil.underline("Thread Name"), "╰┈➤" + oldValue, false); + + default -> { + eb.addField("Unimplemented Change Key", changeKey, false); + log.info("Unimplemented Change Key on Thread Delete: {}\nOLD_VALUE: {}\nNEW_VALUE: {}", changeKey, oldValue, newValue); + } + } + }); + + eb.setFooter("Audit Log Entry ID: " + ale.getId()); + eb.setTimestamp(ale.getTimeCreated()); + + performChecksThenBuildAndSendEmbed(event, eb, channelIdToSendTo); + } +} diff --git a/src/main/java/io/github/eggy03/papertrail/bot/handlers/auditlog/UnimplementedEventHandler.java b/src/main/java/io/github/eggy03/papertrail/bot/handlers/auditlog/UnimplementedEventHandler.java new file mode 100644 index 00000000..d102059b --- /dev/null +++ b/src/main/java/io/github/eggy03/papertrail/bot/handlers/auditlog/UnimplementedEventHandler.java @@ -0,0 +1,19 @@ +package io.github.eggy03.papertrail.bot.handlers.auditlog; + +import io.github.eggy03.papertrail.bot.listeners.auditlog.GuildAuditLogEntryCreateEventHandler; +import jakarta.enterprise.context.ApplicationScoped; +import lombok.NonNull; +import lombok.extern.slf4j.Slf4j; +import net.dv8tion.jda.api.events.guild.GuildAuditLogEntryCreateEvent; + +// for action types not implemented by PaperTrail yet +@ApplicationScoped +@Slf4j +@SuppressWarnings("java:S1192") +public final class UnimplementedEventHandler extends GuildAuditLogEntryCreateEventHandler { + + @Override + public void onUnimplementedEvent(@NonNull GuildAuditLogEntryCreateEvent event) { + log.warn("Unimplemented Action Type: {} with Target Type: {}", event.getEntry().getType(), event.getEntry().getType().getTargetType()); + } +} diff --git a/src/main/java/io/github/eggy03/papertrail/bot/handlers/auditlog/UnknownEventHandler.java b/src/main/java/io/github/eggy03/papertrail/bot/handlers/auditlog/UnknownEventHandler.java new file mode 100644 index 00000000..3fd1e02f --- /dev/null +++ b/src/main/java/io/github/eggy03/papertrail/bot/handlers/auditlog/UnknownEventHandler.java @@ -0,0 +1,81 @@ +package io.github.eggy03.papertrail.bot.handlers.auditlog; + +import io.github.eggy03.papertrail.bot.listeners.auditlog.GuildAuditLogEntryCreateEventHandler; +import io.github.eggy03.papertrail.sdk.client.AuditLogRegistrationClient; +import io.github.eggy03.papertrail.sdk.entity.AuditLogRegistrationEntity; +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.inject.Inject; +import lombok.NonNull; +import lombok.extern.slf4j.Slf4j; +import net.dv8tion.jda.api.EmbedBuilder; +import net.dv8tion.jda.api.audit.AuditLogEntry; +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 net.dv8tion.jda.api.utils.MarkdownUtil; +import org.apache.commons.lang3.StringUtils; + +import java.awt.Color; + +// for events not defined by JDA +@ApplicationScoped +@Slf4j +@SuppressWarnings("java:S1192") +public final class UnknownEventHandler extends GuildAuditLogEntryCreateEventHandler { + + private final @NonNull AuditLogRegistrationClient client; + + @Inject + public UnknownEventHandler(@NonNull AuditLogRegistrationClient client) { + this.client = client; + } + + @NonNull + private String getRegisteredGuildChannel(@NonNull String guildId) { + return client.getRegisteredGuild(guildId) + .map(AuditLogRegistrationEntity::getChannelId).orElse(StringUtils.EMPTY); + + } + + private void performChecksThenBuildAndSendEmbed(@NonNull GuildAuditLogEntryCreateEvent event, @NonNull EmbedBuilder embedBuilder, @NonNull String channelIdToSendTo) { + if (!embedBuilder.isValidLength() || embedBuilder.isEmpty()) { + log.warn("Embed is empty or too long (current length: {}).", embedBuilder.length()); + return; + } + + TextChannel sendingChannel = event.getGuild().getTextChannelById(channelIdToSendTo); + if (sendingChannel != null && sendingChannel.canTalk()) { + sendingChannel.sendMessageEmbeds(embedBuilder.build()).queue(); + } + } + + @Override + public void onUnknownEvent(@NonNull GuildAuditLogEntryCreateEvent event) { + + String channelIdToSendTo = getRegisteredGuildChannel(event.getGuild().getId()); + if (channelIdToSendTo.isBlank()) return; + + AuditLogEntry ale = event.getEntry(); + + User executor = ale.getJDA().getUserById(ale.getUserIdLong()); + String mentionableExecutor = executor != null ? executor.getAsMention() : ale.getUserId(); + + EmbedBuilder eb = new EmbedBuilder(); + eb.setTitle("Audit Log Entry | Generic Event"); + eb.setDescription(MarkdownUtil.quoteBlock("Executor: " + mentionableExecutor)); + eb.setColor(Color.LIGHT_GRAY); + + eb.addField(MarkdownUtil.underline("Action Type"), MarkdownUtil.codeblock(ale.getType().toString()), true); + eb.addField(MarkdownUtil.underline("Target Type"), MarkdownUtil.codeblock(ale.getTargetType().toString()), true); + + ale.getChanges().forEach((changeKey, changeValue) -> + eb.addField( + MarkdownUtil.underline(changeKey), + MarkdownUtil.codeblock("OLD VALUE\n" + changeValue.getOldValue() + "\nNEW VALUE\n" + changeValue.getNewValue()), + false + ) + ); + + performChecksThenBuildAndSendEmbed(event, eb, channelIdToSendTo); + } +} diff --git a/src/main/java/io/github/eggy03/papertrail/bot/handlers/auditlog/VoiceChannelStatusEventHandler.java b/src/main/java/io/github/eggy03/papertrail/bot/handlers/auditlog/VoiceChannelStatusEventHandler.java new file mode 100644 index 00000000..6541eef5 --- /dev/null +++ b/src/main/java/io/github/eggy03/papertrail/bot/handlers/auditlog/VoiceChannelStatusEventHandler.java @@ -0,0 +1,118 @@ +package io.github.eggy03.papertrail.bot.handlers.auditlog; + +import io.github.eggy03.papertrail.bot.listeners.auditlog.GuildAuditLogEntryCreateEventHandler; +import io.github.eggy03.papertrail.sdk.client.AuditLogRegistrationClient; +import io.github.eggy03.papertrail.sdk.entity.AuditLogRegistrationEntity; +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.inject.Inject; +import lombok.NonNull; +import lombok.extern.slf4j.Slf4j; +import net.dv8tion.jda.api.EmbedBuilder; +import net.dv8tion.jda.api.audit.AuditLogEntry; +import net.dv8tion.jda.api.entities.User; +import net.dv8tion.jda.api.entities.channel.concrete.TextChannel; +import net.dv8tion.jda.api.entities.channel.middleman.GuildChannel; +import net.dv8tion.jda.api.events.guild.GuildAuditLogEntryCreateEvent; +import net.dv8tion.jda.api.utils.MarkdownUtil; +import org.apache.commons.lang3.StringUtils; + +import java.awt.Color; + +@ApplicationScoped +@Slf4j +@SuppressWarnings("java:S1192") +public final class VoiceChannelStatusEventHandler extends GuildAuditLogEntryCreateEventHandler { + + private final @NonNull AuditLogRegistrationClient client; + + @Inject + public VoiceChannelStatusEventHandler(@NonNull AuditLogRegistrationClient client) { + this.client = client; + } + + @NonNull + private String getRegisteredGuildChannel(@NonNull String guildId) { + return client.getRegisteredGuild(guildId) + .map(AuditLogRegistrationEntity::getChannelId).orElse(StringUtils.EMPTY); + + } + + private void performChecksThenBuildAndSendEmbed(@NonNull GuildAuditLogEntryCreateEvent event, @NonNull EmbedBuilder embedBuilder, @NonNull String channelIdToSendTo) { + if (!embedBuilder.isValidLength() || embedBuilder.isEmpty()) { + log.warn("Embed is empty or too long (current length: {}).", embedBuilder.length()); + return; + } + + TextChannel sendingChannel = event.getGuild().getTextChannelById(channelIdToSendTo); + if (sendingChannel != null && sendingChannel.canTalk()) { + sendingChannel.sendMessageEmbeds(embedBuilder.build()).queue(); + } + } + + @Override + public void onVoiceChannelStatusUpdate(@NonNull GuildAuditLogEntryCreateEvent event) { + String channelIdToSendTo = getRegisteredGuildChannel(event.getGuild().getId()); + if (channelIdToSendTo.isBlank()) return; + + AuditLogEntry ale = event.getEntry(); + + User executor = ale.getJDA().getUserById(ale.getUserId()); + String mentionableExecutor = (executor != null ? executor.getAsMention() : ale.getUserId()); + + GuildChannel targetChannel = ale.getJDA().getGuildChannelById(ale.getTargetId()); + String mentionableTargetChannel = (targetChannel != null ? targetChannel.getAsMention() : ale.getTargetId()); + + EmbedBuilder eb = new EmbedBuilder(); + eb.setTitle("Audit Log Entry | Voice Channel Status Update"); + + eb.setDescription("A voice channel status has been updated"); + eb.setColor(Color.YELLOW); + + eb.addField( + MarkdownUtil.underline("Details"), + MarkdownUtil.quoteBlock( + "Status Updated By: " + mentionableExecutor + "\n" + + "Target Channel: " + mentionableTargetChannel + "\n" + + "Updated Status: " + ale.getOptionByName("status") + ), + false + ); + + eb.setFooter("Audit Log Entry ID: " + ale.getId()); + eb.setTimestamp(ale.getTimeCreated()); + + performChecksThenBuildAndSendEmbed(event, eb, channelIdToSendTo); + } + + @Override + public void onVoiceChannelStatusDelete(@NonNull GuildAuditLogEntryCreateEvent event) { + String channelIdToSendTo = getRegisteredGuildChannel(event.getGuild().getId()); + if (channelIdToSendTo.isBlank()) return; + + AuditLogEntry ale = event.getEntry(); + + User executor = ale.getJDA().getUserById(ale.getUserId()); + String mentionableExecutor = (executor != null ? executor.getAsMention() : ale.getUserId()); + + GuildChannel targetChannel = ale.getJDA().getGuildChannelById(ale.getTargetId()); + String mentionableTargetChannel = (targetChannel != null ? targetChannel.getAsMention() : ale.getTargetId()); + + EmbedBuilder eb = new EmbedBuilder(); + eb.setTitle("Audit Log Entry | Voice Channel Status Delete"); + + eb.setDescription("A voice channel status has been reset"); + eb.setColor(Color.ORANGE); + + // status deletes dont contain the deleted status content + eb.addField( + MarkdownUtil.underline("Details"), + MarkdownUtil.quoteBlock("Status Reset By: " + mentionableExecutor + "\n" + "Target Channel: " + mentionableTargetChannel), + false + ); + + eb.setFooter("Audit Log Entry ID: " + ale.getId()); + eb.setTimestamp(ale.getTimeCreated()); + + performChecksThenBuildAndSendEmbed(event, eb, channelIdToSendTo); + } +} diff --git a/src/main/java/io/github/eggy03/papertrail/bot/handlers/auditlog/WebhookEventHandler.java b/src/main/java/io/github/eggy03/papertrail/bot/handlers/auditlog/WebhookEventHandler.java new file mode 100644 index 00000000..0b504faf --- /dev/null +++ b/src/main/java/io/github/eggy03/papertrail/bot/handlers/auditlog/WebhookEventHandler.java @@ -0,0 +1,195 @@ +package io.github.eggy03.papertrail.bot.handlers.auditlog; + +import io.github.eggy03.papertrail.bot.listeners.auditlog.GuildAuditLogEntryCreateEventHandler; +import io.github.eggy03.papertrail.bot.utils.auditlog.GuildUtils; +import io.github.eggy03.papertrail.bot.utils.auditlog.WebhookUtils; +import io.github.eggy03.papertrail.sdk.client.AuditLogRegistrationClient; +import io.github.eggy03.papertrail.sdk.entity.AuditLogRegistrationEntity; +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.inject.Inject; +import lombok.NonNull; +import lombok.extern.slf4j.Slf4j; +import net.dv8tion.jda.api.EmbedBuilder; +import net.dv8tion.jda.api.audit.AuditLogEntry; +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 net.dv8tion.jda.api.utils.MarkdownUtil; +import org.apache.commons.lang3.StringUtils; + +import java.awt.Color; + +@ApplicationScoped +@Slf4j +@SuppressWarnings("java:S1192") +public final class WebhookEventHandler extends GuildAuditLogEntryCreateEventHandler { + + private final @NonNull AuditLogRegistrationClient client; + + @Inject + public WebhookEventHandler(@NonNull AuditLogRegistrationClient client) { + this.client = client; + } + + @NonNull + private String getRegisteredGuildChannel(@NonNull String guildId) { + return client.getRegisteredGuild(guildId) + .map(AuditLogRegistrationEntity::getChannelId).orElse(StringUtils.EMPTY); + + } + + private void performChecksThenBuildAndSendEmbed(@NonNull GuildAuditLogEntryCreateEvent event, @NonNull EmbedBuilder embedBuilder, @NonNull String channelIdToSendTo) { + if (!embedBuilder.isValidLength() || embedBuilder.isEmpty()) { + log.warn("Embed is empty or too long (current length: {}).", embedBuilder.length()); + return; + } + + TextChannel sendingChannel = event.getGuild().getTextChannelById(channelIdToSendTo); + if (sendingChannel != null && sendingChannel.canTalk()) { + sendingChannel.sendMessageEmbeds(embedBuilder.build()).queue(); + } + } + + @Override + public void onWebhookCreate(@NonNull GuildAuditLogEntryCreateEvent event) { + String channelIdToSendTo = getRegisteredGuildChannel(event.getGuild().getId()); + if (channelIdToSendTo.isBlank()) return; + + AuditLogEntry ale = event.getEntry(); + + User executor = ale.getJDA().getUserById(ale.getUserIdLong()); + String mentionableExecutor = (executor != null ? executor.getAsMention() : ale.getUserId()); + + EmbedBuilder eb = new EmbedBuilder(); + eb.setTitle("Audit Log Entry | Webhook Create Event"); + eb.setDescription(MarkdownUtil.quoteBlock("Webhook Created By: " + mentionableExecutor)); + eb.setColor(Color.GREEN); + + ale.getChanges().forEach((changeKey, changeValue) -> { + Object oldValue = changeValue.getOldValue(); + Object newValue = changeValue.getNewValue(); + + switch (changeKey) { + + case "type" -> + eb.addField(MarkdownUtil.underline("Webhook Type"), "╰┈➤" + WebhookUtils.resolveWebhookEventType(newValue), false); + case "avatar_hash" -> { + // skip + } + case "channel_id" -> + eb.addField(MarkdownUtil.underline("Channel"), "╰┈➤" + GuildUtils.resolveMentionableChannel(newValue, event), false); + case "name" -> eb.addField(MarkdownUtil.underline("Webhook Name"), "╰┈➤" + newValue, false); + case "application_id" -> eb.addField(MarkdownUtil.underline("Application ID"), "╰┈➤" + newValue, false); + default -> { + eb.addField("Unimplemented Change Key", changeKey, false); + log.info("Unimplemented Change Key on Webhook Create: {}\nOLD_VALUE: {}\nNEW_VALUE: {}", changeKey, oldValue, newValue); + } + } + }); + + eb.setFooter("Audit Log Entry ID: " + ale.getId()); + eb.setTimestamp(ale.getTimeCreated()); + + performChecksThenBuildAndSendEmbed(event, eb, channelIdToSendTo); + } + + @Override + public void onWebhookUpdate(@NonNull GuildAuditLogEntryCreateEvent event) { + String channelIdToSendTo = getRegisteredGuildChannel(event.getGuild().getId()); + if (channelIdToSendTo.isBlank()) return; + + AuditLogEntry ale = event.getEntry(); + + User executor = ale.getJDA().getUserById(ale.getUserIdLong()); + String mentionableExecutor = (executor != null ? executor.getAsMention() : ale.getUserId()); + + EmbedBuilder eb = new EmbedBuilder(); + eb.setTitle("Audit Log Entry | Webhook Update Event"); + eb.setDescription(MarkdownUtil.quoteBlock("Webhook Updated By: " + mentionableExecutor)); + eb.setColor(Color.YELLOW); + + ale.getChanges().forEach((changeKey, changeValue) -> { + Object oldValue = changeValue.getOldValue(); + Object newValue = changeValue.getNewValue(); + + switch (changeKey) { + + case "type" -> { + eb.addField(MarkdownUtil.underline("Old Webhook Type"), "╰┈➤" + WebhookUtils.resolveWebhookEventType(oldValue), true); + eb.addField(MarkdownUtil.underline("New Webhook Type"), "╰┈➤" + WebhookUtils.resolveWebhookEventType(newValue), true); + eb.addBlankField(true); + } + case "avatar_hash" -> + eb.addField(MarkdownUtil.underline("Avatar"), "╰┈➤Avatar has been updated", false); + + case "channel_id" -> { + eb.addField(MarkdownUtil.underline("Old Channel"), "╰┈➤" + GuildUtils.resolveMentionableChannel(oldValue, event), true); + eb.addField(MarkdownUtil.underline("New Channel"), "╰┈➤" + GuildUtils.resolveMentionableChannel(newValue, event), true); + eb.addBlankField(true); + } + case "name" -> { + eb.addField(MarkdownUtil.underline("Old Webhook Name"), "╰┈➤" + oldValue, true); + eb.addField(MarkdownUtil.underline("New Webhook Name"), "╰┈➤" + newValue, true); + eb.addBlankField(true); + } + case "application_id" -> { + eb.addField(MarkdownUtil.underline("Old Application ID"), "╰┈➤" + oldValue, true); + eb.addField(MarkdownUtil.underline("New Application ID"), "╰┈➤" + newValue, true); + eb.addBlankField(true); + } + default -> { + eb.addField("Unimplemented Change Key", changeKey, false); + log.info("Unimplemented Change Key on Webhook Update: {}\nOLD_VALUE: {}\nNEW_VALUE: {}", changeKey, oldValue, newValue); + } + } + }); + + eb.setFooter("Audit Log Entry ID: " + ale.getId()); + eb.setTimestamp(ale.getTimeCreated()); + + performChecksThenBuildAndSendEmbed(event, eb, channelIdToSendTo); + } + + @Override + public void onWebhookDelete(@NonNull GuildAuditLogEntryCreateEvent event) { + String channelIdToSendTo = getRegisteredGuildChannel(event.getGuild().getId()); + if (channelIdToSendTo.isBlank()) return; + + AuditLogEntry ale = event.getEntry(); + + User executor = ale.getJDA().getUserById(ale.getUserIdLong()); + String mentionableExecutor = (executor != null ? executor.getAsMention() : ale.getUserId()); + + EmbedBuilder eb = new EmbedBuilder(); + eb.setTitle("Audit Log Entry | Webhook Remove Event"); + eb.setDescription(MarkdownUtil.quoteBlock("Webhook Removed By: " + mentionableExecutor)); + eb.setColor(Color.RED); + + ale.getChanges().forEach((changeKey, changeValue) -> { + Object oldValue = changeValue.getOldValue(); + Object newValue = changeValue.getNewValue(); + + switch (changeKey) { + + case "type" -> + eb.addField(MarkdownUtil.underline("Webhook Type"), "╰┈➤" + WebhookUtils.resolveWebhookEventType(oldValue), false); + case "avatar_hash" -> { + // skip + } + case "channel_id" -> + eb.addField(MarkdownUtil.underline("Channel"), "╰┈➤" + GuildUtils.resolveMentionableChannel(oldValue, event), false); + case "name" -> eb.addField(MarkdownUtil.underline("Webhook Name"), "╰┈➤" + oldValue, false); + case "application_id" -> eb.addField(MarkdownUtil.underline("Application ID"), "╰┈➤" + oldValue, false); + default -> { + eb.addField("Unimplemented Change Key", changeKey, false); + log.info("Unimplemented Change Key on Webhook Remove: {}\nOLD_VALUE: {}\nNEW_VALUE: {}", changeKey, oldValue, newValue); + } + } + }); + + eb.setFooter("Audit Log Entry ID: " + ale.getId()); + eb.setTimestamp(ale.getTimeCreated()); + + performChecksThenBuildAndSendEmbed(event, eb, channelIdToSendTo); + } +} diff --git a/src/main/java/io/github/eggy03/papertrail/bot/handlers/command/AuditLogSetupCommandHandler.java b/src/main/java/io/github/eggy03/papertrail/bot/handlers/command/AuditLogSetupCommandHandler.java new file mode 100644 index 00000000..a3ef703a --- /dev/null +++ b/src/main/java/io/github/eggy03/papertrail/bot/handlers/command/AuditLogSetupCommandHandler.java @@ -0,0 +1,119 @@ +package io.github.eggy03.papertrail.bot.handlers.command; + +import io.github.eggy03.papertrail.sdk.client.AuditLogRegistrationClient; +import io.github.eggy03.papertrail.sdk.entity.AuditLogRegistrationEntity; +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.inject.Inject; +import lombok.NonNull; +import lombok.extern.slf4j.Slf4j; +import net.dv8tion.jda.api.EmbedBuilder; +import net.dv8tion.jda.api.entities.Guild; +import net.dv8tion.jda.api.entities.channel.middleman.GuildChannel; +import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent; +import net.dv8tion.jda.api.utils.MarkdownUtil; + +import java.awt.Color; +import java.util.Optional; + +@ApplicationScoped +@Slf4j +public final class AuditLogSetupCommandHandler { + + private final @NonNull AuditLogRegistrationClient client; + + @Inject + public AuditLogSetupCommandHandler(@NonNull AuditLogRegistrationClient client) { + this.client = client; + } + + public void setAuditLogging(@NonNull SlashCommandInteractionEvent event) { + + Guild callerGuild = event.getGuild(); + GuildChannel callerChannel = event.getChannel().asTextChannel(); + if (callerGuild == null) { + log.warn("An audit log set command may have been called outside of a guild. This should not happen."); + return; + } + + // acknowledge this interaction before calling the API + event.deferReply().queue(); + + // Call the API to register the guild and the channel + boolean success = client.registerGuild(callerGuild.getId(), callerChannel.getId()); + + EmbedBuilder eb = new EmbedBuilder(); + eb.setTitle("Audit Log Registration Process"); + + if (success) { + eb.setColor(Color.GREEN); + eb.addField(MarkdownUtil.underline("Registration Success"), MarkdownUtil.codeblock("All audit log info will be logged here"), false); + } else { + eb.setColor(Color.YELLOW); + eb.addField(MarkdownUtil.underline("Registration Failure"), MarkdownUtil.codeblock("Channel could not be registered. Check if a channel in this guild is already registered for logging."), false); + } + + event.getHook().editOriginalEmbeds(eb.build()).queue(); + } + + public void viewAuditLoggingChannel(@NonNull SlashCommandInteractionEvent event) { + + Guild callerGuild = event.getGuild(); + if (callerGuild == null) { + log.warn("An audit log view command may have been called outside of a guild. This should not happen."); + return; + } + + // acknowledge this interaction before calling the API + event.deferReply().queue(); + + // Call the API to retrieve the registered channel + Optional response = client.getRegisteredGuild(callerGuild.getId()); + + EmbedBuilder eb = new EmbedBuilder(); + eb.setTitle("View Existing Audit Log Configuration"); + + // if there is no channel_id for the given guild_id returned by the API, then inform + // the user of the same, else link the channel that has been registered + response.ifPresentOrElse(success -> { + String registeredChannelId = success.getChannelId(); + GuildChannel registeredChannel = event.getJDA().getGuildChannelById(registeredChannelId); + String registeredChannelName = registeredChannel != null ? registeredChannel.getName() : registeredChannelId; + + eb.setColor(Color.CYAN); + eb.addField(MarkdownUtil.underline("Success"), MarkdownUtil.codeblock(registeredChannelName + " is found to be registered as the audit log channel"), false); + }, () -> { + eb.setColor(Color.YELLOW); + eb.addField(MarkdownUtil.underline("Warning"), MarkdownUtil.codeblock("No channel has been registered for audit logs"), false); + }); + + event.getHook().editOriginalEmbeds(eb.build()).queue(); + } + + public void unsetAuditLogging(@NonNull SlashCommandInteractionEvent event) { + + Guild callerGuild = event.getGuild(); + if (callerGuild == null) { + log.warn("An audit log unset command may have been called outside of a guild. This should not happen."); + return; + } + + // acknowledge this interaction before calling the API + event.deferReply().queue(); + + // Call the API to unregister guild + boolean success = client.deleteRegisteredGuild(callerGuild.getId()); + + EmbedBuilder eb = new EmbedBuilder(); + eb.setTitle("Audit Log Removal Process"); + + if (success) { + eb.setColor(Color.GREEN); + eb.addField(MarkdownUtil.underline("Removal Success"), MarkdownUtil.codeblock("Channel successfully unset"), false); + } else { + eb.setColor(Color.YELLOW); + eb.addField(MarkdownUtil.underline("Removal Failure"), MarkdownUtil.codeblock("Channel could not be unset. This may be because no channel has been registered in this guild yet."), false); + } + + event.getHook().editOriginalEmbeds(eb.build()).queue(); + } +} diff --git a/src/main/java/io/github/eggy03/papertrail/bot/handlers/command/BotSetupInstructionCommandHandler.java b/src/main/java/io/github/eggy03/papertrail/bot/handlers/command/BotSetupInstructionCommandHandler.java new file mode 100644 index 00000000..9e1e2cd3 --- /dev/null +++ b/src/main/java/io/github/eggy03/papertrail/bot/handlers/command/BotSetupInstructionCommandHandler.java @@ -0,0 +1,70 @@ +package io.github.eggy03.papertrail.bot.handlers.command; + +import io.github.eggy03.papertrail.bot.constant.ProjectInfo; +import jakarta.enterprise.context.ApplicationScoped; +import lombok.NonNull; +import net.dv8tion.jda.api.EmbedBuilder; +import net.dv8tion.jda.api.entities.MessageEmbed; +import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent; + +import java.awt.Color; +import java.time.Instant; + +@ApplicationScoped +public final class BotSetupInstructionCommandHandler { + + public void sendInstructions(@NonNull SlashCommandInteractionEvent event) { + + EmbedBuilder eb = new EmbedBuilder(); + eb.setTitle("🛠️ Setup Guide for " + ProjectInfo.APPNAME); + eb.setDescription("Follow the instructions below to set up the bot in your server."); + eb.setColor(Color.decode("#38e8bc")); + + eb.addField("1️⃣ Set Audit Log Channel", + "Use `/auditlog set` to **register this channel** for receiving audit log events.", + false); + + eb.addField("2️⃣ View Audit Log Channel", + "Use `/auditlog view` to **see which channel** is currently receiving audit logs.", + false); + + eb.addField("3️⃣ Remove Audit Log Channel", + "Use `/auditlog remove` to **stop logging** events and remove the registered channel.", + false); + + eb.addField("🔒 Permissions", + "These three commands require the **Administrator** permission.", + false); + + eb.addBlankField(false); + + eb.addField("4️⃣ Set Message Log Channel", + "Use `/messagelog set` to **register this channel** for receiving message logs.", + false); + + eb.addField("5️⃣ View Message Log Channel", + "Use `/messagelog view` to **see which channel** is currently receiving message logs.", + false); + + eb.addField("6️⃣ Remove Message Log Channel", + "Use `/messagelog remove` to **stop logging** messages and remove the registered channel.", + false); + + eb.addField("🔒 Permissions", + "These three commands require the **Administrator** permission.", + false); + + eb.addBlankField(false); + + eb.addField("7️⃣ View Server Stats", + "Use `/stats` to **view useful server information**, including member count, channel count, and more.", + false); + + eb.addField("📬 Need help?", "Create an issue on [GitHub](" + ProjectInfo.PROJECT_ISSUE_LINK + ")", false); + eb.setFooter(ProjectInfo.APPNAME + " " + ProjectInfo.VERSION); + eb.setTimestamp(Instant.now()); + + MessageEmbed mb = eb.build(); + event.replyEmbeds(mb).queue(); + } +} diff --git a/src/main/java/io/github/eggy03/papertrail/bot/handlers/command/DebugCommandHandler.java b/src/main/java/io/github/eggy03/papertrail/bot/handlers/command/DebugCommandHandler.java new file mode 100644 index 00000000..29c15014 --- /dev/null +++ b/src/main/java/io/github/eggy03/papertrail/bot/handlers/command/DebugCommandHandler.java @@ -0,0 +1,161 @@ +package io.github.eggy03.papertrail.bot.handlers.command; + +import io.github.eggy03.papertrail.bot.constant.ProjectInfo; +import io.github.eggy03.papertrail.bot.utils.BooleanUtils; +import io.github.eggy03.papertrail.sdk.client.AuditLogRegistrationClient; +import io.github.eggy03.papertrail.sdk.client.MessageLogRegistrationClient; +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.inject.Inject; +import lombok.NonNull; +import net.dv8tion.jda.api.EmbedBuilder; +import net.dv8tion.jda.api.JDA; +import net.dv8tion.jda.api.Permission; +import net.dv8tion.jda.api.entities.Guild; +import net.dv8tion.jda.api.entities.Member; +import net.dv8tion.jda.api.entities.channel.middleman.GuildChannel; +import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent; +import net.dv8tion.jda.api.utils.MarkdownUtil; + +import java.awt.Color; +import java.time.Instant; +import java.util.EnumSet; +import java.util.Set; + +@ApplicationScoped +public final class DebugCommandHandler { + + private final @NonNull AuditLogRegistrationClient auditLogRegistrationClient; + private final @NonNull MessageLogRegistrationClient messageLogRegistrationClient; + + // necessary permissions for the bot to function + @NonNull + private final Set necessaryPermissions = EnumSet.of( + Permission.VIEW_CHANNEL, + Permission.VIEW_AUDIT_LOGS, + Permission.MANAGE_SERVER, + Permission.MESSAGE_SEND, + Permission.MESSAGE_SEND_IN_THREADS, + Permission.MESSAGE_EMBED_LINKS, + Permission.MESSAGE_HISTORY + ); + + @Inject + public DebugCommandHandler(@NonNull AuditLogRegistrationClient auditLogRegistrationClient, @NonNull MessageLogRegistrationClient messageLogRegistrationClient) { + this.auditLogRegistrationClient = auditLogRegistrationClient; + this.messageLogRegistrationClient = messageLogRegistrationClient; + } + + public void sendDebugInfo(@NonNull SlashCommandInteractionEvent event, @NonNull Guild guild, @NonNull Member member) { + GuildChannel channel = event.getGuildChannel(); + + // acknowledge this interaction but reply when the embed's been built + event.deferReply().queue(); + + EmbedBuilder eb = new EmbedBuilder(); + eb.setTitle("Debug Info"); + eb.setDescription("Server: " + guild.getName()); + eb.setColor(Color.GRAY); + + eb.addField(MarkdownUtil.underline("Bot Permissions"), MarkdownUtil.quoteBlock(getBotPermissions(guild)), true); + eb.addField(MarkdownUtil.underline("Channel Permissions"), MarkdownUtil.quoteBlock(getBotPermissionsInCurrentChannel(guild, channel)), true); + eb.addField(MarkdownUtil.underline("Server Info"), MarkdownUtil.quoteBlock(getServerInfo(guild, channel)), true); + + eb.addField(MarkdownUtil.underline("User Info"), MarkdownUtil.quoteBlock(getCallerInfo(member)), true); + eb.addField(MarkdownUtil.underline("Bot Info"), MarkdownUtil.quoteBlock(getBotInfo(event)), true); + eb.addField(MarkdownUtil.underline("Configuration Info"), MarkdownUtil.quoteBlock(getConfigurationInfo(guild)), true); + + eb.setFooter(ProjectInfo.APPNAME + " " + ProjectInfo.VERSION); + eb.setTimestamp(Instant.now()); + + event.getHook().editOriginalEmbeds(eb.build()).queue(); + } + + @NonNull + private String getBotPermissions(@NonNull Guild guild) { + return formatPermissions(guild.getSelfMember().getPermissions()); + } + + @NonNull + private String getBotPermissionsInCurrentChannel(@NonNull Guild guild, @NonNull GuildChannel channel) { + return formatPermissions(guild.getSelfMember().getPermissions(channel)); + } + + @NonNull + private String formatPermissions(@NonNull EnumSet grantedGuildOrChannelPermissions) { + // gets all the permissions granted to the bot in the server as a whole or a particular channel + EnumSet grantedPermissions = EnumSet.copyOf(grantedGuildOrChannelPermissions); + + // this will + // 1) REMOVE the UNNECESSARY GRANTED PERMISSIONS (permissions which are granted but not required for bot to function) + // 2) RETAIN those GRANTED PERMISSIONS that match with the NECESSARY ONES + // there may be cases where GRANTED PERMISSIONS is NOT a perfect SUPERSET of NECESSARY PERMISSIONS + // this indicates that some NECESSARY PERMISSIONS have been DENIED + grantedPermissions.retainAll(necessaryPermissions); + + // create a copy of necessary permissions + EnumSet deniedPermissions = EnumSet.copyOf(necessaryPermissions); + // now if you calculate necessary - granted, you will get the set of necessary permissions which are DENIED + deniedPermissions.removeAll(grantedPermissions); + + StringBuilder permString = new StringBuilder(); + grantedPermissions.forEach(permission -> + permString.append("✅ - ") + .append(permission.getName()) + .append("\n") + ); + + deniedPermissions.forEach(permission -> + permString.append("❌ - ") + .append(permission.getName()) + .append("\n") + ); + + return permString.toString().trim(); + } + + @NonNull + private String getServerInfo(@NonNull Guild guild, @NonNull GuildChannel channel) { + return "Server Name: " + MarkdownUtil.underline(guild.getName()) + "\n" + + "Server ID: " + MarkdownUtil.underline(guild.getId()) + "\n" + + "Current Channel Name: " + MarkdownUtil.underline(channel.getName()) + "\n" + + "Current Channel ID: " + MarkdownUtil.underline(channel.getId()); + } + + @NonNull + private String getCallerInfo(@NonNull Member member) { + return "User Name: " + MarkdownUtil.underline(member.getUser().getEffectiveName()) + "\n" + + "User ID: " + MarkdownUtil.underline(member.getId()) + "\n" + + "Is Administrator: " + MarkdownUtil.underline(BooleanUtils.formatToYesOrNo(member.hasPermission(Permission.ADMINISTRATOR))); + } + + @NonNull + private String getBotInfo(@NonNull SlashCommandInteractionEvent event) { + JDA.ShardInfo shardInfo = event.getJDA().getShardInfo(); + return "Current Shard ID: " + shardInfo.getShardId() + "\n" + + "Total Shards: " + shardInfo.getShardTotal(); + } + + @NonNull + private String getConfigurationInfo(@NonNull Guild guild) { + + StringBuilder sb = new StringBuilder(); + + auditLogRegistrationClient.getRegisteredGuild(guild.getId()).ifPresentOrElse(entity -> { + GuildChannel channel = guild.getGuildChannelById(entity.getChannelId()); + if (channel != null) + sb.append("Registered Audit Log Channel: ").append(MarkdownUtil.underline(channel.getName())).append("\n"); + else + sb.append("Registered Audit Log Channel: ").append(MarkdownUtil.underline("Registered Channel Unresolvable")).append("\n"); + }, () -> sb.append(MarkdownUtil.underline("No Channel Registered For Audit Logging")).append("\n")); + + messageLogRegistrationClient.getRegisteredGuild(guild.getId()).ifPresentOrElse(entity -> { + GuildChannel channel = guild.getGuildChannelById(entity.getChannelId()); + if (channel != null) + sb.append("Registered Message Log Channel: ").append(MarkdownUtil.underline(channel.getName())); + else + sb.append("Registered Message Log Channel: ").append(MarkdownUtil.underline("Registered Channel Unresolvable")); + }, () -> sb.append(MarkdownUtil.underline("No Channel Registered For Message Logging"))); + + return sb.toString(); + } +} diff --git a/src/main/java/io/github/eggy03/papertrail/bot/handlers/command/MessageLogSetupCommandHandler.java b/src/main/java/io/github/eggy03/papertrail/bot/handlers/command/MessageLogSetupCommandHandler.java new file mode 100644 index 00000000..92721256 --- /dev/null +++ b/src/main/java/io/github/eggy03/papertrail/bot/handlers/command/MessageLogSetupCommandHandler.java @@ -0,0 +1,119 @@ +package io.github.eggy03.papertrail.bot.handlers.command; + +import io.github.eggy03.papertrail.sdk.client.MessageLogRegistrationClient; +import io.github.eggy03.papertrail.sdk.entity.MessageLogRegistrationEntity; +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.inject.Inject; +import lombok.NonNull; +import lombok.extern.slf4j.Slf4j; +import net.dv8tion.jda.api.EmbedBuilder; +import net.dv8tion.jda.api.entities.Guild; +import net.dv8tion.jda.api.entities.channel.middleman.GuildChannel; +import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent; +import net.dv8tion.jda.api.utils.MarkdownUtil; + +import java.awt.Color; +import java.util.Optional; + +@ApplicationScoped +@Slf4j +public final class MessageLogSetupCommandHandler { + + private final @NonNull MessageLogRegistrationClient client; + + @Inject + public MessageLogSetupCommandHandler(@NonNull MessageLogRegistrationClient client) { + this.client = client; + } + + public void setMessageLogging(@NonNull SlashCommandInteractionEvent event) { + + Guild callerGuild = event.getGuild(); + GuildChannel callerChannel = event.getChannel().asTextChannel(); + if (callerGuild == null) { + log.warn("A message log set command may have been called outside of a guild. This should not happen."); + return; + } + + // acknowledge this interaction before calling the API + event.deferReply().queue(); + + // Call the API to register guild for message logging + boolean success = client.registerGuild(callerGuild.getId(), callerChannel.getId()); + + EmbedBuilder eb = new EmbedBuilder(); + eb.setTitle("Message Log Registration Process"); + + if (success) { + eb.setColor(Color.GREEN); + eb.addField(MarkdownUtil.underline("Registration Success"), MarkdownUtil.codeblock("All edited and deleted messages will be logged here"), false); + } else { + eb.setColor(Color.YELLOW); + eb.addField(MarkdownUtil.underline("Registration Failure"), MarkdownUtil.codeblock("Channel could not be registered. Check if a channel in this guild is already registered for logging."), false); + + } + + event.getHook().editOriginalEmbeds(eb.build()).queue(); + } + + public void viewMessageLoggingChannel(@NonNull SlashCommandInteractionEvent event) { + + Guild callerGuild = event.getGuild(); + if (callerGuild == null) { + log.warn("A message log view command may have been called outside of a guild. This should not happen."); + return; + } + + // acknowledge this interaction before calling the API + event.deferReply().queue(); + + // Call the API to check for registered guild + Optional response = client.getRegisteredGuild(callerGuild.getId()); + + EmbedBuilder eb = new EmbedBuilder(); + eb.setTitle("View Existing Message Log Configuration"); + + response.ifPresentOrElse(success -> { + + String registeredChannelId = success.getChannelId(); + GuildChannel registeredChannel = event.getJDA().getGuildChannelById(registeredChannelId); + String registeredChannelName = registeredChannel != null ? registeredChannel.getName() : registeredChannelId; + + eb.setColor(Color.CYAN); + eb.addField(MarkdownUtil.underline("Success"), MarkdownUtil.codeblock(registeredChannelName + " is found to be registered as the message log channel"), false); + }, () -> { + eb.setColor(Color.YELLOW); + eb.addField(MarkdownUtil.underline("Warning"), MarkdownUtil.codeblock("No channel has been registered for message logs"), false); + }); + + event.getHook().editOriginalEmbeds(eb.build()).queue(); + } + + public void unsetMessageLogging(@NonNull SlashCommandInteractionEvent event) { + + Guild callerGuild = event.getGuild(); + if (callerGuild == null) { + log.warn("A message log unset command may have been called outside of a guild. This should not happen."); + return; + } + + // acknowledge this interaction before calling the API + event.deferReply().queue(); + + // Call the API to unregister guild + boolean success = client.deleteRegisteredGuild(callerGuild.getId()); + + EmbedBuilder eb = new EmbedBuilder(); + eb.setTitle("Message Log Removal Process"); + + if (success) { + eb.setColor(Color.GREEN); + eb.addField(MarkdownUtil.underline("Removal Success"), MarkdownUtil.codeblock("Channel successfully unset"), false); + } else { + eb.setColor(Color.YELLOW); + eb.addField(MarkdownUtil.underline("Removal Failure"), MarkdownUtil.codeblock("Channel could not be unset. This may be because no channel has been registered in this guild yet."), false); + } + + event.getHook().editOriginalEmbeds(eb.build()).queue(); + } +} diff --git a/src/main/java/io/github/eggy03/papertrail/bot/handlers/command/ServerStatCommandHandler.java b/src/main/java/io/github/eggy03/papertrail/bot/handlers/command/ServerStatCommandHandler.java new file mode 100644 index 00000000..3c0e9784 --- /dev/null +++ b/src/main/java/io/github/eggy03/papertrail/bot/handlers/command/ServerStatCommandHandler.java @@ -0,0 +1,93 @@ +package io.github.eggy03.papertrail.bot.handlers.command; + +import jakarta.enterprise.context.ApplicationScoped; +import lombok.NonNull; +import net.dv8tion.jda.api.EmbedBuilder; +import net.dv8tion.jda.api.entities.Guild; +import net.dv8tion.jda.api.entities.Member; +import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent; +import net.dv8tion.jda.api.utils.MarkdownUtil; +import org.jetbrains.annotations.Nullable; + +import java.awt.Color; +import java.time.Instant; +import java.util.List; + +@ApplicationScoped +public final class ServerStatCommandHandler { + + public void sendServerStats(@NonNull SlashCommandInteractionEvent event, @NonNull Guild guild) { + // acknowledge this interaction but reply when the embed's been built + event.deferReply().queue(); + + EmbedBuilder eb = new EmbedBuilder(); + eb.setTitle("Server Statistics"); + eb.setDescription("Statistics For: " + guild.getName()); + eb.setThumbnail(guild.getIconUrl()); + eb.setColor(Color.PINK); + + eb.addField(MarkdownUtil.underline("Guild Owner"), MarkdownUtil.quoteBlock(getGuildOwner(guild)), false); + eb.addField(MarkdownUtil.underline("Guild Created On"), MarkdownUtil.quoteBlock(getGuildCreationDate(guild)), false); + eb.addField(MarkdownUtil.underline("Guild Vanity URL"), MarkdownUtil.quoteBlock(getGuildVanityUrl(guild)), false); + eb.addField(MarkdownUtil.underline("Member Stats"), MarkdownUtil.quoteBlock(getMemberAndBotCount(guild)), false); + eb.addField(MarkdownUtil.underline("Guild Boosters"), MarkdownUtil.quoteBlock(getBoosters(guild)), false); + eb.addField(MarkdownUtil.underline("Guild Boost Count"), MarkdownUtil.quoteBlock(String.valueOf(guild.getBoostCount())), true); + eb.addField(MarkdownUtil.underline("Booster Role"), MarkdownUtil.quoteBlock(getBoosterRole(guild)), true); + eb.addField(MarkdownUtil.underline("Boost Tier"), MarkdownUtil.quoteBlock(guild.getBoostTier().name()), true); + eb.addField(MarkdownUtil.underline("Locale"), MarkdownUtil.quoteBlock(guild.getLocale().getNativeName()), true); + eb.addField(MarkdownUtil.underline("Verification"), MarkdownUtil.quoteBlock(guild.getVerificationLevel().name()), true); + eb.addField(MarkdownUtil.underline("Roles"), MarkdownUtil.quoteBlock(String.valueOf(guild.getRoles().size())), true); + eb.addField(MarkdownUtil.underline("Categories"), MarkdownUtil.quoteBlock(String.valueOf(guild.getCategories().size())), true); + eb.addField(MarkdownUtil.underline("Text Channels"), MarkdownUtil.quoteBlock(String.valueOf(guild.getTextChannels().size())), true); + eb.addField(MarkdownUtil.underline("Voice Channels"), MarkdownUtil.quoteBlock(String.valueOf(guild.getVoiceChannels().size())), true); + + eb.setFooter("Requested By: " + getDataRequestingMember(event.getMember())); + eb.setTimestamp(Instant.now()); + + event.getHook().editOriginalEmbeds(eb.build()).queue(); + } + + @NonNull + private String getMemberAndBotCount(@NonNull Guild guild) { + + List memberCache = guild.getMemberCache().asList(); + int allUserCount = memberCache.size(); + int botCount = memberCache.stream().filter(member -> member.getUser().isBot()).toList().size(); + + return "Users: " + (allUserCount - botCount) + "\nBots: " + botCount + "\nTotal: " + allUserCount; + } + + @NonNull + private String getGuildOwner(@NonNull Guild guild) { + Member owner = guild.getOwner(); + + return owner == null ? "N/A" : owner.getAsMention(); + } + + @NonNull + private String getGuildCreationDate(@NonNull Guild guild) { + return ""; + } + + @NonNull + private String getGuildVanityUrl(@NonNull Guild guild) { + return guild.getVanityUrl() == null ? "N/A" : guild.getVanityUrl(); + } + + @NonNull + private String getBoosters(@NonNull Guild guild) { + StringBuilder boosterString = new StringBuilder(); + guild.getBoosters().forEach(booster -> boosterString.append(booster.getAsMention()).append(" ")); + return boosterString.toString().trim().isEmpty() ? "No Boosters" : boosterString.toString().trim(); + } + + @NonNull + private String getBoosterRole(@NonNull Guild guild) { + return guild.getBoostRole() != null ? guild.getBoostRole().getAsMention() : "No Boost Role Found"; + } + + @NonNull + private String getDataRequestingMember(@Nullable Member requestingMember) { + return requestingMember != null ? requestingMember.getEffectiveName() : "N/A"; + } +} diff --git a/src/main/java/io/github/eggy03/papertrail/bot/handlers/guild/GuildBoostEventHandler.java b/src/main/java/io/github/eggy03/papertrail/bot/handlers/guild/GuildBoostEventHandler.java new file mode 100644 index 00000000..5adbcf8c --- /dev/null +++ b/src/main/java/io/github/eggy03/papertrail/bot/handlers/guild/GuildBoostEventHandler.java @@ -0,0 +1,137 @@ +package io.github.eggy03.papertrail.bot.handlers.guild; + +import io.github.eggy03.papertrail.sdk.client.AuditLogRegistrationClient; +import io.github.eggy03.papertrail.sdk.entity.AuditLogRegistrationEntity; +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.inject.Inject; +import lombok.NonNull; +import lombok.extern.slf4j.Slf4j; +import net.dv8tion.jda.api.EmbedBuilder; +import net.dv8tion.jda.api.entities.Guild; +import net.dv8tion.jda.api.entities.Member; +import net.dv8tion.jda.api.entities.channel.concrete.TextChannel; +import net.dv8tion.jda.api.events.guild.GenericGuildEvent; +import net.dv8tion.jda.api.events.guild.member.update.GuildMemberUpdateBoostTimeEvent; +import net.dv8tion.jda.api.events.guild.update.GuildUpdateBoostCountEvent; +import net.dv8tion.jda.api.events.guild.update.GuildUpdateBoostTierEvent; +import net.dv8tion.jda.api.utils.MarkdownUtil; +import org.apache.commons.lang3.StringUtils; + +import java.awt.Color; +import java.time.Instant; +import java.time.OffsetDateTime; + +@ApplicationScoped +@Slf4j +public final class GuildBoostEventHandler { + + private final @NonNull AuditLogRegistrationClient client; + + @Inject + public GuildBoostEventHandler(@NonNull AuditLogRegistrationClient client) { + this.client = client; + } + + @NonNull + private String getRegisteredGuildChannel(@NonNull String guildId) { + return client.getRegisteredGuild(guildId) + .map(AuditLogRegistrationEntity::getChannelId).orElse(StringUtils.EMPTY); + + } + + private void performChecksThenBuildAndSendEmbed(@NonNull GenericGuildEvent event, @NonNull EmbedBuilder embedBuilder, @NonNull String channelIdToSendTo) { + if (!embedBuilder.isValidLength() || embedBuilder.isEmpty()) { + log.warn("Embed is empty or too long (current length: {}).", embedBuilder.length()); + return; + } + + TextChannel sendingChannel = event.getGuild().getTextChannelById(channelIdToSendTo); + if (sendingChannel != null && sendingChannel.canTalk()) { + sendingChannel.sendMessageEmbeds(embedBuilder.build()).queue(); + } + } + + public void handleUpdateBoostTier(@NonNull GuildUpdateBoostTierEvent event) { + String channelIdToSendTo = getRegisteredGuildChannel(event.getGuild().getId()); + if (channelIdToSendTo.isBlank()) return; + + Guild guild = event.getGuild(); + + EmbedBuilder eb = new EmbedBuilder(); + eb.setTitle("Audit Log Entry | Server Boost Tier Update"); + eb.setDescription(MarkdownUtil.quoteBlock("Guild Boost Tier Updated\nTarget Guild: " + guild.getName())); + eb.setThumbnail(guild.getIconUrl()); + eb.setColor(Color.YELLOW); + + Guild.BoostTier oldBoostTier = event.getOldBoostTier(); + Guild.BoostTier newBoostTier = event.getNewBoostTier(); + + String oldTier = "**Tier:** " + oldBoostTier.name() + "\n" + + "**Max Emojis:** " + oldBoostTier.getMaxEmojis() + "\n" + + "**Max File Size:** " + oldBoostTier.getMaxFileSize() + "\n" + + "**Max Bitrate:** " + oldBoostTier.getMaxBitrate(); + + String newTier = "**Tier:** " + newBoostTier.name() + "\n" + + "**Max Emojis:** " + newBoostTier.getMaxEmojis() + "\n" + + "**Max File Size:** " + newBoostTier.getMaxFileSize() + "\n" + + "**Max Bitrate:** " + newBoostTier.getMaxBitrate(); + + eb.addField(MarkdownUtil.underline("Old Boost Tier Information"), oldTier, false); + eb.addField(MarkdownUtil.underline("New Boost Tier Information"), newTier, false); + + eb.setFooter(guild.getName()); + eb.setTimestamp(Instant.now()); + + performChecksThenBuildAndSendEmbed(event, eb, channelIdToSendTo); + } + + public void handleUpdateBoostCount(@NonNull GuildUpdateBoostCountEvent event) { + String channelIdToSendTo = getRegisteredGuildChannel(event.getGuild().getId()); + if (channelIdToSendTo.isBlank()) return; + + Guild guild = event.getGuild(); + + EmbedBuilder eb = new EmbedBuilder(); + eb.setTitle("Audit Log Entry | Server Boost Event"); + eb.setDescription(MarkdownUtil.quoteBlock("Guild Boost Count Updated\nTarget Guild: " + guild.getName())); + eb.setThumbnail(guild.getIconUrl()); + eb.setColor(Color.YELLOW); + + eb.addField(MarkdownUtil.underline("Old Boost Count"), "╰┈➤" + event.getOldBoostCount(), false); + eb.addField(MarkdownUtil.underline("New Boost Count"), "╰┈➤" + event.getNewBoostCount(), false); + + eb.setFooter(guild.getName()); + eb.setTimestamp(Instant.now()); + + performChecksThenBuildAndSendEmbed(event, eb, channelIdToSendTo); + } + + public void handleMemberUpdateBoostTime(@NonNull GuildMemberUpdateBoostTimeEvent event) { + String channelIdToSendTo = getRegisteredGuildChannel(event.getGuild().getId()); + if (channelIdToSendTo.isBlank()) return; + + Member member = event.getMember(); + Guild guild = event.getGuild(); + + String mentionableMember = member.getAsMention(); + + OffsetDateTime newBoostTime = event.getNewTimeBoosted(); // Will be null if the member stopped boosting + + EmbedBuilder eb = new EmbedBuilder(); + eb.setTitle("Audit Log Entry | Server Boost Event"); + eb.setThumbnail(guild.getIconUrl()); + + if (newBoostTime != null) { + eb.setDescription(MarkdownUtil.quoteBlock("Booster Gained: " + mentionableMember + "\nTarget Server: " + guild.getName())); + eb.setColor(Color.PINK); + } else { + eb.setDescription(MarkdownUtil.quoteBlock("Booster Lost: " + mentionableMember + "\nTarget Server: " + guild.getName())); + eb.setColor(Color.GRAY); + } + + eb.setFooter(guild.getName()); + eb.setTimestamp(Instant.now()); + + performChecksThenBuildAndSendEmbed(event, eb, channelIdToSendTo); + } +} diff --git a/src/main/java/io/github/eggy03/papertrail/bot/handlers/guild/GuildMemberEventHandler.java b/src/main/java/io/github/eggy03/papertrail/bot/handlers/guild/GuildMemberEventHandler.java new file mode 100644 index 00000000..f170b2b3 --- /dev/null +++ b/src/main/java/io/github/eggy03/papertrail/bot/handlers/guild/GuildMemberEventHandler.java @@ -0,0 +1,122 @@ +package io.github.eggy03.papertrail.bot.handlers.guild; + +import io.github.eggy03.papertrail.bot.utils.BooleanUtils; +import io.github.eggy03.papertrail.bot.utils.DurationUtils; +import io.github.eggy03.papertrail.sdk.client.AuditLogRegistrationClient; +import io.github.eggy03.papertrail.sdk.entity.AuditLogRegistrationEntity; +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.inject.Inject; +import lombok.NonNull; +import lombok.extern.slf4j.Slf4j; +import net.dv8tion.jda.api.EmbedBuilder; +import net.dv8tion.jda.api.entities.Guild; +import net.dv8tion.jda.api.entities.Member; +import net.dv8tion.jda.api.entities.User; +import net.dv8tion.jda.api.entities.channel.concrete.TextChannel; +import net.dv8tion.jda.api.events.guild.GenericGuildEvent; +import net.dv8tion.jda.api.events.guild.member.GuildMemberJoinEvent; +import net.dv8tion.jda.api.events.guild.member.GuildMemberRemoveEvent; +import net.dv8tion.jda.api.utils.MarkdownUtil; +import org.apache.commons.lang3.StringUtils; + +import java.awt.Color; +import java.time.Instant; + +@ApplicationScoped +@Slf4j +public final class GuildMemberEventHandler { + + private final @NonNull AuditLogRegistrationClient client; + + @Inject + public GuildMemberEventHandler(@NonNull AuditLogRegistrationClient client) { + this.client = client; + } + + @NonNull + private String getRegisteredGuildChannel(@NonNull String guildId) { + return client.getRegisteredGuild(guildId) + .map(AuditLogRegistrationEntity::getChannelId).orElse(StringUtils.EMPTY); + + } + + private void performChecksThenBuildAndSendEmbed(@NonNull GenericGuildEvent event, @NonNull EmbedBuilder embedBuilder, @NonNull String channelIdToSendTo) { + if (!embedBuilder.isValidLength() || embedBuilder.isEmpty()) { + log.warn("Embed is empty or too long (current length: {}).", embedBuilder.length()); + return; + } + + TextChannel sendingChannel = event.getGuild().getTextChannelById(channelIdToSendTo); + if (sendingChannel != null && sendingChannel.canTalk()) { + sendingChannel.sendMessageEmbeds(embedBuilder.build()).queue(); + } + } + + public void handleGuildMemberJoin(@NonNull GuildMemberJoinEvent event) { + String channelIdToSendTo = getRegisteredGuildChannel(event.getGuild().getId()); + if (channelIdToSendTo.isBlank()) return; + + Guild guild = event.getGuild(); + User user = event.getUser(); + + EmbedBuilder eb = new EmbedBuilder(); + eb.setTitle("Audit Log Entry | Member Join Event"); + eb.setDescription(MarkdownUtil.quoteBlock("Member Joined: " + user.getName() + "\nGuild: " + guild.getName())); + eb.setThumbnail(user.getEffectiveAvatarUrl()); + eb.setColor(Color.GREEN); + + eb.addField(MarkdownUtil.underline("Member Name"), "╰┈➤" + user.getName(), false); + eb.addField(MarkdownUtil.underline("Member Mention"), "╰┈➤" + user.getAsMention(), false); + eb.addField(MarkdownUtil.underline("Member ID"), "╰┈➤" + user.getId(), false); + eb.addField(MarkdownUtil.underline("Account Created"), "╰┈➤" + DurationUtils.isoToLocalTimeCounter(user.getTimeCreated()), false); + eb.addField(MarkdownUtil.underline("Bot Account"), "╰┈➤" + BooleanUtils.formatToYesOrNo(user.isBot()), false); + + eb.setFooter(event.getGuild().getName()); + eb.setTimestamp(Instant.now()); + + performChecksThenBuildAndSendEmbed(event, eb, channelIdToSendTo); + } + + public void handleGuildMemberRemove(@NonNull GuildMemberRemoveEvent event) { + String channelIdToSendTo = getRegisteredGuildChannel(event.getGuild().getId()); + if (channelIdToSendTo.isBlank()) return; + + Guild guild = event.getGuild(); + User user = event.getUser(); + + EmbedBuilder eb = new EmbedBuilder(); + eb.setTitle("Audit Log Entry | Member Leave Event"); + eb.setDescription(MarkdownUtil.quoteBlock("Member Left: " + user.getName() + "\nGuild: " + guild.getName())); + eb.setThumbnail(user.getEffectiveAvatarUrl()); + eb.setColor(Color.RED); + + eb.addField(MarkdownUtil.underline("Member Name"), "╰┈➤" + user.getName(), false); + eb.addField(MarkdownUtil.underline("Member ID"), "╰┈➤" + user.getId(), false); + eb.addField(MarkdownUtil.underline("Member Account Created"), "╰┈➤" + DurationUtils.isoToLocalTimeCounter(user.getTimeCreated()), false); + eb.addField(MarkdownUtil.underline("Member Joined The Server On"), "╰┈➤" + getMemberJoinDate(event), false); + eb.addField(MarkdownUtil.underline("Member Left The Server On"), "╰┈➤" + getMemberLeaveDate(), false); + + eb.setFooter(event.getGuild().getName()); + eb.setTimestamp(Instant.now()); + + performChecksThenBuildAndSendEmbed(event, eb, channelIdToSendTo); + } + + @NonNull + private String getMemberJoinDate(@NonNull GuildMemberRemoveEvent event) { + + Member member = event.getMember(); + if (member == null) + return "Member not cached"; + + if (member.hasTimeJoined()) + return ""; + + return "Unavailable"; + } + + @NonNull + private String getMemberLeaveDate() { + return ""; + } +} diff --git a/src/main/java/io/github/eggy03/papertrail/bot/listeners/auditlogsupl/helper/guild/GuildPollEventHelper.java b/src/main/java/io/github/eggy03/papertrail/bot/handlers/guild/GuildPollEventHandler.java similarity index 54% rename from src/main/java/io/github/eggy03/papertrail/bot/listeners/auditlogsupl/helper/guild/GuildPollEventHelper.java rename to src/main/java/io/github/eggy03/papertrail/bot/handlers/guild/GuildPollEventHandler.java index d81ee32a..dc1f5fcf 100644 --- a/src/main/java/io/github/eggy03/papertrail/bot/listeners/auditlogsupl/helper/guild/GuildPollEventHelper.java +++ b/src/main/java/io/github/eggy03/papertrail/bot/handlers/guild/GuildPollEventHandler.java @@ -1,24 +1,60 @@ -package io.github.eggy03.papertrail.bot.listeners.auditlogsupl.helper.guild; +package io.github.eggy03.papertrail.bot.handlers.guild; import io.github.eggy03.papertrail.bot.utils.BooleanUtils; +import io.github.eggy03.papertrail.sdk.client.AuditLogRegistrationClient; +import io.github.eggy03.papertrail.sdk.entity.AuditLogRegistrationEntity; +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.inject.Inject; import lombok.NonNull; -import lombok.experimental.UtilityClass; import lombok.extern.slf4j.Slf4j; import net.dv8tion.jda.api.EmbedBuilder; import net.dv8tion.jda.api.entities.channel.concrete.TextChannel; import net.dv8tion.jda.api.entities.messages.MessagePoll; import net.dv8tion.jda.api.events.message.MessageReceivedEvent; import net.dv8tion.jda.api.utils.MarkdownUtil; -import org.jetbrains.annotations.NotNull; +import org.apache.commons.lang3.StringUtils; import java.awt.Color; import java.time.Instant; -@UtilityClass +@ApplicationScoped @Slf4j -public class GuildPollEventHelper { +public final class GuildPollEventHandler { - public static void format(@NonNull MessageReceivedEvent event, @NonNull MessagePoll messagePoll, @NonNull String channelIdToSendTo) { + private final @NonNull AuditLogRegistrationClient client; + + @Inject + public GuildPollEventHandler(@NonNull AuditLogRegistrationClient client) { + this.client = client; + } + + @NonNull + private String getRegisteredGuildChannel(@NonNull String guildId) { + return client.getRegisteredGuild(guildId) + .map(AuditLogRegistrationEntity::getChannelId).orElse(StringUtils.EMPTY); + + } + + private void performChecksThenBuildAndSendEmbed(@NonNull MessageReceivedEvent event, @NonNull EmbedBuilder embedBuilder, @NonNull String channelIdToSendTo) { + if (!embedBuilder.isValidLength() || embedBuilder.isEmpty()) { + log.warn("Embed is empty or too long (current length: {}).", embedBuilder.length()); + return; + } + + TextChannel sendingChannel = event.getGuild().getTextChannelById(channelIdToSendTo); + if (sendingChannel != null && sendingChannel.canTalk()) { + sendingChannel.sendMessageEmbeds(embedBuilder.build()).queue(); + } + } + + public void handlePollCreationEvent(@NonNull MessageReceivedEvent event) { + // check if message has a poll + MessagePoll messagePoll = event.getMessage().getPoll(); + if (messagePoll == null) + return; + + String channelIdToSendTo = getRegisteredGuildChannel(event.getGuild().getId()); + if (channelIdToSendTo.isBlank()) return; EmbedBuilder eb = new EmbedBuilder(); eb.setTitle("Audit Log Entry | Poll Creation Event"); @@ -33,19 +69,12 @@ public static void format(@NonNull MessageReceivedEvent event, @NonNull MessageP eb.setFooter(event.getGuild().getName()); eb.setTimestamp(Instant.now()); - if (!eb.isValidLength() || eb.isEmpty()) { - log.warn("Embed is empty or too long (current length: {}).", eb.length()); - return; - } + performChecksThenBuildAndSendEmbed(event, eb, channelIdToSendTo); - TextChannel sendingChannel = event.getGuild().getTextChannelById(channelIdToSendTo); - if (sendingChannel != null && sendingChannel.canTalk()) { - sendingChannel.sendMessageEmbeds(eb.build()).queue(); - } } - @NotNull - private static String getMessagePollAnswers(@NonNull MessagePoll messagePoll) { + @NonNull + private String getMessagePollAnswers(@NonNull MessagePoll messagePoll) { StringBuilder answers = new StringBuilder(); messagePoll.getAnswers().forEach(answer -> answers @@ -59,8 +88,8 @@ private static String getMessagePollAnswers(@NonNull MessagePoll messagePoll) { return answers.toString().trim(); } - @NotNull - private static String getPollExpiryTime(@NonNull MessagePoll messagePoll) { + @NonNull + private String getPollExpiryTime(@NonNull MessagePoll messagePoll) { return messagePoll.getTimeExpiresAt() != null ? "" : "Never Expires"; diff --git a/src/main/java/io/github/eggy03/papertrail/bot/listeners/auditlogsupl/helper/guild/GuildVoiceEventHelper.java b/src/main/java/io/github/eggy03/papertrail/bot/handlers/guild/GuildVoiceEventHandler.java similarity index 63% rename from src/main/java/io/github/eggy03/papertrail/bot/listeners/auditlogsupl/helper/guild/GuildVoiceEventHelper.java rename to src/main/java/io/github/eggy03/papertrail/bot/handlers/guild/GuildVoiceEventHandler.java index 176bf5a4..543be74e 100644 --- a/src/main/java/io/github/eggy03/papertrail/bot/listeners/auditlogsupl/helper/guild/GuildVoiceEventHelper.java +++ b/src/main/java/io/github/eggy03/papertrail/bot/handlers/guild/GuildVoiceEventHandler.java @@ -1,23 +1,57 @@ -package io.github.eggy03.papertrail.bot.listeners.auditlogsupl.helper.guild; +package io.github.eggy03.papertrail.bot.handlers.guild; +import io.github.eggy03.papertrail.sdk.client.AuditLogRegistrationClient; +import io.github.eggy03.papertrail.sdk.entity.AuditLogRegistrationEntity; +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.inject.Inject; import lombok.NonNull; -import lombok.experimental.UtilityClass; import lombok.extern.slf4j.Slf4j; import net.dv8tion.jda.api.EmbedBuilder; import net.dv8tion.jda.api.entities.Member; import net.dv8tion.jda.api.entities.channel.concrete.TextChannel; import net.dv8tion.jda.api.entities.channel.middleman.AudioChannel; +import net.dv8tion.jda.api.events.guild.GenericGuildEvent; import net.dv8tion.jda.api.events.guild.voice.GuildVoiceUpdateEvent; import net.dv8tion.jda.api.utils.MarkdownUtil; +import org.apache.commons.lang3.StringUtils; import java.awt.Color; import java.time.Instant; -@UtilityClass +@ApplicationScoped @Slf4j -public class GuildVoiceEventHelper { +public final class GuildVoiceEventHandler { - public static void format(@NonNull GuildVoiceUpdateEvent event, @NonNull String channelIdToSendTo) { + private final @NonNull AuditLogRegistrationClient client; + + @Inject + public GuildVoiceEventHandler(@NonNull AuditLogRegistrationClient client) { + this.client = client; + } + + @NonNull + private String getRegisteredGuildChannel(@NonNull String guildId) { + return client.getRegisteredGuild(guildId) + .map(AuditLogRegistrationEntity::getChannelId).orElse(StringUtils.EMPTY); + + } + + private void performChecksThenBuildAndSendEmbed(@NonNull GenericGuildEvent event, @NonNull EmbedBuilder embedBuilder, @NonNull String channelIdToSendTo) { + if (!embedBuilder.isValidLength() || embedBuilder.isEmpty()) { + log.warn("Embed is empty or too long (current length: {}).", embedBuilder.length()); + return; + } + + TextChannel sendingChannel = event.getGuild().getTextChannelById(channelIdToSendTo); + if (sendingChannel != null && sendingChannel.canTalk()) { + sendingChannel.sendMessageEmbeds(embedBuilder.build()).queue(); + } + } + + public void handleVoiceUpdateEvent(@NonNull GuildVoiceUpdateEvent event) { + + String channelIdToSendTo = getRegisteredGuildChannel(event.getGuild().getId()); + if (channelIdToSendTo.isBlank()) return; Member member = event.getMember(); AudioChannel left = event.getOldValue(); // can be null if user joined for first time @@ -61,14 +95,6 @@ public static void format(@NonNull GuildVoiceUpdateEvent event, @NonNull String eb.setFooter(event.getGuild().getName()); eb.setTimestamp(Instant.now()); - if (!eb.isValidLength() || eb.isEmpty()) { - log.warn("Embed is empty or too long (current length: {}).", eb.length()); - return; - } - - TextChannel sendingChannel = event.getGuild().getTextChannelById(channelIdToSendTo); - if (sendingChannel != null && sendingChannel.canTalk()) { - sendingChannel.sendMessageEmbeds(eb.build()).queue(); - } + performChecksThenBuildAndSendEmbed(event, eb, channelIdToSendTo); } } diff --git a/src/main/java/io/github/eggy03/papertrail/bot/handlers/message/GuildMessageEventHandler.java b/src/main/java/io/github/eggy03/papertrail/bot/handlers/message/GuildMessageEventHandler.java new file mode 100644 index 00000000..ea3cc446 --- /dev/null +++ b/src/main/java/io/github/eggy03/papertrail/bot/handlers/message/GuildMessageEventHandler.java @@ -0,0 +1,154 @@ +package io.github.eggy03.papertrail.bot.handlers.message; + +import com.google.common.base.Splitter; +import io.github.eggy03.papertrail.sdk.client.MessageLogContentClient; +import io.github.eggy03.papertrail.sdk.client.MessageLogRegistrationClient; +import io.github.eggy03.papertrail.sdk.entity.MessageLogContentEntity; +import io.github.eggy03.papertrail.sdk.entity.MessageLogRegistrationEntity; +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.inject.Inject; +import lombok.NonNull; +import lombok.extern.slf4j.Slf4j; +import net.dv8tion.jda.api.EmbedBuilder; +import net.dv8tion.jda.api.entities.User; +import net.dv8tion.jda.api.entities.channel.concrete.TextChannel; +import net.dv8tion.jda.api.events.message.GenericMessageEvent; +import net.dv8tion.jda.api.events.message.MessageDeleteEvent; +import net.dv8tion.jda.api.events.message.MessageReceivedEvent; +import net.dv8tion.jda.api.events.message.MessageUpdateEvent; +import net.dv8tion.jda.api.utils.MarkdownUtil; +import org.apache.commons.lang3.StringUtils; + +import java.awt.Color; +import java.time.Instant; +import java.util.List; +import java.util.Optional; + +@ApplicationScoped +@Slf4j +public final class GuildMessageEventHandler { + + private final @NonNull MessageLogRegistrationClient registrationClient; + private final @NonNull MessageLogContentClient contentClient; + + @Inject + public GuildMessageEventHandler(@NonNull MessageLogRegistrationClient registrationClient, @NonNull MessageLogContentClient contentClient) { + this.registrationClient = registrationClient; + this.contentClient = contentClient; + } + + private boolean isGuildRegistered(@NonNull String guildId) { + return registrationClient.getRegisteredGuild(guildId).isPresent(); + } + + @NonNull + private String getRegisteredGuildChannel(@NonNull String guildId) { + return registrationClient.getRegisteredGuild(guildId) + .map(MessageLogRegistrationEntity::getChannelId).orElse(StringUtils.EMPTY); + + } + + private void performChecksThenBuildAndSendEmbed(@NonNull GenericMessageEvent event, @NonNull EmbedBuilder embedBuilder, @NonNull String channelIdToSendTo) { + if (!embedBuilder.isValidLength() || embedBuilder.isEmpty()) { + log.warn("Message Embed is empty or too long (current length: {}).", embedBuilder.length()); + return; + } + + TextChannel sendingChannel = event.getGuild().getTextChannelById(channelIdToSendTo); + if (sendingChannel != null && sendingChannel.canTalk()) { + sendingChannel.sendMessageEmbeds(embedBuilder.build()).queue(); + } + } + + public void handleMessageReceivedEvent(@NonNull MessageReceivedEvent event) { + if (!isGuildRegistered(event.getGuild().getId())) + return; + + String messageId = event.getMessageId(); + String messageContent = event.getMessage().getContentDisplay(); + String authorId = event.getAuthor().getId(); + + contentClient.logMessage(messageId, messageContent, authorId); + } + + public void handleMessageUpdateEvent(@NonNull MessageUpdateEvent event) { + String channelIdToSendTo = getRegisteredGuildChannel(event.getGuild().getId()); + if (channelIdToSendTo.isBlank()) + return; + + // fetch the old message object from the API + Optional oldMessageContentOptional = contentClient.retrieveMessage(event.getMessageId()); + if (oldMessageContentOptional.isEmpty()) + return; + + MessageLogContentEntity oldMessageContentEntity = oldMessageContentOptional.get(); + // Fetch the old message + String oldMessage = oldMessageContentEntity.getMessageContent(); + // fetch the updated message and its author from the event + String updatedMessage = event.getMessage().getContentDisplay(); + String updatedMessageAuthor = event.getAuthor().getAsMention(); + + // Ignore events where the message content wasn't edited (e.g., pin, embed resolve, thread creates and updates) + // This is required since MessageUpdateEvent is triggered in case of pins and embed resolves with no change to content + if (updatedMessage.equals(oldMessage)) + return; + + // Splitting is required because each field in an embed can display only up-to 1024 characters + // A full embed can display up-to 6000 characters + List oldMessageSplits = Splitter.fixedLength(1000).splitToList(oldMessage); + List updatedMessageSplits = Splitter.fixedLength(1000).splitToList(updatedMessage); + + EmbedBuilder eb = new EmbedBuilder(); + eb.setTitle("Message Edit Event"); + eb.setDescription(MarkdownUtil.quoteBlock("Author: " + updatedMessageAuthor + "\n" + "Channel: " + event.getChannel().getAsMention())); + eb.setColor(Color.YELLOW); + + oldMessageSplits.forEach(split -> eb.addField(MarkdownUtil.underline("Old Message"), MarkdownUtil.codeblock(split), false)); + updatedMessageSplits.forEach(split -> eb.addField(MarkdownUtil.underline("New Message"), MarkdownUtil.codeblock(split), false)); + + eb.setFooter(event.getGuild().getName()); + eb.setTimestamp(Instant.now()); + + // update the database with the new message + contentClient.updateMessage(event.getMessageId(), updatedMessage, event.getAuthor().getId()); + + performChecksThenBuildAndSendEmbed(event, eb, channelIdToSendTo); + } + + public void handleMessageDeleteEvent(@NonNull MessageDeleteEvent event) { + String channelIdToSendTo = getRegisteredGuildChannel(event.getGuild().getId()); + if (channelIdToSendTo.isBlank()) + return; + + // fetch the message object from the API which was just deleted + Optional deletedMessageContentOptional = contentClient.retrieveMessage(event.getMessageId()); + if (deletedMessageContentOptional.isEmpty()) + return; + + MessageLogContentEntity deletedMessageContentEntity = deletedMessageContentOptional.get(); + // Fetch the deleted message and it's author id + String deletedMessage = deletedMessageContentEntity.getMessageContent(); + String deletedMessageAuthorId = deletedMessageContentEntity.getAuthorId(); + + User author = event.getJDA().getUserById(deletedMessageAuthorId); + String mentionableAuthor = (author != null ? author.getAsMention() : deletedMessageAuthorId); + + // Splitting is required because each field in an embed can display only up-to 1024 characters + List deletedMessageSplits = Splitter.fixedLength(1000).splitToList(deletedMessage); + + EmbedBuilder eb = new EmbedBuilder(); + eb.setTitle("Message Delete Event"); + eb.setDescription(MarkdownUtil.quoteBlock("Author: " + mentionableAuthor + "\n" + "Channel: " + event.getChannel().getAsMention())); + eb.setColor(Color.RED); + + deletedMessageSplits.forEach(split -> eb.addField(MarkdownUtil.underline("Deleted Message"), MarkdownUtil.codeblock(split), false)); + + eb.setFooter(event.getGuild().getName()); + eb.setTimestamp(Instant.now()); + + // delete the message from the database + contentClient.deleteMessage(event.getMessageId()); + + performChecksThenBuildAndSendEmbed(event, eb, channelIdToSendTo); + } +} diff --git a/src/main/java/io/github/eggy03/papertrail/bot/listeners/auditlog/GuildAuditLogEntryCreateEventHandler.java b/src/main/java/io/github/eggy03/papertrail/bot/listeners/auditlog/GuildAuditLogEntryCreateEventHandler.java new file mode 100644 index 00000000..5548aebf --- /dev/null +++ b/src/main/java/io/github/eggy03/papertrail/bot/listeners/auditlog/GuildAuditLogEntryCreateEventHandler.java @@ -0,0 +1,428 @@ +package io.github.eggy03.papertrail.bot.listeners.auditlog; + +import lombok.NonNull; +import net.dv8tion.jda.api.audit.ActionType; +import net.dv8tion.jda.api.events.guild.GuildAuditLogEntryCreateEvent; + +/** + *

+ * Abstract base class for routing {@link GuildAuditLogEntryCreateEvent} + * instances to their appropriate handler methods. + * Routing is performed by + * {@link #handleEvent(GuildAuditLogEntryCreateEvent)}. + *

+ * + *

+ * {@link GuildAuditLogEntryCreateEvent} is emitted for all actions that + * appear in a Discord guild's audit log. The specific audit log action + * (e.g. BAN, KICK, UNBAN) can be determined from {@link ActionType}. + * This class exposes overridable methods for each supported + * {@link ActionType}, allowing subclasses to implement only the handlers + * they are interested in. + *

+ * + *

+ * Subclasses may override only the event handlers they require. The + * {@code handleEvent(...)} method is responsible for determining which + * handler method should be invoked for a given audit log action. + *

+ * + *

+ * If multiple subclasses are registered as CDI beans and are iterated + * through {@code Instance}, each handler + * instance will independently receive and process the event. + *

+ * + *

+ * For example, if two subclasses override {@code onBan()}, both + * implementations will be executed when a BAN audit log event is + * processed, assuming both handler instances are iterated and invoked. + *

+ * + *

+ * The design philosophy is inspired by JDA's + * {@link net.dv8tion.jda.api.hooks.ListenerAdapter}, providing a simple + * inheritance-based mechanism for handling only the events that are + * relevant to a particular implementation. + *

+ * + *

+ * Example usage: + *

+ * + *
{@code
+ * @ApplicationScoped
+ * public class MyHandler extends GuildAuditLogEntryCreateEventHandler {
+ *
+ *     @Override
+ *     public void onBan(@NonNull GuildAuditLogEntryCreateEvent event,
+ *                       @NonNull String channelIdToSendTo) {
+ *         // your logic here
+ *     }
+ * }
+ * }
+ * + *

+ * Calling {@code handleEvent(...)} on {@code MyHandler} will + * automatically route BAN audit log events to the overridden + * {@code onBan()} method. + *

+ * + *

+ * Multiple handler beans may also extend this class simultaneously. + * These handlers can be dynamically resolved and iterated using: + *

+ * + *
{@code
+ * @Inject
+ * Instance eventHandlerInstance;
+ *
+ * eventHandlerInstance.forEach(handler ->
+ *     handler.handleEvent(event)
+ * );
+ * }
+ * + *

+ * A concrete example of this pattern can be found in + * {@link GuildAuditLogEntryEventListener}. + *

+ */ +public abstract class GuildAuditLogEntryCreateEventHandler { + + public void onAutoModerationFlagToChannel(@NonNull GuildAuditLogEntryCreateEvent event) { + } + + public void onAutoModerationMemberTimeout(@NonNull GuildAuditLogEntryCreateEvent event) { + } + + public void onAutoModerationRuleBlockMessage(@NonNull GuildAuditLogEntryCreateEvent event) { + } + + public void onAutoModerationRuleCreate(@NonNull GuildAuditLogEntryCreateEvent event) { + } + + public void onAutoModerationRuleUpdate(@NonNull GuildAuditLogEntryCreateEvent event) { + } + + public void onAutoModerationRuleDelete(@NonNull GuildAuditLogEntryCreateEvent event) { + } + + public void onKick(@NonNull GuildAuditLogEntryCreateEvent event) { + } + + public void onPrune(@NonNull GuildAuditLogEntryCreateEvent event) { + } + + public void onBan(@NonNull GuildAuditLogEntryCreateEvent event) { + } + + public void onUnban(@NonNull GuildAuditLogEntryCreateEvent event) { + } + + public void onBotAdd(@NonNull GuildAuditLogEntryCreateEvent event) { + } + + public void onChannelCreate(@NonNull GuildAuditLogEntryCreateEvent event) { + } + + public void onChannelUpdate(@NonNull GuildAuditLogEntryCreateEvent event) { + } + + public void onChannelDelete(@NonNull GuildAuditLogEntryCreateEvent event) { + } + + public void onChannelOverrideCreate(@NonNull GuildAuditLogEntryCreateEvent event) { + } + + public void onChannelOverrideUpdate(@NonNull GuildAuditLogEntryCreateEvent event) { + } + + public void onChannelOverrideDelete(@NonNull GuildAuditLogEntryCreateEvent event) { + } + + public void onRoleCreate(@NonNull GuildAuditLogEntryCreateEvent event) { + } + + public void onRoleUpdate(@NonNull GuildAuditLogEntryCreateEvent event) { + } + + public void onRoleDelete(@NonNull GuildAuditLogEntryCreateEvent event) { + } + + public void onEmojiCreate(@NonNull GuildAuditLogEntryCreateEvent event) { + } + + public void onEmojiUpdate(@NonNull GuildAuditLogEntryCreateEvent event) { + } + + public void onEmojiDelete(@NonNull GuildAuditLogEntryCreateEvent event) { + } + + public void onStickerCreate(@NonNull GuildAuditLogEntryCreateEvent event) { + } + + public void onStickerUpdate(@NonNull GuildAuditLogEntryCreateEvent event) { + } + + public void onStickerDelete(@NonNull GuildAuditLogEntryCreateEvent event) { + } + + public void onGuildUpdate(@NonNull GuildAuditLogEntryCreateEvent event) { + } + + public void onGuildProfileUpdate(@NonNull GuildAuditLogEntryCreateEvent event) { + } + + public void onIntegrationCreate(@NonNull GuildAuditLogEntryCreateEvent event) { + } + + public void onIntegrationUpdate(@NonNull GuildAuditLogEntryCreateEvent event) { + } + + public void onIntegrationDelete(@NonNull GuildAuditLogEntryCreateEvent event) { + } + + public void onApplicationCommandPrivilegesUpdate(@NonNull GuildAuditLogEntryCreateEvent event) { + } + + public void onInviteCreate(@NonNull GuildAuditLogEntryCreateEvent event) { + } + + public void onInviteUpdate(@NonNull GuildAuditLogEntryCreateEvent event) { + } + + public void onInviteDelete(@NonNull GuildAuditLogEntryCreateEvent event) { + } + + public void onMemberRoleUpdate(@NonNull GuildAuditLogEntryCreateEvent event) { + } + + public void onMemberUpdate(@NonNull GuildAuditLogEntryCreateEvent event) { + } + + public void onMemberVoiceKick(@NonNull GuildAuditLogEntryCreateEvent event) { + } + + public void onMemberVoiceMove(@NonNull GuildAuditLogEntryCreateEvent event) { + } + + public void onMessagePin(@NonNull GuildAuditLogEntryCreateEvent event) { + } + + public void onMessageUnpin(@NonNull GuildAuditLogEntryCreateEvent event) { + } + + public void onScheduledEventCreate(@NonNull GuildAuditLogEntryCreateEvent event) { + } + + public void onScheduledEventUpdate(@NonNull GuildAuditLogEntryCreateEvent event) { + } + + public void onScheduledEventDelete(@NonNull GuildAuditLogEntryCreateEvent event) { + } + + public void onStageInstanceCreate(@NonNull GuildAuditLogEntryCreateEvent event) { + } + + public void onStageInstanceUpdate(@NonNull GuildAuditLogEntryCreateEvent event) { + } + + public void onStageInstanceDelete(@NonNull GuildAuditLogEntryCreateEvent event) { + } + + public void onThreadCreate(@NonNull GuildAuditLogEntryCreateEvent event) { + } + + public void onThreadUpdate(@NonNull GuildAuditLogEntryCreateEvent event) { + } + + public void onThreadDelete(@NonNull GuildAuditLogEntryCreateEvent event) { + } + + public void onVoiceChannelStatusUpdate(@NonNull GuildAuditLogEntryCreateEvent event) { + } + + public void onVoiceChannelStatusDelete(@NonNull GuildAuditLogEntryCreateEvent event) { + } + + public void onWebhookCreate(@NonNull GuildAuditLogEntryCreateEvent event) { + } + + public void onWebhookUpdate(@NonNull GuildAuditLogEntryCreateEvent event) { + } + + public void onWebhookDelete(@NonNull GuildAuditLogEntryCreateEvent event) { + } + + public void onSoundboardSoundCreate(@NonNull GuildAuditLogEntryCreateEvent event) { + } + + public void onSoundboardSoundUpdate(@NonNull GuildAuditLogEntryCreateEvent event) { + } + + public void onSoundboardSoundDelete(@NonNull GuildAuditLogEntryCreateEvent event) { + } + + public void onOnboardingCreate(@NonNull GuildAuditLogEntryCreateEvent event) { + } + + public void onOnboardingUpdate(@NonNull GuildAuditLogEntryCreateEvent event) { + } + + public void onOnboardingPromptCreate(@NonNull GuildAuditLogEntryCreateEvent event) { + } + + public void onOnboardingPromptUpdate(@NonNull GuildAuditLogEntryCreateEvent event) { + } + + public void onOnboardingPromptDelete(@NonNull GuildAuditLogEntryCreateEvent event) { + } + + public void onHomeSettingsCreate(@NonNull GuildAuditLogEntryCreateEvent event) { + } + + public void onHomeSettingsUpdate(@NonNull GuildAuditLogEntryCreateEvent event) { + } + + public void onMessageBulkDelete(@NonNull GuildAuditLogEntryCreateEvent event) { + } + + public void onMessageCreate(@NonNull GuildAuditLogEntryCreateEvent event) { + } + + public void onMessageUpdate(@NonNull GuildAuditLogEntryCreateEvent event) { + } + + public void onMessageDelete(@NonNull GuildAuditLogEntryCreateEvent event) { + } + + /** + * For {@link ActionType} not fully known by JDA yet + */ + public void onUnknownEvent(@NonNull GuildAuditLogEntryCreateEvent event) { + } + + /** + * For {@link ActionType}s which are defined but not implemented by PaperTrail + */ + public void onUnimplementedEvent(@NonNull GuildAuditLogEntryCreateEvent event) { + } + + /** + *

+ * Routes a {@link GuildAuditLogEntryCreateEvent} to its corresponding + * event handler method based on the {@link ActionType} of the audit log entry. + *

+ * + *

+ * Each event handler method can be overridden multiple times + *

+ * + *

+ * This method is marked as {@code final} and cannot be overridden + *

+ * + * @param event the audit log event received from JDA + */ + public final void handleEvent(@NonNull GuildAuditLogEntryCreateEvent event) { + ActionType action = event.getEntry().getType(); + + switch (action) { + case AUTO_MODERATION_FLAG_TO_CHANNEL -> onAutoModerationFlagToChannel(event); + case AUTO_MODERATION_MEMBER_TIMEOUT -> onAutoModerationMemberTimeout(event); + case AUTO_MODERATION_RULE_BLOCK_MESSAGE -> onAutoModerationRuleBlockMessage(event); + case AUTO_MODERATION_RULE_CREATE -> onAutoModerationRuleCreate(event); + case AUTO_MODERATION_RULE_UPDATE -> onAutoModerationRuleUpdate(event); + case AUTO_MODERATION_RULE_DELETE -> onAutoModerationRuleDelete(event); + + case KICK -> onKick(event); + case PRUNE -> onPrune(event); // never happened to trigger + case BAN -> onBan(event); + case UNBAN -> onUnban(event); + case BOT_ADD -> onBotAdd(event); + + case CHANNEL_CREATE -> onChannelCreate(event); + case CHANNEL_UPDATE -> onChannelUpdate(event); + case CHANNEL_DELETE -> onChannelDelete(event); + case CHANNEL_OVERRIDE_CREATE -> onChannelOverrideCreate(event); + case CHANNEL_OVERRIDE_UPDATE -> onChannelOverrideUpdate(event); + case CHANNEL_OVERRIDE_DELETE -> onChannelOverrideDelete(event); + + case ROLE_CREATE -> onRoleCreate(event); + case ROLE_UPDATE -> onRoleUpdate(event); + case ROLE_DELETE -> onRoleDelete(event); + + case EMOJI_CREATE -> onEmojiCreate(event); + case EMOJI_UPDATE -> onEmojiUpdate(event); + case EMOJI_DELETE -> onEmojiDelete(event); + + case STICKER_CREATE -> onStickerCreate(event); + case STICKER_UPDATE -> onStickerUpdate(event); + case STICKER_DELETE -> onStickerDelete(event); + + case GUILD_UPDATE -> onGuildUpdate(event); + case GUILD_PROFILE_UPDATE -> onGuildProfileUpdate(event); + + case INTEGRATION_CREATE -> onIntegrationCreate(event); + case INTEGRATION_UPDATE -> onIntegrationUpdate(event); // never triggers + case INTEGRATION_DELETE -> onIntegrationDelete(event); + case APPLICATION_COMMAND_PRIVILEGES_UPDATE -> onApplicationCommandPrivilegesUpdate(event); + + case INVITE_CREATE -> onInviteCreate(event); + case INVITE_UPDATE -> onInviteUpdate(event); // never triggers + case INVITE_DELETE -> onInviteDelete(event); + + case MEMBER_ROLE_UPDATE -> onMemberRoleUpdate(event); + case MEMBER_UPDATE -> onMemberUpdate(event); + + case MEMBER_VOICE_KICK -> onMemberVoiceKick(event); + case MEMBER_VOICE_MOVE -> onMemberVoiceMove(event); + + case MESSAGE_PIN -> onMessagePin(event); + case MESSAGE_UNPIN -> onMessageUnpin(event); + + // these seemingly don't trigger properly, or are unreliable + case MESSAGE_BULK_DELETE -> onMessageBulkDelete(event); + case MESSAGE_CREATE -> onMessageCreate(event); + case MESSAGE_DELETE -> onMessageDelete(event); + case MESSAGE_UPDATE -> onMessageUpdate(event); + + case SCHEDULED_EVENT_CREATE -> onScheduledEventCreate(event); + case SCHEDULED_EVENT_UPDATE -> onScheduledEventUpdate(event); + case SCHEDULED_EVENT_DELETE -> onScheduledEventDelete(event); + + case STAGE_INSTANCE_CREATE -> onStageInstanceCreate(event); + case STAGE_INSTANCE_UPDATE -> onStageInstanceUpdate(event); + case STAGE_INSTANCE_DELETE -> onStageInstanceDelete(event); + + case THREAD_CREATE -> onThreadCreate(event); + case THREAD_UPDATE -> onThreadUpdate(event); + case THREAD_DELETE -> onThreadDelete(event); + + case VOICE_CHANNEL_STATUS_UPDATE -> onVoiceChannelStatusUpdate(event); + case VOICE_CHANNEL_STATUS_DELETE -> onVoiceChannelStatusDelete(event); + + case WEBHOOK_CREATE -> onWebhookCreate(event); + case WEBHOOK_UPDATE -> onWebhookUpdate(event); + case WEBHOOK_REMOVE -> onWebhookDelete(event); + + case SOUNDBOARD_SOUND_CREATE -> onSoundboardSoundCreate(event); + case SOUNDBOARD_SOUND_UPDATE -> onSoundboardSoundUpdate(event); + case SOUNDBOARD_SOUND_DELETE -> onSoundboardSoundDelete(event); + + case ONBOARDING_CREATE -> onOnboardingCreate(event); // unreliable + case ONBOARDING_UPDATE -> onOnboardingUpdate(event); + + case ONBOARDING_PROMPT_CREATE -> onOnboardingPromptCreate(event); + case ONBOARDING_PROMPT_UPDATE -> onOnboardingPromptUpdate(event); + case ONBOARDING_PROMPT_DELETE -> onOnboardingPromptDelete(event); + + case HOME_SETTINGS_CREATE -> onHomeSettingsCreate(event); + case HOME_SETTINGS_UPDATE -> onHomeSettingsUpdate(event); + + case UNKNOWN -> onUnknownEvent(event); + + default -> onUnimplementedEvent(event); + } + } +} diff --git a/src/main/java/io/github/eggy03/papertrail/bot/listeners/auditlog/GuildAuditLogEntryEventListener.java b/src/main/java/io/github/eggy03/papertrail/bot/listeners/auditlog/GuildAuditLogEntryEventListener.java new file mode 100644 index 00000000..55675020 --- /dev/null +++ b/src/main/java/io/github/eggy03/papertrail/bot/listeners/auditlog/GuildAuditLogEntryEventListener.java @@ -0,0 +1,45 @@ +package io.github.eggy03.papertrail.bot.listeners.auditlog; + +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.enterprise.inject.Instance; +import jakarta.inject.Inject; +import lombok.NonNull; +import lombok.extern.slf4j.Slf4j; +import net.dv8tion.jda.api.events.guild.GuildAuditLogEntryCreateEvent; +import net.dv8tion.jda.api.hooks.ListenerAdapter; + +/** + * Listener responsible for receiving {@link GuildAuditLogEntryCreateEvent} + * events from JDA and delegating them to all registered + * {@link GuildAuditLogEntryCreateEventHandler} CDI beans. + * + *

+ * Event handlers are resolved dynamically using + * {@code Instance}, allowing multiple + * independent handler implementations to process the same audit log event. + *

+ * + *

+ * Each discovered handler instance will receive the event through + * {@link GuildAuditLogEntryCreateEventHandler#handleEvent(GuildAuditLogEntryCreateEvent)}. + * This enables a multicast-style event processing pipeline where multiple + * handler beans may react to the same audit log action independently. + *

+ */ +@Slf4j +@ApplicationScoped +public final class GuildAuditLogEntryEventListener extends ListenerAdapter { + + private final @NonNull Instance guildAuditLogEntryCreateEventHandlers; + + @Inject + public GuildAuditLogEntryEventListener(@NonNull Instance guildAuditLogEntryCreateEventHandlers) { + this.guildAuditLogEntryCreateEventHandlers = guildAuditLogEntryCreateEventHandlers; + } + + @Override + public void onGuildAuditLogEntryCreate(@NonNull GuildAuditLogEntryCreateEvent event) { + guildAuditLogEntryCreateEventHandlers.forEach(handler -> handler.handleEvent(event)); + } + +} \ No newline at end of file diff --git a/src/main/java/io/github/eggy03/papertrail/bot/listeners/auditlog/event/AuditLogEventListener.java b/src/main/java/io/github/eggy03/papertrail/bot/listeners/auditlog/event/AuditLogEventListener.java deleted file mode 100644 index c16d8c7d..00000000 --- a/src/main/java/io/github/eggy03/papertrail/bot/listeners/auditlog/event/AuditLogEventListener.java +++ /dev/null @@ -1,207 +0,0 @@ -package io.github.eggy03.papertrail.bot.listeners.auditlog.event; - -import io.github.eggy03.papertrail.bot.listeners.auditlog.helper.automod.AutoModerationFlagToChannelEventHelper; -import io.github.eggy03.papertrail.bot.listeners.auditlog.helper.automod.AutoModerationMemberTimeoutEventHelper; -import io.github.eggy03.papertrail.bot.listeners.auditlog.helper.automod.AutoModerationRuleBlockMessageEventHelper; -import io.github.eggy03.papertrail.bot.listeners.auditlog.helper.automod.AutoModerationRuleCreateEventHelper; -import io.github.eggy03.papertrail.bot.listeners.auditlog.helper.automod.AutoModerationRuleDeleteEventHelper; -import io.github.eggy03.papertrail.bot.listeners.auditlog.helper.automod.AutoModerationRuleUpdateEventHelper; -import io.github.eggy03.papertrail.bot.listeners.auditlog.helper.bot.BotAddEventHelper; -import io.github.eggy03.papertrail.bot.listeners.auditlog.helper.channel.ChannelCreateEventHelper; -import io.github.eggy03.papertrail.bot.listeners.auditlog.helper.channel.ChannelDeleteEventHelper; -import io.github.eggy03.papertrail.bot.listeners.auditlog.helper.channel.ChannelOverrideCreateEventHelper; -import io.github.eggy03.papertrail.bot.listeners.auditlog.helper.channel.ChannelOverrideDeleteEventHelper; -import io.github.eggy03.papertrail.bot.listeners.auditlog.helper.channel.ChannelOverrideUpdateEventHelper; -import io.github.eggy03.papertrail.bot.listeners.auditlog.helper.channel.ChannelUpdateEventHelper; -import io.github.eggy03.papertrail.bot.listeners.auditlog.helper.channel.VoiceChannelStatusDeleteEventHelper; -import io.github.eggy03.papertrail.bot.listeners.auditlog.helper.channel.VoiceChannelStatusUpdateEventHelper; -import io.github.eggy03.papertrail.bot.listeners.auditlog.helper.emoji.EmojiCreateEventHelper; -import io.github.eggy03.papertrail.bot.listeners.auditlog.helper.emoji.EmojiDeleteEventHelper; -import io.github.eggy03.papertrail.bot.listeners.auditlog.helper.emoji.EmojiUpdateEventHelper; -import io.github.eggy03.papertrail.bot.listeners.auditlog.helper.generic.GenericAuditLogEventHelper; -import io.github.eggy03.papertrail.bot.listeners.auditlog.helper.guild.GuildProfileUpdateEventHelper; -import io.github.eggy03.papertrail.bot.listeners.auditlog.helper.guild.GuildUpdateEventHelper; -import io.github.eggy03.papertrail.bot.listeners.auditlog.helper.homesettings.HomeSettingsCreateEventHelper; -import io.github.eggy03.papertrail.bot.listeners.auditlog.helper.homesettings.HomeSettingsUpdateEventHelper; -import io.github.eggy03.papertrail.bot.listeners.auditlog.helper.integration.ApplicationCommandPrivilegesUpdateEventHelper; -import io.github.eggy03.papertrail.bot.listeners.auditlog.helper.integration.IntegrationCreateEventHelper; -import io.github.eggy03.papertrail.bot.listeners.auditlog.helper.integration.IntegrationDeleteEventHelper; -import io.github.eggy03.papertrail.bot.listeners.auditlog.helper.invite.InviteCreateEventHelper; -import io.github.eggy03.papertrail.bot.listeners.auditlog.helper.invite.InviteDeleteEventHelper; -import io.github.eggy03.papertrail.bot.listeners.auditlog.helper.member.MemberRoleUpdateEventHelper; -import io.github.eggy03.papertrail.bot.listeners.auditlog.helper.member.MemberUpdateEventHelper; -import io.github.eggy03.papertrail.bot.listeners.auditlog.helper.member.MemberVoiceKickEventHelper; -import io.github.eggy03.papertrail.bot.listeners.auditlog.helper.member.MemberVoiceMoveEventHelper; -import io.github.eggy03.papertrail.bot.listeners.auditlog.helper.message.MessagePinEventHelper; -import io.github.eggy03.papertrail.bot.listeners.auditlog.helper.message.MessageUnpinEventHelper; -import io.github.eggy03.papertrail.bot.listeners.auditlog.helper.modactions.BanEventHelper; -import io.github.eggy03.papertrail.bot.listeners.auditlog.helper.modactions.KickEventHelper; -import io.github.eggy03.papertrail.bot.listeners.auditlog.helper.modactions.UnbanEventHelper; -import io.github.eggy03.papertrail.bot.listeners.auditlog.helper.onboarding.OnboardingPromptCreateEventHelper; -import io.github.eggy03.papertrail.bot.listeners.auditlog.helper.onboarding.OnboardingPromptDeleteEventHelper; -import io.github.eggy03.papertrail.bot.listeners.auditlog.helper.onboarding.OnboardingPromptUpdateEventHelper; -import io.github.eggy03.papertrail.bot.listeners.auditlog.helper.onboarding.OnboardingUpdateEventHelper; -import io.github.eggy03.papertrail.bot.listeners.auditlog.helper.role.RoleCreateEventHelper; -import io.github.eggy03.papertrail.bot.listeners.auditlog.helper.role.RoleDeleteEventHelper; -import io.github.eggy03.papertrail.bot.listeners.auditlog.helper.role.RoleUpdateEventHelper; -import io.github.eggy03.papertrail.bot.listeners.auditlog.helper.scheduledevent.ScheduledEventCreateEventHelper; -import io.github.eggy03.papertrail.bot.listeners.auditlog.helper.scheduledevent.ScheduledEventDeleteEventHelper; -import io.github.eggy03.papertrail.bot.listeners.auditlog.helper.scheduledevent.ScheduledEventUpdateEventHelper; -import io.github.eggy03.papertrail.bot.listeners.auditlog.helper.soundboard.SoundboardSoundCreateEventHelper; -import io.github.eggy03.papertrail.bot.listeners.auditlog.helper.soundboard.SoundboardSoundDeleteEventHelper; -import io.github.eggy03.papertrail.bot.listeners.auditlog.helper.soundboard.SoundboardSoundUpdateEventHelper; -import io.github.eggy03.papertrail.bot.listeners.auditlog.helper.stage.StageInstanceCreateEventHelper; -import io.github.eggy03.papertrail.bot.listeners.auditlog.helper.stage.StageInstanceDeleteEventHelper; -import io.github.eggy03.papertrail.bot.listeners.auditlog.helper.stage.StageInstanceUpdateEventHelper; -import io.github.eggy03.papertrail.bot.listeners.auditlog.helper.sticker.StickerCreateEventHelper; -import io.github.eggy03.papertrail.bot.listeners.auditlog.helper.sticker.StickerDeleteEventHelper; -import io.github.eggy03.papertrail.bot.listeners.auditlog.helper.sticker.StickerUpdateEventHelper; -import io.github.eggy03.papertrail.bot.listeners.auditlog.helper.thread.ThreadCreateEventHelper; -import io.github.eggy03.papertrail.bot.listeners.auditlog.helper.thread.ThreadDeleteEventHelper; -import io.github.eggy03.papertrail.bot.listeners.auditlog.helper.thread.ThreadUpdateEventHelper; -import io.github.eggy03.papertrail.bot.listeners.auditlog.helper.webhook.WebhookCreateEventHelper; -import io.github.eggy03.papertrail.bot.listeners.auditlog.helper.webhook.WebhookRemoveEventHelper; -import io.github.eggy03.papertrail.bot.listeners.auditlog.helper.webhook.WebhookUpdateEventHelper; -import io.github.eggy03.papertrail.sdk.client.AuditLogRegistrationClient; -import io.github.eggy03.papertrail.sdk.entity.AuditLogRegistrationEntity; -import lombok.NonNull; -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import net.dv8tion.jda.api.audit.ActionType; -import net.dv8tion.jda.api.audit.AuditLogEntry; -import net.dv8tion.jda.api.events.guild.GuildAuditLogEntryCreateEvent; -import net.dv8tion.jda.api.hooks.ListenerAdapter; - -import java.util.Optional; -import java.util.concurrent.Executor; - -@Slf4j -@RequiredArgsConstructor -public class AuditLogEventListener extends ListenerAdapter { - - @NonNull - private final AuditLogRegistrationClient client; - - @NonNull - private final Executor vThreadPool; - - @Override - public void onGuildAuditLogEntryCreate(@NonNull GuildAuditLogEntryCreateEvent event) { - vThreadPool.execute(() -> { - // Call the API and see if the event came from a registered Guild - Optional response = client.getRegisteredGuild(event.getGuild().getId()); - response.ifPresent(success -> auditLogParser(event, success.getChannelId())); - }); - } - - private void auditLogParser(@NonNull GuildAuditLogEntryCreateEvent event, @NonNull String channelIdToSendTo) { - AuditLogEntry ale = event.getEntry(); - ActionType action = ale.getType(); - switch (action) { - - case AUTO_MODERATION_FLAG_TO_CHANNEL -> - AutoModerationFlagToChannelEventHelper.format(event, channelIdToSendTo); - case AUTO_MODERATION_MEMBER_TIMEOUT -> - AutoModerationMemberTimeoutEventHelper.format(event, channelIdToSendTo); - case AUTO_MODERATION_RULE_BLOCK_MESSAGE -> - AutoModerationRuleBlockMessageEventHelper.format(event, channelIdToSendTo); - case AUTO_MODERATION_RULE_CREATE -> AutoModerationRuleCreateEventHelper.format(event, channelIdToSendTo); - case AUTO_MODERATION_RULE_UPDATE -> AutoModerationRuleUpdateEventHelper.format(event, channelIdToSendTo); - case AUTO_MODERATION_RULE_DELETE -> AutoModerationRuleDeleteEventHelper.format(event, channelIdToSendTo); - - case KICK -> KickEventHelper.format(event, channelIdToSendTo); - case BAN -> BanEventHelper.format(event, channelIdToSendTo); - case UNBAN -> UnbanEventHelper.format(event, channelIdToSendTo); - case BOT_ADD -> BotAddEventHelper.format(event, channelIdToSendTo); - // PRUNE has generic formatting - - case CHANNEL_CREATE -> ChannelCreateEventHelper.format(event, channelIdToSendTo); - case CHANNEL_UPDATE -> ChannelUpdateEventHelper.format(event, channelIdToSendTo); - case CHANNEL_DELETE -> ChannelDeleteEventHelper.format(event, channelIdToSendTo); - case CHANNEL_OVERRIDE_CREATE -> ChannelOverrideCreateEventHelper.format(event, channelIdToSendTo); - case CHANNEL_OVERRIDE_UPDATE -> ChannelOverrideUpdateEventHelper.format(event, channelIdToSendTo); - case CHANNEL_OVERRIDE_DELETE -> ChannelOverrideDeleteEventHelper.format(event, channelIdToSendTo); - - case ROLE_CREATE -> RoleCreateEventHelper.format(event, channelIdToSendTo); - case ROLE_UPDATE -> RoleUpdateEventHelper.format(event, channelIdToSendTo); - case ROLE_DELETE -> RoleDeleteEventHelper.format(event, channelIdToSendTo); - - case EMOJI_CREATE -> EmojiCreateEventHelper.format(event, channelIdToSendTo); - case EMOJI_UPDATE -> EmojiUpdateEventHelper.format(event, channelIdToSendTo); - case EMOJI_DELETE -> EmojiDeleteEventHelper.format(event, channelIdToSendTo); - - case STICKER_CREATE -> StickerCreateEventHelper.format(event, channelIdToSendTo); - case STICKER_UPDATE -> StickerUpdateEventHelper.format(event, channelIdToSendTo); - case STICKER_DELETE -> StickerDeleteEventHelper.format(event, channelIdToSendTo); - - case GUILD_UPDATE -> GuildUpdateEventHelper.format(event, channelIdToSendTo); - case GUILD_PROFILE_UPDATE -> GuildProfileUpdateEventHelper.format(event, channelIdToSendTo); - - case INTEGRATION_CREATE -> IntegrationCreateEventHelper.format(event, channelIdToSendTo); - case INTEGRATION_DELETE -> IntegrationDeleteEventHelper.format(event, channelIdToSendTo); - case APPLICATION_COMMAND_PRIVILEGES_UPDATE -> - ApplicationCommandPrivilegesUpdateEventHelper.format(event, channelIdToSendTo); - // INTEGRATION_UPDATE has generic formatting - - case INVITE_CREATE -> InviteCreateEventHelper.format(event, channelIdToSendTo); - case INVITE_DELETE -> InviteDeleteEventHelper.format(event, channelIdToSendTo); - // INVITE_UPDATE has generic formatting - - case MEMBER_ROLE_UPDATE -> MemberRoleUpdateEventHelper.format(event, channelIdToSendTo); - case MEMBER_UPDATE -> MemberUpdateEventHelper.format(event, channelIdToSendTo); - - case MEMBER_VOICE_KICK -> MemberVoiceKickEventHelper.format(event, channelIdToSendTo); - case MEMBER_VOICE_MOVE -> MemberVoiceMoveEventHelper.format(event, channelIdToSendTo); - - case MESSAGE_PIN -> MessagePinEventHelper.format(event, channelIdToSendTo); - case MESSAGE_UNPIN -> MessageUnpinEventHelper.format(event, channelIdToSendTo); - - case SCHEDULED_EVENT_CREATE -> ScheduledEventCreateEventHelper.format(event, channelIdToSendTo); - case SCHEDULED_EVENT_UPDATE -> ScheduledEventUpdateEventHelper.format(event, channelIdToSendTo); - case SCHEDULED_EVENT_DELETE -> ScheduledEventDeleteEventHelper.format(event, channelIdToSendTo); - - case STAGE_INSTANCE_CREATE -> StageInstanceCreateEventHelper.format(event, channelIdToSendTo); - case STAGE_INSTANCE_UPDATE -> StageInstanceUpdateEventHelper.format(event, channelIdToSendTo); - case STAGE_INSTANCE_DELETE -> StageInstanceDeleteEventHelper.format(event, channelIdToSendTo); - - case THREAD_CREATE -> ThreadCreateEventHelper.format(event, channelIdToSendTo); - case THREAD_UPDATE -> ThreadUpdateEventHelper.format(event, channelIdToSendTo); - case THREAD_DELETE -> ThreadDeleteEventHelper.format(event, channelIdToSendTo); - - case VOICE_CHANNEL_STATUS_DELETE -> VoiceChannelStatusDeleteEventHelper.format(event, channelIdToSendTo); - case VOICE_CHANNEL_STATUS_UPDATE -> VoiceChannelStatusUpdateEventHelper.format(event, channelIdToSendTo); - - case WEBHOOK_CREATE -> WebhookCreateEventHelper.format(event, channelIdToSendTo); - case WEBHOOK_UPDATE -> WebhookUpdateEventHelper.format(event, channelIdToSendTo); - case WEBHOOK_REMOVE -> WebhookRemoveEventHelper.format(event, channelIdToSendTo); - - case SOUNDBOARD_SOUND_CREATE -> SoundboardSoundCreateEventHelper.format(event, channelIdToSendTo); - case SOUNDBOARD_SOUND_UPDATE -> SoundboardSoundUpdateEventHelper.format(event, channelIdToSendTo); - case SOUNDBOARD_SOUND_DELETE -> SoundboardSoundDeleteEventHelper.format(event, 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 -> HomeSettingsCreateEventHelper.format(event, channelIdToSendTo); - case HOME_SETTINGS_UPDATE -> HomeSettingsUpdateEventHelper.format(event, channelIdToSendTo); - - // these seemingly don't trigger properly, or are unreliable - case MESSAGE_BULK_DELETE, - MESSAGE_CREATE, - MESSAGE_DELETE, - MESSAGE_UPDATE -> GenericAuditLogEventHelper.format(event, channelIdToSendTo); - - // except UNKNOWN, the rest have never been seen to be triggered - case PRUNE, INTEGRATION_UPDATE, - INVITE_UPDATE, ONBOARDING_CREATE, - UNKNOWN -> GenericAuditLogEventHelper.format(event, channelIdToSendTo); - - default -> { - GenericAuditLogEventHelper.format(event, channelIdToSendTo); - log.warn("The following event is either not covered by JDA's UNKNOWN type or is not implemented by PaperTrail yet {}", ale.getType().name()); - } - } - } -} diff --git a/src/main/java/io/github/eggy03/papertrail/bot/listeners/auditlog/helper/automod/AutoModerationFlagToChannelEventHelper.java b/src/main/java/io/github/eggy03/papertrail/bot/listeners/auditlog/helper/automod/AutoModerationFlagToChannelEventHelper.java deleted file mode 100644 index 8ad1cc7f..00000000 --- a/src/main/java/io/github/eggy03/papertrail/bot/listeners/auditlog/helper/automod/AutoModerationFlagToChannelEventHelper.java +++ /dev/null @@ -1,51 +0,0 @@ -package io.github.eggy03.papertrail.bot.listeners.auditlog.helper.automod; - -import lombok.NonNull; -import lombok.experimental.UtilityClass; -import lombok.extern.slf4j.Slf4j; -import net.dv8tion.jda.api.EmbedBuilder; -import net.dv8tion.jda.api.audit.AuditLogEntry; -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 net.dv8tion.jda.api.utils.MarkdownUtil; - -import java.awt.Color; - -@UtilityClass -@Slf4j -public class AutoModerationFlagToChannelEventHelper { - - public static void format(@NonNull GuildAuditLogEntryCreateEvent event, @NonNull String channelIdToSendTo) { - - AuditLogEntry ale = event.getEntry(); - - EmbedBuilder eb = new EmbedBuilder(); - eb.setTitle("Audit Log Entry | Auto-Mod Event"); - - User targetUser = ale.getJDA().getUserById(ale.getTargetId()); - String targetMention = (targetUser != null ? targetUser.getAsMention() : ale.getTargetId()); - - eb.setDescription(MarkdownUtil.quoteBlock("Event: AutoMod Message Flag\nTarget Member: " + targetMention)); - eb.setColor(Color.YELLOW); - - eb.addField( - MarkdownUtil.underline("Additional Info"), - MarkdownUtil.codeblock("Flagged message will be available in the channel set to receive AutoMod events."), - false - ); - - eb.setFooter("Audit Log Entry ID: " + ale.getId()); - eb.setTimestamp(ale.getTimeCreated()); - - if (!eb.isValidLength() || eb.isEmpty()) { - log.warn("Embed is empty or too long (current length: {}).", eb.length()); - return; - } - - TextChannel sendingChannel = event.getGuild().getTextChannelById(channelIdToSendTo); - if (sendingChannel != null && sendingChannel.canTalk()) { - sendingChannel.sendMessageEmbeds(eb.build()).queue(); - } - } -} diff --git a/src/main/java/io/github/eggy03/papertrail/bot/listeners/auditlog/helper/automod/AutoModerationMemberTimeoutEventHelper.java b/src/main/java/io/github/eggy03/papertrail/bot/listeners/auditlog/helper/automod/AutoModerationMemberTimeoutEventHelper.java deleted file mode 100644 index 57c96033..00000000 --- a/src/main/java/io/github/eggy03/papertrail/bot/listeners/auditlog/helper/automod/AutoModerationMemberTimeoutEventHelper.java +++ /dev/null @@ -1,51 +0,0 @@ -package io.github.eggy03.papertrail.bot.listeners.auditlog.helper.automod; - -import lombok.NonNull; -import lombok.experimental.UtilityClass; -import lombok.extern.slf4j.Slf4j; -import net.dv8tion.jda.api.EmbedBuilder; -import net.dv8tion.jda.api.audit.AuditLogEntry; -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 net.dv8tion.jda.api.utils.MarkdownUtil; - -import java.awt.Color; - -@UtilityClass -@Slf4j -public class AutoModerationMemberTimeoutEventHelper { - - public static void format(@NonNull GuildAuditLogEntryCreateEvent event, @NonNull String channelIdToSendTo) { - - AuditLogEntry ale = event.getEntry(); - - EmbedBuilder eb = new EmbedBuilder(); - eb.setTitle("Audit Log Entry | Auto-mod Event"); - - User targetUser = ale.getJDA().getUserById(ale.getTargetId()); - String targetMention = (targetUser != null ? targetUser.getAsMention() : ale.getTargetId()); - - eb.setDescription(MarkdownUtil.quoteBlock("Event: AutoMod Member Timeout\nTarget Member: " + targetMention)); - eb.setColor(Color.MAGENTA); - - eb.addField( - MarkdownUtil.underline("Additional Info"), - MarkdownUtil.codeblock("Timeout Rule and Reason will be available in the channel set to receive AutoMod events."), - false - ); - - eb.setFooter("Audit Log Entry ID: " + ale.getId()); - eb.setTimestamp(ale.getTimeCreated()); - - if (!eb.isValidLength() || eb.isEmpty()) { - log.warn("Embed is empty or too long (current length: {}).", eb.length()); - return; - } - - TextChannel sendingChannel = event.getGuild().getTextChannelById(channelIdToSendTo); - if (sendingChannel != null && sendingChannel.canTalk()) { - sendingChannel.sendMessageEmbeds(eb.build()).queue(); - } - } -} diff --git a/src/main/java/io/github/eggy03/papertrail/bot/listeners/auditlog/helper/automod/AutoModerationRuleBlockMessageEventHelper.java b/src/main/java/io/github/eggy03/papertrail/bot/listeners/auditlog/helper/automod/AutoModerationRuleBlockMessageEventHelper.java deleted file mode 100644 index 8bdfa152..00000000 --- a/src/main/java/io/github/eggy03/papertrail/bot/listeners/auditlog/helper/automod/AutoModerationRuleBlockMessageEventHelper.java +++ /dev/null @@ -1,51 +0,0 @@ -package io.github.eggy03.papertrail.bot.listeners.auditlog.helper.automod; - -import lombok.NonNull; -import lombok.experimental.UtilityClass; -import lombok.extern.slf4j.Slf4j; -import net.dv8tion.jda.api.EmbedBuilder; -import net.dv8tion.jda.api.audit.AuditLogEntry; -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 net.dv8tion.jda.api.utils.MarkdownUtil; - -import java.awt.Color; - -@UtilityClass -@Slf4j -public class AutoModerationRuleBlockMessageEventHelper { - - public static void format(@NonNull GuildAuditLogEntryCreateEvent event, @NonNull String channelIdToSendTo) { - - AuditLogEntry ale = event.getEntry(); - - EmbedBuilder eb = new EmbedBuilder(); - eb.setTitle("Audit Log Entry | Auto-mod Event"); - - User targetUser = ale.getJDA().getUserById(ale.getTargetId()); - String targetMention = (targetUser != null ? targetUser.getAsMention() : ale.getTargetId()); - - eb.setDescription(MarkdownUtil.quoteBlock("Event: AutoMod Message Block\nTarget Member: " + targetMention)); - eb.setColor(Color.ORANGE); - - eb.addField( - MarkdownUtil.underline("Additional Info"), - MarkdownUtil.codeblock("Blocked message will be available in the channel set to receive AutoMod events."), - false - ); - - eb.setFooter("Audit Log Entry ID: " + ale.getId()); - eb.setTimestamp(ale.getTimeCreated()); - - if (!eb.isValidLength() || eb.isEmpty()) { - log.warn("Embed is empty or too long (current length: {}).", eb.length()); - return; - } - - TextChannel sendingChannel = event.getGuild().getTextChannelById(channelIdToSendTo); - if (sendingChannel != null && sendingChannel.canTalk()) { - sendingChannel.sendMessageEmbeds(eb.build()).queue(); - } - } -} diff --git a/src/main/java/io/github/eggy03/papertrail/bot/listeners/auditlog/helper/automod/AutoModerationRuleCreateEventHelper.java b/src/main/java/io/github/eggy03/papertrail/bot/listeners/auditlog/helper/automod/AutoModerationRuleCreateEventHelper.java deleted file mode 100644 index 5859df59..00000000 --- a/src/main/java/io/github/eggy03/papertrail/bot/listeners/auditlog/helper/automod/AutoModerationRuleCreateEventHelper.java +++ /dev/null @@ -1,71 +0,0 @@ -package io.github.eggy03.papertrail.bot.listeners.auditlog.helper.automod; - -import io.github.eggy03.papertrail.bot.listeners.auditlog.helper.automod.utils.AutoModUtils; -import io.github.eggy03.papertrail.bot.utils.BooleanUtils; -import lombok.NonNull; -import lombok.experimental.UtilityClass; -import lombok.extern.slf4j.Slf4j; -import net.dv8tion.jda.api.EmbedBuilder; -import net.dv8tion.jda.api.audit.AuditLogEntry; -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 net.dv8tion.jda.api.utils.MarkdownUtil; - -import java.awt.Color; - -@UtilityClass -@Slf4j -public class AutoModerationRuleCreateEventHelper { - - public static void format(@NonNull GuildAuditLogEntryCreateEvent event, @NonNull String channelIdToSendTo) { - - AuditLogEntry ale = event.getEntry(); - - EmbedBuilder eb = new EmbedBuilder(); - eb.setTitle("Audit Log Entry | AutoMod Rule Create"); - - User executor = ale.getJDA().getUserById(ale.getUserIdLong()); - String mentionableExecutor = (executor != null ? executor.getAsMention() : ale.getUserId()); - - eb.setDescription(MarkdownUtil.quoteBlock("Rule Created By: " + mentionableExecutor + "\nRule Created For: AutoMod")); - eb.setColor(Color.GREEN); - - ale.getChanges().forEach((changeKey, changeValue) -> { - - Object newValue = changeValue.getNewValue(); - - switch (changeKey) { - - case "enabled" -> - eb.addField(MarkdownUtil.underline("Enabled"), "╰┈➤" + BooleanUtils.formatToYesOrNo(newValue), false); - - case "trigger_type" -> - eb.addField(MarkdownUtil.underline("Trigger Type"), "╰┈➤" + AutoModUtils.autoModTriggerTypeResolver(newValue), false); - - case "event_type" -> - eb.addField(MarkdownUtil.underline("Event Type"), "╰┈➤" + AutoModUtils.autoModEventTypeResolver(newValue), false); - - case "name" -> eb.addField(MarkdownUtil.underline("AutoMod Rule Name "), "╰┈➤" + newValue, false); - - default -> { - // ignore everything else - } - } - }); - - eb.addField("Additional Info", MarkdownUtil.codeblock("For more info on trigger metadata, actions, exempt roles and channels, visit Safety Setup in your server"), false); - eb.setFooter("Audit Log Entry ID: " + ale.getId()); - eb.setTimestamp(ale.getTimeCreated()); - - if (!eb.isValidLength() || eb.isEmpty()) { - log.warn("Embed is empty or too long (current length: {}).", eb.length()); - return; - } - - TextChannel sendingChannel = event.getGuild().getTextChannelById(channelIdToSendTo); - if (sendingChannel != null && sendingChannel.canTalk()) { - sendingChannel.sendMessageEmbeds(eb.build()).queue(); - } - } -} diff --git a/src/main/java/io/github/eggy03/papertrail/bot/listeners/auditlog/helper/automod/AutoModerationRuleDeleteEventHelper.java b/src/main/java/io/github/eggy03/papertrail/bot/listeners/auditlog/helper/automod/AutoModerationRuleDeleteEventHelper.java deleted file mode 100644 index 8d8ebc5d..00000000 --- a/src/main/java/io/github/eggy03/papertrail/bot/listeners/auditlog/helper/automod/AutoModerationRuleDeleteEventHelper.java +++ /dev/null @@ -1,54 +0,0 @@ -package io.github.eggy03.papertrail.bot.listeners.auditlog.helper.automod; - -import lombok.NonNull; -import lombok.experimental.UtilityClass; -import lombok.extern.slf4j.Slf4j; -import net.dv8tion.jda.api.EmbedBuilder; -import net.dv8tion.jda.api.audit.AuditLogEntry; -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 net.dv8tion.jda.api.utils.MarkdownUtil; - -import java.awt.Color; - -@UtilityClass -@Slf4j -public class AutoModerationRuleDeleteEventHelper { - - public static void format(@NonNull GuildAuditLogEntryCreateEvent event, @NonNull String channelIdToSendTo) { - - AuditLogEntry ale = event.getEntry(); - - EmbedBuilder eb = new EmbedBuilder(); - eb.setTitle("Audit Log Entry | AutoMod Rule Delete"); - - User executor = ale.getJDA().getUserById(ale.getUserIdLong()); - String mentionableExecutor = (executor != null ? executor.getAsMention() : ale.getUserId()); - - eb.setDescription(MarkdownUtil.quoteBlock("Rule Deleted By: " + mentionableExecutor + "\nRule Deleted For: AutoMod")); - eb.setColor(Color.RED); - - ale.getChanges().forEach((changeKey, changeValue) -> { - - Object oldValue = changeValue.getOldValue(); - - if (changeKey.equals("name")) { - eb.addField(MarkdownUtil.underline("AutoMod Rule Name"), "╰┈➤" + oldValue, false); - } - }); - - eb.setFooter("Audit Log Entry ID: " + ale.getId()); - eb.setTimestamp(ale.getTimeCreated()); - - if (!eb.isValidLength() || eb.isEmpty()) { - log.warn("Embed is empty or too long (current length: {}).", eb.length()); - return; - } - - TextChannel sendingChannel = event.getGuild().getTextChannelById(channelIdToSendTo); - if (sendingChannel != null && sendingChannel.canTalk()) { - sendingChannel.sendMessageEmbeds(eb.build()).queue(); - } - } -} diff --git a/src/main/java/io/github/eggy03/papertrail/bot/listeners/auditlog/helper/automod/AutoModerationRuleUpdateEventHelper.java b/src/main/java/io/github/eggy03/papertrail/bot/listeners/auditlog/helper/automod/AutoModerationRuleUpdateEventHelper.java deleted file mode 100644 index 7f71781f..00000000 --- a/src/main/java/io/github/eggy03/papertrail/bot/listeners/auditlog/helper/automod/AutoModerationRuleUpdateEventHelper.java +++ /dev/null @@ -1,52 +0,0 @@ -package io.github.eggy03.papertrail.bot.listeners.auditlog.helper.automod; - -import lombok.NonNull; -import lombok.experimental.UtilityClass; -import lombok.extern.slf4j.Slf4j; -import net.dv8tion.jda.api.EmbedBuilder; -import net.dv8tion.jda.api.audit.AuditLogEntry; -import net.dv8tion.jda.api.entities.User; -import net.dv8tion.jda.api.entities.automod.AutoModRule; -import net.dv8tion.jda.api.entities.channel.concrete.TextChannel; -import net.dv8tion.jda.api.events.guild.GuildAuditLogEntryCreateEvent; -import net.dv8tion.jda.api.utils.MarkdownUtil; - -import java.awt.Color; - -@UtilityClass -@Slf4j -public class AutoModerationRuleUpdateEventHelper { - - public static void format(@NonNull GuildAuditLogEntryCreateEvent event, @NonNull String channelIdToSendTo) { - - AuditLogEntry ale = event.getEntry(); - - EmbedBuilder eb = new EmbedBuilder(); - eb.setTitle("Audit Log Entry | AutoMod Rule Update"); - - User executor = ale.getJDA().getUserById(ale.getUserIdLong()); - String mentionableExecutor = (executor != null ? executor.getAsMention() : ale.getUserId()); - - eb.setDescription(MarkdownUtil.quoteBlock("Rule Updated By: " + mentionableExecutor + "\nRule Updated For: AutoMod")); - eb.setColor(Color.YELLOW); - - // add name of the rule which got updated - AutoModRule rule = ale.getGuild().retrieveAutoModRuleById(ale.getTargetId()).complete(); - eb.addField(MarkdownUtil.underline("AutoMod Rule Name"), "╰┈➤" + rule.getName(), false); - - eb.addField(MarkdownUtil.underline("Additional Info"), MarkdownUtil.codeblock("For more info on trigger metadata, actions, exempt roles and channel changes, visit Safety Setup in your server"), false); - - eb.setFooter("Audit Log Entry ID: " + ale.getId()); - eb.setTimestamp(ale.getTimeCreated()); - - if (!eb.isValidLength() || eb.isEmpty()) { - log.warn("Embed is empty or too long (current length: {}).", eb.length()); - return; - } - - TextChannel sendingChannel = event.getGuild().getTextChannelById(channelIdToSendTo); - if (sendingChannel != null && sendingChannel.canTalk()) { - sendingChannel.sendMessageEmbeds(eb.build()).queue(); - } - } -} diff --git a/src/main/java/io/github/eggy03/papertrail/bot/listeners/auditlog/helper/bot/BotAddEventHelper.java b/src/main/java/io/github/eggy03/papertrail/bot/listeners/auditlog/helper/bot/BotAddEventHelper.java deleted file mode 100644 index 9e9ea77b..00000000 --- a/src/main/java/io/github/eggy03/papertrail/bot/listeners/auditlog/helper/bot/BotAddEventHelper.java +++ /dev/null @@ -1,49 +0,0 @@ -package io.github.eggy03.papertrail.bot.listeners.auditlog.helper.bot; - -import lombok.NonNull; -import lombok.experimental.UtilityClass; -import lombok.extern.slf4j.Slf4j; -import net.dv8tion.jda.api.EmbedBuilder; -import net.dv8tion.jda.api.audit.AuditLogEntry; -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 net.dv8tion.jda.api.utils.MarkdownUtil; - -import java.awt.Color; - -@UtilityClass -@Slf4j -public class BotAddEventHelper { - - public static void format(@NonNull GuildAuditLogEntryCreateEvent event, @NonNull String channelIdToSendTo) { - - AuditLogEntry ale = event.getEntry(); - - User executor = ale.getJDA().getUserById(ale.getUserIdLong()); - String mentionableExecutor = (executor != null ? executor.getAsMention() : ale.getUserId()); - - User target = ale.getJDA().getUserById(ale.getTargetIdLong()); - String mentionableTarget = (target != null ? target.getAsMention() : ale.getTargetId()); - - EmbedBuilder eb = new EmbedBuilder(); - eb.setTitle("Audit Log Entry | Bot Add Event"); - eb.setDescription(MarkdownUtil.quoteBlock("Bot Added By: " + mentionableExecutor + "\nBot ID: " + ale.getTargetId())); - eb.setColor(Color.CYAN); - - eb.addField(MarkdownUtil.underline("Bot Added"), "╰┈➤" + mentionableTarget, false); - - eb.setFooter("Audit Log Entry ID: " + ale.getId()); - eb.setTimestamp(ale.getTimeCreated()); - - if (!eb.isValidLength() || eb.isEmpty()) { - log.warn("Embed is empty or too long (current length: {}).", eb.length()); - return; - } - - TextChannel sendingChannel = event.getGuild().getTextChannelById(channelIdToSendTo); - if (sendingChannel != null && sendingChannel.canTalk()) { - sendingChannel.sendMessageEmbeds(eb.build()).queue(); - } - } -} diff --git a/src/main/java/io/github/eggy03/papertrail/bot/listeners/auditlog/helper/channel/ChannelCreateEventHelper.java b/src/main/java/io/github/eggy03/papertrail/bot/listeners/auditlog/helper/channel/ChannelCreateEventHelper.java deleted file mode 100644 index 917eb3e9..00000000 --- a/src/main/java/io/github/eggy03/papertrail/bot/listeners/auditlog/helper/channel/ChannelCreateEventHelper.java +++ /dev/null @@ -1,87 +0,0 @@ -package io.github.eggy03.papertrail.bot.listeners.auditlog.helper.channel; - -import io.github.eggy03.papertrail.bot.listeners.auditlog.helper.channel.utils.ChannelUtils; -import io.github.eggy03.papertrail.bot.utils.BooleanUtils; -import io.github.eggy03.papertrail.bot.utils.DurationUtils; -import lombok.NonNull; -import lombok.experimental.UtilityClass; -import lombok.extern.slf4j.Slf4j; -import net.dv8tion.jda.api.EmbedBuilder; -import net.dv8tion.jda.api.audit.AuditLogEntry; -import net.dv8tion.jda.api.entities.User; -import net.dv8tion.jda.api.entities.channel.concrete.TextChannel; -import net.dv8tion.jda.api.entities.channel.middleman.GuildChannel; -import net.dv8tion.jda.api.events.guild.GuildAuditLogEntryCreateEvent; -import net.dv8tion.jda.api.utils.MarkdownUtil; - -import java.awt.Color; - -@UtilityClass -@Slf4j -public class ChannelCreateEventHelper { - - public static void format(@NonNull GuildAuditLogEntryCreateEvent event, @NonNull String channelIdToSendTo) { - - AuditLogEntry ale = event.getEntry(); - - User executor = ale.getJDA().getUserById(ale.getUserIdLong()); - String mentionableExecutor = (executor != null ? executor.getAsMention() : ale.getUserId()); - - GuildChannel targetChannel = ale.getGuild().getGuildChannelById(ale.getTargetId()); - String targetChannelMention = (targetChannel != null ? targetChannel.getAsMention() : ale.getTargetId()); - - EmbedBuilder eb = new EmbedBuilder(); - eb.setTitle("Audit Log Entry | Channel Create Event"); - - eb.setDescription(MarkdownUtil.quoteBlock("Channel Created By: " + mentionableExecutor + "\nTarget Channel: " + targetChannelMention)); - eb.setColor(Color.GREEN); - - ale.getChanges().forEach((changeKey, changeValue) -> { - - Object oldValue = changeValue.getOldValue(); - Object newValue = changeValue.getNewValue(); - - switch (changeKey) { - case "user_limit" -> - eb.addField(MarkdownUtil.underline("User Limit"), "╰┈➤" + ChannelUtils.resolveVoiceChannelUserLimit(newValue), false); - - case "rate_limit_per_user" -> - eb.addField(MarkdownUtil.underline("Slow Mode"), "╰┈➤" + DurationUtils.formatSeconds(newValue), false); - - case "type" -> - eb.addField(MarkdownUtil.underline("Channel Type"), "╰┈➤" + ChannelUtils.resolveChannelType(newValue), false); - - case "nsfw" -> - eb.addField(MarkdownUtil.underline("Is NSFW"), "╰┈➤" + BooleanUtils.formatToYesOrNo(newValue), false); - - case "name" -> eb.addField(MarkdownUtil.underline("Channel Name"), "╰┈➤" + newValue, false); - - case "bitrate" -> - eb.addField(MarkdownUtil.underline("Voice Channel Bitrate"), "╰┈➤" + ChannelUtils.resolveVoiceChannelBitrate(newValue), false); - - case "permission_overwrites", "flags", "template", "available_tags" -> { - // the first two are for all types of channels and may stay empty during creation events - // the second two are forum only cases which stay empty during creation - } - - default -> { - eb.addField("Unimplemented Change Key", changeKey, false); - log.info("Unimplemented Change Key: {}\nOLD_VALUE: {}\nNEW_VALUE: {}", changeKey, oldValue, newValue); - } - } - }); - - eb.setFooter("Audit Log Entry ID: " + ale.getId()); - eb.setTimestamp(ale.getTimeCreated()); - - if (!eb.isValidLength() || eb.isEmpty()) { - log.warn("Embed is empty or too long (current length: {}).", eb.length()); - return; - } - - TextChannel sendingChannel = event.getGuild().getTextChannelById(channelIdToSendTo); - if (sendingChannel != null && sendingChannel.canTalk()) { - sendingChannel.sendMessageEmbeds(eb.build()).queue(); - } - } -} diff --git a/src/main/java/io/github/eggy03/papertrail/bot/listeners/auditlog/helper/channel/ChannelDeleteEventHelper.java b/src/main/java/io/github/eggy03/papertrail/bot/listeners/auditlog/helper/channel/ChannelDeleteEventHelper.java deleted file mode 100644 index 9e31c1c4..00000000 --- a/src/main/java/io/github/eggy03/papertrail/bot/listeners/auditlog/helper/channel/ChannelDeleteEventHelper.java +++ /dev/null @@ -1,62 +0,0 @@ -package io.github.eggy03.papertrail.bot.listeners.auditlog.helper.channel; - -import io.github.eggy03.papertrail.bot.listeners.auditlog.helper.channel.utils.ChannelUtils; -import lombok.NonNull; -import lombok.experimental.UtilityClass; -import lombok.extern.slf4j.Slf4j; -import net.dv8tion.jda.api.EmbedBuilder; -import net.dv8tion.jda.api.audit.AuditLogEntry; -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 net.dv8tion.jda.api.utils.MarkdownUtil; - -import java.awt.Color; - -@UtilityClass -@Slf4j -public class ChannelDeleteEventHelper { - - public static void format(@NonNull GuildAuditLogEntryCreateEvent event, @NonNull String channelIdToSendTo) { - - AuditLogEntry ale = event.getEntry(); - - User executor = ale.getJDA().getUserById(ale.getUserIdLong()); - String mentionableExecutor = (executor != null ? executor.getAsMention() : ale.getUserId()); - - EmbedBuilder eb = new EmbedBuilder(); - eb.setTitle("Audit Log Entry | Channel Delete Event"); - - eb.setDescription(MarkdownUtil.quoteBlock("Channel Deleted By: " + mentionableExecutor + "\nTarget Channel ID: " + ale.getTargetId())); - eb.setColor(Color.RED); - - ale.getChanges().forEach((changeKey, changeValue) -> { - - Object oldValue = changeValue.getOldValue(); - - switch (changeKey) { - case "name" -> eb.addField(MarkdownUtil.underline("Name"), "╰┈➤" + oldValue, false); - - case "type" -> - eb.addField(MarkdownUtil.underline("Type"), "╰┈➤" + ChannelUtils.resolveChannelType(oldValue), false); - - default -> { - // omit all other fields - } - } - }); - - eb.setFooter("Audit Log Entry ID: " + ale.getId()); - eb.setTimestamp(ale.getTimeCreated()); - - if (!eb.isValidLength() || eb.isEmpty()) { - log.warn("Embed is empty or too long (current length: {}).", eb.length()); - return; - } - - TextChannel sendingChannel = event.getGuild().getTextChannelById(channelIdToSendTo); - if (sendingChannel != null && sendingChannel.canTalk()) { - sendingChannel.sendMessageEmbeds(eb.build()).queue(); - } - } -} diff --git a/src/main/java/io/github/eggy03/papertrail/bot/listeners/auditlog/helper/channel/ChannelOverrideCreateEventHelper.java b/src/main/java/io/github/eggy03/papertrail/bot/listeners/auditlog/helper/channel/ChannelOverrideCreateEventHelper.java deleted file mode 100644 index 33f6f8dc..00000000 --- a/src/main/java/io/github/eggy03/papertrail/bot/listeners/auditlog/helper/channel/ChannelOverrideCreateEventHelper.java +++ /dev/null @@ -1,75 +0,0 @@ -package io.github.eggy03.papertrail.bot.listeners.auditlog.helper.channel; - -import io.github.eggy03.papertrail.bot.listeners.auditlog.helper.channel.utils.ChannelUtils; -import lombok.NonNull; -import lombok.experimental.UtilityClass; -import lombok.extern.slf4j.Slf4j; -import net.dv8tion.jda.api.EmbedBuilder; -import net.dv8tion.jda.api.audit.AuditLogEntry; -import net.dv8tion.jda.api.entities.User; -import net.dv8tion.jda.api.entities.channel.concrete.TextChannel; -import net.dv8tion.jda.api.entities.channel.middleman.GuildChannel; -import net.dv8tion.jda.api.events.guild.GuildAuditLogEntryCreateEvent; -import net.dv8tion.jda.api.utils.MarkdownUtil; - -import java.awt.Color; - -@UtilityClass -@Slf4j -public class ChannelOverrideCreateEventHelper { - - public static void format(@NonNull GuildAuditLogEntryCreateEvent event, @NonNull String channelIdToSendTo) { - - AuditLogEntry ale = event.getEntry(); - - User executor = ale.getJDA().getUserById(ale.getUserIdLong()); - String mentionableExecutor = (executor != null ? executor.getAsMention() : ale.getUserId()); - - GuildChannel targetChannel = event.getGuild().getGuildChannelById(ale.getTargetId()); - String targetChannelMention = (targetChannel != null ? targetChannel.getAsMention() : ale.getTargetId()); - - EmbedBuilder eb = new EmbedBuilder(); - eb.setTitle("Audit Log Entry | Channel Override Create"); - eb.setDescription(MarkdownUtil.quoteBlock("Override Created By: " + mentionableExecutor + "\nTarget Channel: " + targetChannelMention)); - eb.setColor(Color.GREEN); - - ale.getChanges().forEach((changeKey, changeValue) -> { - Object oldValue = changeValue.getOldValue(); - Object newValue = changeValue.getNewValue(); - - switch (changeKey) { - - case "type" -> - eb.addField(MarkdownUtil.underline("Override Type"), "╰┈➤" + ChannelUtils.resolveChannelOverrideTargetType(newValue), false); - - case "deny" -> - eb.addField(MarkdownUtil.underline("Denied Permissions"), ChannelUtils.resolveChannelOverridePermissions(newValue, "❌"), false); - case "allow" -> - eb.addField(MarkdownUtil.underline("Allowed Permissions"), ChannelUtils.resolveChannelOverridePermissions(newValue, "✅"), false); - - // id exposes the member/role id which for which the channel permissions are overridden - // only one member/role permission id is fetched per loop - case "id" -> - eb.addField(MarkdownUtil.underline("Target Member/Role"), "╰┈➤" + ChannelUtils.autoResolveMemberOrRole(newValue, event), false); - - default -> { - eb.addField("Unimplemented Change Key", changeKey, false); - log.info("Unimplemented Change Key: {}\nOLD_VALUE: {}\nNEW_VALUE: {}", changeKey, oldValue, newValue); - } - } - }); - - eb.setFooter("Audit Log Entry ID: " + ale.getId()); - eb.setTimestamp(ale.getTimeCreated()); - - if (!eb.isValidLength() || eb.isEmpty()) { - log.warn("Embed is empty or too long (current length: {}).", eb.length()); - return; - } - - TextChannel sendingChannel = event.getGuild().getTextChannelById(channelIdToSendTo); - if (sendingChannel != null && sendingChannel.canTalk()) { - sendingChannel.sendMessageEmbeds(eb.build()).queue(); - } - } -} diff --git a/src/main/java/io/github/eggy03/papertrail/bot/listeners/auditlog/helper/channel/ChannelOverrideDeleteEventHelper.java b/src/main/java/io/github/eggy03/papertrail/bot/listeners/auditlog/helper/channel/ChannelOverrideDeleteEventHelper.java deleted file mode 100644 index 860dbcee..00000000 --- a/src/main/java/io/github/eggy03/papertrail/bot/listeners/auditlog/helper/channel/ChannelOverrideDeleteEventHelper.java +++ /dev/null @@ -1,76 +0,0 @@ -package io.github.eggy03.papertrail.bot.listeners.auditlog.helper.channel; - -import io.github.eggy03.papertrail.bot.listeners.auditlog.helper.channel.utils.ChannelUtils; -import lombok.NonNull; -import lombok.experimental.UtilityClass; -import lombok.extern.slf4j.Slf4j; -import net.dv8tion.jda.api.EmbedBuilder; -import net.dv8tion.jda.api.audit.AuditLogEntry; -import net.dv8tion.jda.api.entities.User; -import net.dv8tion.jda.api.entities.channel.concrete.TextChannel; -import net.dv8tion.jda.api.entities.channel.middleman.GuildChannel; -import net.dv8tion.jda.api.events.guild.GuildAuditLogEntryCreateEvent; -import net.dv8tion.jda.api.utils.MarkdownUtil; - -import java.awt.Color; - -@UtilityClass -@Slf4j -public class ChannelOverrideDeleteEventHelper { - - public static void format(@NonNull GuildAuditLogEntryCreateEvent event, @NonNull String channelIdToSendTo) { - - AuditLogEntry ale = event.getEntry(); - - User executor = ale.getJDA().getUserById(ale.getUserIdLong()); - String mentionableExecutor = (executor != null ? executor.getAsMention() : ale.getUserId()); - - GuildChannel targetChannel = event.getGuild().getGuildChannelById(ale.getTargetId()); - String targetChannelMention = (targetChannel != null ? targetChannel.getAsMention() : ale.getTargetId()); - - EmbedBuilder eb = new EmbedBuilder(); - eb.setTitle("Audit Log Entry | Channel Override Delete"); - - eb.setDescription(MarkdownUtil.quoteBlock("Override Deleted By: " + mentionableExecutor + "\nTarget Channel: " + targetChannelMention)); - eb.setColor(Color.RED); - - ale.getChanges().forEach((changeKey, changeValue) -> { - Object oldValue = changeValue.getOldValue(); - Object newValue = changeValue.getNewValue(); - - switch (changeKey) { - - case "type" -> - eb.addField(MarkdownUtil.underline("Override Type"), "╰┈➤" + ChannelUtils.resolveChannelOverrideTargetType(oldValue), false); - - case "deny" -> - eb.addField(MarkdownUtil.underline("Denied Permissions"), ChannelUtils.resolveChannelOverridePermissions(oldValue, "❌"), false); - case "allow" -> - eb.addField(MarkdownUtil.underline("Allowed Permissions"), ChannelUtils.resolveChannelOverridePermissions(oldValue, "✅"), false); - - // id exposes the member/role id which for which the channel permissions are overridden - // only one member/role permission id is fetched per loop - case "id" -> - eb.addField(MarkdownUtil.underline("Target Member/Role"), "╰┈➤" + ChannelUtils.autoResolveMemberOrRole(oldValue, event), false); - - default -> { - eb.addField("Unimplemented Change Key", changeKey, false); - log.info("Unimplemented Change Key: {}\nOLD_VALUE: {}\nNEW_VALUE: {}", changeKey, oldValue, newValue); - } - } - }); - - eb.setFooter("Audit Log Entry ID: " + ale.getId()); - eb.setTimestamp(ale.getTimeCreated()); - - if (!eb.isValidLength() || eb.isEmpty()) { - log.warn("Embed is empty or too long (current length: {}).", eb.length()); - return; - } - - TextChannel sendingChannel = event.getGuild().getTextChannelById(channelIdToSendTo); - if (sendingChannel != null && sendingChannel.canTalk()) { - sendingChannel.sendMessageEmbeds(eb.build()).queue(); - } - } -} diff --git a/src/main/java/io/github/eggy03/papertrail/bot/listeners/auditlog/helper/channel/ChannelOverrideUpdateEventHelper.java b/src/main/java/io/github/eggy03/papertrail/bot/listeners/auditlog/helper/channel/ChannelOverrideUpdateEventHelper.java deleted file mode 100644 index f3b6f96d..00000000 --- a/src/main/java/io/github/eggy03/papertrail/bot/listeners/auditlog/helper/channel/ChannelOverrideUpdateEventHelper.java +++ /dev/null @@ -1,107 +0,0 @@ -package io.github.eggy03.papertrail.bot.listeners.auditlog.helper.channel; - -import io.github.eggy03.papertrail.bot.listeners.auditlog.helper.channel.utils.ChannelUtils; -import lombok.NonNull; -import lombok.experimental.UtilityClass; -import lombok.extern.slf4j.Slf4j; -import net.dv8tion.jda.api.EmbedBuilder; -import net.dv8tion.jda.api.audit.AuditLogEntry; -import net.dv8tion.jda.api.entities.Member; -import net.dv8tion.jda.api.entities.Role; -import net.dv8tion.jda.api.entities.User; -import net.dv8tion.jda.api.entities.channel.concrete.TextChannel; -import net.dv8tion.jda.api.entities.channel.middleman.GuildChannel; -import net.dv8tion.jda.api.events.guild.GuildAuditLogEntryCreateEvent; -import net.dv8tion.jda.api.utils.MarkdownUtil; -import org.jetbrains.annotations.NotNull; - -import java.awt.Color; - -@UtilityClass -@Slf4j -public class ChannelOverrideUpdateEventHelper { - - public static void format(@NonNull GuildAuditLogEntryCreateEvent event, @NonNull String channelIdToSendTo) { - - AuditLogEntry ale = event.getEntry(); - - User executor = ale.getJDA().getUserById(ale.getUserIdLong()); - String mentionableExecutor = (executor != null ? executor.getAsMention() : ale.getUserId()); - - GuildChannel targetChannel = event.getGuild().getGuildChannelById(ale.getTargetId()); - String targetChannelMention = (targetChannel != null ? targetChannel.getAsMention() : ale.getTargetId()); - - EmbedBuilder eb = new EmbedBuilder(); - eb.setTitle("Audit Log Entry | Channel Override Update"); - eb.setDescription(MarkdownUtil.quoteBlock("Override Updated By: " + mentionableExecutor + "\nTarget Channel: " + targetChannelMention)); - eb.setColor(Color.YELLOW); - - eb.addField(MarkdownUtil.underline("Override Type"), "╰┈➤" + ChannelUtils.resolveChannelOverrideTargetType(ale.getOptionByName("type")), false); - eb.addField(MarkdownUtil.underline("Permissions Overridden For"), "╰┈➤" + getTargetRoleOrMember(ale, event), false); - - ale.getChanges().forEach((changeKey, changeValue) -> { - - Object oldValue = changeValue.getOldValue(); - Object newValue = changeValue.getNewValue(); - - switch (changeKey) { - - case "deny" -> - eb.addField(MarkdownUtil.underline("Denied Permissions"), ChannelUtils.resolveChannelOverridePermissions(newValue, "❌"), false); - case "allow" -> - eb.addField(MarkdownUtil.underline("Allowed Permissions"), ChannelUtils.resolveChannelOverridePermissions(newValue, "✅"), false); - - default -> { - eb.addField("Unimplemented Change Key", changeKey, false); - log.info("Unimplemented Change Key: {}\nOLD_VALUE: {}\nNEW_VALUE: {}", changeKey, oldValue, newValue); - } - - } - }); - - eb.setFooter("Audit Log Entry ID: " + ale.getId()); - eb.setTimestamp(ale.getTimeCreated()); - - if (!eb.isValidLength() || eb.isEmpty()) { - log.warn("Embed is empty or too long (current length: {}).", eb.length()); - return; - } - - TextChannel sendingChannel = event.getGuild().getTextChannelById(channelIdToSendTo); - if (sendingChannel != null && sendingChannel.canTalk()) { - sendingChannel.sendMessageEmbeds(eb.build()).queue(); - } - } - - // ALE changes do not expose the id and type keys in case of override updates - // therefore, this hacky method is required - // IDK why channel override updates don't show this info - @NotNull - private static String getTargetRoleOrMember(@NonNull AuditLogEntry ale, @NonNull GuildAuditLogEntryCreateEvent event) { - - String overriddenId = ale.getOptionByName("id"); // id of the member or role - String overriddenType = ale.getOptionByName("type"); // type that determines if the ID is that of a role or a member - - if (overriddenId == null) - return "Member or Role ID is null"; - - return switch (overriddenType) { - - case "0" -> { - // It’s a role - Role role = event.getGuild().getRoleById(overriddenId); - yield role != null ? role.getAsMention() : overriddenId; - } - - case "1" -> { - // It's a member - Member member = event.getGuild().getMemberById(overriddenId); - yield member != null ? member.getAsMention() : overriddenId; - } - - case null -> "Override Type is null"; - default -> "Unimplemented Override Type: " + overriddenType; - - }; - } -} diff --git a/src/main/java/io/github/eggy03/papertrail/bot/listeners/auditlog/helper/channel/VoiceChannelStatusDeleteEventHelper.java b/src/main/java/io/github/eggy03/papertrail/bot/listeners/auditlog/helper/channel/VoiceChannelStatusDeleteEventHelper.java deleted file mode 100644 index 1f556614..00000000 --- a/src/main/java/io/github/eggy03/papertrail/bot/listeners/auditlog/helper/channel/VoiceChannelStatusDeleteEventHelper.java +++ /dev/null @@ -1,56 +0,0 @@ -package io.github.eggy03.papertrail.bot.listeners.auditlog.helper.channel; - -import lombok.NonNull; -import lombok.experimental.UtilityClass; -import lombok.extern.slf4j.Slf4j; -import net.dv8tion.jda.api.EmbedBuilder; -import net.dv8tion.jda.api.audit.AuditLogEntry; -import net.dv8tion.jda.api.entities.User; -import net.dv8tion.jda.api.entities.channel.concrete.TextChannel; -import net.dv8tion.jda.api.entities.channel.middleman.GuildChannel; -import net.dv8tion.jda.api.events.guild.GuildAuditLogEntryCreateEvent; -import net.dv8tion.jda.api.utils.MarkdownUtil; - -import java.awt.Color; - -@UtilityClass -@Slf4j -public class VoiceChannelStatusDeleteEventHelper { - - public static void format(@NonNull GuildAuditLogEntryCreateEvent event, @NonNull String channelIdToSendTo) { - - AuditLogEntry ale = event.getEntry(); - - User executor = ale.getJDA().getUserById(ale.getUserId()); - String mentionableExecutor = (executor != null ? executor.getAsMention() : ale.getUserId()); - - GuildChannel targetChannel = ale.getJDA().getGuildChannelById(ale.getTargetId()); - String mentionableTargetChannel = (targetChannel != null ? targetChannel.getAsMention() : ale.getTargetId()); - - EmbedBuilder eb = new EmbedBuilder(); - eb.setTitle("Audit Log Entry | Voice Channel Status Delete"); - - eb.setDescription("A voice channel status has been reset"); - eb.setColor(Color.ORANGE); - - // status deletes dont contain the deleted status content - eb.addField( - MarkdownUtil.underline("Details"), - MarkdownUtil.quoteBlock("Status Reset By: " + mentionableExecutor + "\n" + "Target Channel: " + mentionableTargetChannel), - false - ); - - eb.setFooter("Audit Log Entry ID: " + ale.getId()); - eb.setTimestamp(ale.getTimeCreated()); - - if (!eb.isValidLength() || eb.isEmpty()) { - log.warn("Embed is empty or too long (current length: {}).", eb.length()); - return; - } - - TextChannel sendingChannel = event.getGuild().getTextChannelById(channelIdToSendTo); - if (sendingChannel != null && sendingChannel.canTalk()) { - sendingChannel.sendMessageEmbeds(eb.build()).queue(); - } - } -} diff --git a/src/main/java/io/github/eggy03/papertrail/bot/listeners/auditlog/helper/channel/VoiceChannelStatusUpdateEventHelper.java b/src/main/java/io/github/eggy03/papertrail/bot/listeners/auditlog/helper/channel/VoiceChannelStatusUpdateEventHelper.java deleted file mode 100644 index 8cf11430..00000000 --- a/src/main/java/io/github/eggy03/papertrail/bot/listeners/auditlog/helper/channel/VoiceChannelStatusUpdateEventHelper.java +++ /dev/null @@ -1,59 +0,0 @@ -package io.github.eggy03.papertrail.bot.listeners.auditlog.helper.channel; - -import lombok.NonNull; -import lombok.experimental.UtilityClass; -import lombok.extern.slf4j.Slf4j; -import net.dv8tion.jda.api.EmbedBuilder; -import net.dv8tion.jda.api.audit.AuditLogEntry; -import net.dv8tion.jda.api.entities.User; -import net.dv8tion.jda.api.entities.channel.concrete.TextChannel; -import net.dv8tion.jda.api.entities.channel.middleman.GuildChannel; -import net.dv8tion.jda.api.events.guild.GuildAuditLogEntryCreateEvent; -import net.dv8tion.jda.api.utils.MarkdownUtil; - -import java.awt.Color; - -@UtilityClass -@Slf4j -public class VoiceChannelStatusUpdateEventHelper { - - public static void format(@NonNull GuildAuditLogEntryCreateEvent event, @NonNull String channelIdToSendTo) { - - AuditLogEntry ale = event.getEntry(); - - User executor = ale.getJDA().getUserById(ale.getUserId()); - String mentionableExecutor = (executor != null ? executor.getAsMention() : ale.getUserId()); - - GuildChannel targetChannel = ale.getJDA().getGuildChannelById(ale.getTargetId()); - String mentionableTargetChannel = (targetChannel != null ? targetChannel.getAsMention() : ale.getTargetId()); - - EmbedBuilder eb = new EmbedBuilder(); - eb.setTitle("Audit Log Entry | Voice Channel Status Update"); - - eb.setDescription("A voice channel status has been updated"); - eb.setColor(Color.YELLOW); - - eb.addField( - MarkdownUtil.underline("Details"), - MarkdownUtil.quoteBlock( - "Status Updated By: " + mentionableExecutor + "\n" + - "Target Channel: " + mentionableTargetChannel + "\n" + - "Updated Status: " + ale.getOptionByName("status") - ), - false - ); - - eb.setFooter("Audit Log Entry ID: " + ale.getId()); - eb.setTimestamp(ale.getTimeCreated()); - - if (!eb.isValidLength() || eb.isEmpty()) { - log.warn("Embed is empty or too long (current length: {}).", eb.length()); - return; - } - - TextChannel sendingChannel = event.getGuild().getTextChannelById(channelIdToSendTo); - if (sendingChannel != null && sendingChannel.canTalk()) { - sendingChannel.sendMessageEmbeds(eb.build()).queue(); - } - } -} diff --git a/src/main/java/io/github/eggy03/papertrail/bot/listeners/auditlog/helper/emoji/EmojiCreateEventHelper.java b/src/main/java/io/github/eggy03/papertrail/bot/listeners/auditlog/helper/emoji/EmojiCreateEventHelper.java deleted file mode 100644 index 1ae2a1a8..00000000 --- a/src/main/java/io/github/eggy03/papertrail/bot/listeners/auditlog/helper/emoji/EmojiCreateEventHelper.java +++ /dev/null @@ -1,58 +0,0 @@ -package io.github.eggy03.papertrail.bot.listeners.auditlog.helper.emoji; - -import lombok.NonNull; -import lombok.experimental.UtilityClass; -import lombok.extern.slf4j.Slf4j; -import net.dv8tion.jda.api.EmbedBuilder; -import net.dv8tion.jda.api.audit.AuditLogEntry; -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 net.dv8tion.jda.api.utils.MarkdownUtil; - -import java.awt.Color; - -@UtilityClass -@Slf4j -public class EmojiCreateEventHelper { - - public static void format(@NonNull GuildAuditLogEntryCreateEvent event, @NonNull String channelIdToSendTo) { - - AuditLogEntry ale = event.getEntry(); - - User executor = ale.getJDA().getUserById(ale.getUserIdLong()); - String mentionableExecutor = (executor != null ? executor.getAsMention() : ale.getUserId()); - - EmbedBuilder eb = new EmbedBuilder(); - eb.setTitle("Audit Log Entry | Emoji Create Event"); - eb.setDescription(MarkdownUtil.quoteBlock("Emoji Created By: " + mentionableExecutor)); - eb.setColor(Color.GREEN); - - ale.getChanges().forEach((changeKey, changeValue) -> { - - Object oldValue = changeValue.getOldValue(); - Object newValue = changeValue.getNewValue(); - - if (changeKey.equals("name")) { - eb.addField(MarkdownUtil.underline("Emoji Name"), "╰┈➤" + newValue, false); - eb.addField(MarkdownUtil.underline("Emoji"), "╰┈➤" + "<:" + newValue + ":" + ale.getTargetId() + ">", false); // ale's TargetID retrieves the ID of the created emoji - } else { - eb.addField("Unimplemented Change Key", changeKey, false); - log.info("Unimplemented Change Key: {}\nOLD_VALUE: {}\nNEW_VALUE: {}", changeKey, oldValue, newValue); - } - }); - - eb.setFooter("Audit Log Entry ID: " + ale.getId()); - eb.setTimestamp(ale.getTimeCreated()); - - if (!eb.isValidLength() || eb.isEmpty()) { - log.warn("Embed is empty or too long (current length: {}).", eb.length()); - return; - } - - TextChannel sendingChannel = event.getGuild().getTextChannelById(channelIdToSendTo); - if (sendingChannel != null && sendingChannel.canTalk()) { - sendingChannel.sendMessageEmbeds(eb.build()).queue(); - } - } -} diff --git a/src/main/java/io/github/eggy03/papertrail/bot/listeners/auditlog/helper/emoji/EmojiDeleteEventHelper.java b/src/main/java/io/github/eggy03/papertrail/bot/listeners/auditlog/helper/emoji/EmojiDeleteEventHelper.java deleted file mode 100644 index 03582948..00000000 --- a/src/main/java/io/github/eggy03/papertrail/bot/listeners/auditlog/helper/emoji/EmojiDeleteEventHelper.java +++ /dev/null @@ -1,58 +0,0 @@ -package io.github.eggy03.papertrail.bot.listeners.auditlog.helper.emoji; - -import lombok.NonNull; -import lombok.experimental.UtilityClass; -import lombok.extern.slf4j.Slf4j; -import net.dv8tion.jda.api.EmbedBuilder; -import net.dv8tion.jda.api.audit.AuditLogEntry; -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 net.dv8tion.jda.api.utils.MarkdownUtil; - -import java.awt.Color; - -@UtilityClass -@Slf4j -public class EmojiDeleteEventHelper { - - public static void format(@NonNull GuildAuditLogEntryCreateEvent event, @NonNull String channelIdToSendTo) { - - AuditLogEntry ale = event.getEntry(); - - User executor = ale.getJDA().getUserById(ale.getUserIdLong()); - String mentionableExecutor = (executor != null ? executor.getAsMention() : ale.getUserId()); - - EmbedBuilder eb = new EmbedBuilder(); - eb.setTitle("Audit Log Entry | Emoji Delete Event"); - eb.setDescription(MarkdownUtil.quoteBlock("Emoji Deleted By: " + mentionableExecutor)); - eb.setColor(Color.RED); - - ale.getChanges().forEach((changeKey, changeValue) -> { - - Object oldValue = changeValue.getOldValue(); - Object newValue = changeValue.getNewValue(); - - if (changeKey.equals("name")) { - eb.addField(MarkdownUtil.underline("Emoji Name"), "╰┈➤" + oldValue, false); - } else { - eb.addField("Unimplemented Change Key", changeKey, false); - log.info("Unimplemented Change Key: {}\nOLD_VALUE: {}\nNEW_VALUE: {}", changeKey, oldValue, newValue); - } - }); - eb.addField("Deleted Emoji ID", "╰┈➤" + ale.getTargetId(), false); - - eb.setFooter("Audit Log Entry ID: " + ale.getId()); - eb.setTimestamp(ale.getTimeCreated()); - - if (!eb.isValidLength() || eb.isEmpty()) { - log.warn("Embed is empty or too long (current length: {}).", eb.length()); - return; - } - - TextChannel sendingChannel = event.getGuild().getTextChannelById(channelIdToSendTo); - if (sendingChannel != null && sendingChannel.canTalk()) { - sendingChannel.sendMessageEmbeds(eb.build()).queue(); - } - } -} diff --git a/src/main/java/io/github/eggy03/papertrail/bot/listeners/auditlog/helper/emoji/EmojiUpdateEventHelper.java b/src/main/java/io/github/eggy03/papertrail/bot/listeners/auditlog/helper/emoji/EmojiUpdateEventHelper.java deleted file mode 100644 index 9f368a79..00000000 --- a/src/main/java/io/github/eggy03/papertrail/bot/listeners/auditlog/helper/emoji/EmojiUpdateEventHelper.java +++ /dev/null @@ -1,59 +0,0 @@ -package io.github.eggy03.papertrail.bot.listeners.auditlog.helper.emoji; - -import lombok.NonNull; -import lombok.experimental.UtilityClass; -import lombok.extern.slf4j.Slf4j; -import net.dv8tion.jda.api.EmbedBuilder; -import net.dv8tion.jda.api.audit.AuditLogEntry; -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 net.dv8tion.jda.api.utils.MarkdownUtil; - -import java.awt.Color; - -@UtilityClass -@Slf4j -public class EmojiUpdateEventHelper { - - public static void format(@NonNull GuildAuditLogEntryCreateEvent event, @NonNull String channelIdToSendTo) { - - AuditLogEntry ale = event.getEntry(); - - User executor = ale.getJDA().getUserById(ale.getUserIdLong()); - String mentionableExecutor = (executor != null ? executor.getAsMention() : ale.getUserId()); - - - EmbedBuilder eb = new EmbedBuilder(); - eb.setTitle("Audit Log Entry | Emoji Update Event"); - eb.setDescription(MarkdownUtil.quoteBlock("Emoji Updated By: " + mentionableExecutor)); - eb.setColor(Color.YELLOW); - - ale.getChanges().forEach((changeKey, changeValue) -> { - - Object oldValue = changeValue.getOldValue(); - Object newValue = changeValue.getNewValue(); - - if (changeKey.equals("name")) { - eb.addField(MarkdownUtil.underline("Emoji Name Updated"), "╰┈➤" + "From " + oldValue + " to " + newValue, false); - eb.addField(MarkdownUtil.underline("Target Emoji"), "╰┈➤" + "<:" + newValue + ":" + ale.getTargetId() + ">", false); - } else { - eb.addField("Unimplemented Change Key", changeKey, false); - log.info("Unimplemented Change Key: {}\nOLD_VALUE: {}\nNEW_VALUE: {}", changeKey, oldValue, newValue); - } - }); - - eb.setFooter("Audit Log Entry ID: " + ale.getId()); - eb.setTimestamp(ale.getTimeCreated()); - - if (!eb.isValidLength() || eb.isEmpty()) { - log.warn("Embed is empty or too long (current length: {}).", eb.length()); - return; - } - - TextChannel sendingChannel = event.getGuild().getTextChannelById(channelIdToSendTo); - if (sendingChannel != null && sendingChannel.canTalk()) { - sendingChannel.sendMessageEmbeds(eb.build()).queue(); - } - } -} diff --git a/src/main/java/io/github/eggy03/papertrail/bot/listeners/auditlog/helper/generic/GenericAuditLogEventHelper.java b/src/main/java/io/github/eggy03/papertrail/bot/listeners/auditlog/helper/generic/GenericAuditLogEventHelper.java deleted file mode 100644 index 8a0f9ac2..00000000 --- a/src/main/java/io/github/eggy03/papertrail/bot/listeners/auditlog/helper/generic/GenericAuditLogEventHelper.java +++ /dev/null @@ -1,56 +0,0 @@ -package io.github.eggy03.papertrail.bot.listeners.auditlog.helper.generic; - -import lombok.NonNull; -import lombok.experimental.UtilityClass; -import lombok.extern.slf4j.Slf4j; -import net.dv8tion.jda.api.EmbedBuilder; -import net.dv8tion.jda.api.audit.AuditLogEntry; -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 net.dv8tion.jda.api.utils.MarkdownUtil; - -import java.awt.Color; - -// for events not defined by JDA yet or not implemented by papertrail -@UtilityClass -@Slf4j -public class GenericAuditLogEventHelper { - - public static void format(@NonNull GuildAuditLogEntryCreateEvent event, @NonNull String channelIdToSendTo) { - - AuditLogEntry ale = event.getEntry(); - - User executor = ale.getJDA().getUserById(ale.getUserIdLong()); - String mentionableExecutor = executor != null ? executor.getAsMention() : ale.getUserId(); - - EmbedBuilder eb = new EmbedBuilder(); - eb.setTitle("Audit Log Entry | Generic Event"); - eb.setDescription(MarkdownUtil.quoteBlock("Executor: " + mentionableExecutor)); - eb.setColor(Color.LIGHT_GRAY); - - eb.addField(MarkdownUtil.underline("Action Type"), MarkdownUtil.codeblock(ale.getType().toString()), true); - eb.addField(MarkdownUtil.underline("Target Type"), MarkdownUtil.codeblock(ale.getTargetType().toString()), true); - - ale.getChanges() - .forEach((changeKey, changeValue) -> - eb.addField( - MarkdownUtil.underline(changeKey), - MarkdownUtil.codeblock("OLD VALUE\n" + changeValue.getOldValue() + "\nNEW VALUE\n" + changeValue.getNewValue()), - false - ) - ); - - - - if (!eb.isValidLength() || eb.isEmpty()) { - log.warn("Embed is empty or too long (current length: {}).", eb.length()); - return; - } - - TextChannel sendingChannel = event.getGuild().getTextChannelById(channelIdToSendTo); - if (sendingChannel != null && sendingChannel.canTalk()) { - sendingChannel.sendMessageEmbeds(eb.build()).queue(); - } - } -} diff --git a/src/main/java/io/github/eggy03/papertrail/bot/listeners/auditlog/helper/guild/GuildProfileUpdateEventHelper.java b/src/main/java/io/github/eggy03/papertrail/bot/listeners/auditlog/helper/guild/GuildProfileUpdateEventHelper.java deleted file mode 100644 index 70a8efc5..00000000 --- a/src/main/java/io/github/eggy03/papertrail/bot/listeners/auditlog/helper/guild/GuildProfileUpdateEventHelper.java +++ /dev/null @@ -1,57 +0,0 @@ -package io.github.eggy03.papertrail.bot.listeners.auditlog.helper.guild; - -import lombok.NonNull; -import lombok.experimental.UtilityClass; -import lombok.extern.slf4j.Slf4j; -import net.dv8tion.jda.api.EmbedBuilder; -import net.dv8tion.jda.api.audit.AuditLogEntry; -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 net.dv8tion.jda.api.utils.MarkdownUtil; - -import java.awt.Color; - -@UtilityClass -@Slf4j -public class GuildProfileUpdateEventHelper { - - public static void format(@NonNull GuildAuditLogEntryCreateEvent event, @NonNull String channelIdToSendTo) { - - AuditLogEntry ale = event.getEntry(); - - User executor = ale.getJDA().getUserById(ale.getUserIdLong()); - String mentionableExecutor = (executor != null ? executor.getAsMention() : ale.getUserId()); - - EmbedBuilder eb = new EmbedBuilder(); - eb.setTitle("Audit Log Entry | Guild Profile Update Event"); - eb.setDescription(MarkdownUtil.quoteBlock("Guild Profile Updated By: " + mentionableExecutor + "\nTarget Guild: " + event.getGuild().getName())); - eb.setColor(Color.PINK); - - ale.getChanges().keySet().forEach(key -> { - switch (key) { - case "traits" -> - eb.addField(MarkdownUtil.underline("Server Traits"), "╰┈➤Server Traits have been updated", false); - case "visibility" -> - eb.addField(MarkdownUtil.underline("Visibility"), "╰┈➤Profile Visibility has been changed", false); - case "brand_color_primary" -> - eb.addField(MarkdownUtil.underline("Banner Color"), "╰┈➤Banner Color has been updated", false); - case "game_application_ids" -> - eb.addField(MarkdownUtil.underline("Games"), "╰┈➤Games have been updated", false); - default -> eb.addField(MarkdownUtil.underline(key), "╰┈➤" + key + " has/have been updated", false); - } - }); - eb.setFooter("Audit Log Entry ID: " + ale.getId()); - eb.setTimestamp(ale.getTimeCreated()); - - if (!eb.isValidLength() || eb.isEmpty()) { - log.warn("Embed is empty or too long (current length: {}).", eb.length()); - return; - } - - TextChannel sendingChannel = event.getGuild().getTextChannelById(channelIdToSendTo); - if (sendingChannel != null && sendingChannel.canTalk()) { - sendingChannel.sendMessageEmbeds(eb.build()).queue(); - } - } -} diff --git a/src/main/java/io/github/eggy03/papertrail/bot/listeners/auditlog/helper/homesettings/HomeSettingsCreateEventHelper.java b/src/main/java/io/github/eggy03/papertrail/bot/listeners/auditlog/helper/homesettings/HomeSettingsCreateEventHelper.java deleted file mode 100644 index fa2d8917..00000000 --- a/src/main/java/io/github/eggy03/papertrail/bot/listeners/auditlog/helper/homesettings/HomeSettingsCreateEventHelper.java +++ /dev/null @@ -1,51 +0,0 @@ -package io.github.eggy03.papertrail.bot.listeners.auditlog.helper.homesettings; - -import lombok.NonNull; -import lombok.experimental.UtilityClass; -import lombok.extern.slf4j.Slf4j; -import net.dv8tion.jda.api.EmbedBuilder; -import net.dv8tion.jda.api.audit.AuditLogEntry; -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 net.dv8tion.jda.api.utils.MarkdownUtil; - -import java.awt.Color; - -@UtilityClass -@Slf4j -public class HomeSettingsCreateEventHelper { - - public static void format(@NonNull GuildAuditLogEntryCreateEvent event, @NonNull String channelIdToSendTo) { - - AuditLogEntry ale = event.getEntry(); - - User executor = ale.getJDA().getUserById(ale.getUserIdLong()); - String mentionableExecutor = (executor != null ? executor.getAsMention() : ale.getUserId()); - - EmbedBuilder eb = new EmbedBuilder(); - eb.setTitle("Audit Log Entry | Server Guide Create Event"); - eb.setDescription(MarkdownUtil.quoteBlock("Server Guide Created By: " + mentionableExecutor)); - eb.setColor(Color.GREEN); - - eb.addField( - MarkdownUtil.underline("More Info"), - MarkdownUtil.codeblock("To view the created guide, either visit the Server Guide section or the Onboarding section of your guild."), - false - ); - - eb.setFooter("Audit Log Entry ID: " + ale.getId()); - eb.setTimestamp(ale.getTimeCreated()); - - if (!eb.isValidLength() || eb.isEmpty()) { - log.warn("Embed is empty or too long (current length: {}).", eb.length()); - return; - } - - TextChannel sendingChannel = event.getGuild().getTextChannelById(channelIdToSendTo); - if (sendingChannel != null && sendingChannel.canTalk()) { - sendingChannel.sendMessageEmbeds(eb.build()).queue(); - } - - } -} diff --git a/src/main/java/io/github/eggy03/papertrail/bot/listeners/auditlog/helper/homesettings/HomeSettingsUpdateEventHelper.java b/src/main/java/io/github/eggy03/papertrail/bot/listeners/auditlog/helper/homesettings/HomeSettingsUpdateEventHelper.java deleted file mode 100644 index 2431f1fb..00000000 --- a/src/main/java/io/github/eggy03/papertrail/bot/listeners/auditlog/helper/homesettings/HomeSettingsUpdateEventHelper.java +++ /dev/null @@ -1,57 +0,0 @@ -package io.github.eggy03.papertrail.bot.listeners.auditlog.helper.homesettings; - -import lombok.NonNull; -import lombok.experimental.UtilityClass; -import lombok.extern.slf4j.Slf4j; -import net.dv8tion.jda.api.EmbedBuilder; -import net.dv8tion.jda.api.audit.AuditLogEntry; -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 net.dv8tion.jda.api.utils.MarkdownUtil; - -import java.awt.Color; - -@UtilityClass -@Slf4j -public class HomeSettingsUpdateEventHelper { - - public static void format(@NonNull GuildAuditLogEntryCreateEvent event, @NonNull String channelIdToSendTo) { - - AuditLogEntry ale = event.getEntry(); - - User executor = ale.getJDA().getUserById(ale.getUserIdLong()); - String mentionableExecutor = (executor != null ? executor.getAsMention() : ale.getUserId()); - - EmbedBuilder eb = new EmbedBuilder(); - eb.setTitle("Audit Log Entry | Server Guide Update Event"); - eb.setDescription(MarkdownUtil.quoteBlock("Server Guide Updated By: " + mentionableExecutor)); - eb.setColor(Color.YELLOW); - - ale.getChanges().keySet().forEach(key -> { - switch (key) { - case "welcome_message" -> - eb.addField(MarkdownUtil.underline("Welcome Message"), "╰┈➤Welcome Message has been updated", false); - case "resource_channels" -> - eb.addField(MarkdownUtil.underline("Resources"), "╰┈➤Resources have been updated", false); - case "new_member_actions" -> - eb.addField(MarkdownUtil.underline("New Member Join To-Do"), "╰┈➤Interactive Actions have been updated", false); - default -> eb.addField(MarkdownUtil.underline(key), "╰┈➤" + key + " has/have been updated", false); - } - }); - - eb.setFooter("Audit Log Entry ID: " + ale.getId()); - eb.setTimestamp(ale.getTimeCreated()); - - if (!eb.isValidLength() || eb.isEmpty()) { - log.warn("Embed is empty or too long (current length: {}).", eb.length()); - return; - } - - TextChannel sendingChannel = event.getGuild().getTextChannelById(channelIdToSendTo); - if (sendingChannel != null && sendingChannel.canTalk()) { - sendingChannel.sendMessageEmbeds(eb.build()).queue(); - } - - } -} diff --git a/src/main/java/io/github/eggy03/papertrail/bot/listeners/auditlog/helper/integration/ApplicationCommandPrivilegesUpdateEventHelper.java b/src/main/java/io/github/eggy03/papertrail/bot/listeners/auditlog/helper/integration/ApplicationCommandPrivilegesUpdateEventHelper.java deleted file mode 100644 index e734eb2c..00000000 --- a/src/main/java/io/github/eggy03/papertrail/bot/listeners/auditlog/helper/integration/ApplicationCommandPrivilegesUpdateEventHelper.java +++ /dev/null @@ -1,46 +0,0 @@ -package io.github.eggy03.papertrail.bot.listeners.auditlog.helper.integration; - -import lombok.NonNull; -import lombok.experimental.UtilityClass; -import lombok.extern.slf4j.Slf4j; -import net.dv8tion.jda.api.EmbedBuilder; -import net.dv8tion.jda.api.audit.AuditLogEntry; -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 net.dv8tion.jda.api.utils.MarkdownUtil; - -import java.awt.Color; - -@UtilityClass -@Slf4j -public class ApplicationCommandPrivilegesUpdateEventHelper { - - public static void format(@NonNull GuildAuditLogEntryCreateEvent event, @NonNull String channelIdToSendTo) { - - AuditLogEntry ale = event.getEntry(); - - User executor = ale.getJDA().getUserById(ale.getUserIdLong()); - String mentionableExecutor = (executor != null ? executor.getAsMention() : ale.getUserId()); - - EmbedBuilder eb = new EmbedBuilder(); - eb.setTitle("Audit Log Entry | Application Command Privilege Update"); - eb.setDescription(MarkdownUtil.quoteBlock("Application Command Privilege Updated By: " + mentionableExecutor)); - eb.setColor(Color.PINK); - - eb.addField(MarkdownUtil.underline("More Info"), MarkdownUtil.codeblock("To know more about what changes were made, visit the Integrations section"), false); - - eb.setFooter("Audit Log Entry ID: " + ale.getId()); - eb.setTimestamp(ale.getTimeCreated()); - - if (!eb.isValidLength() || eb.isEmpty()) { - log.warn("Embed is empty or too long (current length: {}).", eb.length()); - return; - } - - TextChannel sendingChannel = event.getGuild().getTextChannelById(channelIdToSendTo); - if (sendingChannel != null && sendingChannel.canTalk()) { - sendingChannel.sendMessageEmbeds(eb.build()).queue(); - } - } -} diff --git a/src/main/java/io/github/eggy03/papertrail/bot/listeners/auditlog/helper/integration/IntegrationCreateEventHelper.java b/src/main/java/io/github/eggy03/papertrail/bot/listeners/auditlog/helper/integration/IntegrationCreateEventHelper.java deleted file mode 100644 index d3e9f97d..00000000 --- a/src/main/java/io/github/eggy03/papertrail/bot/listeners/auditlog/helper/integration/IntegrationCreateEventHelper.java +++ /dev/null @@ -1,60 +0,0 @@ -package io.github.eggy03.papertrail.bot.listeners.auditlog.helper.integration; - -import lombok.NonNull; -import lombok.experimental.UtilityClass; -import lombok.extern.slf4j.Slf4j; -import net.dv8tion.jda.api.EmbedBuilder; -import net.dv8tion.jda.api.audit.AuditLogEntry; -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 net.dv8tion.jda.api.utils.MarkdownUtil; - -import java.awt.Color; - -@UtilityClass -@Slf4j -public class IntegrationCreateEventHelper { - - public static void format(@NonNull GuildAuditLogEntryCreateEvent event, @NonNull String channelIdToSendTo) { - - AuditLogEntry ale = event.getEntry(); - - User executor = ale.getJDA().getUserById(ale.getUserIdLong()); - String mentionableExecutor = (executor != null ? executor.getAsMention() : ale.getUserId()); - - EmbedBuilder eb = new EmbedBuilder(); - eb.setTitle("Audit Log Entry | Integration Create Event"); - eb.setDescription(MarkdownUtil.quoteBlock("Integration Created By: " + mentionableExecutor)); - eb.setColor(Color.PINK); - - ale.getChanges().forEach((changeKey, changeValue) -> { - - Object oldValue = changeValue.getOldValue(); - Object newValue = changeValue.getNewValue(); - - switch (changeKey) { - case "type" -> eb.addField(MarkdownUtil.underline("Integration Type"), "╰┈➤" + newValue, false); - case "name" -> eb.addField(MarkdownUtil.underline("Integration Name"), "╰┈➤" + newValue, false); - - default -> { - eb.addField("Unimplemented Change Key", changeKey, false); - log.info("Unimplemented Change Key: {}\nOLD_VALUE: {}\nNEW_VALUE: {}", changeKey, oldValue, newValue); - } - } - }); - - eb.setFooter("Audit Log Entry ID: " + ale.getId()); - eb.setTimestamp(ale.getTimeCreated()); - - if (!eb.isValidLength() || eb.isEmpty()) { - log.warn("Embed is empty or too long (current length: {}).", eb.length()); - return; - } - - TextChannel sendingChannel = event.getGuild().getTextChannelById(channelIdToSendTo); - if (sendingChannel != null && sendingChannel.canTalk()) { - sendingChannel.sendMessageEmbeds(eb.build()).queue(); - } - } -} diff --git a/src/main/java/io/github/eggy03/papertrail/bot/listeners/auditlog/helper/integration/IntegrationDeleteEventHelper.java b/src/main/java/io/github/eggy03/papertrail/bot/listeners/auditlog/helper/integration/IntegrationDeleteEventHelper.java deleted file mode 100644 index 135cd2f6..00000000 --- a/src/main/java/io/github/eggy03/papertrail/bot/listeners/auditlog/helper/integration/IntegrationDeleteEventHelper.java +++ /dev/null @@ -1,59 +0,0 @@ -package io.github.eggy03.papertrail.bot.listeners.auditlog.helper.integration; - -import lombok.NonNull; -import lombok.experimental.UtilityClass; -import lombok.extern.slf4j.Slf4j; -import net.dv8tion.jda.api.EmbedBuilder; -import net.dv8tion.jda.api.audit.AuditLogEntry; -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 net.dv8tion.jda.api.utils.MarkdownUtil; - -import java.awt.Color; - -@UtilityClass -@Slf4j -public class IntegrationDeleteEventHelper { - - public static void format(@NonNull GuildAuditLogEntryCreateEvent event, @NonNull String channelIdToSendTo) { - - AuditLogEntry ale = event.getEntry(); - - User executor = ale.getJDA().getUserById(ale.getUserIdLong()); - String mentionableExecutor = (executor != null ? executor.getAsMention() : ale.getUserId()); - - EmbedBuilder eb = new EmbedBuilder(); - eb.setTitle("Audit Log Entry | Integration Delete Event"); - eb.setDescription(MarkdownUtil.quoteBlock("Integration Deleted By: " + mentionableExecutor)); - eb.setColor(Color.MAGENTA); - - ale.getChanges().forEach((changeKey, changeValue) -> { - Object oldValue = changeValue.getOldValue(); - Object newValue = changeValue.getNewValue(); - - switch (changeKey) { - case "type" -> eb.addField(MarkdownUtil.underline("Integration Type"), "╰┈➤" + oldValue, false); - case "name" -> eb.addField(MarkdownUtil.underline("Integration Name"), "╰┈➤" + oldValue, false); - - default -> { - eb.addField("Unimplemented Change Key", changeKey, false); - log.info("Unimplemented Change Key: {}\nOLD_VALUE: {}\nNEW_VALUE: {}", changeKey, oldValue, newValue); - } - } - }); - - eb.setFooter("Audit Log Entry ID: " + ale.getId()); - eb.setTimestamp(ale.getTimeCreated()); - - if (!eb.isValidLength() || eb.isEmpty()) { - log.warn("Embed is empty or too long (current length: {}).", eb.length()); - return; - } - - TextChannel sendingChannel = event.getGuild().getTextChannelById(channelIdToSendTo); - if (sendingChannel != null && sendingChannel.canTalk()) { - sendingChannel.sendMessageEmbeds(eb.build()).queue(); - } - } -} diff --git a/src/main/java/io/github/eggy03/papertrail/bot/listeners/auditlog/helper/invite/InviteCreateEventHelper.java b/src/main/java/io/github/eggy03/papertrail/bot/listeners/auditlog/helper/invite/InviteCreateEventHelper.java deleted file mode 100644 index 4d61cb34..00000000 --- a/src/main/java/io/github/eggy03/papertrail/bot/listeners/auditlog/helper/invite/InviteCreateEventHelper.java +++ /dev/null @@ -1,87 +0,0 @@ -package io.github.eggy03.papertrail.bot.listeners.auditlog.helper.invite; - -import io.github.eggy03.papertrail.bot.listeners.auditlog.helper.invite.utils.InviteUtils; -import io.github.eggy03.papertrail.bot.utils.BooleanUtils; -import io.github.eggy03.papertrail.bot.utils.DurationUtils; -import lombok.NonNull; -import lombok.experimental.UtilityClass; -import lombok.extern.slf4j.Slf4j; -import net.dv8tion.jda.api.EmbedBuilder; -import net.dv8tion.jda.api.audit.AuditLogEntry; -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 net.dv8tion.jda.api.utils.MarkdownUtil; - -import java.awt.Color; - -@UtilityClass -@Slf4j -public class InviteCreateEventHelper { - - public static void format(@NonNull GuildAuditLogEntryCreateEvent event, @NonNull String channelIdToSendTo) { - - AuditLogEntry ale = event.getEntry(); - - User executor = ale.getJDA().getUserById(ale.getUserIdLong()); - String mentionableExecutor = (executor != null ? executor.getAsMention() : ale.getUserId()); - - EmbedBuilder eb = new EmbedBuilder(); - eb.setTitle("Audit Log Entry | Invite Create Event"); - - eb.setDescription(MarkdownUtil.quoteBlock("Invite Created By: " + mentionableExecutor)); - eb.setColor(Color.CYAN); - - ale.getChanges().forEach((changeKey, changeValue) -> { - - Object oldValue = changeValue.getOldValue(); - Object newValue = changeValue.getNewValue(); - - switch (changeKey) { - - case "code" -> eb.addField(MarkdownUtil.underline("Invite Code"), "╰┈➤" + newValue, false); - - case "inviter_id" -> - eb.addField(MarkdownUtil.underline("Invite Created By"), "╰┈➤" + InviteUtils.resolveInviter(newValue, event), false); - - case "temporary" -> - eb.addField(MarkdownUtil.underline("Is Temporary"), "╰┈➤" + BooleanUtils.formatToYesOrNo(newValue), false); - - case "max_uses" -> - eb.addField(MarkdownUtil.underline("Max Uses"), "╰┈➤" + InviteUtils.resolveMaxUses(newValue), false); - - case "uses", "flags" -> { - // ignore - } - - case "role_ids" -> - eb.addField(MarkdownUtil.underline("Roles Attached"), "╰┈➤" + InviteUtils.resolveInviteRoleList(event, newValue), false); - - case "max_age" -> - eb.addField(MarkdownUtil.underline("Expires After"), "╰┈➤" + DurationUtils.formatSeconds(newValue), false); - - case "channel_id" -> - eb.addField(MarkdownUtil.underline("Invite Channel"), "╰┈➤" + InviteUtils.resolveInviteChannel(newValue, event), false); - - default -> { - eb.addField("Unimplemented Change Key", changeKey, false); - log.info("Unimplemented Change Key: {}\nOLD_VALUE: {}\nNEW_VALUE: {}", changeKey, oldValue, newValue); - } - } - }); - - eb.setFooter("Audit Log Entry ID: " + ale.getId()); - eb.setTimestamp(ale.getTimeCreated()); - - if (!eb.isValidLength() || eb.isEmpty()) { - log.warn("Embed is empty or too long (current length: {}).", eb.length()); - return; - } - - TextChannel sendingChannel = event.getGuild().getTextChannelById(channelIdToSendTo); - if (sendingChannel != null && sendingChannel.canTalk()) { - sendingChannel.sendMessageEmbeds(eb.build()).queue(); - } - - } -} diff --git a/src/main/java/io/github/eggy03/papertrail/bot/listeners/auditlog/helper/invite/InviteDeleteEventHelper.java b/src/main/java/io/github/eggy03/papertrail/bot/listeners/auditlog/helper/invite/InviteDeleteEventHelper.java deleted file mode 100644 index 0089cd74..00000000 --- a/src/main/java/io/github/eggy03/papertrail/bot/listeners/auditlog/helper/invite/InviteDeleteEventHelper.java +++ /dev/null @@ -1,81 +0,0 @@ -package io.github.eggy03.papertrail.bot.listeners.auditlog.helper.invite; - -import io.github.eggy03.papertrail.bot.listeners.auditlog.helper.invite.utils.InviteUtils; -import io.github.eggy03.papertrail.bot.utils.BooleanUtils; -import lombok.NonNull; -import lombok.experimental.UtilityClass; -import lombok.extern.slf4j.Slf4j; -import net.dv8tion.jda.api.EmbedBuilder; -import net.dv8tion.jda.api.audit.AuditLogEntry; -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 net.dv8tion.jda.api.utils.MarkdownUtil; - -import java.awt.Color; - -@UtilityClass -@Slf4j -public class InviteDeleteEventHelper { - - public static void format(@NonNull GuildAuditLogEntryCreateEvent event, @NonNull String channelIdToSendTo) { - - AuditLogEntry ale = event.getEntry(); - - EmbedBuilder eb = new EmbedBuilder(); - eb.setTitle("Audit Log Entry | Invite Delete Event"); - - User executor = ale.getJDA().getUserById(ale.getUserIdLong()); - String mentionableExecutor = (executor != null ? executor.getAsMention() : ale.getUserId()); - - eb.setDescription(MarkdownUtil.quoteBlock("Invite Deleted By: " + mentionableExecutor)); - eb.setColor(Color.BLUE); - - ale.getChanges().forEach((changeKey, changeValue) -> { - Object oldValue = changeValue.getOldValue(); - Object newValue = changeValue.getNewValue(); - - switch (changeKey) { - - case "code" -> eb.addField(MarkdownUtil.underline("Deleted Invite Code"), "╰┈➤" + oldValue, false); - - case "inviter_id" -> - eb.addField(MarkdownUtil.underline("Invite Deleted By"), "╰┈➤" + InviteUtils.resolveInviter(oldValue, event), false); - - case "temporary" -> - eb.addField(MarkdownUtil.underline("Was Temporary"), "╰┈➤" + BooleanUtils.formatToYesOrNo(oldValue), false); - - case "max_uses", "flags", "max_age" -> { - // ignore - } - - case "role_ids" -> - eb.addField(MarkdownUtil.underline("Roles Attached"), "╰┈➤" + InviteUtils.resolveInviteRoleList(event, oldValue), false); - - case "uses" -> eb.addField(MarkdownUtil.underline("Use Count"), "╰┈➤" + oldValue, false); - - case "channel_id" -> - eb.addField(MarkdownUtil.underline("Invite Channel"), "╰┈➤" + InviteUtils.resolveInviteChannel(oldValue, event), false); - - default -> { - eb.addField("Unimplemented Change Key", changeKey, false); - log.info("Unimplemented Change Key: {}\nOLD_VALUE: {}\nNEW_VALUE: {}", changeKey, oldValue, newValue); - } - - } - }); - - eb.setFooter("Audit Log Entry ID: " + ale.getId()); - eb.setTimestamp(ale.getTimeCreated()); - - if (!eb.isValidLength() || eb.isEmpty()) { - log.warn("Embed is empty or too long (current length: {}).", eb.length()); - return; - } - - TextChannel sendingChannel = event.getGuild().getTextChannelById(channelIdToSendTo); - if (sendingChannel != null && sendingChannel.canTalk()) { - sendingChannel.sendMessageEmbeds(eb.build()).queue(); - } - } -} diff --git a/src/main/java/io/github/eggy03/papertrail/bot/listeners/auditlog/helper/member/MemberRoleUpdateEventHelper.java b/src/main/java/io/github/eggy03/papertrail/bot/listeners/auditlog/helper/member/MemberRoleUpdateEventHelper.java deleted file mode 100644 index 393847b3..00000000 --- a/src/main/java/io/github/eggy03/papertrail/bot/listeners/auditlog/helper/member/MemberRoleUpdateEventHelper.java +++ /dev/null @@ -1,69 +0,0 @@ -package io.github.eggy03.papertrail.bot.listeners.auditlog.helper.member; - -import io.github.eggy03.papertrail.bot.listeners.auditlog.helper.member.utils.MemberUtils; -import lombok.NonNull; -import lombok.experimental.UtilityClass; -import lombok.extern.slf4j.Slf4j; -import net.dv8tion.jda.api.EmbedBuilder; -import net.dv8tion.jda.api.audit.AuditLogEntry; -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 net.dv8tion.jda.api.utils.MarkdownUtil; - -import java.awt.Color; - -@UtilityClass -@Slf4j -public class MemberRoleUpdateEventHelper { - - public static void format(@NonNull GuildAuditLogEntryCreateEvent event, @NonNull String channelIdToSendTo) { - - AuditLogEntry ale = event.getEntry(); - - User executor = ale.getJDA().getUserById(ale.getUserIdLong()); - String mentionableExecutor = (executor != null ? executor.getAsMention() : ale.getUserId()); - - User targetUser = ale.getJDA().getUserById(ale.getTargetIdLong()); - String mentionableTargetUser = (targetUser != null ? targetUser.getAsMention() : ale.getTargetId()); - - EmbedBuilder eb = new EmbedBuilder(); - eb.setTitle("Audit Log Entry | Member Role Update"); - eb.setDescription(MarkdownUtil.quoteBlock("Executor: " + mentionableExecutor + "\nTarget: " + mentionableTargetUser)); - eb.setColor(Color.YELLOW); - - if (targetUser != null) - eb.setThumbnail(targetUser.getEffectiveAvatarUrl()); - - ale.getChanges().forEach((changeKey, changeValue) -> { - Object oldValue = changeValue.getOldValue(); - Object newValue = changeValue.getNewValue(); - - switch (changeKey) { - case "$add" -> - eb.addField(MarkdownUtil.underline("✅ Role(s) Added"), "╰┈➤" + MemberUtils.parseRoleListMap(event, newValue), false); - - case "$remove" -> - eb.addField(MarkdownUtil.underline("❌ Role(s) Removed"), "╰┈➤" + MemberUtils.parseRoleListMap(event, newValue), false); - - default -> { - eb.addField("Unimplemented Change Key", changeKey, false); - log.info("Unimplemented Change Key: {}\nOLD_VALUE: {}\nNEW_VALUE: {}", changeKey, oldValue, newValue); - } - } - }); - - eb.setFooter("Audit Log Entry ID: " + ale.getId()); - eb.setTimestamp(ale.getTimeCreated()); - - if (!eb.isValidLength() || eb.isEmpty()) { - log.warn("Embed is empty or too long (current length: {}).", eb.length()); - return; - } - - TextChannel sendingChannel = event.getGuild().getTextChannelById(channelIdToSendTo); - if (sendingChannel != null && sendingChannel.canTalk()) { - sendingChannel.sendMessageEmbeds(eb.build()).queue(); - } - } -} diff --git a/src/main/java/io/github/eggy03/papertrail/bot/listeners/auditlog/helper/member/MemberUpdateEventHelper.java b/src/main/java/io/github/eggy03/papertrail/bot/listeners/auditlog/helper/member/MemberUpdateEventHelper.java deleted file mode 100644 index 9749cbf2..00000000 --- a/src/main/java/io/github/eggy03/papertrail/bot/listeners/auditlog/helper/member/MemberUpdateEventHelper.java +++ /dev/null @@ -1,110 +0,0 @@ -package io.github.eggy03.papertrail.bot.listeners.auditlog.helper.member; - -import io.github.eggy03.papertrail.bot.utils.BooleanUtils; -import io.github.eggy03.papertrail.bot.utils.DurationUtils; -import lombok.NonNull; -import lombok.experimental.UtilityClass; -import lombok.extern.slf4j.Slf4j; -import net.dv8tion.jda.api.EmbedBuilder; -import net.dv8tion.jda.api.audit.AuditLogEntry; -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 net.dv8tion.jda.api.utils.MarkdownUtil; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -import java.awt.Color; - -@UtilityClass -@Slf4j -public class MemberUpdateEventHelper { - - public static void format(@NonNull GuildAuditLogEntryCreateEvent event, @NonNull String channelIdToSendTo) { - - AuditLogEntry ale = event.getEntry(); - - User executor = ale.getJDA().getUserById(ale.getUserIdLong()); - String mentionableExecutor = (executor != null ? executor.getAsMention() : ale.getUserId()); - - User targetUser = ale.getJDA().getUserById(ale.getTargetIdLong()); - String mentionableTargetUser = (targetUser != null ? targetUser.getAsMention() : ale.getTargetId()); - - EmbedBuilder eb = new EmbedBuilder(); - eb.setTitle("Audit Log Entry | Member Update Event"); - eb.setDescription(MarkdownUtil.quoteBlock("Executor: " + mentionableExecutor + "\nTarget: " + mentionableTargetUser)); - eb.setColor(Color.CYAN); - - if (targetUser != null) - eb.setThumbnail(targetUser.getEffectiveAvatarUrl()); - - ale.getChanges().forEach((changeKey, changeValue) -> { - Object oldValue = changeValue.getOldValue(); - Object newValue = changeValue.getNewValue(); - - switch (changeKey) { - - case "communication_disabled_until" -> { - if (newValue == null) { - eb.setColor(Color.GREEN); - eb.addField(MarkdownUtil.underline("Timeout Lifted"), "╰┈➤ Timeout has been removed", false); - } else { - eb.setColor(Color.YELLOW); - eb.addField(MarkdownUtil.underline("Timeout Received"), "╰┈➤ Member has received a timeout", false); - eb.addField(MarkdownUtil.underline("Timeout Ends On"), "╰┈➤" + DurationUtils.isoToLocalTimeCounter(newValue), false); - eb.addField(MarkdownUtil.underline("Timeout Reason"), "╰┈➤" + (ale.getReason() != null ? ale.getReason() : "No Reason Provided"), false); - } - } - case "nick" -> - eb.addField(MarkdownUtil.underline("Nickname Update"), resolveNickNameChanges(oldValue, newValue), false); - - case "mute" -> - eb.addField(MarkdownUtil.underline("Is Muted in VC"), "╰┈➤" + BooleanUtils.formatToYesOrNo(newValue), false); - - case "deaf" -> - eb.addField(MarkdownUtil.underline("Is Deafened in VC"), "╰┈➤" + BooleanUtils.formatToYesOrNo(newValue), false); - - case "bypasses_verification" -> - eb.addField(MarkdownUtil.underline("Bypass Verification"), "╰┈➤" + BooleanUtils.formatToEnabledOrDisabled(newValue), false); - - default -> { - eb.addField("Unimplemented Change Key", changeKey, false); - log.info("Unimplemented Change Key: {}\nOLD_VALUE: {}\nNEW_VALUE: {}", changeKey, oldValue, newValue); - } - } - }); - - eb.setFooter("Audit Log Entry ID: " + ale.getId()); - eb.setTimestamp(ale.getTimeCreated()); - - if (!eb.isValidLength() || eb.isEmpty()) { - log.warn("Embed is empty or too long (current length: {}).", eb.length()); - return; - } - - TextChannel sendingChannel = event.getGuild().getTextChannelById(channelIdToSendTo); - if (sendingChannel != null && sendingChannel.canTalk()) { - sendingChannel.sendMessageEmbeds(eb.build()).queue(); - } - } - - @NotNull - @SuppressWarnings("all") - private static String resolveNickNameChanges(@Nullable Object oldNickValue, @Nullable Object newNickValue) { - - if (oldNickValue == null && newNickValue != null) { // change from global name to a new nickname in the server - return "Added Nickname: " + MarkdownUtil.underline(newNickValue.toString()); - } - - if (oldNickValue != null && newNickValue == null) { // change to the global name from having a nickname - return "Reset Nickname From: " + MarkdownUtil.underline(oldNickValue.toString()); - } - - if (oldNickValue != null && newNickValue != null) { // changing from one nick to another - return "Changed Nickname From: " + MarkdownUtil.underline(oldNickValue.toString()) + " to: " + MarkdownUtil.underline(newNickValue.toString()); - } - - // both shouldn't be null which indicates that names couldn't be fetched from the event - return MarkdownUtil.underline("Changes could not be resolved!"); - } -} diff --git a/src/main/java/io/github/eggy03/papertrail/bot/listeners/auditlog/helper/member/MemberVoiceKickEventHelper.java b/src/main/java/io/github/eggy03/papertrail/bot/listeners/auditlog/helper/member/MemberVoiceKickEventHelper.java deleted file mode 100644 index c74fcf57..00000000 --- a/src/main/java/io/github/eggy03/papertrail/bot/listeners/auditlog/helper/member/MemberVoiceKickEventHelper.java +++ /dev/null @@ -1,52 +0,0 @@ -package io.github.eggy03.papertrail.bot.listeners.auditlog.helper.member; - -import io.github.eggy03.papertrail.bot.listeners.auditlogsupl.helper.guild.GuildVoiceEventHelper; -import lombok.NonNull; -import lombok.experimental.UtilityClass; -import lombok.extern.slf4j.Slf4j; -import net.dv8tion.jda.api.EmbedBuilder; -import net.dv8tion.jda.api.audit.AuditLogEntry; -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 net.dv8tion.jda.api.utils.MarkdownUtil; - -import java.awt.Color; - -/** - * This helper specifically detects the mod who kicked a member from a Voice Channel - * - * @see GuildVoiceEventHelper - for member only data regarding voice activities - */ -@UtilityClass -@Slf4j -public class MemberVoiceKickEventHelper { - - // the audit log does not expose much information regarding member vc move and kick events - // therefore GuildVoiceEventListener has been created to know about channels the target has been moved or kicked from - public static void format(@NonNull GuildAuditLogEntryCreateEvent event, @NonNull String channelIdToSendTo) { - - AuditLogEntry ale = event.getEntry(); - - User executor = ale.getJDA().getUserById(ale.getUserId()); - String mentionableExecutor = (executor != null ? executor.getAsMention() : ale.getUserId()); - - EmbedBuilder eb = new EmbedBuilder(); - eb.setTitle("Audit Log Entry | Member Voice Kick Event"); - eb.setDescription(MarkdownUtil.quoteBlock("Member Kicked From a Voice Channel\n By: " + mentionableExecutor)); - eb.setColor(Color.RED); - - eb.setFooter("Audit Log Entry ID: " + ale.getId()); - eb.setTimestamp(ale.getTimeCreated()); - - if (!eb.isValidLength() || eb.isEmpty()) { - log.warn("Embed is empty or too long (current length: {}).", eb.length()); - return; - } - - TextChannel sendingChannel = event.getGuild().getTextChannelById(channelIdToSendTo); - if (sendingChannel != null && sendingChannel.canTalk()) { - sendingChannel.sendMessageEmbeds(eb.build()).queue(); - } - } -} diff --git a/src/main/java/io/github/eggy03/papertrail/bot/listeners/auditlog/helper/member/MemberVoiceMoveEventHelper.java b/src/main/java/io/github/eggy03/papertrail/bot/listeners/auditlog/helper/member/MemberVoiceMoveEventHelper.java deleted file mode 100644 index 6950dabf..00000000 --- a/src/main/java/io/github/eggy03/papertrail/bot/listeners/auditlog/helper/member/MemberVoiceMoveEventHelper.java +++ /dev/null @@ -1,52 +0,0 @@ -package io.github.eggy03.papertrail.bot.listeners.auditlog.helper.member; - -import io.github.eggy03.papertrail.bot.listeners.auditlogsupl.helper.guild.GuildVoiceEventHelper; -import lombok.NonNull; -import lombok.experimental.UtilityClass; -import lombok.extern.slf4j.Slf4j; -import net.dv8tion.jda.api.EmbedBuilder; -import net.dv8tion.jda.api.audit.AuditLogEntry; -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 net.dv8tion.jda.api.utils.MarkdownUtil; - -import java.awt.Color; - -/** - * This helper specifically detects the mod who moved a member to a different voice channel - * - * @see GuildVoiceEventHelper - for member only data regarding voice activities - */ -@UtilityClass -@Slf4j -public class MemberVoiceMoveEventHelper { - - // the audit log does not expose much information regarding member vc move and kick events - // therefore GuildVoiceEventListener has been created to know about channels the target has been moved or kicked from - public static void format(@NonNull GuildAuditLogEntryCreateEvent event, @NonNull String channelIdToSendTo) { - - AuditLogEntry ale = event.getEntry(); - - User executor = ale.getJDA().getUserById(ale.getUserId()); - String mentionableExecutor = (executor != null ? executor.getAsMention() : ale.getUserId()); - - EmbedBuilder eb = new EmbedBuilder(); - eb.setTitle("Audit Log Entry | Member Voice Move Event"); - eb.setDescription(MarkdownUtil.quoteBlock("Member Moved To A Different Voice Channel\n By: " + mentionableExecutor)); - eb.setColor(Color.YELLOW); - - eb.setFooter("Audit Log Entry ID: " + ale.getId()); - eb.setTimestamp(ale.getTimeCreated()); - - if (!eb.isValidLength() || eb.isEmpty()) { - log.warn("Embed is empty or too long (current length: {}).", eb.length()); - return; - } - - TextChannel sendingChannel = event.getGuild().getTextChannelById(channelIdToSendTo); - if (sendingChannel != null && sendingChannel.canTalk()) { - sendingChannel.sendMessageEmbeds(eb.build()).queue(); - } - } -} diff --git a/src/main/java/io/github/eggy03/papertrail/bot/listeners/auditlog/helper/message/MessagePinEventHelper.java b/src/main/java/io/github/eggy03/papertrail/bot/listeners/auditlog/helper/message/MessagePinEventHelper.java deleted file mode 100644 index a3adb994..00000000 --- a/src/main/java/io/github/eggy03/papertrail/bot/listeners/auditlog/helper/message/MessagePinEventHelper.java +++ /dev/null @@ -1,56 +0,0 @@ -package io.github.eggy03.papertrail.bot.listeners.auditlog.helper.message; - -import io.github.eggy03.papertrail.bot.listeners.auditlog.helper.message.utils.MessageUtils; -import lombok.NonNull; -import lombok.experimental.UtilityClass; -import lombok.extern.slf4j.Slf4j; -import net.dv8tion.jda.api.EmbedBuilder; -import net.dv8tion.jda.api.audit.AuditLogEntry; -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 net.dv8tion.jda.api.utils.MarkdownUtil; - -import java.awt.Color; - -@UtilityClass -@Slf4j -public class MessagePinEventHelper { - - public static void format(@NonNull GuildAuditLogEntryCreateEvent event, @NonNull String channelIdToSendTo) { - - AuditLogEntry ale = event.getEntry(); - - EmbedBuilder eb = new EmbedBuilder(); - eb.setTitle("Audit Log Entry | Message Pin Event"); - - User executor = ale.getJDA().getUserById(ale.getUserId()); - String mentionableExecutor = (executor != null ? executor.getAsMention() : ale.getUserId()); - - User target = ale.getJDA().getUserById(ale.getTargetId()); - String mentionableTarget = (target != null ? target.getAsMention() : ale.getTargetId()); - - eb.setDescription(MarkdownUtil.quoteBlock("Message Pinned By: " + mentionableExecutor + "\nMessage Author: " + mentionableTarget)); - eb.setColor(Color.PINK); - - eb.addField( - MarkdownUtil.underline("Pinned Message Jump URL"), - MessageUtils.resolveMessageJumpUrlFromId(ale.getOptionByName("channel_id"), ale.getOptionByName("message_id"), event), - false - ); - - eb.setFooter("Audit Log Entry ID: " + ale.getId()); - eb.setTimestamp(ale.getTimeCreated()); - - if (!eb.isValidLength() || eb.isEmpty()) { - log.warn("Embed is empty or too long (current length: {}).", eb.length()); - return; - } - - TextChannel sendingChannel = event.getGuild().getTextChannelById(channelIdToSendTo); - if (sendingChannel != null && sendingChannel.canTalk()) { - sendingChannel.sendMessageEmbeds(eb.build()).queue(); - } - } - -} diff --git a/src/main/java/io/github/eggy03/papertrail/bot/listeners/auditlog/helper/message/MessageUnpinEventHelper.java b/src/main/java/io/github/eggy03/papertrail/bot/listeners/auditlog/helper/message/MessageUnpinEventHelper.java deleted file mode 100644 index b2857d58..00000000 --- a/src/main/java/io/github/eggy03/papertrail/bot/listeners/auditlog/helper/message/MessageUnpinEventHelper.java +++ /dev/null @@ -1,55 +0,0 @@ -package io.github.eggy03.papertrail.bot.listeners.auditlog.helper.message; - -import io.github.eggy03.papertrail.bot.listeners.auditlog.helper.message.utils.MessageUtils; -import lombok.NonNull; -import lombok.experimental.UtilityClass; -import lombok.extern.slf4j.Slf4j; -import net.dv8tion.jda.api.EmbedBuilder; -import net.dv8tion.jda.api.audit.AuditLogEntry; -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 net.dv8tion.jda.api.utils.MarkdownUtil; - -import java.awt.Color; - -@UtilityClass -@Slf4j -public class MessageUnpinEventHelper { - - public static void format(@NonNull GuildAuditLogEntryCreateEvent event, @NonNull String channelIdToSendTo) { - - AuditLogEntry ale = event.getEntry(); - - EmbedBuilder eb = new EmbedBuilder(); - eb.setTitle("Audit Log Entry | Message Unpin Event"); - - User executor = ale.getJDA().getUserById(ale.getUserId()); - String mentionableExecutor = (executor != null ? executor.getAsMention() : ale.getUserId()); - - User target = ale.getJDA().getUserById(ale.getTargetId()); - String mentionableTarget = (target != null ? target.getAsMention() : ale.getTargetId()); - - eb.setDescription(MarkdownUtil.quoteBlock("Message Un-Pinned By: " + mentionableExecutor + "\nMessage Author: " + mentionableTarget)); - eb.setColor(Color.MAGENTA); - - eb.addField( - MarkdownUtil.underline("Un-Pinned Message Jump URL"), - MessageUtils.resolveMessageJumpUrlFromId(ale.getOptionByName("channel_id"), ale.getOptionByName("message_id"), event), - false - ); - - eb.setFooter("Audit Log Entry ID: " + ale.getId()); - eb.setTimestamp(ale.getTimeCreated()); - - if (!eb.isValidLength() || eb.isEmpty()) { - log.warn("Embed is empty or too long (current length: {}).", eb.length()); - return; - } - - TextChannel sendingChannel = event.getGuild().getTextChannelById(channelIdToSendTo); - if (sendingChannel != null && sendingChannel.canTalk()) { - sendingChannel.sendMessageEmbeds(eb.build()).queue(); - } - } -} diff --git a/src/main/java/io/github/eggy03/papertrail/bot/listeners/auditlog/helper/modactions/BanEventHelper.java b/src/main/java/io/github/eggy03/papertrail/bot/listeners/auditlog/helper/modactions/BanEventHelper.java deleted file mode 100644 index 9e66a1bb..00000000 --- a/src/main/java/io/github/eggy03/papertrail/bot/listeners/auditlog/helper/modactions/BanEventHelper.java +++ /dev/null @@ -1,54 +0,0 @@ -package io.github.eggy03.papertrail.bot.listeners.auditlog.helper.modactions; - -import lombok.NonNull; -import lombok.experimental.UtilityClass; -import lombok.extern.slf4j.Slf4j; -import net.dv8tion.jda.api.EmbedBuilder; -import net.dv8tion.jda.api.audit.AuditLogEntry; -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 net.dv8tion.jda.api.utils.MarkdownUtil; - -import java.awt.Color; - -@UtilityClass -@Slf4j -public class BanEventHelper { - - public static void format(@NonNull GuildAuditLogEntryCreateEvent event, @NonNull String channelIdToSendTo) { - - AuditLogEntry ale = event.getEntry(); - - User moderator = ale.getJDA().getUserById(ale.getUserIdLong()); - String mentionableModerator = (moderator != null ? moderator.getAsMention() : ale.getUserId()); - String reasonForBan = ale.getReason() == null ? "No Reason Provided" : ale.getReason(); - - // A REST Action is required here because banned members are not cached - event.getJDA().retrieveUserById(ale.getTargetId()).queue(bannedUser -> { - - String mentionableBannedUser = bannedUser != null ? bannedUser.getAsMention() : ale.getTargetId(); - - EmbedBuilder eb = new EmbedBuilder(); - eb.setTitle("Audit Log Entry | Ban Event"); - eb.setDescription(MarkdownUtil.quoteBlock("A Member Has Been Banned By: " + mentionableModerator)); - eb.setColor(Color.RED); - - eb.addField(MarkdownUtil.underline("Banned Member"), "╰┈➤" + mentionableBannedUser, false); - eb.addField(MarkdownUtil.underline("Ban Reason"), "╰┈➤" + reasonForBan, false); - - eb.setFooter("Audit Log Entry ID: " + ale.getId()); - eb.setTimestamp(ale.getTimeCreated()); - - if (!eb.isValidLength() || eb.isEmpty()) { - log.warn("Embed is empty or too long (current length: {}).", eb.length()); - return; - } - - TextChannel sendingChannel = event.getGuild().getTextChannelById(channelIdToSendTo); - if (sendingChannel != null && sendingChannel.canTalk()) { - sendingChannel.sendMessageEmbeds(eb.build()).queue(); - } - }); - } -} diff --git a/src/main/java/io/github/eggy03/papertrail/bot/listeners/auditlog/helper/modactions/KickEventHelper.java b/src/main/java/io/github/eggy03/papertrail/bot/listeners/auditlog/helper/modactions/KickEventHelper.java deleted file mode 100644 index 18d5a579..00000000 --- a/src/main/java/io/github/eggy03/papertrail/bot/listeners/auditlog/helper/modactions/KickEventHelper.java +++ /dev/null @@ -1,54 +0,0 @@ -package io.github.eggy03.papertrail.bot.listeners.auditlog.helper.modactions; - -import lombok.NonNull; -import lombok.experimental.UtilityClass; -import lombok.extern.slf4j.Slf4j; -import net.dv8tion.jda.api.EmbedBuilder; -import net.dv8tion.jda.api.audit.AuditLogEntry; -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 net.dv8tion.jda.api.utils.MarkdownUtil; - -import java.awt.Color; - -@UtilityClass -@Slf4j -public class KickEventHelper { - - public static void format(@NonNull GuildAuditLogEntryCreateEvent event, @NonNull String channelIdToSendTo) { - - AuditLogEntry ale = event.getEntry(); - - User moderator = ale.getJDA().getUserById(ale.getUserIdLong()); - String mentionableModerator = (moderator != null ? moderator.getAsMention() : ale.getUserId()); - String reasonForKick = ale.getReason() == null ? "No Reason Provided" : ale.getReason(); - - // A REST Action is required here because kicked members are not cached - event.getJDA().retrieveUserById(ale.getTargetId()).queue(kickedUser -> { - - String mentionableKickedUser = kickedUser != null ? kickedUser.getAsMention() : ale.getTargetId(); - - EmbedBuilder eb = new EmbedBuilder(); - eb.setTitle("Audit Log Entry | Kick Event"); - eb.setDescription(MarkdownUtil.quoteBlock("A Member Has Been Kicked By: " + mentionableModerator)); - eb.setColor(Color.ORANGE); - - eb.addField(MarkdownUtil.underline("Kicked Member"), "╰┈➤" + mentionableKickedUser, false); - eb.addField(MarkdownUtil.underline("Reason"), "╰┈➤" + reasonForKick, false); - - eb.setFooter("Audit Log Entry ID: " + ale.getId()); - eb.setTimestamp(ale.getTimeCreated()); - - if (!eb.isValidLength() || eb.isEmpty()) { - log.warn("Embed is empty or too long (current length: {}).", eb.length()); - return; - } - - TextChannel sendingChannel = event.getGuild().getTextChannelById(channelIdToSendTo); - if (sendingChannel != null && sendingChannel.canTalk()) { - sendingChannel.sendMessageEmbeds(eb.build()).queue(); - } - }); - } -} diff --git a/src/main/java/io/github/eggy03/papertrail/bot/listeners/auditlog/helper/modactions/UnbanEventHelper.java b/src/main/java/io/github/eggy03/papertrail/bot/listeners/auditlog/helper/modactions/UnbanEventHelper.java deleted file mode 100644 index 966a575a..00000000 --- a/src/main/java/io/github/eggy03/papertrail/bot/listeners/auditlog/helper/modactions/UnbanEventHelper.java +++ /dev/null @@ -1,51 +0,0 @@ -package io.github.eggy03.papertrail.bot.listeners.auditlog.helper.modactions; - -import lombok.NonNull; -import lombok.experimental.UtilityClass; -import lombok.extern.slf4j.Slf4j; -import net.dv8tion.jda.api.EmbedBuilder; -import net.dv8tion.jda.api.audit.AuditLogEntry; -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 net.dv8tion.jda.api.utils.MarkdownUtil; - -import java.awt.Color; - -@UtilityClass -@Slf4j -public class UnbanEventHelper { - - public static void format(@NonNull GuildAuditLogEntryCreateEvent event, @NonNull String channelIdToSendTo) { - - AuditLogEntry ale = event.getEntry(); - - User moderator = ale.getJDA().getUserById(ale.getUserIdLong()); - String mentionableModerator = (moderator != null ? moderator.getAsMention() : ale.getUserId()); - - event.getJDA().retrieveUserById(ale.getTargetId()).queue(unbannedUser -> { - - String mentionableUnbannedUser = unbannedUser != null ? unbannedUser.getAsMention() : ale.getTargetId(); - - EmbedBuilder eb = new EmbedBuilder(); - eb.setTitle("Audit Log Entry | Member Unban Event"); - eb.setDescription(MarkdownUtil.quoteBlock("A Member Has Been Un-Banned By: " + mentionableModerator)); - eb.setColor(Color.GREEN); - - eb.addField(MarkdownUtil.underline("Un-banned User"), "╰┈➤" + mentionableUnbannedUser, false); - - eb.setFooter("Audit Log Entry ID: " + ale.getId()); - eb.setTimestamp(ale.getTimeCreated()); - - if (!eb.isValidLength() || eb.isEmpty()) { - log.warn("Embed is empty or too long (current length: {}).", eb.length()); - return; - } - - TextChannel sendingChannel = event.getGuild().getTextChannelById(channelIdToSendTo); - if (sendingChannel != null && sendingChannel.canTalk()) { - sendingChannel.sendMessageEmbeds(eb.build()).queue(); - } - }); - } -} diff --git a/src/main/java/io/github/eggy03/papertrail/bot/listeners/auditlog/helper/onboarding/OnboardingPromptCreateEventHelper.java b/src/main/java/io/github/eggy03/papertrail/bot/listeners/auditlog/helper/onboarding/OnboardingPromptCreateEventHelper.java deleted file mode 100644 index 2172fe7f..00000000 --- a/src/main/java/io/github/eggy03/papertrail/bot/listeners/auditlog/helper/onboarding/OnboardingPromptCreateEventHelper.java +++ /dev/null @@ -1,78 +0,0 @@ -package io.github.eggy03.papertrail.bot.listeners.auditlog.helper.onboarding; - -import io.github.eggy03.papertrail.bot.utils.BooleanUtils; -import lombok.NonNull; -import lombok.experimental.UtilityClass; -import lombok.extern.slf4j.Slf4j; -import net.dv8tion.jda.api.EmbedBuilder; -import net.dv8tion.jda.api.audit.AuditLogEntry; -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 net.dv8tion.jda.api.utils.MarkdownUtil; - -import java.awt.Color; - -@UtilityClass -@Slf4j -public class OnboardingPromptCreateEventHelper { - - public static void format(@NonNull GuildAuditLogEntryCreateEvent event, @NonNull 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(MarkdownUtil.quoteBlock("Onboarding Prompt Created By: " + mentionableExecutor)); - eb.setColor(Color.GREEN); - - ale.getChanges().forEach((changeKey, changeValue) -> { - - Object oldValue = changeValue.getOldValue(); - Object newValue = changeValue.getNewValue(); - - switch (changeKey) { - case "single_select" -> - eb.addField(MarkdownUtil.underline("Single Selection Mode"), BooleanUtils.formatToYesOrNo(newValue), false); - - case "required" -> - eb.addField(MarkdownUtil.underline("Is Required"), BooleanUtils.formatToYesOrNo(newValue), false); - - case "type", "id" -> { - // skip - } - - case "title" -> eb.addField(MarkdownUtil.underline("Question Title"), String.valueOf(newValue), false); - - case "options" -> - eb.addField(MarkdownUtil.underline("Question Options"), "Review the options in Onboarding Settings", false); - - case "in_onboarding" -> - eb.addField(MarkdownUtil.underline("Is a Pre-Join Question"), BooleanUtils.formatToYesOrNo(newValue), false); - - default -> { - eb.addField("Unimplemented Change Key", changeKey, false); - log.info("Unimplemented Change Key: {}\nOLD_VALUE: {}\nNEW_VALUE: {}", changeKey, oldValue, newValue); - } - } - - }); - - eb.setFooter("Audit Log Entry ID: " + ale.getId()); - eb.setTimestamp(ale.getTimeCreated()); - - if (!eb.isValidLength() || eb.isEmpty()) { - log.warn("Embed is empty or too long (current length: {}).", eb.length()); - return; - } - - TextChannel sendingChannel = event.getGuild().getTextChannelById(channelIdToSendTo); - if (sendingChannel != null && sendingChannel.canTalk()) { - sendingChannel.sendMessageEmbeds(eb.build()).queue(); - } - } -} diff --git a/src/main/java/io/github/eggy03/papertrail/bot/listeners/auditlog/helper/onboarding/OnboardingPromptDeleteEventHelper.java b/src/main/java/io/github/eggy03/papertrail/bot/listeners/auditlog/helper/onboarding/OnboardingPromptDeleteEventHelper.java deleted file mode 100644 index 968758d5..00000000 --- a/src/main/java/io/github/eggy03/papertrail/bot/listeners/auditlog/helper/onboarding/OnboardingPromptDeleteEventHelper.java +++ /dev/null @@ -1,75 +0,0 @@ -package io.github.eggy03.papertrail.bot.listeners.auditlog.helper.onboarding; - -import io.github.eggy03.papertrail.bot.utils.BooleanUtils; -import lombok.NonNull; -import lombok.experimental.UtilityClass; -import lombok.extern.slf4j.Slf4j; -import net.dv8tion.jda.api.EmbedBuilder; -import net.dv8tion.jda.api.audit.AuditLogEntry; -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 net.dv8tion.jda.api.utils.MarkdownUtil; - -import java.awt.Color; - -@UtilityClass -@Slf4j -public class OnboardingPromptDeleteEventHelper { - - public static void format(@NonNull GuildAuditLogEntryCreateEvent event, @NonNull 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(MarkdownUtil.quoteBlock("Onboarding Prompt Deleted By: " + mentionableExecutor)); - eb.setColor(Color.RED); - - ale.getChanges().forEach((changeKey, changeValue) -> { - - Object oldValue = changeValue.getOldValue(); - Object newValue = changeValue.getNewValue(); - - switch (changeKey) { - - case "single_select" -> - eb.addField(MarkdownUtil.underline("Single Selection Mode"), BooleanUtils.formatToYesOrNo(oldValue), false); - - case "required" -> - eb.addField(MarkdownUtil.underline("Was Required"), BooleanUtils.formatToYesOrNo(oldValue), false); - - case "type", "id", "options" -> { - // skip - } - case "title" -> eb.addField(MarkdownUtil.underline("Question Title"), String.valueOf(oldValue), false); - - case "in_onboarding" -> - eb.addField(MarkdownUtil.underline("Was a Pre-Join Question"), BooleanUtils.formatToYesOrNo(oldValue), false); - - default -> { - eb.addField("Unimplemented Change Key", changeKey, false); - log.info("Unimplemented Change Key: {}\nOLD_VALUE: {}\nNEW_VALUE: {}", changeKey, oldValue, newValue); - } - } - }); - - eb.setFooter("Audit Log Entry ID: " + ale.getId()); - eb.setTimestamp(ale.getTimeCreated()); - - if (!eb.isValidLength() || eb.isEmpty()) { - log.warn("Embed is empty or too long (current length: {}).", eb.length()); - return; - } - - TextChannel sendingChannel = event.getGuild().getTextChannelById(channelIdToSendTo); - if (sendingChannel != null && sendingChannel.canTalk()) { - sendingChannel.sendMessageEmbeds(eb.build()).queue(); - } - } - -} diff --git a/src/main/java/io/github/eggy03/papertrail/bot/listeners/auditlog/helper/onboarding/OnboardingPromptUpdateEventHelper.java b/src/main/java/io/github/eggy03/papertrail/bot/listeners/auditlog/helper/onboarding/OnboardingPromptUpdateEventHelper.java deleted file mode 100644 index 357a0fdc..00000000 --- a/src/main/java/io/github/eggy03/papertrail/bot/listeners/auditlog/helper/onboarding/OnboardingPromptUpdateEventHelper.java +++ /dev/null @@ -1,86 +0,0 @@ -package io.github.eggy03.papertrail.bot.listeners.auditlog.helper.onboarding; - -import io.github.eggy03.papertrail.bot.utils.BooleanUtils; -import lombok.NonNull; -import lombok.experimental.UtilityClass; -import lombok.extern.slf4j.Slf4j; -import net.dv8tion.jda.api.EmbedBuilder; -import net.dv8tion.jda.api.audit.AuditLogEntry; -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 net.dv8tion.jda.api.utils.MarkdownUtil; - -import java.awt.Color; - -@UtilityClass -@Slf4j -public class OnboardingPromptUpdateEventHelper { - - public static void format(@NonNull GuildAuditLogEntryCreateEvent event, @NonNull 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(MarkdownUtil.quoteBlock("Onboarding Prompt Updated By: " + mentionableExecutor)); - eb.setColor(Color.YELLOW); - - ale.getChanges().forEach((changeKey, changeValue) -> { - - Object oldValue = changeValue.getOldValue(); - Object newValue = changeValue.getNewValue(); - - switch (changeKey) { - case "single_select" -> { - eb.addField(MarkdownUtil.underline("Old Single Selection Mode"), BooleanUtils.formatToYesOrNo(oldValue), false); - eb.addField(MarkdownUtil.underline("New Single Selection Mode"), BooleanUtils.formatToYesOrNo(newValue), false); - } - - case "required" -> { - eb.addField(MarkdownUtil.underline("Was Required"), BooleanUtils.formatToYesOrNo(oldValue), false); - eb.addField(MarkdownUtil.underline("Is Required"), BooleanUtils.formatToYesOrNo(newValue), false); - } - - case "type", "id" -> { - // skip - } - - case "title" -> { - eb.addField(MarkdownUtil.underline("Old Question Title"), String.valueOf(oldValue), false); - eb.addField(MarkdownUtil.underline("New Question Title"), String.valueOf(newValue), false); - } - - case "options" -> - eb.addField(MarkdownUtil.underline("Question Options"), "Review the changed options in Onboarding Settings", false); - - case "in_onboarding" -> { - eb.addField(MarkdownUtil.underline("Was a Pre-Join Question"), BooleanUtils.formatToYesOrNo(oldValue), false); - eb.addField(MarkdownUtil.underline("Is a Pre-Join Question"), BooleanUtils.formatToYesOrNo(newValue), false); - } - - default -> { - eb.addField("Unimplemented Change Key", changeKey, false); - log.info("Unimplemented Change Key: {}\nOLD_VALUE: {}\nNEW_VALUE: {}", changeKey, oldValue, newValue); - } - } - }); - - eb.setFooter("Audit Log Entry ID: " + ale.getId()); - eb.setTimestamp(ale.getTimeCreated()); - - if (!eb.isValidLength() || eb.isEmpty()) { - log.warn("Embed is empty or too long (current length: {}).", eb.length()); - return; - } - - TextChannel sendingChannel = event.getGuild().getTextChannelById(channelIdToSendTo); - if (sendingChannel != null && sendingChannel.canTalk()) { - sendingChannel.sendMessageEmbeds(eb.build()).queue(); - } - } -} diff --git a/src/main/java/io/github/eggy03/papertrail/bot/listeners/auditlog/helper/role/RoleCreateEventHelper.java b/src/main/java/io/github/eggy03/papertrail/bot/listeners/auditlog/helper/role/RoleCreateEventHelper.java deleted file mode 100644 index 7b7ad57f..00000000 --- a/src/main/java/io/github/eggy03/papertrail/bot/listeners/auditlog/helper/role/RoleCreateEventHelper.java +++ /dev/null @@ -1,70 +0,0 @@ -package io.github.eggy03.papertrail.bot.listeners.auditlog.helper.role; - -import lombok.NonNull; -import lombok.experimental.UtilityClass; -import lombok.extern.slf4j.Slf4j; -import net.dv8tion.jda.api.EmbedBuilder; -import net.dv8tion.jda.api.audit.AuditLogEntry; -import net.dv8tion.jda.api.entities.Role; -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 net.dv8tion.jda.api.utils.MarkdownUtil; - -import java.awt.Color; - -@UtilityClass -@Slf4j -public class RoleCreateEventHelper { - - public static void format(@NonNull GuildAuditLogEntryCreateEvent event, @NonNull String channelIdToSendTo) { - - AuditLogEntry ale = event.getEntry(); - - User executor = ale.getJDA().getUserById(ale.getUserId()); - String mentionableExecutor = (executor != null ? executor.getAsMention() : ale.getUserId()); - - Role targetRole = ale.getJDA().getRoleById(ale.getTargetId()); - String mentionableTargetRole = (targetRole != null ? targetRole.getAsMention() : ale.getTargetId()); - - EmbedBuilder eb = new EmbedBuilder(); - eb.setTitle("Audit Log Entry | Role Create Event"); - eb.setDescription(MarkdownUtil.quoteBlock("Role Created By: " + mentionableExecutor + "\nTarget Role: " + mentionableTargetRole)); - eb.setColor(Color.GREEN); - - ale.getChanges().forEach((changeKey, changeValue) -> { - - Object oldValue = changeValue.getOldValue(); - Object newValue = changeValue.getNewValue(); - - switch (changeKey) { - - case "name" -> eb.addField(MarkdownUtil.underline("Role Name"), "╰┈➤" + newValue, false); - - case "colors", "hoist", "color", "permissions", "mentionable" -> { - /* discord for some reason shows the following to be default/null even - * when you set them during the creation of the role itself - * and delegates them to ROLE_UPDATE event - */ - } - default -> { - eb.addField("Unimplemented Change Key", changeKey, false); - log.info("Unimplemented Change Key: {}\nOLD_VALUE: {}\nNEW_VALUE: {}", changeKey, oldValue, newValue); - } - } - }); - - eb.setFooter("Audit Log Entry ID: " + ale.getId()); - eb.setTimestamp(ale.getTimeCreated()); - - if (!eb.isValidLength() || eb.isEmpty()) { - log.warn("Embed is empty or too long (current length: {}).", eb.length()); - return; - } - - TextChannel sendingChannel = event.getGuild().getTextChannelById(channelIdToSendTo); - if (sendingChannel != null && sendingChannel.canTalk()) { - sendingChannel.sendMessageEmbeds(eb.build()).queue(); - } - } -} diff --git a/src/main/java/io/github/eggy03/papertrail/bot/listeners/auditlog/helper/role/RoleDeleteEventHelper.java b/src/main/java/io/github/eggy03/papertrail/bot/listeners/auditlog/helper/role/RoleDeleteEventHelper.java deleted file mode 100644 index 06fa82e9..00000000 --- a/src/main/java/io/github/eggy03/papertrail/bot/listeners/auditlog/helper/role/RoleDeleteEventHelper.java +++ /dev/null @@ -1,77 +0,0 @@ -package io.github.eggy03.papertrail.bot.listeners.auditlog.helper.role; - -import io.github.eggy03.papertrail.bot.listeners.auditlog.helper.role.utils.RoleUtils; -import io.github.eggy03.papertrail.bot.utils.BooleanUtils; -import lombok.NonNull; -import lombok.experimental.UtilityClass; -import lombok.extern.slf4j.Slf4j; -import net.dv8tion.jda.api.EmbedBuilder; -import net.dv8tion.jda.api.audit.AuditLogEntry; -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 net.dv8tion.jda.api.utils.MarkdownUtil; - -import java.awt.Color; - -@UtilityClass -@Slf4j -public class RoleDeleteEventHelper { - - public static void format(@NonNull GuildAuditLogEntryCreateEvent event, @NonNull String channelIdToSendTo) { - - AuditLogEntry ale = event.getEntry(); - - User executor = ale.getJDA().getUserById(ale.getUserId()); - String mentionableExecutor = (executor != null ? executor.getAsMention() : ale.getUserId()); - - EmbedBuilder eb = new EmbedBuilder(); - eb.setTitle("Audit Log Entry | Role Delete Event"); - eb.setDescription(MarkdownUtil.quoteBlock("Role Deleted By: " + mentionableExecutor + "\nTarget Role ID: " + ale.getTargetId())); - eb.setColor(Color.RED); - - ale.getChanges().forEach((changeKey, changeValue) -> { - Object oldValue = changeValue.getOldValue(); - Object newValue = changeValue.getNewValue(); - - switch (changeKey) { - - case "name" -> eb.addField(MarkdownUtil.underline("Role Name"), "╰┈➤" + oldValue, false); - - case "hoist" -> - eb.addField(MarkdownUtil.underline("Display Separately"), "╰┈➤" + BooleanUtils.formatToYesOrNo(oldValue), false); - - case "color" -> - eb.addField(MarkdownUtil.underline("Color"), "╰┈➤" + RoleUtils.formatToHex(oldValue), false); - - case "permissions" -> - eb.addField(MarkdownUtil.underline("Role Permissions"), RoleUtils.resolveRolePermissions(oldValue, "✅"), false); - - case "mentionable" -> - eb.addField(MarkdownUtil.underline("Mentionable"), "╰┈➤" + BooleanUtils.formatToYesOrNo(oldValue), false); - - case "colors" -> - eb.addField(MarkdownUtil.underline("Gradient Color System"), RoleUtils.formatGradientToHex(oldValue), false); - - default -> { - eb.addField("Unimplemented Change Key", changeKey, false); - log.info("Unimplemented Change Key: {}\nOLD_VALUE: {}\nNEW_VALUE: {}", changeKey, oldValue, newValue); - } - } - - }); - - eb.setFooter("Audit Log Entry ID: " + ale.getId()); - eb.setTimestamp(ale.getTimeCreated()); - - if (!eb.isValidLength() || eb.isEmpty()) { - log.warn("Embed is empty or too long (current length: {}).", eb.length()); - return; - } - - TextChannel sendingChannel = event.getGuild().getTextChannelById(channelIdToSendTo); - if (sendingChannel != null && sendingChannel.canTalk()) { - sendingChannel.sendMessageEmbeds(eb.build()).queue(); - } - } -} diff --git a/src/main/java/io/github/eggy03/papertrail/bot/listeners/auditlog/helper/role/RoleUpdateEventHelper.java b/src/main/java/io/github/eggy03/papertrail/bot/listeners/auditlog/helper/role/RoleUpdateEventHelper.java deleted file mode 100644 index a08c544d..00000000 --- a/src/main/java/io/github/eggy03/papertrail/bot/listeners/auditlog/helper/role/RoleUpdateEventHelper.java +++ /dev/null @@ -1,101 +0,0 @@ -package io.github.eggy03.papertrail.bot.listeners.auditlog.helper.role; - -import io.github.eggy03.papertrail.bot.listeners.auditlog.helper.role.utils.RoleUtils; -import io.github.eggy03.papertrail.bot.utils.BooleanUtils; -import lombok.NonNull; -import lombok.experimental.UtilityClass; -import lombok.extern.slf4j.Slf4j; -import net.dv8tion.jda.api.EmbedBuilder; -import net.dv8tion.jda.api.audit.AuditLogEntry; -import net.dv8tion.jda.api.entities.Role; -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 net.dv8tion.jda.api.utils.MarkdownUtil; - -import java.awt.Color; - -@UtilityClass -@Slf4j -public class RoleUpdateEventHelper { - - public static void format(@NonNull GuildAuditLogEntryCreateEvent event, @NonNull String channelIdToSendTo) { - - AuditLogEntry ale = event.getEntry(); - - User executor = ale.getJDA().getUserById(ale.getUserId()); - String mentionableExecutor = (executor != null ? executor.getAsMention() : ale.getUserId()); - - Role targetRole = ale.getJDA().getRoleById(ale.getTargetId()); - String mentionableTargetRole = (targetRole != null ? targetRole.getAsMention() : ale.getTargetId()); - - EmbedBuilder eb = new EmbedBuilder(); - eb.setTitle("Audit Log Entry | Role Update Event"); - eb.setDescription(MarkdownUtil.quoteBlock("Role Updated By: " + mentionableExecutor + "\nTarget Role: " + mentionableTargetRole)); - eb.setColor(Color.YELLOW); - - ale.getChanges().forEach((changeKey, changeValue) -> { - - Object oldValue = changeValue.getOldValue(); - Object newValue = changeValue.getNewValue(); - - switch (changeKey) { - - case "name" -> { - eb.addField(MarkdownUtil.underline("Old Role Name"), "╰┈➤" + oldValue, true); - eb.addField(MarkdownUtil.underline("New Role Name"), "╰┈➤" + newValue, true); - eb.addBlankField(true); - } - - case "hoist" -> { - eb.addField(MarkdownUtil.underline("Old Display Separately"), "╰┈➤" + BooleanUtils.formatToYesOrNo(oldValue), true); - eb.addField(MarkdownUtil.underline("New Display Separately"), "╰┈➤" + BooleanUtils.formatToYesOrNo(newValue), true); - eb.addBlankField(true); - } - - case "color" -> { - eb.addField(MarkdownUtil.underline("Old Color"), "╰┈➤" + RoleUtils.formatToHex(oldValue), true); - eb.addField(MarkdownUtil.underline("New Color"), "╰┈➤" + RoleUtils.formatToHex(newValue), true); - eb.addBlankField(true); - } - - case "permissions" -> { - eb.addField(MarkdownUtil.underline("Old Role Permissions"), RoleUtils.resolveRolePermissions(oldValue, "✅"), true); - eb.addField(MarkdownUtil.underline("New Role Permissions"), RoleUtils.resolveRolePermissions(newValue, "✅"), true); - eb.addBlankField(true); - } - - case "mentionable" -> { - eb.addField(MarkdownUtil.underline("Old Mentionable"), "╰┈➤" + BooleanUtils.formatToYesOrNo(oldValue), true); - eb.addField(MarkdownUtil.underline("New Mentionable"), "╰┈➤" + BooleanUtils.formatToYesOrNo(newValue), true); - eb.addBlankField(true); - } - - case "colors" -> { - eb.addField(MarkdownUtil.underline("Old Gradient Color System"), RoleUtils.formatGradientToHex(oldValue), true); - eb.addField(MarkdownUtil.underline("New Gradient Color System"), RoleUtils.formatGradientToHex(newValue), true); - eb.addBlankField(true); - } - - default -> { - eb.addField("Unimplemented Change Key", changeKey, false); - log.info("Unimplemented Change Key: {}\nOLD_VALUE: {}\nNEW_VALUE: {}", changeKey, oldValue, newValue); - } - - } - }); - - eb.setFooter("Audit Log Entry ID: " + ale.getId()); - eb.setTimestamp(ale.getTimeCreated()); - - if (!eb.isValidLength() || eb.isEmpty()) { - log.warn("Embed is empty or too long (current length: {}).", eb.length()); - return; - } - - TextChannel sendingChannel = event.getGuild().getTextChannelById(channelIdToSendTo); - if (sendingChannel != null && sendingChannel.canTalk()) { - sendingChannel.sendMessageEmbeds(eb.build()).queue(); - } - } -} diff --git a/src/main/java/io/github/eggy03/papertrail/bot/listeners/auditlog/helper/scheduledevent/ScheduledEventCreateEventHelper.java b/src/main/java/io/github/eggy03/papertrail/bot/listeners/auditlog/helper/scheduledevent/ScheduledEventCreateEventHelper.java deleted file mode 100644 index c803ec88..00000000 --- a/src/main/java/io/github/eggy03/papertrail/bot/listeners/auditlog/helper/scheduledevent/ScheduledEventCreateEventHelper.java +++ /dev/null @@ -1,67 +0,0 @@ -package io.github.eggy03.papertrail.bot.listeners.auditlog.helper.scheduledevent; - -import io.github.eggy03.papertrail.bot.listeners.auditlog.helper.scheduledevent.utils.ScheduledEventUtils; -import lombok.NonNull; -import lombok.experimental.UtilityClass; -import lombok.extern.slf4j.Slf4j; -import net.dv8tion.jda.api.EmbedBuilder; -import net.dv8tion.jda.api.audit.AuditLogEntry; -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 net.dv8tion.jda.api.utils.MarkdownUtil; - -import java.awt.Color; - -@UtilityClass -@Slf4j -public class ScheduledEventCreateEventHelper { - - public static void format(@NonNull GuildAuditLogEntryCreateEvent event, @NonNull String channelIdToSendTo) { - - AuditLogEntry ale = event.getEntry(); - - User executor = ale.getJDA().getUserById(ale.getUserIdLong()); - String mentionableExecutor = (executor != null ? executor.getAsMention() : ale.getUserId()); - - EmbedBuilder eb = new EmbedBuilder(); - eb.setTitle("Audit Log Entry | Scheduled Event Create Event"); - eb.setDescription(MarkdownUtil.quoteBlock("Scheduled Event Created By: " + mentionableExecutor)); - eb.setColor(Color.GREEN); - - ale.getChanges().forEach((changeKey, changeValue) -> { - Object oldValue = changeValue.getOldValue(); - Object newValue = changeValue.getNewValue(); - - switch (changeKey) { - case "entity_type" -> - eb.addField(MarkdownUtil.underline("Event Type"), "╰┈➤" + ScheduledEventUtils.resolveEventType(newValue), false); - case "name" -> eb.addField(MarkdownUtil.underline("Event Name"), "╰┈➤" + newValue, false); - case "description" -> eb.addField(MarkdownUtil.underline("Event Description"), "╰┈➤" + newValue, false); - case "status" -> - eb.addField(MarkdownUtil.underline("Event Status"), "╰┈➤" + ScheduledEventUtils.resolveStatusType(newValue), false); - case "location" -> eb.addField(MarkdownUtil.underline("Event Location"), "╰┈➤" + newValue, false); - case "privacy_level", "image_hash", "channel_id", "recurrence_rule" -> { - // skip - } - default -> { - eb.addField("Unimplemented Change Key", changeKey, false); - log.info("Unimplemented Change Key: {}\nOLD_VALUE: {}\nNEW_VALUE: {}", changeKey, oldValue, newValue); - } - } - }); - - eb.setFooter("Audit Log Entry ID: " + ale.getId()); - eb.setTimestamp(ale.getTimeCreated()); - - if (!eb.isValidLength() || eb.isEmpty()) { - log.warn("Embed is empty or too long (current length: {}).", eb.length()); - return; - } - - TextChannel sendingChannel = event.getGuild().getTextChannelById(channelIdToSendTo); - if (sendingChannel != null && sendingChannel.canTalk()) { - sendingChannel.sendMessageEmbeds(eb.build()).queue(); - } - } -} diff --git a/src/main/java/io/github/eggy03/papertrail/bot/listeners/auditlog/helper/scheduledevent/ScheduledEventDeleteEventHelper.java b/src/main/java/io/github/eggy03/papertrail/bot/listeners/auditlog/helper/scheduledevent/ScheduledEventDeleteEventHelper.java deleted file mode 100644 index 55195541..00000000 --- a/src/main/java/io/github/eggy03/papertrail/bot/listeners/auditlog/helper/scheduledevent/ScheduledEventDeleteEventHelper.java +++ /dev/null @@ -1,67 +0,0 @@ -package io.github.eggy03.papertrail.bot.listeners.auditlog.helper.scheduledevent; - -import io.github.eggy03.papertrail.bot.listeners.auditlog.helper.scheduledevent.utils.ScheduledEventUtils; -import lombok.NonNull; -import lombok.experimental.UtilityClass; -import lombok.extern.slf4j.Slf4j; -import net.dv8tion.jda.api.EmbedBuilder; -import net.dv8tion.jda.api.audit.AuditLogEntry; -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 net.dv8tion.jda.api.utils.MarkdownUtil; - -import java.awt.Color; - -@UtilityClass -@Slf4j -public class ScheduledEventDeleteEventHelper { - - public static void format(@NonNull GuildAuditLogEntryCreateEvent event, @NonNull String channelIdToSendTo) { - - AuditLogEntry ale = event.getEntry(); - - User executor = ale.getJDA().getUserById(ale.getUserIdLong()); - String mentionableExecutor = (executor != null ? executor.getAsMention() : ale.getUserId()); - - EmbedBuilder eb = new EmbedBuilder(); - eb.setTitle("Audit Log Entry | Scheduled Event Delete Event"); - eb.setDescription(MarkdownUtil.quoteBlock("Scheduled Event Deleted By: " + mentionableExecutor)); - eb.setColor(Color.RED); - - ale.getChanges().forEach((changeKey, changeValue) -> { - Object oldValue = changeValue.getOldValue(); - Object newValue = changeValue.getNewValue(); - - switch (changeKey) { - case "entity_type" -> - eb.addField(MarkdownUtil.underline("Event Type"), "╰┈➤" + ScheduledEventUtils.resolveEventType(oldValue), false); - case "name" -> eb.addField(MarkdownUtil.underline("Event Name"), "╰┈➤" + oldValue, false); - case "description" -> eb.addField(MarkdownUtil.underline("Event Description"), "╰┈➤" + oldValue, false); - case "status" -> - eb.addField(MarkdownUtil.underline("Event Status"), "╰┈➤" + ScheduledEventUtils.resolveStatusType(oldValue), false); - case "location" -> eb.addField(MarkdownUtil.underline("Event Location"), "╰┈➤" + oldValue, false); - case "privacy_level", "image_hash", "channel_id", "recurrence_rule" -> { - // skip - } - default -> { - eb.addField("Unimplemented Change Key", changeKey, false); - log.info("Unimplemented Change Key: {}\nOLD_VALUE: {}\nNEW_VALUE: {}", changeKey, oldValue, newValue); - } - } - }); - - eb.setFooter("Audit Log Entry ID: " + ale.getId()); - eb.setTimestamp(ale.getTimeCreated()); - - if (!eb.isValidLength() || eb.isEmpty()) { - log.warn("Embed is empty or too long (current length: {}).", eb.length()); - return; - } - - TextChannel sendingChannel = event.getGuild().getTextChannelById(channelIdToSendTo); - if (sendingChannel != null && sendingChannel.canTalk()) { - sendingChannel.sendMessageEmbeds(eb.build()).queue(); - } - } -} diff --git a/src/main/java/io/github/eggy03/papertrail/bot/listeners/auditlog/helper/scheduledevent/ScheduledEventUpdateEventHelper.java b/src/main/java/io/github/eggy03/papertrail/bot/listeners/auditlog/helper/scheduledevent/ScheduledEventUpdateEventHelper.java deleted file mode 100644 index f578c902..00000000 --- a/src/main/java/io/github/eggy03/papertrail/bot/listeners/auditlog/helper/scheduledevent/ScheduledEventUpdateEventHelper.java +++ /dev/null @@ -1,91 +0,0 @@ -package io.github.eggy03.papertrail.bot.listeners.auditlog.helper.scheduledevent; - -import io.github.eggy03.papertrail.bot.listeners.auditlog.helper.scheduledevent.utils.ScheduledEventUtils; -import lombok.NonNull; -import lombok.experimental.UtilityClass; -import lombok.extern.slf4j.Slf4j; -import net.dv8tion.jda.api.EmbedBuilder; -import net.dv8tion.jda.api.audit.AuditLogEntry; -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 net.dv8tion.jda.api.utils.MarkdownUtil; - -import java.awt.Color; - -@UtilityClass -@Slf4j -public class ScheduledEventUpdateEventHelper { - - public static void format(@NonNull GuildAuditLogEntryCreateEvent event, @NonNull String channelIdToSendTo) { - - AuditLogEntry ale = event.getEntry(); - - User executor = ale.getJDA().getUserById(ale.getUserIdLong()); - String mentionableExecutor = (executor != null ? executor.getAsMention() : ale.getUserId()); - - EmbedBuilder eb = new EmbedBuilder(); - eb.setTitle("Audit Log Entry | Scheduled Event Update Event"); - eb.setDescription(MarkdownUtil.quoteBlock("Scheduled Event Updated By: " + mentionableExecutor)); - eb.setColor(Color.YELLOW); - - ale.getChanges().forEach((changeKey, changeValue) -> { - Object oldValue = changeValue.getOldValue(); - Object newValue = changeValue.getNewValue(); - - switch (changeKey) { - case "entity_type" -> { - eb.addField(MarkdownUtil.underline("Old Event Type"), "╰┈➤" + ScheduledEventUtils.resolveEventType(oldValue), true); - eb.addField(MarkdownUtil.underline("New Event Type"), "╰┈➤" + ScheduledEventUtils.resolveEventType(newValue), true); - eb.addBlankField(true); - } - case "name" -> { - eb.addField(MarkdownUtil.underline("Old Event Name"), "╰┈➤" + oldValue, true); - eb.addField(MarkdownUtil.underline("New Event Name"), "╰┈➤" + newValue, true); - eb.addBlankField(true); - } - case "description" -> { - eb.addField(MarkdownUtil.underline("Old Event Description"), "╰┈➤" + oldValue, true); - eb.addField(MarkdownUtil.underline("New Event Description"), "╰┈➤" + newValue, true); - eb.addBlankField(true); - } - case "status" -> { - eb.addField(MarkdownUtil.underline("Old Event Status"), "╰┈➤" + ScheduledEventUtils.resolveStatusType(oldValue), true); - eb.addField(MarkdownUtil.underline("New Event Status"), "╰┈➤" + ScheduledEventUtils.resolveStatusType(newValue), true); - eb.addBlankField(true); - } - case "location" -> { - eb.addField(MarkdownUtil.underline("Event Location"), "╰┈➤" + oldValue, true); - eb.addField(MarkdownUtil.underline("Event Location"), "╰┈➤" + newValue, true); - eb.addBlankField(true); - } - case "privacy_level" -> - eb.addField(MarkdownUtil.underline("Privacy"), "╰┈➤Event privacy has been updated", false); - case "image_hash" -> - eb.addField(MarkdownUtil.underline("Image"), "╰┈➤Event Image has been updated", false); - case "channel_id" -> - eb.addField(MarkdownUtil.underline("Channel"), "╰┈➤Event Channel has been updated", false); - case "recurrence_rule" -> - eb.addField(MarkdownUtil.underline("Recurrence Rule"), "╰┈➤Recurrence Rule has been updated", false); - - default -> { - eb.addField("Unimplemented Change Key", changeKey, false); - log.info("Unimplemented Change Key: {}\nOLD_VALUE: {}\nNEW_VALUE: {}", changeKey, oldValue, newValue); - } - } - }); - - eb.setFooter("Audit Log Entry ID: " + ale.getId()); - eb.setTimestamp(ale.getTimeCreated()); - - if (!eb.isValidLength() || eb.isEmpty()) { - log.warn("Embed is empty or too long (current length: {}).", eb.length()); - return; - } - - TextChannel sendingChannel = event.getGuild().getTextChannelById(channelIdToSendTo); - if (sendingChannel != null && sendingChannel.canTalk()) { - sendingChannel.sendMessageEmbeds(eb.build()).queue(); - } - } -} diff --git a/src/main/java/io/github/eggy03/papertrail/bot/listeners/auditlog/helper/scheduledevent/utils/ScheduledEventUtils.java b/src/main/java/io/github/eggy03/papertrail/bot/listeners/auditlog/helper/scheduledevent/utils/ScheduledEventUtils.java deleted file mode 100644 index d15a4fbd..00000000 --- a/src/main/java/io/github/eggy03/papertrail/bot/listeners/auditlog/helper/scheduledevent/utils/ScheduledEventUtils.java +++ /dev/null @@ -1,125 +0,0 @@ -package io.github.eggy03.papertrail.bot.listeners.auditlog.helper.scheduledevent.utils; - -import io.github.eggy03.papertrail.bot.utils.NumberParseUtils; -import lombok.NonNull; -import lombok.experimental.UtilityClass; -import lombok.extern.slf4j.Slf4j; -import net.dv8tion.jda.api.entities.ScheduledEvent; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -import java.util.Map; - -/* - * See {@link io.github.eggy03.papertrail.bot.utils.StackWalkerUtils} - * and other utilities in the util package - * to know why logging isn't needed in some of the methods here - */ -@UtilityClass -@Slf4j -public class ScheduledEventUtils { - - @NonNull - public static final String FALLBACK_STRING = "N/A"; - - @NotNull - public static String resolveEventType(@Nullable Object eventTypeInteger) { - - Integer eventType = NumberParseUtils.parseInt(eventTypeInteger); - if (eventType == null) - return FALLBACK_STRING; - - return ScheduledEvent.Type.fromKey(eventType).name(); - - } - - @NotNull - public static String resolveStatusType(@Nullable Object eventTypeInteger) { - Integer eventType = NumberParseUtils.parseInt(eventTypeInteger); - if (eventType == null) - return FALLBACK_STRING; - - return ScheduledEvent.Status.fromKey(eventType).name(); - } - - - /** - * @deprecated - */ - @NotNull - @Deprecated(forRemoval = true) - public static String resolveRecurrenceRules(@Nullable Object recurrenceRuleStructure) { - - if (recurrenceRuleStructure == null) { - log.debug("recurrence rule object was null"); - return FALLBACK_STRING; - } - - StringBuilder stringBuilder = new StringBuilder(); - if (recurrenceRuleStructure instanceof Map recurrenceRuleMap) { - - stringBuilder.append("**_Start Time of Interval_**") - .append(System.lineSeparator()) - .append("╰┈➤") - .append(recurrenceRuleMap.get("start")) - .append(System.lineSeparator()); - - stringBuilder.append("**_End Time of Interval_**") - .append(System.lineSeparator()) - .append("╰┈➤") - .append(recurrenceRuleMap.get("end")) - .append(System.lineSeparator()); - - stringBuilder.append("**_Frequency of Interval_**") - .append(System.lineSeparator()) - .append("╰┈➤") - .append(recurrenceRuleMap.get("frequency")) - .append(System.lineSeparator()); - - stringBuilder.append("**_Spacing between events_**") - .append(System.lineSeparator()) - .append("╰┈➤") - .append(recurrenceRuleMap.get("interval")) - .append(System.lineSeparator()); - - stringBuilder.append("**_Weekday Recurrence_**") - .append(System.lineSeparator()) - .append("╰┈➤") - .append(recurrenceRuleMap.get("by_weekday")) - .append(System.lineSeparator()); - - stringBuilder.append("**_Specific days within a weekday to recur on_**") - .append(System.lineSeparator()) - .append("╰┈➤") - .append(recurrenceRuleMap.get("by_n_weekday")) - .append(System.lineSeparator()); - - stringBuilder.append("**_Monthly Recurrence_**") - .append(System.lineSeparator()) - .append("╰┈➤") - .append(recurrenceRuleMap.get("by_month")) - .append(System.lineSeparator()); - - stringBuilder.append("**_Specific days within a month to recur on_**") - .append(System.lineSeparator()) - .append("╰┈➤") - .append(recurrenceRuleMap.get("by_month_day")) - .append(System.lineSeparator()); - - stringBuilder.append("**_Set of days within a year to recur on_**") - .append(System.lineSeparator()) - .append("╰┈➤") - .append(recurrenceRuleMap.get("by_year_day")) - .append(System.lineSeparator()); - - stringBuilder.append("**_Event to be repeated_**") - .append(System.lineSeparator()) - .append("╰┈➤") - .append(recurrenceRuleMap.get("count")); - - } else - log.debug("Recurrence rule object was not an instance of a map, value: {}", recurrenceRuleStructure); - - return stringBuilder.toString().trim(); - } -} diff --git a/src/main/java/io/github/eggy03/papertrail/bot/listeners/auditlog/helper/soundboard/SoundboardSoundCreateEventHelper.java b/src/main/java/io/github/eggy03/papertrail/bot/listeners/auditlog/helper/soundboard/SoundboardSoundCreateEventHelper.java deleted file mode 100644 index cb8fb9ba..00000000 --- a/src/main/java/io/github/eggy03/papertrail/bot/listeners/auditlog/helper/soundboard/SoundboardSoundCreateEventHelper.java +++ /dev/null @@ -1,71 +0,0 @@ -package io.github.eggy03.papertrail.bot.listeners.auditlog.helper.soundboard; - -import io.github.eggy03.papertrail.bot.listeners.auditlog.helper.soundboard.utils.SoundboardUtils; -import lombok.NonNull; -import lombok.experimental.UtilityClass; -import lombok.extern.slf4j.Slf4j; -import net.dv8tion.jda.api.EmbedBuilder; -import net.dv8tion.jda.api.audit.AuditLogEntry; -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 net.dv8tion.jda.api.utils.MarkdownUtil; - -import java.awt.Color; - -@UtilityClass -@Slf4j -public class SoundboardSoundCreateEventHelper { - - public static void format(@NonNull GuildAuditLogEntryCreateEvent event, @NonNull String channelIdToSendTo) { - - AuditLogEntry ale = event.getEntry(); - - User executor = ale.getJDA().getUserById(ale.getUserIdLong()); - String mentionableExecutor = (executor != null ? executor.getAsMention() : ale.getUserId()); - - EmbedBuilder eb = new EmbedBuilder(); - eb.setTitle("Audit Log Entry | Soundboard Sound Create Event"); - eb.setDescription(MarkdownUtil.quoteBlock("Sound Item Added By: " + mentionableExecutor)); - eb.setColor(Color.GREEN); - - ale.getChanges().forEach((changeKey, changeValue) -> { - - Object oldValue = changeValue.getOldValue(); - Object newValue = changeValue.getNewValue(); - - switch (changeKey) { - - case "user_id", "sound_id", "id", "guild_id", "available" -> { - // skip - } - case "volume" -> - eb.addField(MarkdownUtil.underline("Volume"), "╰┈➤" + SoundboardUtils.resolveVolumePercentage(newValue), false); - - case "emoji_name" -> eb.addField(MarkdownUtil.underline("Related Emoji"), "╰┈➤" + newValue, false); - - case "emoji_id" -> eb.addField(MarkdownUtil.underline("Related Emoji ID"), "╰┈➤" + newValue, false); - - case "name" -> eb.addField(MarkdownUtil.underline("Sound Item Name"), "╰┈➤" + newValue, false); - - default -> { - eb.addField("Unimplemented Change Key", changeKey, false); - log.info("Unimplemented Change Key: {}\nOLD_VALUE: {}\nNEW_VALUE: {}", changeKey, oldValue, newValue); - } - } - }); - - eb.setFooter("Audit Log Entry ID: " + ale.getId()); - eb.setTimestamp(ale.getTimeCreated()); - - if (!eb.isValidLength() || eb.isEmpty()) { - log.warn("Embed is empty or too long (current length: {}).", eb.length()); - return; - } - - TextChannel sendingChannel = event.getGuild().getTextChannelById(channelIdToSendTo); - if (sendingChannel != null && sendingChannel.canTalk()) { - sendingChannel.sendMessageEmbeds(eb.build()).queue(); - } - } -} diff --git a/src/main/java/io/github/eggy03/papertrail/bot/listeners/auditlog/helper/soundboard/SoundboardSoundDeleteEventHelper.java b/src/main/java/io/github/eggy03/papertrail/bot/listeners/auditlog/helper/soundboard/SoundboardSoundDeleteEventHelper.java deleted file mode 100644 index 0d50e2a9..00000000 --- a/src/main/java/io/github/eggy03/papertrail/bot/listeners/auditlog/helper/soundboard/SoundboardSoundDeleteEventHelper.java +++ /dev/null @@ -1,71 +0,0 @@ -package io.github.eggy03.papertrail.bot.listeners.auditlog.helper.soundboard; - -import io.github.eggy03.papertrail.bot.listeners.auditlog.helper.soundboard.utils.SoundboardUtils; -import lombok.NonNull; -import lombok.experimental.UtilityClass; -import lombok.extern.slf4j.Slf4j; -import net.dv8tion.jda.api.EmbedBuilder; -import net.dv8tion.jda.api.audit.AuditLogEntry; -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 net.dv8tion.jda.api.utils.MarkdownUtil; - -import java.awt.Color; - -@UtilityClass -@Slf4j -public class SoundboardSoundDeleteEventHelper { - - public static void format(@NonNull GuildAuditLogEntryCreateEvent event, @NonNull String channelIdToSendTo) { - - AuditLogEntry ale = event.getEntry(); - - User executor = ale.getJDA().getUserById(ale.getUserIdLong()); - String mentionableExecutor = (executor != null ? executor.getAsMention() : ale.getUserId()); - - EmbedBuilder eb = new EmbedBuilder(); - eb.setTitle("Audit Log Entry | Soundboard Sound Delete Event"); - eb.setDescription(MarkdownUtil.quoteBlock("Sound Item Deleted By: " + mentionableExecutor)); - eb.setColor(Color.RED); - - ale.getChanges().forEach((changeKey, changeValue) -> { - - Object oldValue = changeValue.getOldValue(); - Object newValue = changeValue.getNewValue(); - - switch (changeKey) { - - case "user_id", "sound_id", "id", "guild_id", "available" -> { - // skip - } - case "volume" -> - eb.addField(MarkdownUtil.underline("Volume"), "╰┈➤" + SoundboardUtils.resolveVolumePercentage(oldValue), false); - - case "emoji_name" -> eb.addField(MarkdownUtil.underline("Related Emoji"), "╰┈➤" + oldValue, false); - - case "emoji_id" -> eb.addField(MarkdownUtil.underline("Related Emoji ID"), "╰┈➤" + oldValue, false); - - case "name" -> eb.addField(MarkdownUtil.underline("Sound Item Name"), "╰┈➤" + oldValue, false); - - default -> { - eb.addField("Unimplemented Change Key", changeKey, false); - log.info("Unimplemented Change Key: {}\nOLD_VALUE: {}\nNEW_VALUE: {}", changeKey, oldValue, newValue); - } - } - }); - - eb.setFooter("Audit Log Entry ID: " + ale.getId()); - eb.setTimestamp(ale.getTimeCreated()); - - if (!eb.isValidLength() || eb.isEmpty()) { - log.warn("Embed is empty or too long (current length: {}).", eb.length()); - return; - } - - TextChannel sendingChannel = event.getGuild().getTextChannelById(channelIdToSendTo); - if (sendingChannel != null && sendingChannel.canTalk()) { - sendingChannel.sendMessageEmbeds(eb.build()).queue(); - } - } -} diff --git a/src/main/java/io/github/eggy03/papertrail/bot/listeners/auditlog/helper/soundboard/SoundboardSoundUpdateEventHelper.java b/src/main/java/io/github/eggy03/papertrail/bot/listeners/auditlog/helper/soundboard/SoundboardSoundUpdateEventHelper.java deleted file mode 100644 index 97f17d95..00000000 --- a/src/main/java/io/github/eggy03/papertrail/bot/listeners/auditlog/helper/soundboard/SoundboardSoundUpdateEventHelper.java +++ /dev/null @@ -1,80 +0,0 @@ -package io.github.eggy03.papertrail.bot.listeners.auditlog.helper.soundboard; - -import io.github.eggy03.papertrail.bot.listeners.auditlog.helper.soundboard.utils.SoundboardUtils; -import lombok.NonNull; -import lombok.experimental.UtilityClass; -import lombok.extern.slf4j.Slf4j; -import net.dv8tion.jda.api.EmbedBuilder; -import net.dv8tion.jda.api.audit.AuditLogEntry; -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 net.dv8tion.jda.api.utils.MarkdownUtil; - -import java.awt.Color; - -@UtilityClass -@Slf4j -public class SoundboardSoundUpdateEventHelper { - - public static void format(@NonNull GuildAuditLogEntryCreateEvent event, @NonNull String channelIdToSendTo) { - - AuditLogEntry ale = event.getEntry(); - - User executor = ale.getJDA().getUserById(ale.getUserIdLong()); - String mentionableExecutor = (executor != null ? executor.getAsMention() : ale.getUserId()); - - EmbedBuilder eb = new EmbedBuilder(); - eb.setTitle("Audit Log Entry | Soundboard Sound Update Event"); - eb.setDescription(MarkdownUtil.quoteBlock("Sound Item Updated By: " + mentionableExecutor)); - eb.setColor(Color.YELLOW); - - ale.getChanges().forEach((changeKey, changeValue) -> { - Object oldValue = changeValue.getOldValue(); - Object newValue = changeValue.getNewValue(); - - switch (changeKey) { - case "user_id", "sound_id", "id", "guild_id", "available" -> { - // skip - } - case "volume" -> { - eb.addField(MarkdownUtil.underline("Old Volume"), "╰┈➤" + SoundboardUtils.resolveVolumePercentage(oldValue), true); - eb.addField(MarkdownUtil.underline("New Volume"), "╰┈➤" + SoundboardUtils.resolveVolumePercentage(newValue), true); - eb.addBlankField(true); - } - case "emoji_name" -> { - eb.addField(MarkdownUtil.underline("Old Related Emoji"), "╰┈➤" + oldValue, true); - eb.addField(MarkdownUtil.underline("New Related Emoji"), "╰┈➤" + newValue, true); - eb.addBlankField(true); - } - case "emoji_id" -> { - eb.addField(MarkdownUtil.underline("Old Related Emoji ID"), "╰┈➤" + oldValue, true); - eb.addField(MarkdownUtil.underline("New Related Emoji ID"), "╰┈➤" + newValue, true); - eb.addBlankField(true); - } - case "name" -> { - eb.addField(MarkdownUtil.underline("Old Sound Item Name"), "╰┈➤" + oldValue, true); - eb.addField(MarkdownUtil.underline("New Sound Item Name"), "╰┈➤" + newValue, true); - eb.addBlankField(true); - } - default -> { - eb.addField("Unimplemented Change Key", changeKey, false); - log.info("Unimplemented Change Key: {}\nOLD_VALUE: {}\nNEW_VALUE: {}", changeKey, oldValue, newValue); - } - } - }); - - eb.setFooter("Audit Log Entry ID: " + ale.getId()); - eb.setTimestamp(ale.getTimeCreated()); - - if (!eb.isValidLength() || eb.isEmpty()) { - log.warn("Embed is empty or too long (current length: {}).", eb.length()); - return; - } - - TextChannel sendingChannel = event.getGuild().getTextChannelById(channelIdToSendTo); - if (sendingChannel != null && sendingChannel.canTalk()) { - sendingChannel.sendMessageEmbeds(eb.build()).queue(); - } - } -} diff --git a/src/main/java/io/github/eggy03/papertrail/bot/listeners/auditlog/helper/stage/StageInstanceCreateEventHelper.java b/src/main/java/io/github/eggy03/papertrail/bot/listeners/auditlog/helper/stage/StageInstanceCreateEventHelper.java deleted file mode 100644 index 5b3e25e6..00000000 --- a/src/main/java/io/github/eggy03/papertrail/bot/listeners/auditlog/helper/stage/StageInstanceCreateEventHelper.java +++ /dev/null @@ -1,62 +0,0 @@ -package io.github.eggy03.papertrail.bot.listeners.auditlog.helper.stage; - -import io.github.eggy03.papertrail.bot.listeners.auditlog.helper.stage.utils.StageUtils; -import lombok.NonNull; -import lombok.experimental.UtilityClass; -import lombok.extern.slf4j.Slf4j; -import net.dv8tion.jda.api.EmbedBuilder; -import net.dv8tion.jda.api.audit.AuditLogEntry; -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 net.dv8tion.jda.api.utils.MarkdownUtil; - -import java.awt.Color; - -@UtilityClass -@Slf4j -public class StageInstanceCreateEventHelper { - - public static void format(@NonNull GuildAuditLogEntryCreateEvent event, @NonNull String channelIdToSendTo) { - - AuditLogEntry ale = event.getEntry(); - - User executor = ale.getJDA().getUserById(ale.getUserIdLong()); - String mentionableExecutor = (executor != null ? executor.getAsMention() : ale.getUserId()); - - EmbedBuilder eb = new EmbedBuilder(); - eb.setTitle("Audit Log Entry | Stage Instance Create Event"); - eb.setDescription(MarkdownUtil.quoteBlock("Stage Instance Created By: " + mentionableExecutor)); - eb.setColor(Color.GREEN); - - ale.getChanges().forEach((changeKey, changeValue) -> { - Object oldValue = changeValue.getOldValue(); - Object newValue = changeValue.getNewValue(); - - switch (changeKey) { - case "topic" -> eb.addField(MarkdownUtil.underline("Stage Topic"), "╰┈➤" + newValue, false); - - case "privacy_level" -> - eb.addField(MarkdownUtil.underline("Stage Privacy"), "╰┈➤" + StageUtils.resolveStagePrivacyLevel(newValue), false); - - default -> { - eb.addField("Unimplemented Change Key", changeKey, false); - log.info("Unimplemented Change Key: {}\nOLD_VALUE: {}\nNEW_VALUE: {}", changeKey, oldValue, newValue); - } - } - }); - - eb.setFooter("Audit Log Entry ID: " + ale.getId()); - eb.setTimestamp(ale.getTimeCreated()); - - if (!eb.isValidLength() || eb.isEmpty()) { - log.warn("Embed is empty or too long (current length: {}).", eb.length()); - return; - } - - TextChannel sendingChannel = event.getGuild().getTextChannelById(channelIdToSendTo); - if (sendingChannel != null && sendingChannel.canTalk()) { - sendingChannel.sendMessageEmbeds(eb.build()).queue(); - } - } -} diff --git a/src/main/java/io/github/eggy03/papertrail/bot/listeners/auditlog/helper/stage/StageInstanceDeleteEventHelper.java b/src/main/java/io/github/eggy03/papertrail/bot/listeners/auditlog/helper/stage/StageInstanceDeleteEventHelper.java deleted file mode 100644 index 399b67f6..00000000 --- a/src/main/java/io/github/eggy03/papertrail/bot/listeners/auditlog/helper/stage/StageInstanceDeleteEventHelper.java +++ /dev/null @@ -1,61 +0,0 @@ -package io.github.eggy03.papertrail.bot.listeners.auditlog.helper.stage; - -import io.github.eggy03.papertrail.bot.listeners.auditlog.helper.stage.utils.StageUtils; -import lombok.NonNull; -import lombok.experimental.UtilityClass; -import lombok.extern.slf4j.Slf4j; -import net.dv8tion.jda.api.EmbedBuilder; -import net.dv8tion.jda.api.audit.AuditLogEntry; -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 net.dv8tion.jda.api.utils.MarkdownUtil; - -import java.awt.Color; - -@UtilityClass -@Slf4j -public class StageInstanceDeleteEventHelper { - - public static void format(@NonNull GuildAuditLogEntryCreateEvent event, @NonNull String channelIdToSendTo) { - - AuditLogEntry ale = event.getEntry(); - - User executor = ale.getJDA().getUserById(ale.getUserIdLong()); - String mentionableExecutor = (executor != null ? executor.getAsMention() : ale.getUserId()); - - EmbedBuilder eb = new EmbedBuilder(); - eb.setTitle("Audit Log Entry | Stage Instance Delete Event"); - eb.setDescription(MarkdownUtil.quoteBlock("Stage Instance Deleted By: " + mentionableExecutor)); - eb.setColor(Color.RED); - - ale.getChanges().forEach((changeKey, changeValue) -> { - Object oldValue = changeValue.getOldValue(); - Object newValue = changeValue.getNewValue(); - - switch (changeKey) { - case "topic" -> eb.addField(MarkdownUtil.underline("Stage Topic"), "╰┈➤" + oldValue, false); - - case "privacy_level" -> - eb.addField(MarkdownUtil.underline("Stage Privacy"), "╰┈➤" + StageUtils.resolveStagePrivacyLevel(oldValue), false); - - default -> { - eb.addField("Unimplemented Change Key", changeKey, false); - log.info("Unimplemented Change Key: {}\nOLD_VALUE: {}\nNEW_VALUE: {}", changeKey, oldValue, newValue); - } - } - }); - eb.setFooter("Audit Log Entry ID: " + ale.getId()); - eb.setTimestamp(ale.getTimeCreated()); - - if (!eb.isValidLength() || eb.isEmpty()) { - log.warn("Embed is empty or too long (current length: {}).", eb.length()); - return; - } - - TextChannel sendingChannel = event.getGuild().getTextChannelById(channelIdToSendTo); - if (sendingChannel != null && sendingChannel.canTalk()) { - sendingChannel.sendMessageEmbeds(eb.build()).queue(); - } - } -} diff --git a/src/main/java/io/github/eggy03/papertrail/bot/listeners/auditlog/helper/stage/StageInstanceUpdateEventHelper.java b/src/main/java/io/github/eggy03/papertrail/bot/listeners/auditlog/helper/stage/StageInstanceUpdateEventHelper.java deleted file mode 100644 index 219c487f..00000000 --- a/src/main/java/io/github/eggy03/papertrail/bot/listeners/auditlog/helper/stage/StageInstanceUpdateEventHelper.java +++ /dev/null @@ -1,68 +0,0 @@ -package io.github.eggy03.papertrail.bot.listeners.auditlog.helper.stage; - -import io.github.eggy03.papertrail.bot.listeners.auditlog.helper.stage.utils.StageUtils; -import lombok.NonNull; -import lombok.experimental.UtilityClass; -import lombok.extern.slf4j.Slf4j; -import net.dv8tion.jda.api.EmbedBuilder; -import net.dv8tion.jda.api.audit.AuditLogEntry; -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 net.dv8tion.jda.api.utils.MarkdownUtil; - -import java.awt.Color; - -@UtilityClass -@Slf4j -public class StageInstanceUpdateEventHelper { - - public static void format(@NonNull GuildAuditLogEntryCreateEvent event, @NonNull String channelIdToSendTo) { - - AuditLogEntry ale = event.getEntry(); - - User executor = ale.getJDA().getUserById(ale.getUserIdLong()); - String mentionableExecutor = (executor != null ? executor.getAsMention() : ale.getUserId()); - - EmbedBuilder eb = new EmbedBuilder(); - eb.setTitle("Audit Log Entry | Stage Instance Update Event"); - eb.setDescription(MarkdownUtil.quoteBlock("Stage Instance Updated By: " + mentionableExecutor)); - eb.setColor(Color.YELLOW); - - ale.getChanges().forEach((changeKey, changeValue) -> { - Object oldValue = changeValue.getOldValue(); - Object newValue = changeValue.getNewValue(); - - switch (changeKey) { - case "topic" -> { - eb.addField(MarkdownUtil.underline("Old Stage Topic"), "╰┈➤" + oldValue, true); - eb.addField(MarkdownUtil.underline("New Stage Topic"), "╰┈➤" + newValue, true); - eb.addBlankField(true); - } - case "privacy_level" -> { - eb.addField(MarkdownUtil.underline("Old Stage Privacy"), "╰┈➤" + StageUtils.resolveStagePrivacyLevel(oldValue), true); - eb.addField(MarkdownUtil.underline("New Stage Privacy"), "╰┈➤" + StageUtils.resolveStagePrivacyLevel(newValue), true); - eb.addBlankField(true); - } - - default -> { - eb.addField("Unimplemented Change Key", changeKey, false); - log.info("Unimplemented Change Key: {}\nOLD_VALUE: {}\nNEW_VALUE: {}", changeKey, oldValue, newValue); - } - } - }); - - eb.setFooter("Audit Log Entry ID: " + ale.getId()); - eb.setTimestamp(ale.getTimeCreated()); - - if (!eb.isValidLength() || eb.isEmpty()) { - log.warn("Embed is empty or too long (current length: {}).", eb.length()); - return; - } - - TextChannel sendingChannel = event.getGuild().getTextChannelById(channelIdToSendTo); - if (sendingChannel != null && sendingChannel.canTalk()) { - sendingChannel.sendMessageEmbeds(eb.build()).queue(); - } - } -} diff --git a/src/main/java/io/github/eggy03/papertrail/bot/listeners/auditlog/helper/sticker/StickerCreateEventHelper.java b/src/main/java/io/github/eggy03/papertrail/bot/listeners/auditlog/helper/sticker/StickerCreateEventHelper.java deleted file mode 100644 index 6949e4b9..00000000 --- a/src/main/java/io/github/eggy03/papertrail/bot/listeners/auditlog/helper/sticker/StickerCreateEventHelper.java +++ /dev/null @@ -1,73 +0,0 @@ -package io.github.eggy03.papertrail.bot.listeners.auditlog.helper.sticker; - -import io.github.eggy03.papertrail.bot.listeners.auditlog.helper.sticker.utils.StickerUtils; -import lombok.NonNull; -import lombok.experimental.UtilityClass; -import lombok.extern.slf4j.Slf4j; -import net.dv8tion.jda.api.EmbedBuilder; -import net.dv8tion.jda.api.audit.AuditLogEntry; -import net.dv8tion.jda.api.entities.User; -import net.dv8tion.jda.api.entities.channel.concrete.TextChannel; -import net.dv8tion.jda.api.entities.sticker.GuildSticker; -import net.dv8tion.jda.api.events.guild.GuildAuditLogEntryCreateEvent; -import net.dv8tion.jda.api.utils.MarkdownUtil; - -import java.awt.Color; - -@UtilityClass -@Slf4j -public class StickerCreateEventHelper { - - public static void format(@NonNull GuildAuditLogEntryCreateEvent event, @NonNull String channelIdToSendTo) { - - AuditLogEntry ale = event.getEntry(); - - User executor = ale.getJDA().getUserById(ale.getUserIdLong()); - String mentionableExecutor = (executor != null ? executor.getAsMention() : ale.getUserId()); - - GuildSticker sticker = event.getGuild().getStickerById(ale.getTargetId()); - String mentionableSticker = (sticker != null ? sticker.getName() : ale.getTargetId()); - - EmbedBuilder eb = new EmbedBuilder(); - eb.setTitle("Audit Log Entry | Sticker Create Event"); - eb.setDescription(MarkdownUtil.quoteBlock("Sticker Created By: " + mentionableExecutor + "\nCreated Sticker: " + mentionableSticker)); - eb.setColor(Color.GREEN); - - ale.getChanges().forEach((changeKey, changeValue) -> { - Object oldValue = changeValue.getOldValue(); - Object newValue = changeValue.getNewValue(); - - switch (changeKey) { - case "format_type", "type", "asset", "available", "guild_id" -> { - // skip - } - case "id" -> { - eb.addField(MarkdownUtil.underline("Sticker ID"), "╰┈➤" + newValue, false); - eb.addField(MarkdownUtil.underline("Sticker Link"), "╰┈➤" + StickerUtils.resolveStickerUrl(event, newValue), false); - } - case "tags" -> - eb.addField(MarkdownUtil.underline("Related Emoji"), "╰┈➤" + StickerUtils.resolveRelatedEmoji(event, newValue), false); - case "description" -> eb.addField(MarkdownUtil.underline("Description"), "╰┈➤" + newValue, false); - case "name" -> eb.addField(MarkdownUtil.underline("Sticker Name"), "╰┈➤" + newValue, false); - - default -> { - eb.addField("Unimplemented Change Key", changeKey, false); - log.info("Unimplemented Change Key: {}\nOLD_VALUE: {}\nNEW_VALUE: {}", changeKey, oldValue, newValue); - } - } - }); - - eb.setFooter("Audit Log Entry ID: " + ale.getId()); - eb.setTimestamp(ale.getTimeCreated()); - - if (!eb.isValidLength() || eb.isEmpty()) { - log.warn("Embed is empty or too long (current length: {}).", eb.length()); - return; - } - - TextChannel sendingChannel = event.getGuild().getTextChannelById(channelIdToSendTo); - if (sendingChannel != null && sendingChannel.canTalk()) { - sendingChannel.sendMessageEmbeds(eb.build()).queue(); - } - } -} diff --git a/src/main/java/io/github/eggy03/papertrail/bot/listeners/auditlog/helper/sticker/StickerDeleteEventHelper.java b/src/main/java/io/github/eggy03/papertrail/bot/listeners/auditlog/helper/sticker/StickerDeleteEventHelper.java deleted file mode 100644 index aafcf0dc..00000000 --- a/src/main/java/io/github/eggy03/papertrail/bot/listeners/auditlog/helper/sticker/StickerDeleteEventHelper.java +++ /dev/null @@ -1,73 +0,0 @@ -package io.github.eggy03.papertrail.bot.listeners.auditlog.helper.sticker; - -import io.github.eggy03.papertrail.bot.listeners.auditlog.helper.sticker.utils.StickerUtils; -import lombok.NonNull; -import lombok.experimental.UtilityClass; -import lombok.extern.slf4j.Slf4j; -import net.dv8tion.jda.api.EmbedBuilder; -import net.dv8tion.jda.api.audit.AuditLogEntry; -import net.dv8tion.jda.api.entities.User; -import net.dv8tion.jda.api.entities.channel.concrete.TextChannel; -import net.dv8tion.jda.api.entities.sticker.GuildSticker; -import net.dv8tion.jda.api.events.guild.GuildAuditLogEntryCreateEvent; -import net.dv8tion.jda.api.utils.MarkdownUtil; - -import java.awt.Color; - -@UtilityClass -@Slf4j -public class StickerDeleteEventHelper { - - public static void format(@NonNull GuildAuditLogEntryCreateEvent event, @NonNull String channelIdToSendTo) { - - AuditLogEntry ale = event.getEntry(); - - User executor = ale.getJDA().getUserById(ale.getUserIdLong()); - String mentionableExecutor = (executor != null ? executor.getAsMention() : ale.getUserId()); - - GuildSticker sticker = event.getGuild().getStickerById(ale.getTargetId()); - String mentionableSticker = (sticker != null ? sticker.getName() : ale.getTargetId()); - - EmbedBuilder eb = new EmbedBuilder(); - eb.setTitle("Audit Log Entry | Sticker Delete Event"); - eb.setDescription(MarkdownUtil.quoteBlock("Sticker Deleted By: " + mentionableExecutor + "\nDeleted Sticker ID: " + mentionableSticker)); - eb.setColor(Color.RED); - - ale.getChanges().forEach((changeKey, changeValue) -> { - Object oldValue = changeValue.getOldValue(); - Object newValue = changeValue.getNewValue(); - - switch (changeKey) { - case "format_type", "type", "asset", "available", "guild_id" -> { - // skip - } - case "id" -> { - eb.addField(MarkdownUtil.underline("Sticker ID"), "╰┈➤" + oldValue, false); - eb.addField(MarkdownUtil.underline("Sticker Link"), "╰┈➤" + StickerUtils.resolveStickerUrl(event, oldValue), false); - } - case "tags" -> - eb.addField(MarkdownUtil.underline("Related Emoji"), "╰┈➤" + StickerUtils.resolveRelatedEmoji(event, oldValue), false); - case "description" -> eb.addField(MarkdownUtil.underline("Description"), "╰┈➤" + oldValue, false); - case "name" -> eb.addField(MarkdownUtil.underline("Sticker Name"), "╰┈➤" + oldValue, false); - - default -> { - eb.addField("Unimplemented Change Key", changeKey, false); - log.info("Unimplemented Change Key: {}\nOLD_VALUE: {}\nNEW_VALUE: {}", changeKey, oldValue, newValue); - } - } - }); - - eb.setFooter("Audit Log Entry ID: " + ale.getId()); - eb.setTimestamp(ale.getTimeCreated()); - - if (!eb.isValidLength() || eb.isEmpty()) { - log.warn("Embed is empty or too long (current length: {}).", eb.length()); - return; - } - - TextChannel sendingChannel = event.getGuild().getTextChannelById(channelIdToSendTo); - if (sendingChannel != null && sendingChannel.canTalk()) { - sendingChannel.sendMessageEmbeds(eb.build()).queue(); - } - } -} diff --git a/src/main/java/io/github/eggy03/papertrail/bot/listeners/auditlog/helper/sticker/StickerUpdateEventHelper.java b/src/main/java/io/github/eggy03/papertrail/bot/listeners/auditlog/helper/sticker/StickerUpdateEventHelper.java deleted file mode 100644 index 94ff9854..00000000 --- a/src/main/java/io/github/eggy03/papertrail/bot/listeners/auditlog/helper/sticker/StickerUpdateEventHelper.java +++ /dev/null @@ -1,79 +0,0 @@ -package io.github.eggy03.papertrail.bot.listeners.auditlog.helper.sticker; - -import io.github.eggy03.papertrail.bot.listeners.auditlog.helper.sticker.utils.StickerUtils; -import lombok.NonNull; -import lombok.experimental.UtilityClass; -import lombok.extern.slf4j.Slf4j; -import net.dv8tion.jda.api.EmbedBuilder; -import net.dv8tion.jda.api.audit.AuditLogEntry; -import net.dv8tion.jda.api.entities.User; -import net.dv8tion.jda.api.entities.channel.concrete.TextChannel; -import net.dv8tion.jda.api.entities.sticker.GuildSticker; -import net.dv8tion.jda.api.events.guild.GuildAuditLogEntryCreateEvent; -import net.dv8tion.jda.api.utils.MarkdownUtil; - -import java.awt.Color; - -@UtilityClass -@Slf4j -public class StickerUpdateEventHelper { - - public static void format(@NonNull GuildAuditLogEntryCreateEvent event, @NonNull String channelIdToSendTo) { - - AuditLogEntry ale = event.getEntry(); - - User executor = ale.getJDA().getUserById(ale.getUserIdLong()); - String mentionableExecutor = (executor != null ? executor.getAsMention() : ale.getUserId()); - - GuildSticker sticker = event.getGuild().getStickerById(ale.getTargetId()); - String mentionableSticker = (sticker != null ? sticker.getName() : ale.getTargetId()); - - EmbedBuilder eb = new EmbedBuilder(); - eb.setTitle("Audit Log Entry | Sticker Update Event"); - eb.setDescription(MarkdownUtil.quoteBlock("Sticker Updated By: " + mentionableExecutor + "\nUpdated Sticker: " + mentionableSticker)); - eb.setColor(Color.YELLOW); - - ale.getChanges().forEach((changeKey, changeValue) -> { - Object oldValue = changeValue.getOldValue(); - Object newValue = changeValue.getNewValue(); - - switch (changeKey) { - case "format_type", "type", "asset", "available", "guild_id", "id" -> { - // skip - } - case "tags" -> { - eb.addField(MarkdownUtil.underline("Old Related Emoji"), "╰┈➤" + StickerUtils.resolveRelatedEmoji(event, oldValue), true); - eb.addField(MarkdownUtil.underline("New Related Emoji"), "╰┈➤" + StickerUtils.resolveRelatedEmoji(event, newValue), true); - eb.addBlankField(true); - } - case "description" -> { - eb.addField(MarkdownUtil.underline("Old Description"), "╰┈➤" + oldValue, true); - eb.addField(MarkdownUtil.underline("New Description"), "╰┈➤" + newValue, true); - eb.addBlankField(true); - } - case "name" -> { - eb.addField(MarkdownUtil.underline("Old Sticker Name"), "╰┈➤" + oldValue, true); - eb.addField(MarkdownUtil.underline("New Sticker Name"), "╰┈➤" + newValue, true); - eb.addBlankField(true); - } - default -> { - eb.addField("Unimplemented Change Key", changeKey, false); - log.info("Unimplemented Change Key: {}\nOLD_VALUE: {}\nNEW_VALUE: {}", changeKey, oldValue, newValue); - } - } - }); - - eb.setFooter("Audit Log Entry ID: " + ale.getId()); - eb.setTimestamp(ale.getTimeCreated()); - - if (!eb.isValidLength() || eb.isEmpty()) { - log.warn("Embed is empty or too long (current length: {}).", eb.length()); - return; - } - - TextChannel sendingChannel = event.getGuild().getTextChannelById(channelIdToSendTo); - if (sendingChannel != null && sendingChannel.canTalk()) { - sendingChannel.sendMessageEmbeds(eb.build()).queue(); - } - } -} diff --git a/src/main/java/io/github/eggy03/papertrail/bot/listeners/auditlog/helper/thread/ThreadCreateEventHelper.java b/src/main/java/io/github/eggy03/papertrail/bot/listeners/auditlog/helper/thread/ThreadCreateEventHelper.java deleted file mode 100644 index 797b4b62..00000000 --- a/src/main/java/io/github/eggy03/papertrail/bot/listeners/auditlog/helper/thread/ThreadCreateEventHelper.java +++ /dev/null @@ -1,88 +0,0 @@ -package io.github.eggy03.papertrail.bot.listeners.auditlog.helper.thread; - -import io.github.eggy03.papertrail.bot.listeners.auditlog.helper.channel.utils.ChannelUtils; -import io.github.eggy03.papertrail.bot.listeners.auditlog.helper.thread.utils.ThreadUtils; -import io.github.eggy03.papertrail.bot.utils.BooleanUtils; -import io.github.eggy03.papertrail.bot.utils.DurationUtils; -import lombok.NonNull; -import lombok.experimental.UtilityClass; -import lombok.extern.slf4j.Slf4j; -import net.dv8tion.jda.api.EmbedBuilder; -import net.dv8tion.jda.api.audit.AuditLogEntry; -import net.dv8tion.jda.api.entities.User; -import net.dv8tion.jda.api.entities.channel.concrete.TextChannel; -import net.dv8tion.jda.api.entities.channel.concrete.ThreadChannel; -import net.dv8tion.jda.api.events.guild.GuildAuditLogEntryCreateEvent; -import net.dv8tion.jda.api.utils.MarkdownUtil; - -import java.awt.Color; - -@UtilityClass -@Slf4j -public class ThreadCreateEventHelper { - - public static void format(@NonNull GuildAuditLogEntryCreateEvent event, @NonNull String channelIdToSendTo) { - - AuditLogEntry ale = event.getEntry(); - - User executor = ale.getJDA().getUserById(ale.getUserIdLong()); - String mentionableExecutor = (executor != null ? executor.getAsMention() : ale.getUserId()); - - ThreadChannel targetThread = event.getGuild().getThreadChannelById(ale.getTargetId()); - String mentionableTargetThread = (targetThread != null ? targetThread.getAsMention() : ale.getTargetId()); - - EmbedBuilder eb = new EmbedBuilder(); - eb.setTitle("Audit Log Entry | Thread Create Event"); - eb.setDescription(MarkdownUtil.quoteBlock("Thread Created By: " + mentionableExecutor + "\nTarget Thread: " + mentionableTargetThread)); - eb.setColor(Color.GREEN); - - ale.getChanges().forEach((changeKey, changeValue) -> { - Object oldValue = changeValue.getOldValue(); - Object newValue = changeValue.getNewValue(); - - switch (changeKey) { - - case "locked" -> - eb.addField(MarkdownUtil.underline("Is Locked"), "╰┈➤" + BooleanUtils.formatToYesOrNo(newValue), false); - - case "auto_archive_duration" -> - eb.addField(MarkdownUtil.underline("Auto Archive Duration"), "╰┈➤" + ThreadUtils.resolveAutoArchiveDuration(newValue), false); - - case "rate_limit_per_user" -> - eb.addField(MarkdownUtil.underline("Slow Mode Limit"), "╰┈➤" + DurationUtils.formatSeconds(newValue), false); - - case "type" -> - eb.addField(MarkdownUtil.underline("Thread Type"), "╰┈➤" + ChannelUtils.resolveChannelType(newValue), false); - - case "archived" -> - eb.addField(MarkdownUtil.underline("Archived"), "╰┈➤" + BooleanUtils.formatToYesOrNo(newValue), false); - - case "flags" -> { - // skip - } - case "invitable" -> - eb.addField(MarkdownUtil.underline("Invitable"), "╰┈➤" + BooleanUtils.formatToYesOrNo(newValue), false); - - case "name" -> eb.addField(MarkdownUtil.underline("Thread Name"), "╰┈➤" + newValue, false); - - default -> { - eb.addField("Unimplemented Change Key", changeKey, false); - log.info("Unimplemented Change Key: {}\nOLD_VALUE: {}\nNEW_VALUE: {}", changeKey, oldValue, newValue); - } - } - }); - - eb.setFooter("Audit Log Entry ID: " + ale.getId()); - eb.setTimestamp(ale.getTimeCreated()); - - if (!eb.isValidLength() || eb.isEmpty()) { - log.warn("Embed is empty or too long (current length: {}).", eb.length()); - return; - } - - TextChannel sendingChannel = event.getGuild().getTextChannelById(channelIdToSendTo); - if (sendingChannel != null && sendingChannel.canTalk()) { - sendingChannel.sendMessageEmbeds(eb.build()).queue(); - } - } -} diff --git a/src/main/java/io/github/eggy03/papertrail/bot/listeners/auditlog/helper/thread/ThreadDeleteEventHelper.java b/src/main/java/io/github/eggy03/papertrail/bot/listeners/auditlog/helper/thread/ThreadDeleteEventHelper.java deleted file mode 100644 index 56bb1e68..00000000 --- a/src/main/java/io/github/eggy03/papertrail/bot/listeners/auditlog/helper/thread/ThreadDeleteEventHelper.java +++ /dev/null @@ -1,85 +0,0 @@ -package io.github.eggy03.papertrail.bot.listeners.auditlog.helper.thread; - -import io.github.eggy03.papertrail.bot.listeners.auditlog.helper.channel.utils.ChannelUtils; -import io.github.eggy03.papertrail.bot.listeners.auditlog.helper.thread.utils.ThreadUtils; -import io.github.eggy03.papertrail.bot.utils.BooleanUtils; -import io.github.eggy03.papertrail.bot.utils.DurationUtils; -import lombok.NonNull; -import lombok.experimental.UtilityClass; -import lombok.extern.slf4j.Slf4j; -import net.dv8tion.jda.api.EmbedBuilder; -import net.dv8tion.jda.api.audit.AuditLogEntry; -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 net.dv8tion.jda.api.utils.MarkdownUtil; - -import java.awt.Color; - -@UtilityClass -@Slf4j -public class ThreadDeleteEventHelper { - - public static void format(@NonNull GuildAuditLogEntryCreateEvent event, @NonNull String channelIdToSendTo) { - - AuditLogEntry ale = event.getEntry(); - - User executor = ale.getJDA().getUserById(ale.getUserIdLong()); - String mentionableExecutor = (executor != null ? executor.getAsMention() : ale.getUserId()); - - EmbedBuilder eb = new EmbedBuilder(); - eb.setTitle("Audit Log Entry | Thread Delete Event"); - eb.setDescription(MarkdownUtil.quoteBlock("Thread Deleted By: " + mentionableExecutor + "\nTarget Thread ID: " + ale.getTargetId())); - eb.setColor(Color.RED); - - ale.getChanges().forEach((changeKey, changeValue) -> { - Object oldValue = changeValue.getOldValue(); - Object newValue = changeValue.getNewValue(); - - switch (changeKey) { - - case "locked" -> - eb.addField(MarkdownUtil.underline("Was Locked"), "╰┈➤" + BooleanUtils.formatToYesOrNo(oldValue), false); - - case "auto_archive_duration" -> - eb.addField(MarkdownUtil.underline("Auto Archive Duration"), "╰┈➤" + ThreadUtils.resolveAutoArchiveDuration(oldValue), false); - - case "rate_limit_per_user" -> - eb.addField(MarkdownUtil.underline("Slow Mode Limit"), "╰┈➤" + DurationUtils.formatSeconds(oldValue), false); - - case "type" -> - eb.addField(MarkdownUtil.underline("Thread Type"), "╰┈➤" + ChannelUtils.resolveChannelType(oldValue), false); - - case "archived" -> - eb.addField(MarkdownUtil.underline("Archived"), "╰┈➤" + BooleanUtils.formatToYesOrNo(oldValue), false); - - case "flags" -> { - // skip - } - - case "invitable" -> - eb.addField(MarkdownUtil.underline("Invitable"), "╰┈➤" + BooleanUtils.formatToYesOrNo(oldValue), false); - - case "name" -> eb.addField(MarkdownUtil.underline("Thread Name"), "╰┈➤" + oldValue, false); - - default -> { - eb.addField("Unimplemented Change Key", changeKey, false); - log.info("Unimplemented Change Key: {}\nOLD_VALUE: {}\nNEW_VALUE: {}", changeKey, oldValue, newValue); - } - } - }); - - eb.setFooter("Audit Log Entry ID: " + ale.getId()); - eb.setTimestamp(ale.getTimeCreated()); - - if (!eb.isValidLength() || eb.isEmpty()) { - log.warn("Embed is empty or too long (current length: {}).", eb.length()); - return; - } - - TextChannel sendingChannel = event.getGuild().getTextChannelById(channelIdToSendTo); - if (sendingChannel != null && sendingChannel.canTalk()) { - sendingChannel.sendMessageEmbeds(eb.build()).queue(); - } - } -} diff --git a/src/main/java/io/github/eggy03/papertrail/bot/listeners/auditlog/helper/thread/ThreadUpdateEventHelper.java b/src/main/java/io/github/eggy03/papertrail/bot/listeners/auditlog/helper/thread/ThreadUpdateEventHelper.java deleted file mode 100644 index dec7d32e..00000000 --- a/src/main/java/io/github/eggy03/papertrail/bot/listeners/auditlog/helper/thread/ThreadUpdateEventHelper.java +++ /dev/null @@ -1,103 +0,0 @@ -package io.github.eggy03.papertrail.bot.listeners.auditlog.helper.thread; - -import io.github.eggy03.papertrail.bot.listeners.auditlog.helper.channel.utils.ChannelUtils; -import io.github.eggy03.papertrail.bot.listeners.auditlog.helper.thread.utils.ThreadUtils; -import io.github.eggy03.papertrail.bot.utils.BooleanUtils; -import io.github.eggy03.papertrail.bot.utils.DurationUtils; -import lombok.NonNull; -import lombok.experimental.UtilityClass; -import lombok.extern.slf4j.Slf4j; -import net.dv8tion.jda.api.EmbedBuilder; -import net.dv8tion.jda.api.audit.AuditLogEntry; -import net.dv8tion.jda.api.entities.User; -import net.dv8tion.jda.api.entities.channel.concrete.TextChannel; -import net.dv8tion.jda.api.entities.channel.concrete.ThreadChannel; -import net.dv8tion.jda.api.events.guild.GuildAuditLogEntryCreateEvent; -import net.dv8tion.jda.api.utils.MarkdownUtil; - -import java.awt.Color; - -@UtilityClass -@Slf4j -public class ThreadUpdateEventHelper { - - public static void format(@NonNull GuildAuditLogEntryCreateEvent event, @NonNull String channelIdToSendTo) { - - AuditLogEntry ale = event.getEntry(); - - User executor = ale.getJDA().getUserById(ale.getUserIdLong()); - String mentionableExecutor = (executor != null ? executor.getAsMention() : ale.getUserId()); - - ThreadChannel targetThread = event.getGuild().getThreadChannelById(ale.getTargetId()); - String mentionableTargetThread = (targetThread != null ? targetThread.getAsMention() : ale.getTargetId()); - - EmbedBuilder eb = new EmbedBuilder(); - eb.setTitle("Audit Log Entry | Thread Update Event"); - eb.setDescription(MarkdownUtil.quoteBlock("Thread Updated By: " + mentionableExecutor + "\nTarget Thread: " + mentionableTargetThread)); - eb.setColor(Color.YELLOW); - - - ale.getChanges().forEach((changeKey, changeValue) -> { - Object oldValue = changeValue.getOldValue(); - Object newValue = changeValue.getNewValue(); - - switch (changeKey) { - - case "locked" -> { - eb.addField(MarkdownUtil.underline("Was Locked"), "╰┈➤" + BooleanUtils.formatToYesOrNo(oldValue), true); - eb.addField(MarkdownUtil.underline("Is Locked"), "╰┈➤" + BooleanUtils.formatToYesOrNo(newValue), true); - eb.addBlankField(true); - } - case "auto_archive_duration" -> { - eb.addField(MarkdownUtil.underline("Old Auto Archive Duration"), "╰┈➤" + ThreadUtils.resolveAutoArchiveDuration(oldValue), true); - eb.addField(MarkdownUtil.underline("New Auto Archive Duration"), "╰┈➤" + ThreadUtils.resolveAutoArchiveDuration(newValue), true); - eb.addBlankField(true); - } - case "rate_limit_per_user" -> { - eb.addField(MarkdownUtil.underline("Old Slow Mode Limit"), "╰┈➤" + DurationUtils.formatSeconds(oldValue), true); - eb.addField(MarkdownUtil.underline("New Slow Mode Limit"), "╰┈➤" + DurationUtils.formatSeconds(newValue), true); - eb.addBlankField(true); - } - case "type" -> { - eb.addField(MarkdownUtil.underline("Old Thread Type"), "╰┈➤" + ChannelUtils.resolveChannelType(oldValue), true); - eb.addField(MarkdownUtil.underline("New Thread Type"), "╰┈➤" + ChannelUtils.resolveChannelType(newValue), true); - eb.addBlankField(true); - } - case "archived" -> { - eb.addField(MarkdownUtil.underline("Old Archive Status"), "╰┈➤" + BooleanUtils.formatToEnabledOrDisabled(oldValue), true); - eb.addField(MarkdownUtil.underline("New Archive Status"), "╰┈➤" + BooleanUtils.formatToEnabledOrDisabled(newValue), true); - eb.addBlankField(true); - } - case "flags" -> eb.addField(MarkdownUtil.underline("Flags"), "╰┈➤Thread flags were updated", false); - - case "invitable" -> { - eb.addField(MarkdownUtil.underline("Was Invitable"), "╰┈➤" + BooleanUtils.formatToYesOrNo(oldValue), true); - eb.addField(MarkdownUtil.underline("Is Invitable"), "╰┈➤" + BooleanUtils.formatToYesOrNo(newValue), true); - eb.addBlankField(true); - } - case "name" -> { - eb.addField(MarkdownUtil.underline("Old Thread Name"), "╰┈➤" + oldValue, true); - eb.addField(MarkdownUtil.underline("New Thread Name"), "╰┈➤" + newValue, true); - eb.addBlankField(true); - } - default -> { - eb.addField("Unimplemented Change Key", changeKey, false); - log.info("Unimplemented Change Key: {}\nOLD_VALUE: {}\nNEW_VALUE: {}", changeKey, oldValue, newValue); - } - } - }); - - eb.setFooter("Audit Log Entry ID: " + ale.getId()); - eb.setTimestamp(ale.getTimeCreated()); - - if (!eb.isValidLength() || eb.isEmpty()) { - log.warn("Embed is empty or too long (current length: {}).", eb.length()); - return; - } - - TextChannel sendingChannel = event.getGuild().getTextChannelById(channelIdToSendTo); - if (sendingChannel != null && sendingChannel.canTalk()) { - sendingChannel.sendMessageEmbeds(eb.build()).queue(); - } - } -} diff --git a/src/main/java/io/github/eggy03/papertrail/bot/listeners/auditlog/helper/webhook/WebhookCreateEventHelper.java b/src/main/java/io/github/eggy03/papertrail/bot/listeners/auditlog/helper/webhook/WebhookCreateEventHelper.java deleted file mode 100644 index 51d5b494..00000000 --- a/src/main/java/io/github/eggy03/papertrail/bot/listeners/auditlog/helper/webhook/WebhookCreateEventHelper.java +++ /dev/null @@ -1,68 +0,0 @@ -package io.github.eggy03.papertrail.bot.listeners.auditlog.helper.webhook; - -import io.github.eggy03.papertrail.bot.listeners.auditlog.helper.guild.utils.GuildUtils; -import io.github.eggy03.papertrail.bot.listeners.auditlog.helper.webhook.utils.WebhookUtils; -import lombok.NonNull; -import lombok.experimental.UtilityClass; -import lombok.extern.slf4j.Slf4j; -import net.dv8tion.jda.api.EmbedBuilder; -import net.dv8tion.jda.api.audit.AuditLogEntry; -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 net.dv8tion.jda.api.utils.MarkdownUtil; - -import java.awt.Color; - -@UtilityClass -@Slf4j -public class WebhookCreateEventHelper { - - public static void format(@NonNull GuildAuditLogEntryCreateEvent event, @NonNull String channelIdToSendTo) { - - AuditLogEntry ale = event.getEntry(); - - User executor = ale.getJDA().getUserById(ale.getUserIdLong()); - String mentionableExecutor = (executor != null ? executor.getAsMention() : ale.getUserId()); - - EmbedBuilder eb = new EmbedBuilder(); - eb.setTitle("Audit Log Entry | Webhook Create Event"); - eb.setDescription(MarkdownUtil.quoteBlock("Webhook Created By: " + mentionableExecutor)); - eb.setColor(Color.GREEN); - - ale.getChanges().forEach((changeKey, changeValue) -> { - Object oldValue = changeValue.getOldValue(); - Object newValue = changeValue.getNewValue(); - - switch (changeKey) { - - case "type" -> - eb.addField(MarkdownUtil.underline("Webhook Type"), "╰┈➤" + WebhookUtils.resolveWebhookEventType(newValue), false); - case "avatar_hash" -> { - // skip - } - case "channel_id" -> - eb.addField(MarkdownUtil.underline("Channel"), "╰┈➤" + GuildUtils.resolveMentionableChannel(newValue, event), false); - case "name" -> eb.addField(MarkdownUtil.underline("Webhook Name"), "╰┈➤" + newValue, false); - case "application_id" -> eb.addField(MarkdownUtil.underline("Application ID"), "╰┈➤" + newValue, false); - default -> { - eb.addField("Unimplemented Change Key", changeKey, false); - log.info("Unimplemented Change Key: {}\nOLD_VALUE: {}\nNEW_VALUE: {}", changeKey, oldValue, newValue); - } - } - }); - - eb.setFooter("Audit Log Entry ID: " + ale.getId()); - eb.setTimestamp(ale.getTimeCreated()); - - if (!eb.isValidLength() || eb.isEmpty()) { - log.warn("Embed is empty or too long (current length: {}).", eb.length()); - return; - } - - TextChannel sendingChannel = event.getGuild().getTextChannelById(channelIdToSendTo); - if (sendingChannel != null && sendingChannel.canTalk()) { - sendingChannel.sendMessageEmbeds(eb.build()).queue(); - } - } -} diff --git a/src/main/java/io/github/eggy03/papertrail/bot/listeners/auditlog/helper/webhook/WebhookRemoveEventHelper.java b/src/main/java/io/github/eggy03/papertrail/bot/listeners/auditlog/helper/webhook/WebhookRemoveEventHelper.java deleted file mode 100644 index 24fdeb6d..00000000 --- a/src/main/java/io/github/eggy03/papertrail/bot/listeners/auditlog/helper/webhook/WebhookRemoveEventHelper.java +++ /dev/null @@ -1,68 +0,0 @@ -package io.github.eggy03.papertrail.bot.listeners.auditlog.helper.webhook; - -import io.github.eggy03.papertrail.bot.listeners.auditlog.helper.guild.utils.GuildUtils; -import io.github.eggy03.papertrail.bot.listeners.auditlog.helper.webhook.utils.WebhookUtils; -import lombok.NonNull; -import lombok.experimental.UtilityClass; -import lombok.extern.slf4j.Slf4j; -import net.dv8tion.jda.api.EmbedBuilder; -import net.dv8tion.jda.api.audit.AuditLogEntry; -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 net.dv8tion.jda.api.utils.MarkdownUtil; - -import java.awt.Color; - -@UtilityClass -@Slf4j -public class WebhookRemoveEventHelper { - - public static void format(@NonNull GuildAuditLogEntryCreateEvent event, @NonNull String channelIdToSendTo) { - - AuditLogEntry ale = event.getEntry(); - - User executor = ale.getJDA().getUserById(ale.getUserIdLong()); - String mentionableExecutor = (executor != null ? executor.getAsMention() : ale.getUserId()); - - EmbedBuilder eb = new EmbedBuilder(); - eb.setTitle("Audit Log Entry | Webhook Remove Event"); - eb.setDescription(MarkdownUtil.quoteBlock("Webhook Removed By: " + mentionableExecutor)); - eb.setColor(Color.RED); - - ale.getChanges().forEach((changeKey, changeValue) -> { - Object oldValue = changeValue.getOldValue(); - Object newValue = changeValue.getNewValue(); - - switch (changeKey) { - - case "type" -> - eb.addField(MarkdownUtil.underline("Webhook Type"), "╰┈➤" + WebhookUtils.resolveWebhookEventType(oldValue), false); - case "avatar_hash" -> { - // skip - } - case "channel_id" -> - eb.addField(MarkdownUtil.underline("Channel"), "╰┈➤" + GuildUtils.resolveMentionableChannel(oldValue, event), false); - case "name" -> eb.addField(MarkdownUtil.underline("Webhook Name"), "╰┈➤" + oldValue, false); - case "application_id" -> eb.addField(MarkdownUtil.underline("Application ID"), "╰┈➤" + oldValue, false); - default -> { - eb.addField("Unimplemented Change Key", changeKey, false); - log.info("Unimplemented Change Key: {}\nOLD_VALUE: {}\nNEW_VALUE: {}", changeKey, oldValue, newValue); - } - } - }); - - eb.setFooter("Audit Log Entry ID: " + ale.getId()); - eb.setTimestamp(ale.getTimeCreated()); - - if (!eb.isValidLength() || eb.isEmpty()) { - log.warn("Embed is empty or too long (current length: {}).", eb.length()); - return; - } - - TextChannel sendingChannel = event.getGuild().getTextChannelById(channelIdToSendTo); - if (sendingChannel != null && sendingChannel.canTalk()) { - sendingChannel.sendMessageEmbeds(eb.build()).queue(); - } - } -} diff --git a/src/main/java/io/github/eggy03/papertrail/bot/listeners/auditlog/helper/webhook/WebhookUpdateEventHelper.java b/src/main/java/io/github/eggy03/papertrail/bot/listeners/auditlog/helper/webhook/WebhookUpdateEventHelper.java deleted file mode 100644 index 0f4b1bf2..00000000 --- a/src/main/java/io/github/eggy03/papertrail/bot/listeners/auditlog/helper/webhook/WebhookUpdateEventHelper.java +++ /dev/null @@ -1,83 +0,0 @@ -package io.github.eggy03.papertrail.bot.listeners.auditlog.helper.webhook; - -import io.github.eggy03.papertrail.bot.listeners.auditlog.helper.guild.utils.GuildUtils; -import io.github.eggy03.papertrail.bot.listeners.auditlog.helper.webhook.utils.WebhookUtils; -import lombok.NonNull; -import lombok.experimental.UtilityClass; -import lombok.extern.slf4j.Slf4j; -import net.dv8tion.jda.api.EmbedBuilder; -import net.dv8tion.jda.api.audit.AuditLogEntry; -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 net.dv8tion.jda.api.utils.MarkdownUtil; - -import java.awt.Color; - -@UtilityClass -@Slf4j -public class WebhookUpdateEventHelper { - - public static void format(@NonNull GuildAuditLogEntryCreateEvent event, @NonNull String channelIdToSendTo) { - - AuditLogEntry ale = event.getEntry(); - - User executor = ale.getJDA().getUserById(ale.getUserIdLong()); - String mentionableExecutor = (executor != null ? executor.getAsMention() : ale.getUserId()); - - EmbedBuilder eb = new EmbedBuilder(); - eb.setTitle("Audit Log Entry | Webhook Update Event"); - eb.setDescription(MarkdownUtil.quoteBlock("Webhook Updated By: " + mentionableExecutor)); - eb.setColor(Color.YELLOW); - - ale.getChanges().forEach((changeKey, changeValue) -> { - Object oldValue = changeValue.getOldValue(); - Object newValue = changeValue.getNewValue(); - - switch (changeKey) { - - case "type" -> { - eb.addField(MarkdownUtil.underline("Old Webhook Type"), "╰┈➤" + WebhookUtils.resolveWebhookEventType(oldValue), true); - eb.addField(MarkdownUtil.underline("New Webhook Type"), "╰┈➤" + WebhookUtils.resolveWebhookEventType(newValue), true); - eb.addBlankField(true); - } - case "avatar_hash" -> - eb.addField(MarkdownUtil.underline("Avatar"), "╰┈➤Avatar has been updated", false); - - case "channel_id" -> { - eb.addField(MarkdownUtil.underline("Old Channel"), "╰┈➤" + GuildUtils.resolveMentionableChannel(oldValue, event), true); - eb.addField(MarkdownUtil.underline("New Channel"), "╰┈➤" + GuildUtils.resolveMentionableChannel(newValue, event), true); - eb.addBlankField(true); - } - case "name" -> { - eb.addField(MarkdownUtil.underline("Old Webhook Name"), "╰┈➤" + oldValue, true); - eb.addField(MarkdownUtil.underline("New Webhook Name"), "╰┈➤" + newValue, true); - eb.addBlankField(true); - } - case "application_id" -> { - eb.addField(MarkdownUtil.underline("Old Application ID"), "╰┈➤" + oldValue, true); - eb.addField(MarkdownUtil.underline("New Application ID"), "╰┈➤" + newValue, true); - eb.addBlankField(true); - } - default -> { - eb.addField("Unimplemented Change Key", changeKey, false); - log.info("Unimplemented Change Key: {}\nOLD_VALUE: {}\nNEW_VALUE: {}", changeKey, oldValue, newValue); - } - } - }); - - eb.setFooter("Audit Log Entry ID: " + ale.getId()); - eb.setTimestamp(ale.getTimeCreated()); - - if (!eb.isValidLength() || eb.isEmpty()) { - log.warn("Embed is empty or too long (current length: {}).", eb.length()); - return; - } - - TextChannel sendingChannel = event.getGuild().getTextChannelById(channelIdToSendTo); - if (sendingChannel != null && sendingChannel.canTalk()) { - sendingChannel.sendMessageEmbeds(eb.build()).queue(); - } - } - -} diff --git a/src/main/java/io/github/eggy03/papertrail/bot/listeners/auditlogsupl/event/guild/GuildBoostEventListener.java b/src/main/java/io/github/eggy03/papertrail/bot/listeners/auditlogsupl/event/guild/GuildBoostEventListener.java deleted file mode 100644 index 3bb89988..00000000 --- a/src/main/java/io/github/eggy03/papertrail/bot/listeners/auditlogsupl/event/guild/GuildBoostEventListener.java +++ /dev/null @@ -1,60 +0,0 @@ -package io.github.eggy03.papertrail.bot.listeners.auditlogsupl.event.guild; - -import io.github.eggy03.papertrail.bot.listeners.auditlogsupl.helper.guild.GuildMemberUpdateBoostTimeEventHelper; -import io.github.eggy03.papertrail.bot.listeners.auditlogsupl.helper.guild.GuildUpdateBoostCountEventHelper; -import io.github.eggy03.papertrail.bot.listeners.auditlogsupl.helper.guild.GuildUpdateBoostTierEventHelper; -import io.github.eggy03.papertrail.sdk.client.AuditLogRegistrationClient; -import io.github.eggy03.papertrail.sdk.entity.AuditLogRegistrationEntity; -import lombok.NonNull; -import lombok.RequiredArgsConstructor; -import net.dv8tion.jda.api.events.guild.member.update.GuildMemberUpdateBoostTimeEvent; -import net.dv8tion.jda.api.events.guild.update.GuildUpdateBoostCountEvent; -import net.dv8tion.jda.api.events.guild.update.GuildUpdateBoostTierEvent; -import net.dv8tion.jda.api.hooks.ListenerAdapter; - -import java.util.Optional; -import java.util.concurrent.Executor; - -// Experimental -@RequiredArgsConstructor -public class GuildBoostEventListener extends ListenerAdapter { - - @NonNull - private final AuditLogRegistrationClient client; - - @NonNull - private final Executor vThreadPool; - - @Override - public void onGuildUpdateBoostTier(@NonNull GuildUpdateBoostTierEvent event) { - - vThreadPool.execute(() -> { - Optional response = client.getRegisteredGuild(event.getGuild().getId()); - response.ifPresent(success -> - GuildUpdateBoostTierEventHelper.format(event, success.getChannelId()) - ); - }); - } - - @Override - public void onGuildUpdateBoostCount(@NonNull GuildUpdateBoostCountEvent event) { - - vThreadPool.execute(() -> { - Optional response = client.getRegisteredGuild(event.getGuild().getId()); - response.ifPresent(success -> - GuildUpdateBoostCountEventHelper.format(event, success.getChannelId()) - ); - }); - } - - @Override - public void onGuildMemberUpdateBoostTime(@NonNull GuildMemberUpdateBoostTimeEvent event) { - - vThreadPool.execute(() -> { - Optional response = client.getRegisteredGuild(event.getGuild().getId()); - response.ifPresent(success -> - GuildMemberUpdateBoostTimeEventHelper.format(event, success.getChannelId()) - ); - }); - } -} diff --git a/src/main/java/io/github/eggy03/papertrail/bot/listeners/auditlogsupl/event/guild/GuildMemberJoinAndLeaveEventListener.java b/src/main/java/io/github/eggy03/papertrail/bot/listeners/auditlogsupl/event/guild/GuildMemberJoinAndLeaveEventListener.java deleted file mode 100644 index 22570c67..00000000 --- a/src/main/java/io/github/eggy03/papertrail/bot/listeners/auditlogsupl/event/guild/GuildMemberJoinAndLeaveEventListener.java +++ /dev/null @@ -1,51 +0,0 @@ -package io.github.eggy03.papertrail.bot.listeners.auditlogsupl.event.guild; - -import io.github.eggy03.papertrail.bot.listeners.auditlogsupl.helper.guild.GuildMemberJoinEventHelper; -import io.github.eggy03.papertrail.bot.listeners.auditlogsupl.helper.guild.GuildMemberRemoveEventHelper; -import io.github.eggy03.papertrail.sdk.client.AuditLogRegistrationClient; -import io.github.eggy03.papertrail.sdk.entity.AuditLogRegistrationEntity; -import lombok.NonNull; -import lombok.RequiredArgsConstructor; -import net.dv8tion.jda.api.events.guild.member.GuildMemberJoinEvent; -import net.dv8tion.jda.api.events.guild.member.GuildMemberRemoveEvent; -import net.dv8tion.jda.api.hooks.ListenerAdapter; - -import java.util.Optional; -import java.util.concurrent.Executor; - -// this event is not properly logged in the audit logs, hence the usage of JDA's listener is preferred -// this event is logged in the same channel where the audit log events are logged -@RequiredArgsConstructor -public class GuildMemberJoinAndLeaveEventListener extends ListenerAdapter { - - @NonNull - private final AuditLogRegistrationClient client; - - @NonNull - private final Executor vThreadPool; - - @Override - public void onGuildMemberJoin(@NonNull GuildMemberJoinEvent event) { - - vThreadPool.execute(() -> { - // Call the API and see if the event came from a registered Guild - Optional response = client.getRegisteredGuild(event.getGuild().getId()); - response.ifPresent(success -> - GuildMemberJoinEventHelper.format(event, success.getChannelId()) - ); - }); - } - - @Override - public void onGuildMemberRemove(@NonNull GuildMemberRemoveEvent event) { - - vThreadPool.execute(() -> { - // Call the API and see if the event came from a registered Guild - Optional response = client.getRegisteredGuild(event.getGuild().getId()); - response.ifPresent(success -> - GuildMemberRemoveEventHelper.format(event, success.getChannelId()) - ); - }); - } - -} diff --git a/src/main/java/io/github/eggy03/papertrail/bot/listeners/auditlogsupl/event/guild/GuildPollEventListener.java b/src/main/java/io/github/eggy03/papertrail/bot/listeners/auditlogsupl/event/guild/GuildPollEventListener.java deleted file mode 100644 index 2889419e..00000000 --- a/src/main/java/io/github/eggy03/papertrail/bot/listeners/auditlogsupl/event/guild/GuildPollEventListener.java +++ /dev/null @@ -1,44 +0,0 @@ -package io.github.eggy03.papertrail.bot.listeners.auditlogsupl.event.guild; - -import io.github.eggy03.papertrail.bot.listeners.auditlogsupl.helper.guild.GuildPollEventHelper; -import io.github.eggy03.papertrail.sdk.client.AuditLogRegistrationClient; -import io.github.eggy03.papertrail.sdk.entity.AuditLogRegistrationEntity; -import lombok.NonNull; -import lombok.RequiredArgsConstructor; -import net.dv8tion.jda.api.entities.messages.MessagePoll; -import net.dv8tion.jda.api.events.message.MessageReceivedEvent; -import net.dv8tion.jda.api.hooks.ListenerAdapter; - -import java.util.Optional; -import java.util.concurrent.Executor; - -// guild poll events are mapped to audit log table -@RequiredArgsConstructor -public class GuildPollEventListener extends ListenerAdapter { - - @NonNull - private final AuditLogRegistrationClient client; - - @NonNull - private final Executor vThreadPool; - - @Override - public void onMessageReceived(@NonNull MessageReceivedEvent event) { - - if (!event.isFromGuild()) - return; - - // check if message has a poll - MessagePoll messagePoll = event.getMessage().getPoll(); - if (messagePoll == null) - return; - - vThreadPool.execute(() -> { - // Call the API and see if the event came from a registered Guild - Optional response = client.getRegisteredGuild(event.getGuild().getId()); - response.ifPresent(success -> - GuildPollEventHelper.format(event, messagePoll, success.getChannelId()) - ); - }); - } -} diff --git a/src/main/java/io/github/eggy03/papertrail/bot/listeners/auditlogsupl/event/guild/GuildVoiceEventListener.java b/src/main/java/io/github/eggy03/papertrail/bot/listeners/auditlogsupl/event/guild/GuildVoiceEventListener.java deleted file mode 100644 index e3910f60..00000000 --- a/src/main/java/io/github/eggy03/papertrail/bot/listeners/auditlogsupl/event/guild/GuildVoiceEventListener.java +++ /dev/null @@ -1,36 +0,0 @@ -package io.github.eggy03.papertrail.bot.listeners.auditlogsupl.event.guild; - -import io.github.eggy03.papertrail.bot.listeners.auditlogsupl.helper.guild.GuildVoiceEventHelper; -import io.github.eggy03.papertrail.sdk.client.AuditLogRegistrationClient; -import io.github.eggy03.papertrail.sdk.entity.AuditLogRegistrationEntity; -import lombok.NonNull; -import lombok.RequiredArgsConstructor; -import net.dv8tion.jda.api.events.guild.voice.GuildVoiceUpdateEvent; -import net.dv8tion.jda.api.hooks.ListenerAdapter; - -import java.util.Optional; -import java.util.concurrent.Executor; - -// this event is not properly logged in the audit logs, hence the usage of JDA's listener is preferred -// this event is logged in the same channel where the audit log events are logged -@RequiredArgsConstructor -public class GuildVoiceEventListener extends ListenerAdapter { - - @NonNull - private final AuditLogRegistrationClient client; - - @NonNull - private final Executor vThreadPool; - - @Override - public void onGuildVoiceUpdate(@NonNull GuildVoiceUpdateEvent event) { - - vThreadPool.execute(() -> { - // Call the API and see if the event came from a registered Guild - Optional response = client.getRegisteredGuild(event.getGuild().getId()); - response.ifPresent(success -> - GuildVoiceEventHelper.format(event, success.getChannelId()) - ); - }); - } -} \ No newline at end of file diff --git a/src/main/java/io/github/eggy03/papertrail/bot/listeners/auditlogsupl/helper/guild/GuildMemberJoinEventHelper.java b/src/main/java/io/github/eggy03/papertrail/bot/listeners/auditlogsupl/helper/guild/GuildMemberJoinEventHelper.java deleted file mode 100644 index 48f35cef..00000000 --- a/src/main/java/io/github/eggy03/papertrail/bot/listeners/auditlogsupl/helper/guild/GuildMemberJoinEventHelper.java +++ /dev/null @@ -1,52 +0,0 @@ -package io.github.eggy03.papertrail.bot.listeners.auditlogsupl.helper.guild; - -import io.github.eggy03.papertrail.bot.utils.BooleanUtils; -import io.github.eggy03.papertrail.bot.utils.DurationUtils; -import lombok.NonNull; -import lombok.experimental.UtilityClass; -import lombok.extern.slf4j.Slf4j; -import net.dv8tion.jda.api.EmbedBuilder; -import net.dv8tion.jda.api.entities.Guild; -import net.dv8tion.jda.api.entities.User; -import net.dv8tion.jda.api.entities.channel.concrete.TextChannel; -import net.dv8tion.jda.api.events.guild.member.GuildMemberJoinEvent; -import net.dv8tion.jda.api.utils.MarkdownUtil; - -import java.awt.Color; -import java.time.Instant; - -@UtilityClass -@Slf4j -public class GuildMemberJoinEventHelper { - - public static void format(@NonNull GuildMemberJoinEvent event, @NonNull String channelIdToSendTo) { - - Guild guild = event.getGuild(); - User user = event.getUser(); - - EmbedBuilder eb = new EmbedBuilder(); - eb.setTitle("Audit Log Entry | Member Join Event"); - eb.setDescription(MarkdownUtil.quoteBlock("Member Joined: " + user.getName() + "\nGuild: " + guild.getName())); - eb.setThumbnail(user.getEffectiveAvatarUrl()); - eb.setColor(Color.GREEN); - - eb.addField(MarkdownUtil.underline("Member Name"), "╰┈➤" + user.getName(), false); - eb.addField(MarkdownUtil.underline("Member Mention"), "╰┈➤" + user.getAsMention(), false); - eb.addField(MarkdownUtil.underline("Member ID"), "╰┈➤" + user.getId(), false); - eb.addField(MarkdownUtil.underline("Account Created"), "╰┈➤" + DurationUtils.isoToLocalTimeCounter(user.getTimeCreated()), false); - eb.addField(MarkdownUtil.underline("Bot Account"), "╰┈➤" + BooleanUtils.formatToYesOrNo(user.isBot()), false); - - eb.setFooter(event.getGuild().getName()); - eb.setTimestamp(Instant.now()); - - if (!eb.isValidLength() || eb.isEmpty()) { - log.warn("Embed is empty or too long (current length: {}).", eb.length()); - return; - } - - TextChannel sendingChannel = event.getGuild().getTextChannelById(channelIdToSendTo); - if (sendingChannel != null && sendingChannel.canTalk()) { - sendingChannel.sendMessageEmbeds(eb.build()).queue(); - } - } -} diff --git a/src/main/java/io/github/eggy03/papertrail/bot/listeners/auditlogsupl/helper/guild/GuildMemberRemoveEventHelper.java b/src/main/java/io/github/eggy03/papertrail/bot/listeners/auditlogsupl/helper/guild/GuildMemberRemoveEventHelper.java deleted file mode 100644 index 30dfd87d..00000000 --- a/src/main/java/io/github/eggy03/papertrail/bot/listeners/auditlogsupl/helper/guild/GuildMemberRemoveEventHelper.java +++ /dev/null @@ -1,71 +0,0 @@ -package io.github.eggy03.papertrail.bot.listeners.auditlogsupl.helper.guild; - -import io.github.eggy03.papertrail.bot.utils.DurationUtils; -import lombok.NonNull; -import lombok.experimental.UtilityClass; -import lombok.extern.slf4j.Slf4j; -import net.dv8tion.jda.api.EmbedBuilder; -import net.dv8tion.jda.api.entities.Guild; -import net.dv8tion.jda.api.entities.Member; -import net.dv8tion.jda.api.entities.User; -import net.dv8tion.jda.api.entities.channel.concrete.TextChannel; -import net.dv8tion.jda.api.events.guild.member.GuildMemberRemoveEvent; -import net.dv8tion.jda.api.utils.MarkdownUtil; -import org.jetbrains.annotations.NotNull; - -import java.awt.Color; -import java.time.Instant; - -@UtilityClass -@Slf4j -public class GuildMemberRemoveEventHelper { - - public static void format(@NonNull GuildMemberRemoveEvent event, @NonNull String channelIdToSendTo) { - - Guild guild = event.getGuild(); - User user = event.getUser(); - - EmbedBuilder eb = new EmbedBuilder(); - eb.setTitle("Audit Log Entry | Member Leave Event"); - eb.setDescription(MarkdownUtil.quoteBlock("Member Left: " + user.getName() + "\nGuild: " + guild.getName())); - eb.setThumbnail(user.getEffectiveAvatarUrl()); - eb.setColor(Color.RED); - - eb.addField(MarkdownUtil.underline("Member Name"), "╰┈➤" + user.getName(), false); - eb.addField(MarkdownUtil.underline("Member ID"), "╰┈➤" + user.getId(), false); - eb.addField(MarkdownUtil.underline("Member Account Created"), "╰┈➤" + DurationUtils.isoToLocalTimeCounter(user.getTimeCreated()), false); - eb.addField(MarkdownUtil.underline("Member Joined The Server On"), "╰┈➤" + getMemberJoinDate(event), false); - eb.addField(MarkdownUtil.underline("Member Left The Server On"), "╰┈➤" + getMemberLeaveDate(), false); - - eb.setFooter(event.getGuild().getName()); - eb.setTimestamp(Instant.now()); - - if (!eb.isValidLength() || eb.isEmpty()) { - log.warn("Embed is empty or too long (current length: {}).", eb.length()); - return; - } - - TextChannel sendingChannel = event.getGuild().getTextChannelById(channelIdToSendTo); - if (sendingChannel != null && sendingChannel.canTalk()) { - sendingChannel.sendMessageEmbeds(eb.build()).queue(); - } - } - - @NotNull - private static String getMemberJoinDate (@NonNull GuildMemberRemoveEvent event) { - - Member member = event.getMember(); - if(member==null) - return "Member not cached"; - - if (member.hasTimeJoined()) - return ""; - - return "Unavailable"; - } - - @NotNull - private static String getMemberLeaveDate () { - return ""; - } -} diff --git a/src/main/java/io/github/eggy03/papertrail/bot/listeners/auditlogsupl/helper/guild/GuildMemberUpdateBoostTimeEventHelper.java b/src/main/java/io/github/eggy03/papertrail/bot/listeners/auditlogsupl/helper/guild/GuildMemberUpdateBoostTimeEventHelper.java deleted file mode 100644 index a2d63809..00000000 --- a/src/main/java/io/github/eggy03/papertrail/bot/listeners/auditlogsupl/helper/guild/GuildMemberUpdateBoostTimeEventHelper.java +++ /dev/null @@ -1,54 +0,0 @@ -package io.github.eggy03.papertrail.bot.listeners.auditlogsupl.helper.guild; - -import lombok.NonNull; -import lombok.experimental.UtilityClass; -import lombok.extern.slf4j.Slf4j; -import net.dv8tion.jda.api.EmbedBuilder; -import net.dv8tion.jda.api.entities.Guild; -import net.dv8tion.jda.api.entities.Member; -import net.dv8tion.jda.api.entities.channel.concrete.TextChannel; -import net.dv8tion.jda.api.events.guild.member.update.GuildMemberUpdateBoostTimeEvent; -import net.dv8tion.jda.api.utils.MarkdownUtil; - -import java.awt.Color; -import java.time.Instant; -import java.time.OffsetDateTime; - -@UtilityClass -@Slf4j -public class GuildMemberUpdateBoostTimeEventHelper { - - public static void format(@NonNull GuildMemberUpdateBoostTimeEvent event, @NonNull String channelIdToSendTo) { - Member member = event.getMember(); - Guild guild = event.getGuild(); - - String mentionableMember = member.getAsMention(); - - OffsetDateTime newBoostTime = event.getNewTimeBoosted(); // Will be null if the member stopped boosting - - EmbedBuilder eb = new EmbedBuilder(); - eb.setTitle("Audit Log Entry | Server Boost Event"); - eb.setThumbnail(guild.getIconUrl()); - - if (newBoostTime != null) { - eb.setDescription(MarkdownUtil.quoteBlock("Booster Gained: " + mentionableMember + "\nTarget Server: " + guild.getName())); - eb.setColor(Color.PINK); - } else { - eb.setDescription(MarkdownUtil.quoteBlock("Booster Lost: " + mentionableMember + "\nTarget Server: " + guild.getName())); - eb.setColor(Color.GRAY); - } - - eb.setFooter(guild.getName()); - eb.setTimestamp(Instant.now()); - - if (!eb.isValidLength() || eb.isEmpty()) { - log.warn("Embed is empty or too long (current length: {}).", eb.length()); - return; - } - - TextChannel sendingChannel = event.getGuild().getTextChannelById(channelIdToSendTo); - if (sendingChannel != null && sendingChannel.canTalk()) { - sendingChannel.sendMessageEmbeds(eb.build()).queue(); - } - } -} diff --git a/src/main/java/io/github/eggy03/papertrail/bot/listeners/auditlogsupl/helper/guild/GuildUpdateBoostCountEventHelper.java b/src/main/java/io/github/eggy03/papertrail/bot/listeners/auditlogsupl/helper/guild/GuildUpdateBoostCountEventHelper.java deleted file mode 100644 index b3ad6b28..00000000 --- a/src/main/java/io/github/eggy03/papertrail/bot/listeners/auditlogsupl/helper/guild/GuildUpdateBoostCountEventHelper.java +++ /dev/null @@ -1,44 +0,0 @@ -package io.github.eggy03.papertrail.bot.listeners.auditlogsupl.helper.guild; - -import lombok.NonNull; -import lombok.experimental.UtilityClass; -import lombok.extern.slf4j.Slf4j; -import net.dv8tion.jda.api.EmbedBuilder; -import net.dv8tion.jda.api.entities.Guild; -import net.dv8tion.jda.api.entities.channel.concrete.TextChannel; -import net.dv8tion.jda.api.events.guild.update.GuildUpdateBoostCountEvent; -import net.dv8tion.jda.api.utils.MarkdownUtil; - -import java.awt.Color; -import java.time.Instant; - -@UtilityClass -@Slf4j -public class GuildUpdateBoostCountEventHelper { - - public static void format(@NonNull GuildUpdateBoostCountEvent event, @NonNull String channelIdToSendTo) { - Guild guild = event.getGuild(); - - EmbedBuilder eb = new EmbedBuilder(); - eb.setTitle("Audit Log Entry | Server Boost Event"); - eb.setDescription(MarkdownUtil.quoteBlock("Guild Boost Count Updated\nTarget Guild: " + guild.getName())); - eb.setThumbnail(guild.getIconUrl()); - eb.setColor(Color.YELLOW); - - eb.addField(MarkdownUtil.underline("Old Boost Count"), "╰┈➤" + event.getOldBoostCount(), false); - eb.addField(MarkdownUtil.underline("New Boost Count"), "╰┈➤" + event.getNewBoostCount(), false); - - eb.setFooter(guild.getName()); - eb.setTimestamp(Instant.now()); - - if (!eb.isValidLength() || eb.isEmpty()) { - log.warn("Embed is empty or too long (current length: {}).", eb.length()); - return; - } - - TextChannel sendingChannel = event.getGuild().getTextChannelById(channelIdToSendTo); - if (sendingChannel != null && sendingChannel.canTalk()) { - sendingChannel.sendMessageEmbeds(eb.build()).queue(); - } - } -} diff --git a/src/main/java/io/github/eggy03/papertrail/bot/listeners/auditlogsupl/helper/guild/GuildUpdateBoostTierEventHelper.java b/src/main/java/io/github/eggy03/papertrail/bot/listeners/auditlogsupl/helper/guild/GuildUpdateBoostTierEventHelper.java deleted file mode 100644 index 6a7301bf..00000000 --- a/src/main/java/io/github/eggy03/papertrail/bot/listeners/auditlogsupl/helper/guild/GuildUpdateBoostTierEventHelper.java +++ /dev/null @@ -1,58 +0,0 @@ -package io.github.eggy03.papertrail.bot.listeners.auditlogsupl.helper.guild; - -import lombok.NonNull; -import lombok.experimental.UtilityClass; -import lombok.extern.slf4j.Slf4j; -import net.dv8tion.jda.api.EmbedBuilder; -import net.dv8tion.jda.api.entities.Guild; -import net.dv8tion.jda.api.entities.channel.concrete.TextChannel; -import net.dv8tion.jda.api.events.guild.update.GuildUpdateBoostTierEvent; -import net.dv8tion.jda.api.utils.MarkdownUtil; - -import java.awt.Color; -import java.time.Instant; - -@UtilityClass -@Slf4j -public class GuildUpdateBoostTierEventHelper { - - public static void format(@NonNull GuildUpdateBoostTierEvent event, @NonNull String channelIdToSendTo) { - - Guild guild = event.getGuild(); - - EmbedBuilder eb = new EmbedBuilder(); - eb.setTitle("Audit Log Entry | Server Boost Tier Update"); - eb.setDescription(MarkdownUtil.quoteBlock("Guild Boost Tier Updated\nTarget Guild: " + guild.getName())); - eb.setThumbnail(guild.getIconUrl()); - eb.setColor(Color.YELLOW); - - Guild.BoostTier oldBoostTier = event.getOldBoostTier(); - Guild.BoostTier newBoostTier = event.getNewBoostTier(); - - String oldTier = "**Tier:** " + oldBoostTier.name() + "\n" + - "**Max Emojis:** " + oldBoostTier.getMaxEmojis() + "\n" + - "**Max File Size:** " + oldBoostTier.getMaxFileSize() + "\n" + - "**Max Bitrate:** " + oldBoostTier.getMaxBitrate(); - - String newTier = "**Tier:** " + newBoostTier.name() + "\n" + - "**Max Emojis:** " + newBoostTier.getMaxEmojis() + "\n" + - "**Max File Size:** " + newBoostTier.getMaxFileSize() + "\n" + - "**Max Bitrate:** " + newBoostTier.getMaxBitrate(); - - eb.addField(MarkdownUtil.underline("Old Boost Tier Information"), oldTier, false); - eb.addField(MarkdownUtil.underline("New Boost Tier Information"), newTier, false); - - eb.setFooter(guild.getName()); - eb.setTimestamp(Instant.now()); - - if (!eb.isValidLength() || eb.isEmpty()) { - log.warn("Embed is empty or too long (current length: {}).", eb.length()); - return; - } - - TextChannel sendingChannel = event.getGuild().getTextChannelById(channelIdToSendTo); - if (sendingChannel != null && sendingChannel.canTalk()) { - sendingChannel.sendMessageEmbeds(eb.build()).queue(); - } - } -} diff --git a/src/main/java/io/github/eggy03/papertrail/bot/listeners/auditlogsupl/package-info.java b/src/main/java/io/github/eggy03/papertrail/bot/listeners/auditlogsupl/package-info.java deleted file mode 100644 index 32c3b435..00000000 --- a/src/main/java/io/github/eggy03/papertrail/bot/listeners/auditlogsupl/package-info.java +++ /dev/null @@ -1,12 +0,0 @@ -/** - * Contains supplementary audit-style event listeners for actions not covered - * by Discord's native audit log system. - * - *

These listeners observe events that are audit-relevant (such as guild, - * thread, or other structural changes) but cannot be derived from - * {@link net.dv8tion.jda.api.events.guild.GuildAuditLogEntryCreateEvent} entries.

- * - *

All events in this package log to the same destination and follow the same - * formatting and conventions as standard audit log listeners and hence, no additional setup is required.

- */ -package io.github.eggy03.papertrail.bot.listeners.auditlogsupl; \ No newline at end of file diff --git a/src/main/java/io/github/eggy03/papertrail/bot/listeners/command/AuditLogSetupCommandListener.java b/src/main/java/io/github/eggy03/papertrail/bot/listeners/command/AuditLogSetupCommandListener.java index 36f3410f..856b932a 100644 --- a/src/main/java/io/github/eggy03/papertrail/bot/listeners/command/AuditLogSetupCommandListener.java +++ b/src/main/java/io/github/eggy03/papertrail/bot/listeners/command/AuditLogSetupCommandListener.java @@ -1,26 +1,23 @@ package io.github.eggy03.papertrail.bot.listeners.command; -import io.github.eggy03.papertrail.sdk.client.AuditLogRegistrationClient; -import io.github.eggy03.papertrail.sdk.entity.AuditLogRegistrationEntity; +import io.github.eggy03.papertrail.bot.handlers.command.AuditLogSetupCommandHandler; +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.inject.Inject; import lombok.NonNull; -import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; -import net.dv8tion.jda.api.EmbedBuilder; -import net.dv8tion.jda.api.entities.Guild; -import net.dv8tion.jda.api.entities.channel.middleman.GuildChannel; import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent; import net.dv8tion.jda.api.hooks.ListenerAdapter; -import net.dv8tion.jda.api.utils.MarkdownUtil; - -import java.awt.Color; -import java.util.Optional; +@ApplicationScoped @Slf4j -@RequiredArgsConstructor -public class AuditLogSetupCommandListener extends ListenerAdapter { +public final class AuditLogSetupCommandListener extends ListenerAdapter { + + private final @NonNull AuditLogSetupCommandHandler handler; - @NonNull - private final AuditLogRegistrationClient client; + @Inject + public AuditLogSetupCommandListener(@NonNull AuditLogSetupCommandHandler handler) { + this.handler = handler; + } @Override public void onSlashCommandInteraction(@NonNull SlashCommandInteractionEvent event) { @@ -30,103 +27,13 @@ public void onSlashCommandInteraction(@NonNull SlashCommandInteractionEvent even } switch (event.getSubcommandName()) { - case "set" -> setAuditLogging(event); - case "view" -> retrieveAuditLoggingChannel(event); - case "remove" -> unsetAuditLogging(event); + case "set" -> handler.setAuditLogging(event); + case "view" -> handler.viewAuditLoggingChannel(event); + case "remove" -> handler.unsetAuditLogging(event); default -> { // do nothing } } } - private void setAuditLogging(@NonNull SlashCommandInteractionEvent event) { - - Guild callerGuild = event.getGuild(); - GuildChannel callerChannel = event.getChannel().asTextChannel(); - if (callerGuild == null) { - log.warn("An audit log set command may have been called outside of a guild. This should not happen."); - return; - } - - // acknowledge this interaction before calling the API - event.deferReply().queue(); - - // Call the API to register the guild and the channel - boolean success = client.registerGuild(callerGuild.getId(), callerChannel.getId()); - - EmbedBuilder eb = new EmbedBuilder(); - eb.setTitle("Audit Log Registration Process"); - - if (success) { - eb.setColor(Color.GREEN); - eb.addField(MarkdownUtil.underline("Registration Success"), MarkdownUtil.codeblock("All audit log info will be logged here"), false); - } else { - eb.setColor(Color.YELLOW); - eb.addField(MarkdownUtil.underline("Registration Failure"), MarkdownUtil.codeblock("Channel could not be registered. Check if a channel in this guild is already registered for logging."), false); - } - - event.getHook().editOriginalEmbeds(eb.build()).queue(); - } - - private void retrieveAuditLoggingChannel(@NonNull SlashCommandInteractionEvent event) { - - Guild callerGuild = event.getGuild(); - if (callerGuild == null) { - log.warn("An audit log view command may have been called outside of a guild. This should not happen."); - return; - } - - // acknowledge this interaction before calling the API - event.deferReply().queue(); - - // Call the API to retrieve the registered channel - Optional response = client.getRegisteredGuild(callerGuild.getId()); - - EmbedBuilder eb = new EmbedBuilder(); - eb.setTitle("View Existing Audit Log Configuration"); - - // if there is no channel_id for the given guild_id returned by the API, then inform - // the user of the same, else link the channel that has been registered - response.ifPresentOrElse(success -> { - String registeredChannelId = success.getChannelId(); - GuildChannel registeredChannel = event.getJDA().getGuildChannelById(registeredChannelId); - String registeredChannelName = registeredChannel != null ? registeredChannel.getName() : registeredChannelId; - - eb.setColor(Color.CYAN); - eb.addField(MarkdownUtil.underline("Success"), MarkdownUtil.codeblock(registeredChannelName + " is found to be registered as the audit log channel"), false); - }, () -> { - eb.setColor(Color.YELLOW); - eb.addField(MarkdownUtil.underline("Warning"), MarkdownUtil.codeblock("No channel has been registered for audit logs"), false); - }); - - event.getHook().editOriginalEmbeds(eb.build()).queue(); - } - - private void unsetAuditLogging(@NonNull SlashCommandInteractionEvent event) { - - Guild callerGuild = event.getGuild(); - if (callerGuild == null) { - log.warn("An audit log unset command may have been called outside of a guild. This should not happen."); - return; - } - - // acknowledge this interaction before calling the API - event.deferReply().queue(); - - // Call the API to unregister guild - boolean success = client.deleteRegisteredGuild(callerGuild.getId()); - - EmbedBuilder eb = new EmbedBuilder(); - eb.setTitle("Audit Log Removal Process"); - - if (success) { - eb.setColor(Color.GREEN); - eb.addField(MarkdownUtil.underline("Removal Success"), MarkdownUtil.codeblock("Channel successfully unset"), false); - } else { - eb.setColor(Color.YELLOW); - eb.addField(MarkdownUtil.underline("Removal Failure"), MarkdownUtil.codeblock("Channel could not be unset. This may be because no channel has been registered in this guild yet."), false); - } - - event.getHook().editOriginalEmbeds(eb.build()).queue(); - } } diff --git a/src/main/java/io/github/eggy03/papertrail/bot/listeners/command/BotSetupInstructionCommandListener.java b/src/main/java/io/github/eggy03/papertrail/bot/listeners/command/BotSetupInstructionCommandListener.java index 8267d1d5..844649fc 100644 --- a/src/main/java/io/github/eggy03/papertrail/bot/listeners/command/BotSetupInstructionCommandListener.java +++ b/src/main/java/io/github/eggy03/papertrail/bot/listeners/command/BotSetupInstructionCommandListener.java @@ -1,73 +1,27 @@ package io.github.eggy03.papertrail.bot.listeners.command; -import io.github.eggy03.papertrail.bot.constant.ProjectInfo; +import io.github.eggy03.papertrail.bot.handlers.command.BotSetupInstructionCommandHandler; +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.inject.Inject; import lombok.NonNull; -import net.dv8tion.jda.api.EmbedBuilder; -import net.dv8tion.jda.api.entities.MessageEmbed; import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent; import net.dv8tion.jda.api.hooks.ListenerAdapter; -import java.awt.Color; -import java.time.Instant; +@ApplicationScoped +public final class BotSetupInstructionCommandListener extends ListenerAdapter { -public class BotSetupInstructionCommandListener extends ListenerAdapter { + private final @NonNull BotSetupInstructionCommandHandler handler; + + @Inject + public BotSetupInstructionCommandListener(@NonNull BotSetupInstructionCommandHandler handler) { + this.handler = handler; + } @Override public void onSlashCommandInteraction(@NonNull SlashCommandInteractionEvent event) { if (event.getName().equals("setup")) { - - EmbedBuilder eb = new EmbedBuilder(); - eb.setTitle("🛠️ Setup Guide for " + ProjectInfo.APPNAME); - eb.setDescription("Follow the instructions below to set up the bot in your server."); - eb.setColor(Color.decode("#38e8bc")); - - eb.addField("1️⃣ Set Audit Log Channel", - "Use `/auditlog set` to **register this channel** for receiving audit log events.", - false); - - eb.addField("2️⃣ View Audit Log Channel", - "Use `/auditlog view` to **see which channel** is currently receiving audit logs.", - false); - - eb.addField("3️⃣ Remove Audit Log Channel", - "Use `/auditlog remove` to **stop logging** events and remove the registered channel.", - false); - - eb.addField("🔒 Permissions", - "These three commands require the **Administrator** permission.", - false); - - eb.addBlankField(false); - - eb.addField("4️⃣ Set Message Log Channel", - "Use `/messagelog set` to **register this channel** for receiving message logs.", - false); - - eb.addField("5️⃣ View Message Log Channel", - "Use `/messagelog view` to **see which channel** is currently receiving message logs.", - false); - - eb.addField("6️⃣ Remove Message Log Channel", - "Use `/messagelog remove` to **stop logging** messages and remove the registered channel.", - false); - - eb.addField("🔒 Permissions", - "These three commands require the **Administrator** permission.", - false); - - eb.addBlankField(false); - - eb.addField("7️⃣ View Server Stats", - "Use `/stats` to **view useful server information**, including member count, channel count, and more.", - false); - - eb.addField("📬 Need help?", "Create an issue on [GitHub](" + ProjectInfo.PROJECT_ISSUE_LINK + ")", false); - eb.setFooter(ProjectInfo.APPNAME + " " + ProjectInfo.VERSION); - eb.setTimestamp(Instant.now()); - - MessageEmbed mb = eb.build(); - event.replyEmbeds(mb).queue(); + handler.sendInstructions(event); } } } \ No newline at end of file diff --git a/src/main/java/io/github/eggy03/papertrail/bot/listeners/command/DebugCommandListener.java b/src/main/java/io/github/eggy03/papertrail/bot/listeners/command/DebugCommandListener.java index a73604df..13f9d70d 100644 --- a/src/main/java/io/github/eggy03/papertrail/bot/listeners/command/DebugCommandListener.java +++ b/src/main/java/io/github/eggy03/papertrail/bot/listeners/command/DebugCommandListener.java @@ -1,141 +1,24 @@ package io.github.eggy03.papertrail.bot.listeners.command; -import io.github.eggy03.papertrail.bot.constant.ProjectInfo; -import io.github.eggy03.papertrail.bot.utils.BooleanUtils; -import io.github.eggy03.papertrail.sdk.client.AuditLogRegistrationClient; -import io.github.eggy03.papertrail.sdk.client.MessageLogRegistrationClient; +import io.github.eggy03.papertrail.bot.handlers.command.DebugCommandHandler; +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.inject.Inject; import lombok.NonNull; -import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; -import net.dv8tion.jda.api.EmbedBuilder; -import net.dv8tion.jda.api.JDA; -import net.dv8tion.jda.api.Permission; import net.dv8tion.jda.api.entities.Guild; import net.dv8tion.jda.api.entities.Member; -import net.dv8tion.jda.api.entities.channel.middleman.GuildChannel; import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent; import net.dv8tion.jda.api.hooks.ListenerAdapter; -import net.dv8tion.jda.api.utils.MarkdownUtil; -import org.jetbrains.annotations.NotNull; - -import java.awt.Color; -import java.time.Instant; -import java.util.EnumSet; -import java.util.Set; -import java.util.concurrent.ExecutorService; - @Slf4j -@RequiredArgsConstructor -public class DebugCommandListener extends ListenerAdapter { - - @NonNull - private final ExecutorService vThreadPool; - - @NonNull - private final AuditLogRegistrationClient alClient; - - @NonNull - private final MessageLogRegistrationClient mlClient; - - // recommended permissions for the bot to function - @NonNull - private final Set recommendedPermissions = EnumSet.of( - Permission.VIEW_CHANNEL, - Permission.VIEW_AUDIT_LOGS, - Permission.MANAGE_SERVER, - Permission.MESSAGE_SEND, - Permission.MESSAGE_SEND_IN_THREADS, - Permission.MESSAGE_EMBED_LINKS, - Permission.MESSAGE_HISTORY - ); - - @NotNull - private String getBotPermissions(@NonNull Guild guild) { - return formatPermissions(guild.getSelfMember().getPermissions()); - } +@ApplicationScoped +public final class DebugCommandListener extends ListenerAdapter { - @NotNull - private String getBotPermissionsInCurrentChannel(@NonNull Guild guild, @NonNull GuildChannel channel) { - return formatPermissions(guild.getSelfMember().getPermissions(channel)); - } - - @NotNull - private String formatPermissions(@NonNull EnumSet grantedGuildOrChannelPermissions) { - // gets all the permissions granted to the bot in the server as a whole or a particular channel - EnumSet grantedPermissions = EnumSet.copyOf(grantedGuildOrChannelPermissions); - // this will - // 1) REMOVE the UNNECESSARY GRANTED PERMISSIONS - // 2) RETAIN those GRANTED PERMISSIONS that match with the RECOMMENDED ONES - // there may be cases where granted permissions is NOT a perfect superset of recommended permissions - // this indicates that some recommended permissions have been DENIED - grantedPermissions.retainAll(recommendedPermissions); - - // create a copy of recommended permissions - EnumSet deniedPermissions = EnumSet.copyOf(recommendedPermissions); - // now if you calculate recommended - granted, you will get the set of recommended permissions which are DENIED - deniedPermissions.removeAll(grantedPermissions); - - StringBuilder permString = new StringBuilder(); - grantedPermissions.forEach(permission -> - permString.append("✅ - ") - .append(permission.getName()) - .append("\n") - ); - - deniedPermissions.forEach(permission -> - permString.append("❌ - ") - .append(permission.getName()) - .append("\n") - ); - - return permString.toString().trim(); - } + private final @NonNull DebugCommandHandler handler; - @NotNull - private String getServerInfo(@NonNull Guild guild, @NonNull GuildChannel channel) { - return "Server Name: " + MarkdownUtil.underline(guild.getName()) + "\n" + - "Server ID: " + MarkdownUtil.underline(guild.getId()) + "\n" + - "Current Channel Name: " + MarkdownUtil.underline(channel.getName()) + "\n" + - "Current Channel ID: " + MarkdownUtil.underline(channel.getId()); - } - - @NotNull - private String getCallerInfo(@NonNull Member member) { - return "User Name: " + MarkdownUtil.underline(member.getUser().getEffectiveName()) + "\n" + - "User ID: " + MarkdownUtil.underline(member.getId()) + "\n" + - "Is Administrator: " + MarkdownUtil.underline(BooleanUtils.formatToYesOrNo(member.hasPermission(Permission.ADMINISTRATOR))); - } - - @NotNull - private String getBotInfo(@NonNull SlashCommandInteractionEvent event) { - JDA.ShardInfo shardInfo = event.getJDA().getShardInfo(); - return "Current Shard ID: " + shardInfo.getShardId() + "\n" + - "Total Shards: " + shardInfo.getShardTotal(); - } - - @NotNull - private String getConfigurationInfo(@NonNull Guild guild) { - - StringBuilder sb = new StringBuilder(); - - alClient.getRegisteredGuild(guild.getId()).ifPresentOrElse(entity -> { - GuildChannel channel = guild.getGuildChannelById(entity.getChannelId()); - if (channel != null) - sb.append("Registered Audit Log Channel: ").append(MarkdownUtil.underline(channel.getName())).append("\n"); - else - sb.append("Registered Audit Log Channel: ").append(MarkdownUtil.underline("Registered Channel Unresolvable")).append("\n"); - }, () -> sb.append(MarkdownUtil.underline("No Channel Registered For Audit Logging")).append("\n")); - - mlClient.getRegisteredGuild(guild.getId()).ifPresentOrElse(entity -> { - GuildChannel channel = guild.getGuildChannelById(entity.getChannelId()); - if (channel != null) - sb.append("Registered Message Log Channel: ").append(MarkdownUtil.underline(channel.getName())); - else - sb.append("Registered Message Log Channel: ").append(MarkdownUtil.underline("Registered Channel Unresolvable")); - }, () -> sb.append(MarkdownUtil.underline("No Channel Registered For Message Logging"))); - - return sb.toString(); + @Inject + public DebugCommandListener(@NonNull DebugCommandHandler handler) { + this.handler = handler; } @Override @@ -151,29 +34,7 @@ public void onSlashCommandInteraction(@NonNull SlashCommandInteractionEvent even return; } - GuildChannel channel = event.getGuildChannel(); - - // acknowledge this interaction but reply when the embed's been built - event.deferReply().queue(); - - vThreadPool.execute(() -> { - EmbedBuilder eb = new EmbedBuilder(); - eb.setTitle("Debug Info"); - eb.setDescription("Server: " + guild.getName()); - eb.setColor(Color.GRAY); - - eb.addField(MarkdownUtil.underline("Bot Permissions"), MarkdownUtil.quoteBlock(getBotPermissions(guild)), true); - eb.addField(MarkdownUtil.underline("Channel Permissions"), MarkdownUtil.quoteBlock(getBotPermissionsInCurrentChannel(guild, channel)), true); - eb.addField(MarkdownUtil.underline("Server Info"), MarkdownUtil.quoteBlock(getServerInfo(guild, channel)), true); - - eb.addField(MarkdownUtil.underline("User Info"), MarkdownUtil.quoteBlock(getCallerInfo(member)), true); - eb.addField(MarkdownUtil.underline("Bot Info"), MarkdownUtil.quoteBlock(getBotInfo(event)), true); - eb.addField(MarkdownUtil.underline("Configuration Info"), MarkdownUtil.quoteBlock(getConfigurationInfo(guild)), true); - - eb.setFooter(ProjectInfo.APPNAME + " " + ProjectInfo.VERSION); - eb.setTimestamp(Instant.now()); + handler.sendDebugInfo(event, guild, member); - event.getHook().editOriginalEmbeds(eb.build()).queue(); - }); } } diff --git a/src/main/java/io/github/eggy03/papertrail/bot/listeners/command/MessageLogSetupCommandListener.java b/src/main/java/io/github/eggy03/papertrail/bot/listeners/command/MessageLogSetupCommandListener.java index 83a80d13..6db23a4d 100644 --- a/src/main/java/io/github/eggy03/papertrail/bot/listeners/command/MessageLogSetupCommandListener.java +++ b/src/main/java/io/github/eggy03/papertrail/bot/listeners/command/MessageLogSetupCommandListener.java @@ -1,26 +1,23 @@ package io.github.eggy03.papertrail.bot.listeners.command; -import io.github.eggy03.papertrail.sdk.client.MessageLogRegistrationClient; -import io.github.eggy03.papertrail.sdk.entity.MessageLogRegistrationEntity; +import io.github.eggy03.papertrail.bot.handlers.command.MessageLogSetupCommandHandler; +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.inject.Inject; import lombok.NonNull; -import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; -import net.dv8tion.jda.api.EmbedBuilder; -import net.dv8tion.jda.api.entities.Guild; -import net.dv8tion.jda.api.entities.channel.middleman.GuildChannel; import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent; import net.dv8tion.jda.api.hooks.ListenerAdapter; -import net.dv8tion.jda.api.utils.MarkdownUtil; - -import java.awt.Color; -import java.util.Optional; @Slf4j -@RequiredArgsConstructor -public class MessageLogSetupCommandListener extends ListenerAdapter { +@ApplicationScoped +public final class MessageLogSetupCommandListener extends ListenerAdapter { + + private final @NonNull MessageLogSetupCommandHandler handler; - @NonNull - private final MessageLogRegistrationClient client; + @Inject + public MessageLogSetupCommandListener(@NonNull MessageLogSetupCommandHandler handler) { + this.handler = handler; + } @Override public void onSlashCommandInteraction(@NonNull SlashCommandInteractionEvent event) { @@ -30,103 +27,12 @@ public void onSlashCommandInteraction(@NonNull SlashCommandInteractionEvent even } switch (event.getSubcommandName()) { - case "set" -> setMessageLogging(event); - case "view" -> retrieveMessageLoggingChannel(event); - case "remove" -> unsetMessageLogging(event); + case "set" -> handler.setMessageLogging(event); + case "view" -> handler.viewMessageLoggingChannel(event); + case "remove" -> handler.unsetMessageLogging(event); default -> { // skip } } } - - private void setMessageLogging(@NonNull SlashCommandInteractionEvent event) { - - Guild callerGuild = event.getGuild(); - GuildChannel callerChannel = event.getChannel().asTextChannel(); - if (callerGuild == null) { - log.warn("A message log set command may have been called outside of a guild. This should not happen."); - return; - } - - // acknowledge this interaction before calling the API - event.deferReply().queue(); - - // Call the API to register guild for message logging - boolean success = client.registerGuild(callerGuild.getId(), callerChannel.getId()); - - EmbedBuilder eb = new EmbedBuilder(); - eb.setTitle("Message Log Registration Process"); - - if (success) { - eb.setColor(Color.GREEN); - eb.addField(MarkdownUtil.underline("Registration Success"), MarkdownUtil.codeblock("All edited and deleted messages will be logged here"), false); - } else { - eb.setColor(Color.YELLOW); - eb.addField(MarkdownUtil.underline("Registration Failure"), MarkdownUtil.codeblock("Channel could not be registered. Check if a channel in this guild is already registered for logging."), false); - - } - - event.getHook().editOriginalEmbeds(eb.build()).queue(); - } - - private void retrieveMessageLoggingChannel(@NonNull SlashCommandInteractionEvent event) { - - Guild callerGuild = event.getGuild(); - if (callerGuild == null) { - log.warn("A message log view command may have been called outside of a guild. This should not happen."); - return; - } - - // acknowledge this interaction before calling the API - event.deferReply().queue(); - - // Call the API to check for registered guild - Optional response = client.getRegisteredGuild(callerGuild.getId()); - - EmbedBuilder eb = new EmbedBuilder(); - eb.setTitle("View Existing Message Log Configuration"); - - response.ifPresentOrElse(success -> { - - String registeredChannelId = success.getChannelId(); - GuildChannel registeredChannel = event.getJDA().getGuildChannelById(registeredChannelId); - String registeredChannelName = registeredChannel != null ? registeredChannel.getName() : registeredChannelId; - - eb.setColor(Color.CYAN); - eb.addField(MarkdownUtil.underline("Success"), MarkdownUtil.codeblock(registeredChannelName + " is found to be registered as the message log channel"), false); - }, () -> { - eb.setColor(Color.YELLOW); - eb.addField(MarkdownUtil.underline("Warning"), MarkdownUtil.codeblock("No channel has been registered for message logs"), false); - }); - - event.getHook().editOriginalEmbeds(eb.build()).queue(); - } - - private void unsetMessageLogging(@NonNull SlashCommandInteractionEvent event) { - - Guild callerGuild = event.getGuild(); - if (callerGuild == null) { - log.warn("A message log unset command may have been called outside of a guild. This should not happen."); - return; - } - - // acknowledge this interaction before calling the API - event.deferReply().queue(); - - // Call the API to unregister guild - boolean success = client.deleteRegisteredGuild(callerGuild.getId()); - - EmbedBuilder eb = new EmbedBuilder(); - eb.setTitle("Message Log Removal Process"); - - if (success) { - eb.setColor(Color.GREEN); - eb.addField(MarkdownUtil.underline("Removal Success"), MarkdownUtil.codeblock("Channel successfully unset"), false); - } else { - eb.setColor(Color.YELLOW); - eb.addField(MarkdownUtil.underline("Removal Failure"), MarkdownUtil.codeblock("Channel could not be unset. This may be because no channel has been registered in this guild yet."), false); - } - - event.getHook().editOriginalEmbeds(eb.build()).queue(); - } } diff --git a/src/main/java/io/github/eggy03/papertrail/bot/listeners/command/ServerStatCommandListener.java b/src/main/java/io/github/eggy03/papertrail/bot/listeners/command/ServerStatCommandListener.java index f153408f..72b4975e 100644 --- a/src/main/java/io/github/eggy03/papertrail/bot/listeners/command/ServerStatCommandListener.java +++ b/src/main/java/io/github/eggy03/papertrail/bot/listeners/command/ServerStatCommandListener.java @@ -1,65 +1,23 @@ package io.github.eggy03.papertrail.bot.listeners.command; +import io.github.eggy03.papertrail.bot.handlers.command.ServerStatCommandHandler; +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.inject.Inject; import lombok.NonNull; import lombok.extern.slf4j.Slf4j; -import net.dv8tion.jda.api.EmbedBuilder; import net.dv8tion.jda.api.entities.Guild; -import net.dv8tion.jda.api.entities.Member; import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent; import net.dv8tion.jda.api.hooks.ListenerAdapter; -import net.dv8tion.jda.api.utils.MarkdownUtil; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -import java.awt.Color; -import java.time.Instant; -import java.util.List; +@ApplicationScoped @Slf4j -public class ServerStatCommandListener extends ListenerAdapter { - - @NotNull - private String getMemberAndBotCount(@NonNull Guild guild) { - - List memberCache = guild.getMemberCache().asList(); - int allUserCount = memberCache.size(); - int botCount = memberCache.stream().filter(member -> member.getUser().isBot()).toList().size(); - - return "Users: " + (allUserCount - botCount) + "\nBots: " + botCount + "\nTotal: " + allUserCount; - } - - @NotNull - private String getGuildOwner(@NonNull Guild guild) { - Member owner = guild.getOwner(); - - return owner == null ? "N/A" : owner.getAsMention(); - } - - @NotNull - private String getGuildCreationDate(@NonNull Guild guild) { - return ""; - } +public final class ServerStatCommandListener extends ListenerAdapter { - @NotNull - private String getGuildVanityUrl(@NonNull Guild guild) { - return guild.getVanityUrl() == null ? "N/A" : guild.getVanityUrl(); - } - - @NotNull - private String getBoosters(@NonNull Guild guild) { - StringBuilder boosterString = new StringBuilder(); - guild.getBoosters().forEach(booster -> boosterString.append(booster.getAsMention()).append(" ")); - return boosterString.toString().trim().isEmpty() ? "No Boosters" : boosterString.toString().trim(); - } - - @NotNull - private String getBoosterRole(@NonNull Guild guild) { - return guild.getBoostRole() != null ? guild.getBoostRole().getAsMention() : "No Boost Role Found"; - } + private final @NonNull ServerStatCommandHandler handler; - @NotNull - private String getDataRequestingMember(@Nullable Member requestingMember) { - return requestingMember != null ? requestingMember.getEffectiveName() : "N/A"; + @Inject + public ServerStatCommandListener(@NonNull ServerStatCommandHandler handler) { + this.handler = handler; } @Override @@ -75,34 +33,6 @@ public void onSlashCommandInteraction(@NonNull SlashCommandInteractionEvent even return; } - // acknowledge this interaction but reply when the embed's been built - event.deferReply().queue(); - - EmbedBuilder eb = new EmbedBuilder(); - eb.setTitle("Server Statistics"); - eb.setDescription("Statistics For: " + guild.getName()); - eb.setThumbnail(guild.getIconUrl()); - eb.setColor(Color.PINK); - - eb.addField(MarkdownUtil.underline("Guild Owner"), MarkdownUtil.quoteBlock(getGuildOwner(guild)), false); - eb.addField(MarkdownUtil.underline("Guild Created On"), MarkdownUtil.quoteBlock(getGuildCreationDate(guild)), false); - eb.addField(MarkdownUtil.underline("Guild Vanity URL"), MarkdownUtil.quoteBlock(getGuildVanityUrl(guild)), false); - eb.addField(MarkdownUtil.underline("Member Stats"), MarkdownUtil.quoteBlock(getMemberAndBotCount(guild)), false); - eb.addField(MarkdownUtil.underline("Guild Boosters"), MarkdownUtil.quoteBlock(getBoosters(guild)), false); - eb.addField(MarkdownUtil.underline("Guild Boost Count"), MarkdownUtil.quoteBlock(String.valueOf(guild.getBoostCount())), true); - eb.addField(MarkdownUtil.underline("Booster Role"), MarkdownUtil.quoteBlock(getBoosterRole(guild)), true); - eb.addField(MarkdownUtil.underline("Boost Tier"), MarkdownUtil.quoteBlock(guild.getBoostTier().name()), true); - eb.addField(MarkdownUtil.underline("Locale"), MarkdownUtil.quoteBlock(guild.getLocale().getNativeName()), true); - eb.addField(MarkdownUtil.underline("Verification"), MarkdownUtil.quoteBlock(guild.getVerificationLevel().name()), true); - eb.addField(MarkdownUtil.underline("Roles"), MarkdownUtil.quoteBlock(String.valueOf(guild.getRoles().size())), true); - eb.addField(MarkdownUtil.underline("Categories"), MarkdownUtil.quoteBlock(String.valueOf(guild.getCategories().size())), true); - eb.addField(MarkdownUtil.underline("Text Channels"), MarkdownUtil.quoteBlock(String.valueOf(guild.getTextChannels().size())), true); - eb.addField(MarkdownUtil.underline("Voice Channels"), MarkdownUtil.quoteBlock(String.valueOf(guild.getVoiceChannels().size())), true); - - eb.setFooter("Requested By: " + getDataRequestingMember(event.getMember())); - eb.setTimestamp(Instant.now()); - - event.getHook().editOriginalEmbeds(eb.build()).queue(); - + handler.sendServerStats(event, guild); } } diff --git a/src/main/java/io/github/eggy03/papertrail/bot/listeners/guild/GuildBoostEventListener.java b/src/main/java/io/github/eggy03/papertrail/bot/listeners/guild/GuildBoostEventListener.java new file mode 100644 index 00000000..1f04212a --- /dev/null +++ b/src/main/java/io/github/eggy03/papertrail/bot/listeners/guild/GuildBoostEventListener.java @@ -0,0 +1,36 @@ +package io.github.eggy03.papertrail.bot.listeners.guild; + +import io.github.eggy03.papertrail.bot.handlers.guild.GuildBoostEventHandler; +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.inject.Inject; +import lombok.NonNull; +import net.dv8tion.jda.api.events.guild.member.update.GuildMemberUpdateBoostTimeEvent; +import net.dv8tion.jda.api.events.guild.update.GuildUpdateBoostCountEvent; +import net.dv8tion.jda.api.events.guild.update.GuildUpdateBoostTierEvent; +import net.dv8tion.jda.api.hooks.ListenerAdapter; + +@ApplicationScoped +public final class GuildBoostEventListener extends ListenerAdapter { + + private final @NonNull GuildBoostEventHandler handler; + + @Inject + public GuildBoostEventListener(@NonNull GuildBoostEventHandler handler) { + this.handler = handler; + } + + @Override + public void onGuildUpdateBoostTier(@NonNull GuildUpdateBoostTierEvent event) { + handler.handleUpdateBoostTier(event); + } + + @Override + public void onGuildUpdateBoostCount(@NonNull GuildUpdateBoostCountEvent event) { + handler.handleUpdateBoostCount(event); + } + + @Override + public void onGuildMemberUpdateBoostTime(@NonNull GuildMemberUpdateBoostTimeEvent event) { + handler.handleMemberUpdateBoostTime(event); + } +} diff --git a/src/main/java/io/github/eggy03/papertrail/bot/listeners/guild/GuildMemberEventListener.java b/src/main/java/io/github/eggy03/papertrail/bot/listeners/guild/GuildMemberEventListener.java new file mode 100644 index 00000000..e9e26309 --- /dev/null +++ b/src/main/java/io/github/eggy03/papertrail/bot/listeners/guild/GuildMemberEventListener.java @@ -0,0 +1,34 @@ +package io.github.eggy03.papertrail.bot.listeners.guild; + +import io.github.eggy03.papertrail.bot.handlers.guild.GuildMemberEventHandler; +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.inject.Inject; +import lombok.NonNull; +import net.dv8tion.jda.api.events.guild.member.GuildMemberJoinEvent; +import net.dv8tion.jda.api.events.guild.member.GuildMemberRemoveEvent; +import net.dv8tion.jda.api.hooks.ListenerAdapter; + +// this event is not properly logged in the audit logs, hence the usage of JDA's listener is preferred +// this event is logged in the same channel where the audit log events are logged +@ApplicationScoped +public final class GuildMemberEventListener extends ListenerAdapter { + + private final @NonNull GuildMemberEventHandler handler; + + @Inject + public GuildMemberEventListener(@NonNull GuildMemberEventHandler handler) { + this.handler = handler; + } + + + @Override + public void onGuildMemberJoin(@NonNull GuildMemberJoinEvent event) { + handler.handleGuildMemberJoin(event); + } + + @Override + public void onGuildMemberRemove(@NonNull GuildMemberRemoveEvent event) { + handler.handleGuildMemberRemove(event); + } + +} diff --git a/src/main/java/io/github/eggy03/papertrail/bot/listeners/guild/GuildPollEventListener.java b/src/main/java/io/github/eggy03/papertrail/bot/listeners/guild/GuildPollEventListener.java new file mode 100644 index 00000000..54bb1e16 --- /dev/null +++ b/src/main/java/io/github/eggy03/papertrail/bot/listeners/guild/GuildPollEventListener.java @@ -0,0 +1,29 @@ +package io.github.eggy03.papertrail.bot.listeners.guild; + +import io.github.eggy03.papertrail.bot.handlers.guild.GuildPollEventHandler; +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.inject.Inject; +import lombok.NonNull; +import net.dv8tion.jda.api.events.message.MessageReceivedEvent; +import net.dv8tion.jda.api.hooks.ListenerAdapter; + +// guild poll events are mapped to audit log table +@ApplicationScoped +public final class GuildPollEventListener extends ListenerAdapter { + + private final @NonNull GuildPollEventHandler handler; + + @Inject + public GuildPollEventListener(@NonNull GuildPollEventHandler handler) { + this.handler = handler; + } + + @Override + public void onMessageReceived(@NonNull MessageReceivedEvent event) { + + if (!event.isFromGuild()) + return; + + handler.handlePollCreationEvent(event); + } +} diff --git a/src/main/java/io/github/eggy03/papertrail/bot/listeners/guild/GuildVoiceEventListener.java b/src/main/java/io/github/eggy03/papertrail/bot/listeners/guild/GuildVoiceEventListener.java new file mode 100644 index 00000000..51a6d327 --- /dev/null +++ b/src/main/java/io/github/eggy03/papertrail/bot/listeners/guild/GuildVoiceEventListener.java @@ -0,0 +1,26 @@ +package io.github.eggy03.papertrail.bot.listeners.guild; + +import io.github.eggy03.papertrail.bot.handlers.guild.GuildVoiceEventHandler; +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.inject.Inject; +import lombok.NonNull; +import net.dv8tion.jda.api.events.guild.voice.GuildVoiceUpdateEvent; +import net.dv8tion.jda.api.hooks.ListenerAdapter; + +// this event is not properly logged in the audit logs, hence the usage of JDA's listener is preferred +// this event is logged in the same channel where the audit log events are logged +@ApplicationScoped +public final class GuildVoiceEventListener extends ListenerAdapter { + + private final @NonNull GuildVoiceEventHandler handler; + + @Inject + public GuildVoiceEventListener(@NonNull GuildVoiceEventHandler handler) { + this.handler = handler; + } + + @Override + public void onGuildVoiceUpdate(@NonNull GuildVoiceUpdateEvent event) { + handler.handleVoiceUpdateEvent(event); + } +} \ No newline at end of file diff --git a/src/main/java/io/github/eggy03/papertrail/bot/listeners/message/GuildMessageEventListener.java b/src/main/java/io/github/eggy03/papertrail/bot/listeners/message/GuildMessageEventListener.java new file mode 100644 index 00000000..3704875b --- /dev/null +++ b/src/main/java/io/github/eggy03/papertrail/bot/listeners/message/GuildMessageEventListener.java @@ -0,0 +1,53 @@ +package io.github.eggy03.papertrail.bot.listeners.message; + +import io.github.eggy03.papertrail.bot.handlers.message.GuildMessageEventHandler; +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.inject.Inject; +import lombok.NonNull; +import net.dv8tion.jda.api.events.message.MessageDeleteEvent; +import net.dv8tion.jda.api.events.message.MessageReceivedEvent; +import net.dv8tion.jda.api.events.message.MessageUpdateEvent; +import net.dv8tion.jda.api.hooks.ListenerAdapter; + +@ApplicationScoped +public final class GuildMessageEventListener extends ListenerAdapter { + + private final @NonNull GuildMessageEventHandler handler; + + @Inject + public GuildMessageEventListener(@NonNull GuildMessageEventHandler handler) { + this.handler = handler; + } + + @Override + public void onMessageReceived(@NonNull MessageReceivedEvent event) { + + // if the author is a bot or system, don't log + if (event.getAuthor().isBot() || event.getAuthor().isSystem()) { + return; + } + // don't register non-textual contents + if (event.getMessage().getContentRaw().isEmpty()) { + return; + } + + handler.handleMessageReceivedEvent(event); + + } + + @Override + public void onMessageUpdate(@NonNull MessageUpdateEvent event) { + + if (event.getAuthor().isBot() || event.getAuthor().isSystem()) { + return; + } + + handler.handleMessageUpdateEvent(event); + + } + + @Override + public void onMessageDelete(@NonNull MessageDeleteEvent event) { + handler.handleMessageDeleteEvent(event); + } +} diff --git a/src/main/java/io/github/eggy03/papertrail/bot/listeners/messagelog/event/MessageLogListener.java b/src/main/java/io/github/eggy03/papertrail/bot/listeners/messagelog/event/MessageLogListener.java deleted file mode 100644 index 98d04726..00000000 --- a/src/main/java/io/github/eggy03/papertrail/bot/listeners/messagelog/event/MessageLogListener.java +++ /dev/null @@ -1,100 +0,0 @@ -package io.github.eggy03.papertrail.bot.listeners.messagelog.event; - -import io.github.eggy03.papertrail.bot.listeners.messagelog.helper.MessageLogMessageDeleteEventHelper; -import io.github.eggy03.papertrail.bot.listeners.messagelog.helper.MessageLogMessageReceivedEventHelper; -import io.github.eggy03.papertrail.bot.listeners.messagelog.helper.MessageLogMessageUpdateEventHelper; -import io.github.eggy03.papertrail.sdk.client.MessageLogContentClient; -import io.github.eggy03.papertrail.sdk.client.MessageLogRegistrationClient; -import io.github.eggy03.papertrail.sdk.entity.MessageLogRegistrationEntity; -import lombok.NonNull; -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import net.dv8tion.jda.api.events.message.MessageDeleteEvent; -import net.dv8tion.jda.api.events.message.MessageReceivedEvent; -import net.dv8tion.jda.api.events.message.MessageUpdateEvent; -import net.dv8tion.jda.api.hooks.ListenerAdapter; - -import java.util.Optional; -import java.util.concurrent.Executor; - -@Slf4j -@RequiredArgsConstructor -public class MessageLogListener extends ListenerAdapter { - - @NonNull - private final MessageLogRegistrationClient registrationClient; - @NonNull - private final MessageLogContentClient contentClient; - @NonNull - private final Executor vThreadPool; - - @Override - public void onMessageReceived(@NonNull MessageReceivedEvent event) { - - // if the author is a bot or system, don't log - if (event.getAuthor().isBot() || event.getAuthor().isSystem()) { - return; - } - // don't register non-textual contents - if (event.getMessage().getContentRaw().isEmpty()) { - return; - } - - vThreadPool.execute(() -> { - // get the guild id for which the event was fired - String guildId = event.getGuild().getId(); - // Call the API to see if the guild is registered for Message Logging - Optional response = registrationClient.getRegisteredGuild(guildId); - response.ifPresent(success -> - MessageLogMessageReceivedEventHelper.saveMessage(event, contentClient) - ); - }); - } - - @Override - public void onMessageUpdate(@NonNull MessageUpdateEvent event) { - - if (event.getAuthor().isBot() || event.getAuthor().isSystem()) { - return; - } - - vThreadPool.execute(() -> { - // Get the guild id for which the event was fired - String guildId = event.getGuild().getId(); - // Call the API to see if the guild is registered for Message Logging - Optional response = registrationClient.getRegisteredGuild(guildId); - response.ifPresent(success -> { - - // get the message id of the message which was updated - String messageId = event.getMessageId(); - // retrieve the channel id where the logs must be sent - String channelIdToSendTo = success.getChannelId(); - // update message - MessageLogMessageUpdateEventHelper.updateMessage(event, contentClient, messageId, channelIdToSendTo); - }); - }); - } - - @Override - public void onMessageDelete(@NonNull MessageDeleteEvent event) { - - vThreadPool.execute(() -> { - - // Get the guild id for which the event was fired - String guildId = event.getGuild().getId(); - - // Call the API to see if the guild is registered for Message Logging - Optional response = registrationClient.getRegisteredGuild(guildId); - response.ifPresent(success -> { - - // get the message id of the message which was deleted - String messageId = event.getMessageId(); - // retrieve the channel id where the logs must be sent - String channelIdToSendTo = success.getChannelId(); - // delete message - MessageLogMessageDeleteEventHelper.deleteMessage(event, contentClient, messageId, channelIdToSendTo); - - }); - }); - } -} diff --git a/src/main/java/io/github/eggy03/papertrail/bot/listeners/messagelog/helper/MessageLogMessageDeleteEventHelper.java b/src/main/java/io/github/eggy03/papertrail/bot/listeners/messagelog/helper/MessageLogMessageDeleteEventHelper.java deleted file mode 100644 index 2bb8e5be..00000000 --- a/src/main/java/io/github/eggy03/papertrail/bot/listeners/messagelog/helper/MessageLogMessageDeleteEventHelper.java +++ /dev/null @@ -1,64 +0,0 @@ -package io.github.eggy03.papertrail.bot.listeners.messagelog.helper; - -import com.google.common.base.Splitter; -import io.github.eggy03.papertrail.sdk.client.MessageLogContentClient; -import io.github.eggy03.papertrail.sdk.entity.MessageLogContentEntity; -import lombok.NonNull; -import lombok.experimental.UtilityClass; -import lombok.extern.slf4j.Slf4j; -import net.dv8tion.jda.api.EmbedBuilder; -import net.dv8tion.jda.api.entities.User; -import net.dv8tion.jda.api.entities.channel.concrete.TextChannel; -import net.dv8tion.jda.api.events.message.MessageDeleteEvent; -import net.dv8tion.jda.api.utils.MarkdownUtil; - -import java.awt.Color; -import java.time.Instant; -import java.util.List; -import java.util.Optional; - -@UtilityClass -@Slf4j -public class MessageLogMessageDeleteEventHelper { - - public static void deleteMessage(@NonNull MessageDeleteEvent event, @NonNull MessageLogContentClient client, @NonNull String deletedMessageId, @NonNull String channelIdToSendTo) { - // fetch the old message object from the API - Optional oldMessageContent = client.retrieveMessage(deletedMessageId); - oldMessageContent.ifPresent(contentEntity -> { - - // retrieve the stored message and author in the database which was deleted - String deletedMessage = contentEntity.getMessageContent(); - String deletedMessageAuthorId = contentEntity.getAuthorId(); - - User author = event.getJDA().getUserById(deletedMessageAuthorId); - String mentionableAuthor = (author != null ? author.getAsMention() : deletedMessageAuthorId); - - // Splitting is required because each field in an embed can display only up-to 1024 characters - List deletedMessageSplits = Splitter.fixedLength(1000).splitToList(deletedMessage); - - EmbedBuilder eb = new EmbedBuilder(); - eb.setTitle("Message Delete Event"); - eb.setDescription(MarkdownUtil.quoteBlock("Author: " + mentionableAuthor + "\n" + "Channel: " + event.getChannel().getAsMention())); - eb.setColor(Color.RED); - - deletedMessageSplits.forEach(split -> eb.addField(MarkdownUtil.underline("Deleted Message"), MarkdownUtil.codeblock(split), false)); - - eb.setFooter(event.getGuild().getName()); - eb.setTimestamp(Instant.now()); - - // delete the message from the database - client.deleteMessage(deletedMessageId); - - // send the fetched deleted message to the logging channel - if (!eb.isValidLength() || eb.isEmpty()) { - log.warn("Embed is empty or too long (current length: {}).", eb.length()); - return; - } - - TextChannel sendingChannel = event.getGuild().getTextChannelById(channelIdToSendTo); - if (sendingChannel != null && sendingChannel.canTalk()) { - sendingChannel.sendMessageEmbeds(eb.build()).queue(); - } - }); - } -} diff --git a/src/main/java/io/github/eggy03/papertrail/bot/listeners/messagelog/helper/MessageLogMessageReceivedEventHelper.java b/src/main/java/io/github/eggy03/papertrail/bot/listeners/messagelog/helper/MessageLogMessageReceivedEventHelper.java deleted file mode 100644 index 417a6bb8..00000000 --- a/src/main/java/io/github/eggy03/papertrail/bot/listeners/messagelog/helper/MessageLogMessageReceivedEventHelper.java +++ /dev/null @@ -1,19 +0,0 @@ -package io.github.eggy03.papertrail.bot.listeners.messagelog.helper; - -import io.github.eggy03.papertrail.sdk.client.MessageLogContentClient; -import lombok.NonNull; -import lombok.experimental.UtilityClass; -import net.dv8tion.jda.api.events.message.MessageReceivedEvent; - -@UtilityClass -public class MessageLogMessageReceivedEventHelper { - - public static void saveMessage(@NonNull MessageReceivedEvent event, @NonNull MessageLogContentClient client) { - - String messageId = event.getMessageId(); - String messageContent = event.getMessage().getContentDisplay(); - String authorId = event.getAuthor().getId(); - - client.logMessage(messageId, messageContent, authorId); - } -} diff --git a/src/main/java/io/github/eggy03/papertrail/bot/listeners/messagelog/helper/MessageLogMessageUpdateEventHelper.java b/src/main/java/io/github/eggy03/papertrail/bot/listeners/messagelog/helper/MessageLogMessageUpdateEventHelper.java deleted file mode 100644 index 230daca9..00000000 --- a/src/main/java/io/github/eggy03/papertrail/bot/listeners/messagelog/helper/MessageLogMessageUpdateEventHelper.java +++ /dev/null @@ -1,70 +0,0 @@ -package io.github.eggy03.papertrail.bot.listeners.messagelog.helper; - -import com.google.common.base.Splitter; -import io.github.eggy03.papertrail.sdk.client.MessageLogContentClient; -import io.github.eggy03.papertrail.sdk.entity.MessageLogContentEntity; -import lombok.NonNull; -import lombok.experimental.UtilityClass; -import lombok.extern.slf4j.Slf4j; -import net.dv8tion.jda.api.EmbedBuilder; -import net.dv8tion.jda.api.entities.channel.concrete.TextChannel; -import net.dv8tion.jda.api.events.message.MessageUpdateEvent; -import net.dv8tion.jda.api.utils.MarkdownUtil; - -import java.awt.Color; -import java.time.Instant; -import java.util.List; -import java.util.Optional; - -@UtilityClass -@Slf4j -public class MessageLogMessageUpdateEventHelper { - - public static void updateMessage(@NonNull MessageUpdateEvent event, @NonNull MessageLogContentClient client, @NonNull String updatedMessageId, @NonNull String channelIdToSendTo) { - - // fetch the old message object from the API - Optional oldMessageContent = client.retrieveMessage(updatedMessageId); - oldMessageContent.ifPresent(contentEntity -> { - // Fetch the old message - String oldMessage = contentEntity.getMessageContent(); - // fetch the updated message and its author from the event - String updatedMessage = event.getMessage().getContentDisplay(); - - // Ignore events where the message content wasn't edited (e.g., pin, embed resolve, thread creates and updates) - // This is required since MessageUpdateEvent is triggered in case of pins and embed resolves with no change to content - if (updatedMessage.equals(oldMessage)) { - return; - } - - // Splitting is required because each field in an embed can display only up-to 1024 characters - // A full embed can display up-to 6000 characters - List oldMessageSplits = Splitter.fixedLength(1000).splitToList(oldMessage); - List updatedMessageSplits = Splitter.fixedLength(1000).splitToList(updatedMessage); - - EmbedBuilder eb = new EmbedBuilder(); - eb.setTitle("Message Edit Event"); - eb.setDescription(MarkdownUtil.quoteBlock("Author: " + event.getAuthor().getAsMention() + "\n" + "Channel: " + event.getChannel().getAsMention())); - eb.setColor(Color.YELLOW); - - oldMessageSplits.forEach(split -> eb.addField(MarkdownUtil.underline("Old Message"), MarkdownUtil.codeblock(split), false)); - updatedMessageSplits.forEach(split -> eb.addField(MarkdownUtil.underline("New Message"), MarkdownUtil.codeblock(split), false)); - - eb.setFooter(event.getGuild().getName()); - eb.setTimestamp(Instant.now()); - - // update the database with the new message - client.updateMessage(updatedMessageId, updatedMessage, event.getAuthor().getId()); - - if (!eb.isValidLength() || eb.isEmpty()) { - log.warn("Embed is empty or too long (current length: {}).", eb.length()); - return; - } - - // send the old and updated message to the registered channel - TextChannel sendingChannel = event.getGuild().getTextChannelById(channelIdToSendTo); - if (sendingChannel != null && sendingChannel.canTalk()) { - sendingChannel.sendMessageEmbeds(eb.build()).queue(); - } - }); - } -} diff --git a/src/main/java/io/github/eggy03/papertrail/bot/listeners/misc/ActivityUpdateListener.java b/src/main/java/io/github/eggy03/papertrail/bot/listeners/misc/ActivityUpdateListener.java index 5198a726..cb09ce3a 100644 --- a/src/main/java/io/github/eggy03/papertrail/bot/listeners/misc/ActivityUpdateListener.java +++ b/src/main/java/io/github/eggy03/papertrail/bot/listeners/misc/ActivityUpdateListener.java @@ -1,8 +1,9 @@ package io.github.eggy03.papertrail.bot.listeners.misc; import io.github.eggy03.papertrail.bot.constant.ProjectInfo; +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.inject.Inject; import lombok.NonNull; -import lombok.RequiredArgsConstructor; import net.dv8tion.jda.api.entities.Activity; import net.dv8tion.jda.api.events.guild.GuildJoinEvent; import net.dv8tion.jda.api.events.guild.GuildLeaveEvent; @@ -10,15 +11,17 @@ import net.dv8tion.jda.api.hooks.ListenerAdapter; import net.dv8tion.jda.api.sharding.ShardManager; -/* - * This class updates the number of servers the bot is in - */ -@RequiredArgsConstructor -public class ActivityUpdateListener extends ListenerAdapter { +@ApplicationScoped +public final class ActivityUpdateListener extends ListenerAdapter { @NonNull private final ShardManager manager; + @Inject + public ActivityUpdateListener(@NonNull ShardManager manager) { + this.manager = manager; + } + @Override public void onReady(@NonNull ReadyEvent event) { // update on cold start updateActivity(); diff --git a/src/main/java/io/github/eggy03/papertrail/bot/listeners/misc/SelfKickListener.java b/src/main/java/io/github/eggy03/papertrail/bot/listeners/misc/SelfKickListener.java index 34f20b72..dae62e70 100644 --- a/src/main/java/io/github/eggy03/papertrail/bot/listeners/misc/SelfKickListener.java +++ b/src/main/java/io/github/eggy03/papertrail/bot/listeners/misc/SelfKickListener.java @@ -2,19 +2,18 @@ import io.github.eggy03.papertrail.sdk.client.AuditLogRegistrationClient; import io.github.eggy03.papertrail.sdk.client.MessageLogRegistrationClient; +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.inject.Inject; import lombok.NonNull; -import lombok.RequiredArgsConstructor; import net.dv8tion.jda.api.entities.Guild; import net.dv8tion.jda.api.events.guild.GuildLeaveEvent; import net.dv8tion.jda.api.hooks.ListenerAdapter; -import java.util.concurrent.Executor; - /* * This class will have methods that unregister the log channels from the database after the bot has been kicked */ -@RequiredArgsConstructor -public class SelfKickListener extends ListenerAdapter { +@ApplicationScoped +public final class SelfKickListener extends ListenerAdapter { @NonNull private final AuditLogRegistrationClient auditLogRegistrationClient; @@ -22,16 +21,16 @@ public class SelfKickListener extends ListenerAdapter { @NonNull private final MessageLogRegistrationClient messageLogRegistrationClient; - @NonNull - private final Executor vThreadPool; + @Inject + public SelfKickListener(@NonNull AuditLogRegistrationClient auditLogRegistrationClient, @NonNull MessageLogRegistrationClient messageLogRegistrationClient) { + this.auditLogRegistrationClient = auditLogRegistrationClient; + this.messageLogRegistrationClient = messageLogRegistrationClient; + } @Override public void onGuildLeave(@NonNull GuildLeaveEvent event) { - Guild leftGuild = event.getGuild(); - vThreadPool.execute(() -> { - auditLogRegistrationClient.deleteRegisteredGuild(leftGuild.getId()); - messageLogRegistrationClient.deleteRegisteredGuild(leftGuild.getId()); - }); + auditLogRegistrationClient.deleteRegisteredGuild(leftGuild.getId()); + messageLogRegistrationClient.deleteRegisteredGuild(leftGuild.getId()); } } diff --git a/src/main/java/io/github/eggy03/papertrail/bot/listeners/misc/SlashCommandRegistrationListener.java b/src/main/java/io/github/eggy03/papertrail/bot/listeners/misc/SlashCommandRegistrationListener.java index ddf479f4..19958872 100644 --- a/src/main/java/io/github/eggy03/papertrail/bot/listeners/misc/SlashCommandRegistrationListener.java +++ b/src/main/java/io/github/eggy03/papertrail/bot/listeners/misc/SlashCommandRegistrationListener.java @@ -1,5 +1,6 @@ package io.github.eggy03.papertrail.bot.listeners.misc; +import jakarta.enterprise.context.ApplicationScoped; import lombok.NonNull; import net.dv8tion.jda.api.JDA; import net.dv8tion.jda.api.events.session.ReadyEvent; @@ -13,7 +14,8 @@ /* * Registers all the slash commands places throughout the code on startup */ -public class SlashCommandRegistrationListener extends ListenerAdapter { +@ApplicationScoped +public final class SlashCommandRegistrationListener extends ListenerAdapter { @Override public void onReady(@NonNull ReadyEvent event) { diff --git a/src/main/java/io/github/eggy03/papertrail/bot/main/BootstrapService.java b/src/main/java/io/github/eggy03/papertrail/bot/main/BootstrapService.java deleted file mode 100644 index 83e0e4f6..00000000 --- a/src/main/java/io/github/eggy03/papertrail/bot/main/BootstrapService.java +++ /dev/null @@ -1,152 +0,0 @@ -package io.github.eggy03.papertrail.bot.main; - -import io.github.eggy03.papertrail.bot.listeners.auditlog.event.AuditLogEventListener; -import io.github.eggy03.papertrail.bot.listeners.auditlogsupl.event.guild.GuildBoostEventListener; -import io.github.eggy03.papertrail.bot.listeners.auditlogsupl.event.guild.GuildMemberJoinAndLeaveEventListener; -import io.github.eggy03.papertrail.bot.listeners.auditlogsupl.event.guild.GuildPollEventListener; -import io.github.eggy03.papertrail.bot.listeners.auditlogsupl.event.guild.GuildVoiceEventListener; -import io.github.eggy03.papertrail.bot.listeners.command.AuditLogSetupCommandListener; -import io.github.eggy03.papertrail.bot.listeners.command.BotSetupInstructionCommandListener; -import io.github.eggy03.papertrail.bot.listeners.command.DebugCommandListener; -import io.github.eggy03.papertrail.bot.listeners.command.MessageLogSetupCommandListener; -import io.github.eggy03.papertrail.bot.listeners.command.ServerStatCommandListener; -import io.github.eggy03.papertrail.bot.listeners.messagelog.event.MessageLogListener; -import io.github.eggy03.papertrail.bot.listeners.misc.SelfKickListener; -import io.github.eggy03.papertrail.bot.listeners.misc.SlashCommandRegistrationListener; -import io.github.eggy03.papertrail.sdk.client.AuditLogRegistrationClient; -import io.github.eggy03.papertrail.sdk.client.MessageLogContentClient; -import io.github.eggy03.papertrail.sdk.client.MessageLogRegistrationClient; -import lombok.NonNull; -import net.dv8tion.jda.api.OnlineStatus; -import net.dv8tion.jda.api.requests.GatewayIntent; -import net.dv8tion.jda.api.requests.RestConfig; -import net.dv8tion.jda.api.sharding.DefaultShardManagerBuilder; -import net.dv8tion.jda.api.sharding.ShardManager; -import net.dv8tion.jda.api.utils.ChunkingFilter; -import net.dv8tion.jda.api.utils.MemberCachePolicy; -import net.dv8tion.jda.api.utils.cache.CacheFlag; -import org.jetbrains.annotations.ApiStatus; -import org.jspecify.annotations.Nullable; - -import java.util.concurrent.ExecutorService; - -/** - * A wrapper over {@link DefaultShardManagerBuilder} configured with defaults - */ -public class BootstrapService { - - private final @NonNull DefaultShardManagerBuilder builder; - - public BootstrapService(@NonNull String token) { - builder = DefaultShardManagerBuilder.createDefault(token); - } - - public BootstrapService applyRecommendedPreset() { - - builder.enableIntents(GatewayIntent.SCHEDULED_EVENTS, - GatewayIntent.AUTO_MODERATION_EXECUTION, - GatewayIntent.AUTO_MODERATION_CONFIGURATION, - GatewayIntent.MESSAGE_CONTENT, - GatewayIntent.GUILD_MEMBERS, - GatewayIntent.GUILD_EXPRESSIONS, - GatewayIntent.GUILD_PRESENCES, - GatewayIntent.GUILD_MODERATION - ); - - //cache all members - builder.setMemberCachePolicy(MemberCachePolicy.ALL); - // cache all activities - builder.enableCache(CacheFlag.ACTIVITY, - CacheFlag.CLIENT_STATUS, - CacheFlag.EMOJI, - CacheFlag.STICKER, - CacheFlag.ONLINE_STATUS, - CacheFlag.MEMBER_OVERRIDES, - CacheFlag.ROLE_TAGS, - CacheFlag.SCHEDULED_EVENTS - ); - // chunk all guilds - builder.setChunkingFilter(ChunkingFilter.ALL); - return this; - - } - - public BootstrapService applyDefaultStatus() { - builder.setStatus(OnlineStatus.ONLINE); - return this; - } - - public BootstrapService applyPreBuildEventListeners( - @NonNull ExecutorService vThreadPool, - @NonNull AuditLogRegistrationClient auditLogRegistrationClient, - @NonNull MessageLogRegistrationClient messageLogRegistrationClient, - @NonNull MessageLogContentClient messageLogContentClient - ) { - - builder.addEventListeners( - - new AuditLogSetupCommandListener(auditLogRegistrationClient), - new AuditLogEventListener(auditLogRegistrationClient, vThreadPool), - - new MessageLogSetupCommandListener(messageLogRegistrationClient), - new MessageLogListener(messageLogRegistrationClient, messageLogContentClient, vThreadPool), - - new GuildVoiceEventListener(auditLogRegistrationClient, vThreadPool), - new GuildMemberJoinAndLeaveEventListener(auditLogRegistrationClient, vThreadPool), - new GuildPollEventListener(auditLogRegistrationClient, vThreadPool), - new GuildBoostEventListener(auditLogRegistrationClient, vThreadPool), - new SelfKickListener(auditLogRegistrationClient, messageLogRegistrationClient, vThreadPool), - - new ServerStatCommandListener(), - new BotSetupInstructionCommandListener(), - new DebugCommandListener(vThreadPool, auditLogRegistrationClient, messageLogRegistrationClient), - new SlashCommandRegistrationListener() - ); - return this; - } - - public BootstrapService applySharding(@Nullable String minShardId, @Nullable String maxShardId, @Nullable String totalShards) { - - // default to single shards in case of nulls (allows for easier user config) - // only advanced users who know what they are doing should care about sharding - if (minShardId == null || maxShardId == null || totalShards == null) { - builder - .setShardsTotal(1) - .setShards(0, 0); - } else { - builder - .setShardsTotal(Integer.parseInt(totalShards)) - .setShards(Integer.parseInt(minShardId), Integer.parseInt(maxShardId)); - } - return this; - } - - /** - *

- * Allows you to use provide a custom proxy server address that will - * change the base of all routes from {@code discord.com} to {@code baseUrl} - *

- *

- * Can be used with Twilight HTTP Proxy - * to enforce a synchronization of the global rate limit across - * multiple processes/instances of the bot - *

- * - * @param baseUrl in the form of {@code host:port}. No config is applied if the baseUrl is null or blank - * @return the {@link BootstrapService} instance. Useful for chaining. - */ - @ApiStatus.Experimental - public BootstrapService applyProxyConfig(@Nullable String baseUrl) { - - if (baseUrl == null || baseUrl.isBlank()) - return this; - - builder.setRestConfig(new RestConfig().setBaseUrl(baseUrl)); - return this; - } - - public ShardManager start() { - return builder.build(); - } - -} diff --git a/src/main/java/io/github/eggy03/papertrail/bot/main/Start.java b/src/main/java/io/github/eggy03/papertrail/bot/main/Start.java deleted file mode 100644 index b5a4a45d..00000000 --- a/src/main/java/io/github/eggy03/papertrail/bot/main/Start.java +++ /dev/null @@ -1,50 +0,0 @@ -package io.github.eggy03.papertrail.bot.main; - -import io.github.eggy03.papertrail.bot.listeners.misc.ActivityUpdateListener; -import io.github.eggy03.papertrail.bot.utils.EnvConfig; -import io.github.eggy03.papertrail.sdk.client.AuditLogRegistrationClient; -import io.github.eggy03.papertrail.sdk.client.MessageLogContentClient; -import io.github.eggy03.papertrail.sdk.client.MessageLogRegistrationClient; -import net.dv8tion.jda.api.sharding.ShardManager; - -import java.util.Objects; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; - -/* - * The main class of the bot - */ -public class Start { - - static void main() { - - // get env vars - final String token = Objects.requireNonNull(EnvConfig.get("TOKEN"), "Discord Token cannot be null"); - final String papertrailApiBaseUrl = Objects.requireNonNull(EnvConfig.get("API_URL"), "PaperTrail API URL cannot be null"); - final String minShardId = EnvConfig.get("MIN_SHARD_ID"); // min for this instance - final String maxShardId = EnvConfig.get("MAX_SHARD_ID"); // max for this instance - final String totalShards = EnvConfig.get("TOTAL_SHARDS"); // total shards for all instances - final String customBaseUrlProxy = EnvConfig.get("PROXY_URL"); // custom proxy url for the rate limited twilight discord http proxy - - // set v-thread pools for listeners - final ExecutorService vThreadPool = Executors.newVirtualThreadPerTaskExecutor(); - - // initialize SDK clients to call papertrail API service - final AuditLogRegistrationClient auditLogRegistrationClient = new AuditLogRegistrationClient(papertrailApiBaseUrl); - final MessageLogRegistrationClient messageLogRegistrationClient = new MessageLogRegistrationClient(papertrailApiBaseUrl); - final MessageLogContentClient messageLogContentClient = new MessageLogContentClient(papertrailApiBaseUrl); - - // boostrap the bot - ShardManager manager = new BootstrapService(token) - .applyRecommendedPreset() - .applyDefaultStatus() - .applyPreBuildEventListeners(vThreadPool, auditLogRegistrationClient, messageLogRegistrationClient, messageLogContentClient) - .applySharding(minShardId, maxShardId, totalShards) - .applyProxyConfig(customBaseUrlProxy) - .start(); - - // post build listeners that require a fully built shard manager - manager.addEventListener(new ActivityUpdateListener(manager)); - } - -} diff --git a/src/main/java/io/github/eggy03/papertrail/bot/utils/BooleanUtils.java b/src/main/java/io/github/eggy03/papertrail/bot/utils/BooleanUtils.java index a4f3264d..8358f272 100644 --- a/src/main/java/io/github/eggy03/papertrail/bot/utils/BooleanUtils.java +++ b/src/main/java/io/github/eggy03/papertrail/bot/utils/BooleanUtils.java @@ -2,16 +2,15 @@ import lombok.NonNull; import lombok.experimental.UtilityClass; -import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @UtilityClass -public class BooleanUtils { +public final class BooleanUtils { @NonNull private static final String FALLBACK_STRING = "N/A"; - @NotNull + @NonNull public static String formatToEmoji(@Nullable Object booleanValueObject) { if (booleanValueObject == null) { @@ -24,7 +23,7 @@ public static String formatToEmoji(@Nullable Object booleanValueObject) { return "❌"; } - @NotNull + @NonNull public static String formatToYesOrNo(@Nullable Object booleanValueObject) { if (booleanValueObject == null) { @@ -38,7 +37,7 @@ public static String formatToYesOrNo(@Nullable Object booleanValueObject) { return "No"; } - @NotNull + @NonNull public static String formatToEnabledOrDisabled(@Nullable Object booleanValueObject) { if (booleanValueObject == null) { return FALLBACK_STRING; diff --git a/src/main/java/io/github/eggy03/papertrail/bot/utils/DurationUtils.java b/src/main/java/io/github/eggy03/papertrail/bot/utils/DurationUtils.java index 36825fde..03eede04 100644 --- a/src/main/java/io/github/eggy03/papertrail/bot/utils/DurationUtils.java +++ b/src/main/java/io/github/eggy03/papertrail/bot/utils/DurationUtils.java @@ -12,7 +12,7 @@ @UtilityClass @Slf4j -public class DurationUtils { +public final class DurationUtils { @NonNull private static final String FALLBACK_STRING = "N/A"; diff --git a/src/main/java/io/github/eggy03/papertrail/bot/utils/EnvConfig.java b/src/main/java/io/github/eggy03/papertrail/bot/utils/EnvConfig.java deleted file mode 100644 index 9064d407..00000000 --- a/src/main/java/io/github/eggy03/papertrail/bot/utils/EnvConfig.java +++ /dev/null @@ -1,24 +0,0 @@ -package io.github.eggy03.papertrail.bot.utils; - -import io.github.cdimascio.dotenv.Dotenv; -import lombok.NonNull; -import lombok.experimental.UtilityClass; -import org.jspecify.annotations.Nullable; - -@UtilityClass -public class EnvConfig { - - @NonNull - private static final Dotenv dotenv = Dotenv.configure().ignoreIfMalformed().ignoreIfMissing().load(); - - @Nullable - public static String get(@NonNull String key) { - - String value = dotenv.get(key); - if (value != null) { - return value; - } - - return System.getenv(key); - } -} diff --git a/src/main/java/io/github/eggy03/papertrail/bot/utils/NumberParseUtils.java b/src/main/java/io/github/eggy03/papertrail/bot/utils/NumberParseUtils.java index 760b3e97..c3b90b64 100644 --- a/src/main/java/io/github/eggy03/papertrail/bot/utils/NumberParseUtils.java +++ b/src/main/java/io/github/eggy03/papertrail/bot/utils/NumberParseUtils.java @@ -10,7 +10,7 @@ @UtilityClass @Slf4j -public class NumberParseUtils { +public final class NumberParseUtils { @Nullable public static Long parseLong(@Nullable Object possibleLongValue) { diff --git a/src/main/java/io/github/eggy03/papertrail/bot/utils/StackWalkerUtils.java b/src/main/java/io/github/eggy03/papertrail/bot/utils/StackWalkerUtils.java deleted file mode 100644 index 1537cd4d..00000000 --- a/src/main/java/io/github/eggy03/papertrail/bot/utils/StackWalkerUtils.java +++ /dev/null @@ -1,28 +0,0 @@ -package io.github.eggy03.papertrail.bot.utils; - -import lombok.experimental.UtilityClass; -import org.jetbrains.annotations.NotNull; - -import java.util.stream.Collectors; - -@UtilityClass -@Deprecated(forRemoval = true) -@SuppressWarnings({"java:S1123", "java:S1133"}) -public class StackWalkerUtils { - - private static final StackWalker STACK_WALKER = StackWalker.getInstance(StackWalker.Option.RETAIN_CLASS_REFERENCE); - - // will show call hierarchies - @NotNull - @Deprecated(forRemoval = true) - public static String getCallHierarchy() { - return STACK_WALKER.walk(frames -> frames - .skip(1) - .limit(3) - .map(frame -> frame.getDeclaringClass().getSimpleName() + - "#" + frame.getMethodName() + - ":" + frame.getLineNumber() - ).collect(Collectors.joining(" -> ")) - ); - } -} diff --git a/src/main/java/io/github/eggy03/papertrail/bot/listeners/auditlog/helper/automod/utils/AutoModUtils.java b/src/main/java/io/github/eggy03/papertrail/bot/utils/auditlog/AutoModUtils.java similarity index 75% rename from src/main/java/io/github/eggy03/papertrail/bot/listeners/auditlog/helper/automod/utils/AutoModUtils.java rename to src/main/java/io/github/eggy03/papertrail/bot/utils/auditlog/AutoModUtils.java index c83f3b9d..c98646f2 100644 --- a/src/main/java/io/github/eggy03/papertrail/bot/listeners/auditlog/helper/automod/utils/AutoModUtils.java +++ b/src/main/java/io/github/eggy03/papertrail/bot/utils/auditlog/AutoModUtils.java @@ -1,26 +1,19 @@ -package io.github.eggy03.papertrail.bot.listeners.auditlog.helper.automod.utils; +package io.github.eggy03.papertrail.bot.utils.auditlog; import io.github.eggy03.papertrail.bot.utils.NumberParseUtils; import lombok.NonNull; import lombok.experimental.UtilityClass; import net.dv8tion.jda.api.entities.automod.AutoModEventType; import net.dv8tion.jda.api.entities.automod.AutoModTriggerType; -import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; - -/* - * See {@link io.github.eggy03.papertrail.bot.utils.StackWalkerUtils} - * and other utilities in the util package - * to know why logging isn't needed here - */ @UtilityClass -public class AutoModUtils { +public final class AutoModUtils { @NonNull public static final String FALLBACK_STRING = "N/A"; - @NotNull + @NonNull public static String autoModEventTypeResolver(@Nullable Object autoModEventTypeInteger) { Integer eventTypeInt = NumberParseUtils.parseInt(autoModEventTypeInteger); if (eventTypeInt == null) { @@ -30,7 +23,7 @@ public static String autoModEventTypeResolver(@Nullable Object autoModEventTypeI return AutoModEventType.fromKey(eventTypeInt).name(); } - @NotNull + @NonNull public static String autoModTriggerTypeResolver(@Nullable Object autoModTriggerTypeInteger) { Integer triggerTypeInt = NumberParseUtils.parseInt(autoModTriggerTypeInteger); if (triggerTypeInt == null) diff --git a/src/main/java/io/github/eggy03/papertrail/bot/listeners/auditlog/helper/channel/utils/ChannelUtils.java b/src/main/java/io/github/eggy03/papertrail/bot/utils/auditlog/ChannelUtils.java similarity index 90% rename from src/main/java/io/github/eggy03/papertrail/bot/listeners/auditlog/helper/channel/utils/ChannelUtils.java rename to src/main/java/io/github/eggy03/papertrail/bot/utils/auditlog/ChannelUtils.java index 25f3a7a5..d2c5f14b 100644 --- a/src/main/java/io/github/eggy03/papertrail/bot/listeners/auditlog/helper/channel/utils/ChannelUtils.java +++ b/src/main/java/io/github/eggy03/papertrail/bot/utils/auditlog/ChannelUtils.java @@ -1,4 +1,4 @@ -package io.github.eggy03.papertrail.bot.listeners.auditlog.helper.channel.utils; +package io.github.eggy03.papertrail.bot.utils.auditlog; import io.github.eggy03.papertrail.bot.utils.NumberParseUtils; import lombok.NonNull; @@ -9,19 +9,13 @@ import net.dv8tion.jda.api.entities.Role; import net.dv8tion.jda.api.entities.channel.ChannelType; import net.dv8tion.jda.api.events.guild.GenericGuildEvent; -import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.util.EnumSet; -/* - * See {@link io.github.eggy03.papertrail.bot.utils.StackWalkerUtils} - * and other utilities in the util package - * to know why logging isn't needed in some of the methods here - */ @UtilityClass @Slf4j -public class ChannelUtils { +public final class ChannelUtils { @NonNull public static final String FALLBACK_STRING = "N/A"; @@ -29,7 +23,7 @@ public class ChannelUtils { /** * can also be used for threads */ - @NotNull + @NonNull public static String resolveChannelType(@Nullable Object channelTypeInteger) { Integer channelType = NumberParseUtils.parseInt(channelTypeInteger); @@ -39,7 +33,7 @@ public static String resolveChannelType(@Nullable Object channelTypeInteger) { return ChannelType.fromId(channelType).name(); } - @NotNull + @NonNull public static String resolveVoiceChannelUserLimit(@Nullable Object limitNumber) { Integer userLimit = NumberParseUtils.parseInt(limitNumber); if (userLimit == null) @@ -48,7 +42,7 @@ public static String resolveVoiceChannelUserLimit(@Nullable Object limitNumber) return userLimit == 0 ? "Unlimited" : userLimit.toString(); } - @NotNull + @NonNull public static String resolveVoiceChannelBitrate(@Nullable Object bitrateInteger) { Integer bitrate = NumberParseUtils.parseInt(bitrateInteger); if (bitrate == null) @@ -57,7 +51,7 @@ public static String resolveVoiceChannelBitrate(@Nullable Object bitrateInteger) return (bitrate / 1000) + " kbps"; } - @NotNull + @NonNull public static String resolveVoiceChannelVideoQuality(@Nullable Object voiceChannelVideoQualityInteger) { Integer videoQuality = NumberParseUtils.parseInt(voiceChannelVideoQualityInteger); @@ -71,7 +65,7 @@ public static String resolveVoiceChannelVideoQuality(@Nullable Object voiceChann } // CHANNEL OVERRIDE UTILS - @NotNull + @NonNull public static String resolveChannelOverrideTargetType(@Nullable Object targetTypeInteger) { Integer targetType = NumberParseUtils.parseInt(targetTypeInteger); @@ -84,7 +78,7 @@ public static String resolveChannelOverrideTargetType(@Nullable Object targetTyp } - @NotNull + @NonNull public static String resolveChannelOverridePermissions(@Nullable Object permissionValueLong, @NonNull String emoji) { Long permissionValue = NumberParseUtils.parseLong(permissionValueLong); @@ -106,7 +100,7 @@ public static String resolveChannelOverridePermissions(@Nullable Object permissi } // MISC UTILS - @NotNull + @NonNull public static String autoResolveMemberOrRole(@Nullable Object memberOrRoleId, @NonNull GenericGuildEvent event) { if (memberOrRoleId == null) { diff --git a/src/main/java/io/github/eggy03/papertrail/bot/listeners/auditlog/helper/guild/utils/GuildUtils.java b/src/main/java/io/github/eggy03/papertrail/bot/utils/auditlog/GuildUtils.java similarity index 90% rename from src/main/java/io/github/eggy03/papertrail/bot/listeners/auditlog/helper/guild/utils/GuildUtils.java rename to src/main/java/io/github/eggy03/papertrail/bot/utils/auditlog/GuildUtils.java index c5d0a7bd..bea40b4b 100644 --- a/src/main/java/io/github/eggy03/papertrail/bot/listeners/auditlog/helper/guild/utils/GuildUtils.java +++ b/src/main/java/io/github/eggy03/papertrail/bot/utils/auditlog/GuildUtils.java @@ -1,4 +1,4 @@ -package io.github.eggy03.papertrail.bot.listeners.auditlog.helper.guild.utils; +package io.github.eggy03.papertrail.bot.utils.auditlog; import io.github.eggy03.papertrail.bot.utils.NumberParseUtils; import lombok.NonNull; @@ -8,22 +8,16 @@ import net.dv8tion.jda.api.entities.channel.middleman.GuildChannel; import net.dv8tion.jda.api.entities.guild.SystemChannelFlag; import net.dv8tion.jda.api.events.guild.GenericGuildEvent; -import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -/* - * See {@link io.github.eggy03.papertrail.bot.utils.StackWalkerUtils} - * and other utilities in the util package - * to know why logging isn't needed in some of the methods here - */ @UtilityClass -public class GuildUtils { +public final class GuildUtils { @NonNull private static final String FALLBACK_STRING = "N/A"; // GUILD UTILS - @NotNull + @NonNull public static String resolveGuildVerificationLevel(@Nullable Object verificationLevelInteger) { Integer verificationLevel = NumberParseUtils.parseInt(verificationLevelInteger); @@ -39,7 +33,7 @@ public static String resolveGuildVerificationLevel(@Nullable Object verification } - @NotNull + @NonNull public static String resolveGuildModActionMFALevel(@Nullable Object mfaLevelInteger) { Integer mfaLevel = NumberParseUtils.parseInt(mfaLevelInteger); if (mfaLevel == null) @@ -49,7 +43,7 @@ public static String resolveGuildModActionMFALevel(@Nullable Object mfaLevelInte } - @NotNull + @NonNull public static String resolveGuildDefaultMessageNotificationLevel(@Nullable Object notificationLevelInteger) { Integer notificationLevel = NumberParseUtils.parseInt(notificationLevelInteger); if (notificationLevel == null) @@ -59,7 +53,7 @@ public static String resolveGuildDefaultMessageNotificationLevel(@Nullable Objec } - @NotNull + @NonNull public static String resolveExplicitContentFilterLevel(@Nullable Object explicitContentFilterLevelInteger) { Integer ecfLevel = NumberParseUtils.parseInt(explicitContentFilterLevelInteger); if (ecfLevel == null) @@ -68,7 +62,7 @@ public static String resolveExplicitContentFilterLevel(@Nullable Object explicit return Guild.ExplicitContentLevel.fromKey(ecfLevel).getDescription(); } - @NotNull + @NonNull public static String resolveSystemChannelFlags(@Nullable Object systemChannelFlagsIntegerObject) { Integer systemChannelFlagsInteger = NumberParseUtils.parseInt(systemChannelFlagsIntegerObject); @@ -90,7 +84,7 @@ public static String resolveSystemChannelFlags(@Nullable Object systemChannelFla } // MISC GUILD UTILS (BROADER COVERAGE) - @NotNull + @NonNull public static String resolveMentionableChannel(@Nullable Object channelId, @NonNull GenericGuildEvent event) { Long channelIdLong = NumberParseUtils.parseLong(channelId); if (channelIdLong == null) @@ -100,7 +94,7 @@ public static String resolveMentionableChannel(@Nullable Object channelId, @NonN return channel != null ? channel.getAsMention() : channelIdLong.toString(); } - @NotNull + @NonNull public static String resolveOwnerName(@Nullable Object ownerId, @NonNull GenericGuildEvent event) { Long ownerIdLong = NumberParseUtils.parseLong(ownerId); if (ownerIdLong == null) diff --git a/src/main/java/io/github/eggy03/papertrail/bot/listeners/auditlog/helper/invite/utils/InviteUtils.java b/src/main/java/io/github/eggy03/papertrail/bot/utils/auditlog/InviteUtils.java similarity index 92% rename from src/main/java/io/github/eggy03/papertrail/bot/listeners/auditlog/helper/invite/utils/InviteUtils.java rename to src/main/java/io/github/eggy03/papertrail/bot/utils/auditlog/InviteUtils.java index 11bfe041..79d13de7 100644 --- a/src/main/java/io/github/eggy03/papertrail/bot/listeners/auditlog/helper/invite/utils/InviteUtils.java +++ b/src/main/java/io/github/eggy03/papertrail/bot/utils/auditlog/InviteUtils.java @@ -1,4 +1,4 @@ -package io.github.eggy03.papertrail.bot.listeners.auditlog.helper.invite.utils; +package io.github.eggy03.papertrail.bot.utils.auditlog; import io.github.eggy03.papertrail.bot.utils.NumberParseUtils; import lombok.NonNull; @@ -8,7 +8,6 @@ import net.dv8tion.jda.api.entities.channel.middleman.GuildChannel; import net.dv8tion.jda.api.events.guild.GenericGuildEvent; import net.dv8tion.jda.api.events.guild.GuildAuditLogEntryCreateEvent; -import org.jetbrains.annotations.NotNull; import org.jspecify.annotations.Nullable; import java.util.List; @@ -16,11 +15,11 @@ import java.util.stream.Collectors; @UtilityClass -public class InviteUtils { +public final class InviteUtils { public static final String FALLBACK_STRING = "N/A"; - @NotNull + @NonNull public static String resolveInviter(@Nullable Object inviterId, @NonNull GuildAuditLogEntryCreateEvent event) { Long inviterIdLong = NumberParseUtils.parseLong(inviterId); @@ -31,7 +30,7 @@ public static String resolveInviter(@Nullable Object inviterId, @NonNull GuildAu return member != null ? member.getAsMention() : inviterIdLong.toString(); } - @NotNull + @NonNull public static String resolveInviteChannel(@Nullable Object inviteChannelId, @NonNull GuildAuditLogEntryCreateEvent event) { Long inviteChannelIdLong = NumberParseUtils.parseLong(inviteChannelId); @@ -42,7 +41,7 @@ public static String resolveInviteChannel(@Nullable Object inviteChannelId, @Non return channel != null ? channel.getAsMention() : inviteChannelIdLong.toString(); } - @NotNull + @NonNull public static String resolveMaxUses(@Nullable Object usageCountIntegerObject) { Integer maxUses = NumberParseUtils.parseInt(usageCountIntegerObject); @@ -57,7 +56,7 @@ public static String resolveMaxUses(@Nullable Object usageCountIntegerObject) { } // the object is an array of Role IDs - @NotNull + @NonNull public static String resolveInviteRoleList(@NonNull GenericGuildEvent event, @Nullable Object inviteRoleObject) { if (!(inviteRoleObject instanceof List inviteRoleList) || inviteRoleList.isEmpty()) diff --git a/src/main/java/io/github/eggy03/papertrail/bot/listeners/auditlog/helper/member/utils/MemberUtils.java b/src/main/java/io/github/eggy03/papertrail/bot/utils/auditlog/MemberUtils.java similarity index 52% rename from src/main/java/io/github/eggy03/papertrail/bot/listeners/auditlog/helper/member/utils/MemberUtils.java rename to src/main/java/io/github/eggy03/papertrail/bot/utils/auditlog/MemberUtils.java index 8b86170d..c6b3b402 100644 --- a/src/main/java/io/github/eggy03/papertrail/bot/listeners/auditlog/helper/member/utils/MemberUtils.java +++ b/src/main/java/io/github/eggy03/papertrail/bot/utils/auditlog/MemberUtils.java @@ -1,4 +1,4 @@ -package io.github.eggy03.papertrail.bot.listeners.auditlog.helper.member.utils; +package io.github.eggy03.papertrail.bot.utils.auditlog; import io.github.eggy03.papertrail.bot.utils.NumberParseUtils; import lombok.NonNull; @@ -6,7 +6,7 @@ import lombok.extern.slf4j.Slf4j; import net.dv8tion.jda.api.entities.Role; import net.dv8tion.jda.api.events.guild.GenericGuildEvent; -import org.jetbrains.annotations.NotNull; +import net.dv8tion.jda.api.utils.MarkdownUtil; import org.jetbrains.annotations.Nullable; import java.util.List; @@ -14,21 +14,16 @@ import java.util.Objects; import java.util.stream.Collectors; -/* - * See {@link io.github.eggy03.papertrail.bot.utils.StackWalkerUtils} - * and other utilities in the util package - * to know why logging isn't needed in some of the methods here - */ @UtilityClass @Slf4j -public class MemberUtils { +public final class MemberUtils { @NonNull public static final String FALLBACK_STRING = "N/A"; // Parses an array list of map of role objects supplied by JDA // roles are exposed as arraylists of maps [{name=role, id=1}, {name=role2, id=2}] - @NotNull + @NonNull public static String parseRoleListMap(@NonNull GenericGuildEvent event, @Nullable Object roleObject) { if (!(roleObject instanceof List roleList) || roleList.isEmpty()) @@ -45,4 +40,24 @@ public static String parseRoleListMap(@NonNull GenericGuildEvent event, @Nullabl .collect(Collectors.joining(" ")); } + + @NonNull + @SuppressWarnings("all") + public static String resolveNickNameChanges(@Nullable Object oldNickValue, @Nullable Object newNickValue) { + + if (oldNickValue == null && newNickValue != null) { // change from global name to a new nickname in the server + return "Added Nickname: " + MarkdownUtil.underline(newNickValue.toString()); + } + + if (oldNickValue != null && newNickValue == null) { // change to the global name from having a nickname + return "Reset Nickname From: " + MarkdownUtil.underline(oldNickValue.toString()); + } + + if (oldNickValue != null && newNickValue != null) { // changing from one nick to another + return "Changed Nickname From: " + MarkdownUtil.underline(oldNickValue.toString()) + " to: " + MarkdownUtil.underline(newNickValue.toString()); + } + + // both shouldn't be null which indicates that names couldn't be fetched from the event + return MarkdownUtil.underline("Changes could not be resolved!"); + } } diff --git a/src/main/java/io/github/eggy03/papertrail/bot/listeners/auditlog/helper/message/utils/MessageUtils.java b/src/main/java/io/github/eggy03/papertrail/bot/utils/auditlog/MessageUtils.java similarity index 88% rename from src/main/java/io/github/eggy03/papertrail/bot/listeners/auditlog/helper/message/utils/MessageUtils.java rename to src/main/java/io/github/eggy03/papertrail/bot/utils/auditlog/MessageUtils.java index 7a3a90f8..b93b4931 100644 --- a/src/main/java/io/github/eggy03/papertrail/bot/listeners/auditlog/helper/message/utils/MessageUtils.java +++ b/src/main/java/io/github/eggy03/papertrail/bot/utils/auditlog/MessageUtils.java @@ -1,4 +1,4 @@ -package io.github.eggy03.papertrail.bot.listeners.auditlog.helper.message.utils; +package io.github.eggy03.papertrail.bot.utils.auditlog; import io.github.eggy03.papertrail.bot.utils.NumberParseUtils; import lombok.NonNull; @@ -7,15 +7,14 @@ import net.dv8tion.jda.api.entities.channel.concrete.TextChannel; import net.dv8tion.jda.api.events.guild.GenericGuildEvent; import org.jetbrains.annotations.Blocking; -import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @UtilityClass -public class MessageUtils { +public final class MessageUtils { private static final String FALLBACK_STRING = "N/A"; - @NotNull + @NonNull @Blocking public static String resolveMessageJumpUrlFromId(@Nullable Object channelId, @Nullable Object messageId, @NonNull GenericGuildEvent event) { diff --git a/src/main/java/io/github/eggy03/papertrail/bot/listeners/auditlog/helper/onboarding/utils/OnboardingUtils.java b/src/main/java/io/github/eggy03/papertrail/bot/utils/auditlog/OnboardingUtils.java similarity index 89% rename from src/main/java/io/github/eggy03/papertrail/bot/listeners/auditlog/helper/onboarding/utils/OnboardingUtils.java rename to src/main/java/io/github/eggy03/papertrail/bot/utils/auditlog/OnboardingUtils.java index b7892e32..fd8ff7d3 100644 --- a/src/main/java/io/github/eggy03/papertrail/bot/listeners/auditlog/helper/onboarding/utils/OnboardingUtils.java +++ b/src/main/java/io/github/eggy03/papertrail/bot/utils/auditlog/OnboardingUtils.java @@ -1,4 +1,4 @@ -package io.github.eggy03.papertrail.bot.listeners.auditlog.helper.onboarding.utils; +package io.github.eggy03.papertrail.bot.utils.auditlog; import io.github.eggy03.papertrail.bot.utils.NumberParseUtils; import lombok.NonNull; @@ -6,7 +6,6 @@ import lombok.extern.slf4j.Slf4j; import net.dv8tion.jda.api.entities.Guild; import net.dv8tion.jda.api.entities.channel.middleman.GuildChannel; -import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.util.List; @@ -15,12 +14,12 @@ @UtilityClass @Slf4j -public class OnboardingUtils { +public final class OnboardingUtils { @NonNull public static final String FALLBACK_STRING = "N/A"; - @NotNull + @NonNull public static String formatMode(@Nullable Object value) { if (value == null) { log.debug("format mode value was null"); @@ -37,7 +36,7 @@ public static String formatMode(@Nullable Object value) { }; } - @NotNull + @NonNull public static String resolveChannelsFromList(@NonNull Guild guild, @Nullable Object value) { if (!(value instanceof List channelIdList) || channelIdList.isEmpty()) diff --git a/src/main/java/io/github/eggy03/papertrail/bot/listeners/auditlog/helper/role/utils/RoleUtils.java b/src/main/java/io/github/eggy03/papertrail/bot/utils/auditlog/RoleUtils.java similarity index 88% rename from src/main/java/io/github/eggy03/papertrail/bot/listeners/auditlog/helper/role/utils/RoleUtils.java rename to src/main/java/io/github/eggy03/papertrail/bot/utils/auditlog/RoleUtils.java index f340d130..c4c1fbf3 100644 --- a/src/main/java/io/github/eggy03/papertrail/bot/listeners/auditlog/helper/role/utils/RoleUtils.java +++ b/src/main/java/io/github/eggy03/papertrail/bot/utils/auditlog/RoleUtils.java @@ -1,30 +1,24 @@ -package io.github.eggy03.papertrail.bot.listeners.auditlog.helper.role.utils; +package io.github.eggy03.papertrail.bot.utils.auditlog; import io.github.eggy03.papertrail.bot.utils.NumberParseUtils; import lombok.NonNull; import lombok.experimental.UtilityClass; import lombok.extern.slf4j.Slf4j; import net.dv8tion.jda.api.Permission; -import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.util.EnumSet; import java.util.IllegalFormatException; import java.util.Map; -/* - * See {@link io.github.eggy03.papertrail.bot.utils.StackWalkerUtils} - * and other utilities in the util package - * to know why logging isn't needed in some of the methods here - */ @UtilityClass @Slf4j -public class RoleUtils { +public final class RoleUtils { @NonNull private static final String FALLBACK_STRING = "N/A"; - @NotNull + @NonNull public static String resolveRolePermissions(@Nullable Object permissionsValue, @NonNull String emoji) { Long permissionLong = NumberParseUtils.parseLong(permissionsValue); if (permissionLong == null) @@ -46,7 +40,7 @@ public static String resolveRolePermissions(@Nullable Object permissionsValue, @ return permissions.toString().trim(); } - @NotNull + @NonNull public static String formatToHex(@Nullable Object colorValueInteger) { if (colorValueInteger == null) { @@ -72,7 +66,7 @@ public static String formatToHex(@Nullable Object colorValueInteger) { * gradient is returned as a map in the following structure * {"primary_color" = 123456789, "secondary_color" = 123456789, "tertiary_color" = 123456789} */ - @NotNull + @NonNull public static String formatGradientToHex(@Nullable Object gradientMap) { if (gradientMap == null) { diff --git a/src/main/java/io/github/eggy03/papertrail/bot/utils/auditlog/ScheduledEventUtils.java b/src/main/java/io/github/eggy03/papertrail/bot/utils/auditlog/ScheduledEventUtils.java new file mode 100644 index 00000000..b80e3fca --- /dev/null +++ b/src/main/java/io/github/eggy03/papertrail/bot/utils/auditlog/ScheduledEventUtils.java @@ -0,0 +1,36 @@ +package io.github.eggy03.papertrail.bot.utils.auditlog; + +import io.github.eggy03.papertrail.bot.utils.NumberParseUtils; +import lombok.NonNull; +import lombok.experimental.UtilityClass; +import lombok.extern.slf4j.Slf4j; +import net.dv8tion.jda.api.entities.ScheduledEvent; +import org.jetbrains.annotations.Nullable; + +@UtilityClass +@Slf4j +public final class ScheduledEventUtils { + + @NonNull + public static final String FALLBACK_STRING = "N/A"; + + @NonNull + public static String resolveEventType(@Nullable Object eventTypeInteger) { + + Integer eventType = NumberParseUtils.parseInt(eventTypeInteger); + if (eventType == null) + return FALLBACK_STRING; + + return ScheduledEvent.Type.fromKey(eventType).name(); + + } + + @NonNull + public static String resolveStatusType(@Nullable Object eventTypeInteger) { + Integer eventType = NumberParseUtils.parseInt(eventTypeInteger); + if (eventType == null) + return FALLBACK_STRING; + + return ScheduledEvent.Status.fromKey(eventType).name(); + } +} diff --git a/src/main/java/io/github/eggy03/papertrail/bot/listeners/auditlog/helper/soundboard/utils/SoundboardUtils.java b/src/main/java/io/github/eggy03/papertrail/bot/utils/auditlog/SoundboardUtils.java similarity index 57% rename from src/main/java/io/github/eggy03/papertrail/bot/listeners/auditlog/helper/soundboard/utils/SoundboardUtils.java rename to src/main/java/io/github/eggy03/papertrail/bot/utils/auditlog/SoundboardUtils.java index 17f8bca4..cae8c20b 100644 --- a/src/main/java/io/github/eggy03/papertrail/bot/listeners/auditlog/helper/soundboard/utils/SoundboardUtils.java +++ b/src/main/java/io/github/eggy03/papertrail/bot/utils/auditlog/SoundboardUtils.java @@ -1,21 +1,16 @@ -package io.github.eggy03.papertrail.bot.listeners.auditlog.helper.soundboard.utils; +package io.github.eggy03.papertrail.bot.utils.auditlog; import io.github.eggy03.papertrail.bot.utils.NumberParseUtils; +import lombok.NonNull; import lombok.experimental.UtilityClass; -import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.math.RoundingMode; -/* - * See {@link io.github.eggy03.papertrail.bot.utils.StackWalkerUtils} - * and other utilities in the util package - * to know why logging isn't needed in some of the methods here - */ @UtilityClass -public class SoundboardUtils { +public final class SoundboardUtils { - @NotNull + @NonNull public static String resolveVolumePercentage(@Nullable Object decimalVolume) { Double volume = NumberParseUtils.parseDouble(decimalVolume, 4, RoundingMode.HALF_UP); if (volume == null) diff --git a/src/main/java/io/github/eggy03/papertrail/bot/listeners/auditlog/helper/stage/utils/StageUtils.java b/src/main/java/io/github/eggy03/papertrail/bot/utils/auditlog/StageUtils.java similarity index 66% rename from src/main/java/io/github/eggy03/papertrail/bot/listeners/auditlog/helper/stage/utils/StageUtils.java rename to src/main/java/io/github/eggy03/papertrail/bot/utils/auditlog/StageUtils.java index 8994b97d..c8810367 100644 --- a/src/main/java/io/github/eggy03/papertrail/bot/listeners/auditlog/helper/stage/utils/StageUtils.java +++ b/src/main/java/io/github/eggy03/papertrail/bot/utils/auditlog/StageUtils.java @@ -1,20 +1,15 @@ -package io.github.eggy03.papertrail.bot.listeners.auditlog.helper.stage.utils; +package io.github.eggy03.papertrail.bot.utils.auditlog; import io.github.eggy03.papertrail.bot.utils.NumberParseUtils; +import lombok.NonNull; import lombok.experimental.UtilityClass; import net.dv8tion.jda.api.entities.StageInstance; -import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -/* - * See {@link io.github.eggy03.papertrail.bot.utils.StackWalkerUtils} - * and other utilities in the util package - * to know why logging isn't needed in some of the methods here - */ @UtilityClass -public class StageUtils { +public final class StageUtils { - @NotNull + @NonNull public static String resolveStagePrivacyLevel(@Nullable Object stagePrivacyLevelInteger) { Integer privacyLevel = NumberParseUtils.parseInt(stagePrivacyLevelInteger); diff --git a/src/main/java/io/github/eggy03/papertrail/bot/listeners/auditlog/helper/sticker/utils/StickerUtils.java b/src/main/java/io/github/eggy03/papertrail/bot/utils/auditlog/StickerUtils.java similarity index 90% rename from src/main/java/io/github/eggy03/papertrail/bot/listeners/auditlog/helper/sticker/utils/StickerUtils.java rename to src/main/java/io/github/eggy03/papertrail/bot/utils/auditlog/StickerUtils.java index ad629030..731420c4 100644 --- a/src/main/java/io/github/eggy03/papertrail/bot/listeners/auditlog/helper/sticker/utils/StickerUtils.java +++ b/src/main/java/io/github/eggy03/papertrail/bot/utils/auditlog/StickerUtils.java @@ -1,4 +1,4 @@ -package io.github.eggy03.papertrail.bot.listeners.auditlog.helper.sticker.utils; +package io.github.eggy03.papertrail.bot.utils.auditlog; import lombok.NonNull; import lombok.experimental.UtilityClass; @@ -6,17 +6,16 @@ import net.dv8tion.jda.api.entities.emoji.Emoji; import net.dv8tion.jda.api.entities.sticker.GuildSticker; import net.dv8tion.jda.api.events.guild.GenericGuildEvent; -import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @UtilityClass @Slf4j -public class StickerUtils { +public final class StickerUtils { @NonNull public static final String FALLBACK_STRING = "N/A"; - @NotNull + @NonNull public static String resolveStickerUrl(@NonNull GenericGuildEvent event, @Nullable Object stickerIdObject) { if (stickerIdObject == null) { @@ -39,7 +38,7 @@ public static String resolveStickerUrl(@NonNull GenericGuildEvent event, @Nullab // emojiIdObject does NOT give you snowflake IDs in case of Unicode emojis // it only gives u IDs in case of custom emojis // any values caught by NumberFormatException are Unicode emojis and can be returned raw - @NotNull + @NonNull public static String resolveRelatedEmoji(@NonNull GenericGuildEvent event, @Nullable Object emojiIdObject) { if (emojiIdObject == null) { @@ -59,7 +58,7 @@ public static String resolveRelatedEmoji(@NonNull GenericGuildEvent event, @Null } return emoji.getFormatted(); - } catch (NumberFormatException e) { + } catch (NumberFormatException _) { log.debug("value is not numeric, treating as Unicode (value={}, guild={})", emojiIdString, event.getGuild().getId()); return emojiIdString; } diff --git a/src/main/java/io/github/eggy03/papertrail/bot/listeners/auditlog/helper/thread/utils/ThreadUtils.java b/src/main/java/io/github/eggy03/papertrail/bot/utils/auditlog/ThreadUtils.java similarity index 64% rename from src/main/java/io/github/eggy03/papertrail/bot/listeners/auditlog/helper/thread/utils/ThreadUtils.java rename to src/main/java/io/github/eggy03/papertrail/bot/utils/auditlog/ThreadUtils.java index 8fe2cb59..efd6255d 100644 --- a/src/main/java/io/github/eggy03/papertrail/bot/listeners/auditlog/helper/thread/utils/ThreadUtils.java +++ b/src/main/java/io/github/eggy03/papertrail/bot/utils/auditlog/ThreadUtils.java @@ -1,24 +1,18 @@ -package io.github.eggy03.papertrail.bot.listeners.auditlog.helper.thread.utils; +package io.github.eggy03.papertrail.bot.utils.auditlog; import io.github.eggy03.papertrail.bot.utils.NumberParseUtils; import lombok.NonNull; import lombok.experimental.UtilityClass; import net.dv8tion.jda.api.entities.channel.concrete.ThreadChannel; -import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -/* - * See {@link io.github.eggy03.papertrail.bot.utils.StackWalkerUtils} - * and other utilities in the util package - * to know why logging isn't needed in some of the methods here - */ @UtilityClass -public class ThreadUtils { +public final class ThreadUtils { @NonNull public static final String FALLBACK_STRING = "N/A"; - @NotNull + @NonNull public static String resolveAutoArchiveDuration(@Nullable Object minutes) { Integer minuteInt = NumberParseUtils.parseInt(minutes); diff --git a/src/main/java/io/github/eggy03/papertrail/bot/listeners/auditlog/helper/webhook/utils/WebhookUtils.java b/src/main/java/io/github/eggy03/papertrail/bot/utils/auditlog/WebhookUtils.java similarity index 80% rename from src/main/java/io/github/eggy03/papertrail/bot/listeners/auditlog/helper/webhook/utils/WebhookUtils.java rename to src/main/java/io/github/eggy03/papertrail/bot/utils/auditlog/WebhookUtils.java index 2c0a3f11..fc7201d1 100644 --- a/src/main/java/io/github/eggy03/papertrail/bot/listeners/auditlog/helper/webhook/utils/WebhookUtils.java +++ b/src/main/java/io/github/eggy03/papertrail/bot/utils/auditlog/WebhookUtils.java @@ -1,20 +1,19 @@ -package io.github.eggy03.papertrail.bot.listeners.auditlog.helper.webhook.utils; +package io.github.eggy03.papertrail.bot.utils.auditlog; import io.github.eggy03.papertrail.bot.utils.NumberParseUtils; import lombok.NonNull; import lombok.experimental.UtilityClass; import lombok.extern.slf4j.Slf4j; -import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @UtilityClass @Slf4j -public class WebhookUtils { +public final class WebhookUtils { @NonNull public static final String FALLBACK_STRING = "N/A"; - @NotNull + @NonNull public static String resolveWebhookEventType(@Nullable Object webhookInteger) { Integer webhook = NumberParseUtils.parseInt(webhookInteger); diff --git a/src/main/resources/META-INF/io/github/eggy03/papertrailbot/native-image/reachability-metadata.json b/src/main/resources/META-INF/io/github/eggy03/papertrailbot/native-image/reachability-metadata.json new file mode 100644 index 00000000..b355ce76 --- /dev/null +++ b/src/main/resources/META-INF/io/github/eggy03/papertrailbot/native-image/reachability-metadata.json @@ -0,0 +1,79 @@ +{ + "reflection": [ + { + "type": "io.github.eggy03.papertrail.sdk.client.AuditLogRegistrationClient" + }, + { + "type": "io.github.eggy03.papertrail.sdk.client.MessageLogContentClient" + }, + { + "type": "io.github.eggy03.papertrail.sdk.client.MessageLogRegistrationClient" + }, + { + "type": "io.github.eggy03.papertrail.sdk.entity.AuditLogRegistrationEntity", + "allDeclaredConstructors": true, + "allDeclaredFields": true, + "allDeclaredMethods": true + }, + { + "type": "io.github.eggy03.papertrail.sdk.entity.MessageLogContentEntity", + "allDeclaredConstructors": true, + "allDeclaredFields": true, + "allDeclaredMethods": true + }, + { + "type": "io.github.eggy03.papertrail.sdk.entity.MessageLogRegistrationEntity", + "allDeclaredConstructors": true, + "allDeclaredFields": true, + "allDeclaredMethods": true + }, + { + "type": "io.github.eggy03.papertrail.sdk.entity.ErrorEntity", + "allDeclaredConstructors": true, + "allDeclaredFields": true, + "allDeclaredMethods": true + }, + { + "type": "net.dv8tion.jda.api.entities.User[]" + }, + { + "type": "net.dv8tion.jda.api.entities.Role[]" + }, + { + "type": "net.dv8tion.jda.api.entities.Guild[]" + }, + { + "type": "net.dv8tion.jda.api.entities.Member[]" + }, + { + "type": "net.dv8tion.jda.api.entities.ScheduledEvent[]" + }, + { + "type": "net.dv8tion.jda.api.entities.ThreadMember[]" + }, + { + "type": "net.dv8tion.jda.api.entities.channel.Channel[]" + }, + { + "type": "net.dv8tion.jda.api.entities.channel.forums.ForumTag[]" + }, + { + "type": "net.dv8tion.jda.api.entities.channel.middleman.GuildChannel[]" + }, + { + "type": "net.dv8tion.jda.api.entities.emoji.RichCustomEmoji[]" + }, + { + "type": "net.dv8tion.jda.api.entities.sticker.GuildSticker[]" + }, + { + "type": "net.dv8tion.jda.api.managers.AudioManager[]" + }, + { + "type": "net.dv8tion.jda.internal.entities.GuildVoiceStateImpl[]" + }, + { + "type": "net.dv8tion.jda.internal.entities.MemberPresenceImpl[]" + } + ] +} \ No newline at end of file diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties new file mode 100644 index 00000000..c5a3b594 --- /dev/null +++ b/src/main/resources/application.properties @@ -0,0 +1,26 @@ +# Token +discord.token=${TOKEN} + +# PaperTrail API URL +api.url=${API_URL} + +# Shard Config +min.shard.id=${MIN_SHARD_ID:0} +max.shard.id=${MAX_SHARD_ID:0} +total.shards=${TOTAL_SHARDS:1} + +# Twilight HTTP Proxy URL +# default value is a whitespace +twilight.http.proxy.url=${TWILIGHT_HTTP_PROXY_URL: } + +#Port +quarkus.http.port=${PORT:8080} + +# Logging Level +quarkus.log.level=${LOG_LEVEL:INFO} + +# Analytics +quarkus.analytics.disabled=true + +# Banner +quarkus.banner.path=banner.txt \ No newline at end of file diff --git a/src/main/resources/banner.txt b/src/main/resources/banner.txt new file mode 100644 index 00000000..cb67b825 --- /dev/null +++ b/src/main/resources/banner.txt @@ -0,0 +1,8 @@ + _____ _______ _ _ + | __ \ |__ __| (_) | + | |__) |_ _ _ __ ___ _ __| |_ __ __ _ _| | + | ___/ _` | '_ \ / _ \ '__| | '__/ _` | | | + | | | (_| | |_) | __/ | | | | | (_| | | | + |_| \__,_| .__/ \___|_| |_|_| \__,_|_|_| + | | + |_| \ No newline at end of file diff --git a/src/main/resources/tinylog.properties b/src/main/resources/tinylog.properties deleted file mode 100644 index a9bf9fa4..00000000 --- a/src/main/resources/tinylog.properties +++ /dev/null @@ -1,4 +0,0 @@ -writer=console -writer.format={level}: {class}.{method}()\n{message} -writer.level=info -writingthread=true \ No newline at end of file