diff --git a/PRIVACY.md b/PRIVACY.md index 9dc33aab..f0e076ee 100644 --- a/PRIVACY.md +++ b/PRIVACY.md @@ -2,11 +2,17 @@ **Data Controller:** This project is maintained by [@Egg-03](https://github.com/eggy03). -This Discord bot was built as an open source project with a privacy-first mindset. The Service is provided at no cost and is intended for use as-is. +This Discord bot was built as an open source project with a privacy-first mindset. +The Service is provided at no cost and is intended for use as-is. This page is used to inform users regarding our policies with the collection, use, and disclosure of information for anyone choosing to use the bot. -If you choose to use this bot in your Discord server, you agree to the collection and use of information in accordance with this policy. The data collected is strictly limited to what is necessary for the bot's core functionality and moderation features. We do not use or share your data with anyone except as described here. +If you choose to use this bot in your Discord server, you agree to the collection and use of information in accordance with this policy. +The data collected is strictly limited to what is necessary for the bot's core functionality and moderation features. + +We do not sell your data. +We do not share personal data with third parties except where necessary to provide the service, such as cloud hosting and database providers, or in response to lawful requests. +Any third-party processors we use are bound by contractual data-protection requirements and may only process data on our behalf and for the purpose of providing the service. --- @@ -15,7 +21,8 @@ If you choose to use this bot in your Discord server, you agree to the collectio This Privacy Policy applies **only** to the official hosted instance of this bot that is managed by [@Egg-03](https://github.com/eggy03). The official instance can be identified by its **Discord Application ID: `1381658412550590475`**. -If you or someone else self-hosts the bot, that instance is operated independently and is **not covered by this Privacy Policy**. In those cases, data handling is the sole responsibility of the self-host. +If you or someone else self-hosts the bot, that instance is operated independently and is **not covered by this Privacy Policy**. +In those cases, data handling is the sole responsibility of the host of that particular instance. --- @@ -24,14 +31,14 @@ If you or someone else self-hosts the bot, that instance is operated independent The bot only stores data when specific features are explicitly enabled by server administrators: ### If **Message Logging** is enabled: -- Message Content (encrypted at rest, only decrypted when sending logs back to your Discord server) +- Message Content - Message ID - Author ID (Discord user ID) - Channel ID - Guild ID - Timestamp -Message content is never stored in plain text and is not used for analytics or shared outside of your server. +Message content is stored in plain text and is not used for analytics or shared outside your server. ### If **only Audit Logging** is enabled: - Guild ID @@ -45,24 +52,31 @@ The stored data is used solely for server moderation purposes. ## Data Retention -- All stored message data is automatically deleted after **30 days**. When message data is deleted, both the encrypted content and associated metadata are permanently removed from the database. -- No data is permanently retained or used for analytics. -- Configuration data (e.g., log channel IDs) is kept until the server administrator removes it or disables the feature. +- All stored message contents and their metadata are automatically deleted after **30 days**. +- No data is permanently retained or used for any analytics. +- Configuration data (e.g., log channel IDs) is kept until the server administrator unregisters the bot or removes it from the server. - Server administrators can also request immediate deletion of all stored data for their guild by contacting us. --- -## Log Data +## Diagnostic Logs + +In case of runtime errors, the bot may log basic diagnostic information such as error messages, timestamps, and internal event states to assist with debugging. +Logs may include additional metadata such as guild IDs, channel IDs, message IDs, or user IDs when necessary to diagnose issues. -In case of runtime errors, the bot may log basic diagnostic information such as error messages, timestamps, and internal event states to assist with debugging. These logs do not contain any personal user data and are not persisted long-term. +Log retention is governed by our infrastructure providers and operational requirements, and may vary over time. +Logs are not used for analytics. --- ## Security -We take data protection seriously: -- All sensitive data (e.g., message content) is encrypted before being saved. -- Decryption keys are securely managed and are only used to deliver logs back to your Discord server. They are never used for analytics or operator access. +We take reasonable technical and organizational measures to protect stored data from unauthorized access, loss, or misuse. +This includes access controls, limited operator access, and infrastructure security best practices. + +Message content is stored in plain text on cloud infrastructure. +This is the same general model used by Discord (i.e., messages are not end-to-end encrypted). +We do not perform analytics on message content. However, no method of transmission over the internet or method of electronic storage is 100% secure, and we cannot guarantee absolute security. @@ -70,18 +84,21 @@ However, no method of transmission over the internet or method of electronic sto ## Children’s Privacy -This bot is not intended for users under the age of 13. It does not knowingly collect any personal information from children. If it is discovered that such data has been inadvertently stored, it will be deleted immediately upon request. +This bot is not intended for users under the age of 13. It does not knowingly collect any personal information from children. +If it is discovered that such data has been inadvertently stored, it will be deleted immediately upon request. --- -## User Rights (GDPR Compliance) +## User Rights -If you are located in the EU/EEA, you have the following rights under the General Data Protection Regulation (GDPR): +All users, regardless of location, have the following rights: - **Right of Access**: You may request what data (if any) is associated with your Discord user ID. - **Right to Erasure**: You may request deletion of your data from the database. -Due to the encryption of message content, we are unable to provide decrypted content under any circumstances. +To protect user privacy, we will verify the identity of the requestor before fulfilling access or deletion requests (for example: confirmation from the guild owner or proof of control of the Discord user account). +We will respond to verified requests within 30 days. +If additional information is needed, we will notify you and may extend the response period where permitted by law. To request access or deletion, please contact us using the method below. @@ -89,9 +106,9 @@ To request access or deletion, please contact us using the method below. ## Contact -For privacy-related questions or GDPR requests: +For privacy-related questions or other requests: - GitHub: [Submit an issue or discussion](https://github.com/eggy03/PaperTrailBot/issues) -- Email: `egg03@duck.com` +- Email: `eggzerothree@proton.me` --- diff --git a/README.md b/README.md index ebdc6219..a9545f67 100644 --- a/README.md +++ b/README.md @@ -1,10 +1,10 @@ # Overview -PaperTrail is a free and open source, self-hostable and privacy-friendly Discord bot designed to deliver structured, reliable logging across all major audit and runtime events. It hooks into Discord's audit logs to cover for most of the audit log events and for events not covered by Audit Logs, it supplements them with real-time listeners to bridge gaps in native coverage (e.g. voice state, boosts, message edits and deletions, custom triggers). +PaperTrail is a free and open-source, self-hostable, and privacy-friendly Discord bot designed to provide audit log data directly in a channelβ€”without requiring users to navigate server settings each time. Key Features: - Full audit log integration (supports over 50+ event types) and generic support for unknown types -- Encrypted Message logging (edit, delete) +- Message logging (edit, delete) - Member activity tracking (joins, leaves, kicks, bans, updates) - Voice activity logging (join/leave, move) - Auto-deletion of logged messages after 30 days @@ -24,32 +24,27 @@ Key Features: > > It is recommended that you deploy the [Persistence API](https://github.com/Egg-03/PaperTrail-PersistenceAPI?tab=readme-ov-file#papertrail-persistenceapi) service before deploying the bot itself since the bot relies on the URL of the service to communicate -## v1.2.2 Legacy -Checkout the guide for hosting the legacy version [here](https://github.com/Egg-03/PaperTrailBot/blob/legacy-v1.2.2/README.md). -v1.2.2 has unresolved bugs and runs on JDA 5. It is recommended to not use that version anymore. - -## V2 and above -Since v2, the project has been split into two services: +The project is split into two services: 1) The core bot service 2) A [Persistence API](https://github.com/Egg-03/PaperTrail-PersistenceAPI) service The following guide shows how to set up the bot service -To read the guide on deploying the Persistence API Service, click [here](https://github.com/Egg-03/PaperTrail-PersistenceAPI?tab=readme-ov-file#papertrail-persistenceapi) +To read the guide on deploying the Persistence API Service, click [here](https://github.com/eggy03/PaperTrail-PersistenceAPI?tab=readme-ov-file#papertrail-persistenceapi) ### Step 1: Get Required Secrets You will need the following environment variables to run the bot: -| Variable | Description | -| ---------------- | -------------------------------------------------------------------------------------------------------- | -| `TOKEN` | Discord application bot token (from the [Developer Portal](https://discord.com/developers/applications)) | -| `MESSAGE_SECRET` | Random secret string for encrypting/decrypting messages (generate yourself) | -| `API_URL` | Internal URL of the Persistence API (e.g., `http://persistence:8080`) | +| Variable | Description | +|-----------|-----------------------------------------------------------------------------------------------------------| +| `TOKEN` | Discord application bot token (from the [Developer Portal](https://discord.com/developers/applications)) | +| `API_URL` | Internal URL of the Persistence API (e.g., `http://persistence:8080`) | ### Step 2: Deployment Options -Fork this repository to your GitHub account, connect it to your preferred cloud platform, and configure your environment variables in the platform. Some paltform services may also support adding secrets directly from your `.env` file. +Fork this repository to your GitHub account, connect it to your preferred cloud platform, and configure your environment variables in the platform. +Some platform services may also support adding secrets directly from your `.env` file. #### Cloud Platforms with GitHub + Docker Support - These can auto-deploy using the included `Dockerfile` @@ -68,19 +63,18 @@ Fork this repository to your GitHub account, connect it to your preferred cloud The bot exposes a `/ping` endpoint on port **8080**. This endpoint simply returns `200 OK` and is intended for platforms or uptime monitors to check if the bot is alive. -> Note: This is **not a public API** and serves no other function beyond health monitoring. +> Note: This is **not a public API** and serves no other function beyond internal service health monitoring. # Privacy PaperTrail is built with privacy-first principles. By default, it **does not log any personal data** unless features are explicitly enabled by server admins. - Messages are logged for moderation purposes only, if enabled. -- All stored messages are encrypted before being saved to the database. - Logs are automatically deleted after 30 days. - No personal data is used for analytics, profiling, or sold to third parties. - If requested, users can have their data deleted by ID. -*Never post sensitive information in public channels. While PaperTrail encrypts all the data it receives, other bots may not.* +*Never post sensitive information in public channels.* [Read the full Privacy Policy](./PRIVACY.md) @@ -89,14 +83,15 @@ PaperTrail is built with privacy-first principles. By default, it **does not log If you discover a security vulnerability in PaperTrail, please report it **privately**. - Do **not** open public GitHub issues for security bugs. -- Instead, email me at πŸ“§ **egg03@duck.com** +- Instead, email me at πŸ“§ **eggzerothree@proton.me** - I will respond as soon as possible and work with you to resolve the issue. [View the full Security Policy](./SECURITY.md) # Terms of Use -PaperTrail is provided under the Apache 2.0 License and is intended for responsible use. By using the public instance or self-hosting it, you agree to the basic terms outlined in our [Terms of Service](./TERMS.md). +PaperTrail is provided under the Apache 2.0 License and is intended for responsible use. +By using the official hosted instance or self-hosting it, you agree to the basic terms outlined in our [Terms of Service](./TERMS.md). # License @@ -110,5 +105,4 @@ You are free to: Just make sure to include proper attribution and comply with the [terms](https://www.apache.org/licenses/LICENSE-2.0). --- -Feel free to contribute to this guide or raise issues on GitHub if you get stuck! - +Feel free to contribute to this guide or raise issues on GitHub if you get stuck! \ No newline at end of file diff --git a/SECURITY.md b/SECURITY.md index 0ce49ef4..efb7ec42 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -8,7 +8,7 @@ Currently, only the `main` branch of PaperTrail is actively maintained. Bug fixe If you discover a security vulnerability in PaperTrail, please **do not open a GitHub issue**. Instead, report it responsibly by contacting: -πŸ“§ **egg03@duck.com** +πŸ“§ **eggzerothree@proton.me** Please include: diff --git a/TERMS.md b/TERMS.md index a88f620b..5c66e6d7 100644 --- a/TERMS.md +++ b/TERMS.md @@ -1,10 +1,10 @@ # Terms of Service -_Last updated: June 22, 2025_ +_Last updated: February 02, 2026_ -Thank you for using **PaperTrail**, an open-source Discord logging bot. +Thank you for using **PaperTrail**, an open-source Discord audit and message logging bot. -By using this software (either self-hosted or via the public instance), you agree to the following terms: +By using this software (either self-hosted or via the official hosted instance), you agree to the following terms: --- @@ -12,7 +12,7 @@ By using this software (either self-hosted or via the public instance), you agre You may use this bot for free, either: - By hosting it yourself -- Or by using the public hosted instance (if one is available) +- Or by using the official hosted instance (if available) You agree to use the bot responsibly, and not for any of the following: - Harassment, abuse, or spamming users @@ -23,26 +23,43 @@ You agree to use the bot responsibly, and not for any of the following: ## 2. Privacy -This bot logs message and event data **only if you enable those features**. All message content is encrypted, and logs are automatically deleted after 30 days. See our [Privacy Policy](./PRIVACY.md) for details. +This bot logs message and event data **only if you enable those features**. +Message content is stored in plain text and logs are automatically deleted after 30 days. + +See our [Privacy Policy](./PRIVACY.md) for full details on data handling, retention, and user rights. + +--- + +## 3. Self-Hosting + +If you self-host this bot, you are solely responsible for: +- Data storage and retention +- Security practices +- Compliance with applicable privacy laws + +The project maintainers are not responsible for how self-hosted instances handle user data. --- -## 3. Modifications +## 4. Modifications -You are free to fork, modify, or self-host this project under the terms of the [Apache 2.0 License](./LICENSE). If you publicly redistribute a modified version, you must preserve the original license. +You are free to fork, modify, or self-host this project under the terms of the [Apache 2.0 License](./LICENSE). +If you publicly redistribute a modified version, you must preserve the original license and attribution. --- -## 4. No Warranty +## 5. No Warranty -This software is provided **"as is"**, without any warranty of any kind. The developers are not liable for any damages, data loss, or moderation outcomes resulting from the use of this bot. +This software is provided **"as is"**, without any warranty of any kind. +The developers are not liable for any damages, data loss, or moderation outcomes resulting from the use of this bot. --- -## 5. Changes +## 6. Changes -We may update these terms as the project evolves. You are encouraged to check this document periodically. +We may update these terms as the project evolves. +Continued use of the bot after changes constitutes acceptance of the updated terms. --- -If you have any questions or concerns, please open an issue on the [GitHub repository](https://github.com/Egg-03/PaperTrailBot/issues). +If you have any questions or concerns, please open an issue on the [GitHub repository](https://github.com/eggy03/PaperTrailBot/issues). diff --git a/pom.xml b/pom.xml index 039818a3..d222788a 100644 --- a/pom.xml +++ b/pom.xml @@ -1,113 +1,160 @@ - - 4.0.0 - org.egg.papertrail - paper-trail-bot - 2.3.1 - PaperTrail - A simple bot for logging all user actions - - UTF-8 - UTF-8 - 21 - 21 - 1.18.42 - - - - - net.dv8tion - JDA - 6.3.0 - - - org.tinylog - slf4j-tinylog - 2.7.0 - - - org.tinylog - tinylog-api - 2.7.0 - - - org.tinylog - tinylog-impl - 2.7.0 - - - io.github.cdimascio - dotenv-java - 3.2.0 - - - org.apache.commons - commons-lang3 - 3.19.0 - - - org.jasypt - jasypt - 1.9.3 - - - org.bouncycastle - bcprov-jdk18on - 1.81 - - - com.google.guava - guava - 33.4.8-jre - - - - org.springframework.boot - spring-boot-restclient - 4.0.0-M2 - - - - io.vavr - vavr - 0.10.7 - - - com.google.code.gson - gson - 2.13.1 - - - org.projectlombok - lombok - ${lombok.version} - - - - - ${project.artifactId} - - - org.springframework.boot - spring-boot-maven-plugin - 3.5.7 - - org.papertrail.main.FireRun - - - - org.apache.maven.plugins - maven-compiler-plugin - 3.14.1 - - - - org.projectlombok - lombok - ${lombok.version} - - - - - - + + + 4.0.0 + + org.egg.papertrail + paper-trail-bot + 2.4.0 + PaperTrail + A simple bot for logging all user actions + + + UTF-8 + UTF-8 + 21 + 21 + + + 6.3.0 + 1.0.0 + 2.7.0 + 3.2.0 + 3.19.0 + 1.9.3 + 1.83 + 33.4.8-jre + 7.0.3 + 2.13.2 + 1.18.42 + + + 3.5.7 + 3.14.1 + + + + + Central Portal Snapshots + central-portal-snapshots + https://central.sonatype.com/repository/maven-snapshots/ + + false + + + true + + + + + + + net.dv8tion + JDA + ${jda.version} + + + + org.tinylog + slf4j-tinylog + ${tinylog.version} + + + org.tinylog + tinylog-api + ${tinylog.version} + + + org.tinylog + tinylog-impl + ${tinylog.version} + + + + io.github.cdimascio + dotenv-java + ${dotenv.version} + + + + org.apache.commons + commons-lang3 + ${commons-lang3.version} + + + + org.jasypt + jasypt + ${jasypt.version} + + + + org.bouncycastle + bcprov-jdk18on + ${bouncycastle.version} + + + + com.google.guava + guava + ${guava.version} + + + + org.springframework + spring-web + ${spring.version} + + + + io.github.eggy03 + papertrail-sdk + ${papertrail.sdk.version} + + + + com.google.code.gson + gson + ${gson.version} + + + + org.projectlombok + lombok + ${lombok.version} + provided + + + + + ${project.artifactId} + + + + org.springframework.boot + spring-boot-maven-plugin + ${spring-boot-maven-plugin.version} + + org.papertrail.main.Start + + + + + org.apache.maven.plugins + maven-compiler-plugin + ${maven-compiler-plugin.version} + + + + org.projectlombok + lombok + ${lombok.version} + + + + + + + diff --git a/src/main/java/org/papertrail/commons/constant/ProjectInfo.java b/src/main/java/org/papertrail/commons/constant/ProjectInfo.java index 6bfcf42a..9b8cf5fe 100644 --- a/src/main/java/org/papertrail/commons/constant/ProjectInfo.java +++ b/src/main/java/org/papertrail/commons/constant/ProjectInfo.java @@ -7,6 +7,6 @@ private ProjectInfo() { } public static final String APPNAME = "PaperTrail"; - public static final String VERSION = "v2.3.1"; + public static final String VERSION = "v2.4.0"; public static final String PROJECT_ISSUE_LINK="https://github.com/eggy03/PaperTrailBot/issues"; } diff --git a/src/main/java/org/papertrail/commons/sdk/client/AuditLogClient.java b/src/main/java/org/papertrail/commons/sdk/client/AuditLogClient.java deleted file mode 100644 index 1b30ad63..00000000 --- a/src/main/java/org/papertrail/commons/sdk/client/AuditLogClient.java +++ /dev/null @@ -1,72 +0,0 @@ -package org.papertrail.commons.sdk.client; - -import io.vavr.control.Either; -import org.jetbrains.annotations.NotNull; -import org.papertrail.commons.sdk.http.HttpServiceEngine; -import org.papertrail.commons.sdk.model.AuditLogObject; -import org.papertrail.commons.sdk.model.ErrorObject; -import org.papertrail.commons.utilities.EnvConfig; -import org.springframework.http.HttpHeaders; -import org.springframework.http.HttpMethod; - -import java.util.List; - -public class AuditLogClient { - - private static final String BASE_URL = EnvConfig.get("API_URL"); - private static final HttpHeaders httpHeaders = new HttpHeaders(); - private static final HttpServiceEngine engine = HttpServiceEngine.getInstance(); - - static { - httpHeaders.put("Content-Type", List.of("application/json")); - } - - private AuditLogClient() { - throw new IllegalStateException("Client class"); - } - - @NotNull - public static Either registerGuild(String guildId, String channelId){ - - return engine.makeRequestWithBody( - HttpMethod.POST, - BASE_URL +"api/v1/log/audit", - httpHeaders, - new AuditLogObject(guildId, channelId), - AuditLogObject.class - ); - } - - @NotNull - public static Either getRegisteredGuild(String guildId){ - - return engine.makeRequest( - HttpMethod.GET, - BASE_URL +"api/v1/log/audit/"+guildId, - httpHeaders, - AuditLogObject.class - ); - } - - @NotNull - public static Either updateRegisteredGuild(String guildId, String channelId){ - - return engine.makeRequestWithBody( - HttpMethod.PUT, - BASE_URL +"api/v1/log/audit", - httpHeaders, - new AuditLogObject(guildId, channelId), - AuditLogObject.class - ); - } - - public static Either deleteRegisteredGuild(String guildId){ - - return engine.makeRequest( - HttpMethod.DELETE, - BASE_URL +"api/v1/log/audit/"+guildId, - httpHeaders, - Void.class - ); - } -} diff --git a/src/main/java/org/papertrail/commons/sdk/client/MessageContentLogClient.java b/src/main/java/org/papertrail/commons/sdk/client/MessageContentLogClient.java deleted file mode 100644 index 201d66af..00000000 --- a/src/main/java/org/papertrail/commons/sdk/client/MessageContentLogClient.java +++ /dev/null @@ -1,76 +0,0 @@ -package org.papertrail.commons.sdk.client; - -import io.vavr.control.Either; -import org.jetbrains.annotations.NotNull; -import org.papertrail.commons.sdk.http.HttpServiceEngine; -import org.papertrail.commons.sdk.model.ErrorObject; -import org.papertrail.commons.sdk.model.MessageContentObject; -import org.papertrail.commons.utilities.EnvConfig; -import org.springframework.http.HttpHeaders; -import org.springframework.http.HttpMethod; - -import java.util.List; - -public class MessageContentLogClient { - - private static final String BASE_URL = EnvConfig.get("API_URL")+"api/v1/content/message"; - private static final HttpHeaders httpHeaders = new HttpHeaders(); - private static final HttpServiceEngine engine = HttpServiceEngine.getInstance(); - - static { - httpHeaders.put("Content-Type", List.of("application/json")); - } - - private MessageContentLogClient() { - throw new IllegalStateException("Client class"); - } - - @NotNull - public static Either logMessage(String messageId, String messageContent, String authorId){ - - return engine.makeRequestWithBody( - HttpMethod.POST, - BASE_URL, - httpHeaders, - new MessageContentObject(messageId, messageContent, authorId), - MessageContentObject.class - ); - - } - - @NotNull - public static Either retrieveMessage(String messageId){ - - return engine.makeRequest( - HttpMethod.GET, - BASE_URL+"/"+messageId, - httpHeaders, - MessageContentObject.class - ); - } - - @NotNull - public static Either updateMessage(String messageId, String messageContent, String authorId){ - - return engine.makeRequestWithBody( - HttpMethod.PUT, - BASE_URL, - httpHeaders, - new MessageContentObject(messageId, messageContent, authorId), - MessageContentObject.class - ); - } - - @NotNull - public static Either deleteMessage(String messageId) { - - return engine.makeRequest( - HttpMethod.DELETE, - BASE_URL+"/"+messageId, - httpHeaders, - Void.class - ); - - } -} - diff --git a/src/main/java/org/papertrail/commons/sdk/client/MessageLogClient.java b/src/main/java/org/papertrail/commons/sdk/client/MessageLogClient.java deleted file mode 100644 index 733e9d6a..00000000 --- a/src/main/java/org/papertrail/commons/sdk/client/MessageLogClient.java +++ /dev/null @@ -1,72 +0,0 @@ -package org.papertrail.commons.sdk.client; - -import io.vavr.control.Either; -import org.jetbrains.annotations.NotNull; -import org.papertrail.commons.sdk.http.HttpServiceEngine; -import org.papertrail.commons.sdk.model.ErrorObject; -import org.papertrail.commons.sdk.model.MessageLogObject; -import org.papertrail.commons.utilities.EnvConfig; -import org.springframework.http.HttpHeaders; -import org.springframework.http.HttpMethod; - -import java.util.List; - - -public class MessageLogClient { - - private static final String BASE_URL = EnvConfig.get("API_URL"); - private static final HttpHeaders httpHeaders = new HttpHeaders(); - private static final HttpServiceEngine engine = HttpServiceEngine.getInstance(); - - static { - httpHeaders.put("Content-Type", List.of("application/json")); - } - - private MessageLogClient(){ - throw new IllegalStateException("Client class"); - } - - @NotNull - public static Either registerGuild(String guildId, String channelId){ - - return engine.makeRequestWithBody( - HttpMethod.POST, - BASE_URL +"api/v1/log/message", - httpHeaders, - new MessageLogObject(guildId, channelId), - MessageLogObject.class - ); - } - - public static Either getRegisteredGuild(String guildId){ - - return engine.makeRequest( - HttpMethod.GET, - BASE_URL +"api/v1/log/message/"+guildId, - httpHeaders, - MessageLogObject.class - ); - - } - - public static Either updateRegisteredGuild(String guildId, String channelId){ - - return HttpServiceEngine.getInstance().makeRequestWithBody( - HttpMethod.PUT, - BASE_URL + "api/v1/log/message", - httpHeaders, - new MessageLogObject(guildId, channelId), - MessageLogObject.class - ); - } - - public static Either deleteRegisteredGuild(String guildId){ - - return engine.makeRequest( - HttpMethod.DELETE, - BASE_URL +"api/v1/log/message/"+guildId, - httpHeaders, - Void.class - ); - } -} diff --git a/src/main/java/org/papertrail/commons/sdk/http/HttpServiceEngine.java b/src/main/java/org/papertrail/commons/sdk/http/HttpServiceEngine.java deleted file mode 100644 index c7c00469..00000000 --- a/src/main/java/org/papertrail/commons/sdk/http/HttpServiceEngine.java +++ /dev/null @@ -1,93 +0,0 @@ -package org.papertrail.commons.sdk.http; - -import io.vavr.control.Either; -import lombok.extern.slf4j.Slf4j; -import org.jetbrains.annotations.NotNull; -import org.papertrail.commons.sdk.model.ErrorObject; -import org.springframework.http.HttpHeaders; -import org.springframework.http.HttpMethod; -import org.springframework.web.client.HttpClientErrorException; -import org.springframework.web.client.HttpServerErrorException; -import org.springframework.web.client.ResourceAccessException; -import org.springframework.web.client.RestClient; - -import java.net.URI; -import java.time.Instant; - -@Slf4j -public class HttpServiceEngine { - - private final RestClient client; - private static final HttpServiceEngine INSTANCE = new HttpServiceEngine(); - - private HttpServiceEngine() { - client = RestClient.builder().build(); - } - - public static HttpServiceEngine getInstance() { - return INSTANCE; - } - - public Either makeRequest ( - @NotNull HttpMethod httpMethod, - @NotNull String url, - @NotNull HttpHeaders headers, - @NotNull Class successResponseClass) { - - try { - S body = client.method(httpMethod) - .uri(URI.create(url)) - .headers(h-> h.addAll(headers)) - .retrieve() - .toEntity(successResponseClass) - .getBody(); - - return Either.right(body); - } catch (HttpClientErrorException e) { - log.trace("Client error when calling {} {}: {}", httpMethod, url, e.getMessage(), e); - ErrorObject error = e.getResponseBodyAs(ErrorObject.class); - return Either.left(error); - } catch (HttpServerErrorException e) { - log.error("Server error when calling {} {}: {}", httpMethod, url, e.getMessage(), e); - ErrorObject error = e.getResponseBodyAs(ErrorObject.class); - return Either.left(error); - } catch (ResourceAccessException e) { - log.error("Resource access error when calling {} {}: {}", httpMethod, url, e.getMessage(), e); - ErrorObject error = new ErrorObject(503, "API Unreachable", e.getMessage(), Instant.now().toString(), url); - return Either.left(error); - } - } - - public Either makeRequestWithBody ( - @NotNull HttpMethod httpMethod, - @NotNull String url, - @NotNull HttpHeaders headers, - @NotNull Object requestBody, - @NotNull Class successResponseClass) { - - try { - S body = client.method(httpMethod) - .uri(URI.create(url)) - .headers(h-> h.addAll(headers)) - .body(requestBody) - .retrieve() - .toEntity(successResponseClass) - .getBody(); - - return Either.right(body); - - } catch (HttpClientErrorException e) { - log.trace("Client error when calling {} {}: {}", httpMethod, url, e.getMessage(), e); - ErrorObject error = e.getResponseBodyAs(ErrorObject.class); - return Either.left(error); - } catch (HttpServerErrorException e) { - log.error("Server error when calling {} {}: {}", httpMethod, url, e.getMessage(), e); - ErrorObject error = e.getResponseBodyAs(ErrorObject.class); - return Either.left(error); - } catch (ResourceAccessException e) { - log.error("Resource access error when calling {} {}: {}", httpMethod, url, e.getMessage(), e); - ErrorObject error = new ErrorObject(503, "API Unreachable", e.getMessage(), Instant.now().toString(), url); - return Either.left(error); - } - } -} diff --git a/src/main/java/org/papertrail/commons/sdk/model/AuditLogObject.java b/src/main/java/org/papertrail/commons/sdk/model/AuditLogObject.java deleted file mode 100644 index 2d8c8243..00000000 --- a/src/main/java/org/papertrail/commons/sdk/model/AuditLogObject.java +++ /dev/null @@ -1,5 +0,0 @@ -package org.papertrail.commons.sdk.model; - -public record AuditLogObject(String guildId, String channelId) { - -} diff --git a/src/main/java/org/papertrail/commons/sdk/model/ErrorObject.java b/src/main/java/org/papertrail/commons/sdk/model/ErrorObject.java deleted file mode 100644 index d5b11b73..00000000 --- a/src/main/java/org/papertrail/commons/sdk/model/ErrorObject.java +++ /dev/null @@ -1,9 +0,0 @@ -package org.papertrail.commons.sdk.model; - -public record ErrorObject( - int status, - String error, - String message, - String timeStamp, - String path -){} diff --git a/src/main/java/org/papertrail/commons/sdk/model/MessageContentObject.java b/src/main/java/org/papertrail/commons/sdk/model/MessageContentObject.java deleted file mode 100644 index a6329ff3..00000000 --- a/src/main/java/org/papertrail/commons/sdk/model/MessageContentObject.java +++ /dev/null @@ -1,4 +0,0 @@ -package org.papertrail.commons.sdk.model; - -public record MessageContentObject(String messageId, String messageContent, String authorId) { -} diff --git a/src/main/java/org/papertrail/commons/sdk/model/MessageLogObject.java b/src/main/java/org/papertrail/commons/sdk/model/MessageLogObject.java deleted file mode 100644 index d4f41e40..00000000 --- a/src/main/java/org/papertrail/commons/sdk/model/MessageLogObject.java +++ /dev/null @@ -1,5 +0,0 @@ -package org.papertrail.commons.sdk.model; - -public record MessageLogObject(String guildId, String channelId) { - -} diff --git a/src/main/java/org/papertrail/commons/sdk/package-info.java b/src/main/java/org/papertrail/commons/sdk/package-info.java deleted file mode 100644 index 7cbd8608..00000000 --- a/src/main/java/org/papertrail/commons/sdk/package-info.java +++ /dev/null @@ -1,4 +0,0 @@ -/** - * Embedded SDK for resolving calls to the PaperTrail PersistenceAPI - */ -package org.papertrail.commons.sdk; diff --git a/src/main/java/org/papertrail/listeners/audit/event/AuditLogEventListener.java b/src/main/java/org/papertrail/listeners/audit/event/AuditLogEventListener.java index ff593d4b..e07c0c5b 100644 --- a/src/main/java/org/papertrail/listeners/audit/event/AuditLogEventListener.java +++ b/src/main/java/org/papertrail/listeners/audit/event/AuditLogEventListener.java @@ -1,15 +1,14 @@ package org.papertrail.listeners.audit.event; -import io.vavr.control.Either; +import io.github.eggy03.papertrail.sdk.client.AuditLogRegistrationClient; +import io.github.eggy03.papertrail.sdk.entity.AuditLogRegistrationEntity; 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 org.jetbrains.annotations.NotNull; -import org.papertrail.commons.sdk.client.AuditLogClient; -import org.papertrail.commons.sdk.model.AuditLogObject; -import org.papertrail.commons.sdk.model.ErrorObject; +import org.papertrail.commons.utilities.EnvConfig; import org.papertrail.listeners.audit.helper.AutoModerationFlagToChannelEventHelper; import org.papertrail.listeners.audit.helper.AutoModerationMemberTimeoutEventHelper; import org.papertrail.listeners.audit.helper.AutoModerationRuleBlockMessageEventHelper; @@ -65,12 +64,14 @@ import org.papertrail.listeners.audit.helper.WebhookRemoveEventHelper; import org.papertrail.listeners.audit.helper.WebhookUpdateEventHelper; +import java.util.Optional; import java.util.concurrent.Executor; @Slf4j public class AuditLogEventListener extends ListenerAdapter { private final Executor vThreadPool; + private static final AuditLogRegistrationClient client = new AuditLogRegistrationClient(EnvConfig.get("API_URL")); public AuditLogEventListener(Executor vThreadPool) { this.vThreadPool = vThreadPool; @@ -80,15 +81,13 @@ public AuditLogEventListener(Executor vThreadPool) { public void onGuildAuditLogEntryCreate(@NotNull GuildAuditLogEntryCreateEvent event) { vThreadPool.execute(() -> { // Call the API and see if the event came from a registered Guild - Either response = AuditLogClient.getRegisteredGuild(event.getGuild().getId()); - response.peek(success -> { - AuditLogEntry ale = event.getEntry(); - auditLogParser(event, ale, success.channelId()); - }); + Optional response = client.getRegisteredGuild(event.getGuild().getId()); + response.ifPresent(success -> auditLogParser(event, success.getChannelId())); }); } - private void auditLogParser(GuildAuditLogEntryCreateEvent event, AuditLogEntry ale, String channelIdToSendTo) { + private void auditLogParser(GuildAuditLogEntryCreateEvent event, String channelIdToSendTo) { + AuditLogEntry ale = event.getEntry(); ActionType action = ale.getType(); switch (action) { diff --git a/src/main/java/org/papertrail/listeners/audit/event/GuildBoostEventListener.java b/src/main/java/org/papertrail/listeners/audit/event/GuildBoostEventListener.java index 8b268c8f..a07ca290 100644 --- a/src/main/java/org/papertrail/listeners/audit/event/GuildBoostEventListener.java +++ b/src/main/java/org/papertrail/listeners/audit/event/GuildBoostEventListener.java @@ -1,6 +1,7 @@ package org.papertrail.listeners.audit.event; -import io.vavr.control.Either; +import io.github.eggy03.papertrail.sdk.client.AuditLogRegistrationClient; +import io.github.eggy03.papertrail.sdk.entity.AuditLogRegistrationEntity; import net.dv8tion.jda.api.EmbedBuilder; import net.dv8tion.jda.api.entities.Guild; import net.dv8tion.jda.api.entities.Member; @@ -11,18 +12,18 @@ import net.dv8tion.jda.api.events.guild.update.GuildUpdateBoostTierEvent; import net.dv8tion.jda.api.hooks.ListenerAdapter; import org.jspecify.annotations.NonNull; -import org.papertrail.commons.sdk.client.AuditLogClient; -import org.papertrail.commons.sdk.model.AuditLogObject; -import org.papertrail.commons.sdk.model.ErrorObject; +import org.papertrail.commons.utilities.EnvConfig; import java.awt.Color; import java.time.Instant; import java.time.OffsetDateTime; +import java.util.Optional; import java.util.concurrent.Executor; // Experimental public class GuildBoostEventListener extends ListenerAdapter { + private static final AuditLogRegistrationClient client = new AuditLogRegistrationClient(EnvConfig.get("API_URL")); private final Executor vThreadPool; public GuildBoostEventListener(Executor vThreadPool) { @@ -33,10 +34,10 @@ public GuildBoostEventListener(Executor vThreadPool) { public void onGuildUpdateBoostTier(@NonNull GuildUpdateBoostTierEvent event) { vThreadPool.execute(() -> { - Either response = AuditLogClient.getRegisteredGuild(event.getGuild().getId()); - response.peek(auditLogObject -> { + Optional response = client.getRegisteredGuild(event.getGuild().getId()); + response.ifPresent(auditLogObject -> { - String registeredChannelId = auditLogObject.channelId(); + String registeredChannelId = auditLogObject.getChannelId(); Guild guild = event.getGuild(); @@ -70,7 +71,7 @@ public void onGuildUpdateBoostTier(@NonNull GuildUpdateBoostTierEvent event) { MessageEmbed mb = eb.build(); TextChannel sendingChannel = event.getGuild().getTextChannelById(registeredChannelId); - if(sendingChannel!=null && sendingChannel.canTalk()) { + if (sendingChannel != null && sendingChannel.canTalk()) { sendingChannel.sendMessageEmbeds(mb).queue(); } }); @@ -81,9 +82,9 @@ public void onGuildUpdateBoostTier(@NonNull GuildUpdateBoostTierEvent event) { public void onGuildUpdateBoostCount(@NonNull GuildUpdateBoostCountEvent event) { vThreadPool.execute(() -> { - Either response = AuditLogClient.getRegisteredGuild(event.getGuild().getId()); - response.peek(success -> { - String registeredChannelId = success.channelId(); + Optional response = client.getRegisteredGuild(event.getGuild().getId()); + response.ifPresent(success -> { + String registeredChannelId = success.getChannelId(); Guild guild = event.getGuild(); @@ -105,7 +106,7 @@ public void onGuildUpdateBoostCount(@NonNull GuildUpdateBoostCountEvent event) { MessageEmbed mb = eb.build(); TextChannel sendingChannel = event.getGuild().getTextChannelById(registeredChannelId); - if(sendingChannel!=null && sendingChannel.canTalk()) { + if (sendingChannel != null && sendingChannel.canTalk()) { sendingChannel.sendMessageEmbeds(mb).queue(); } }); @@ -116,9 +117,9 @@ public void onGuildUpdateBoostCount(@NonNull GuildUpdateBoostCountEvent event) { public void onGuildMemberUpdateBoostTime(@NonNull GuildMemberUpdateBoostTimeEvent event) { vThreadPool.execute(() -> { - Either response = AuditLogClient.getRegisteredGuild(event.getGuild().getId()); - response.peek(success -> { - String registeredChannelId = success.channelId(); + Optional response = client.getRegisteredGuild(event.getGuild().getId()); + response.ifPresent(success -> { + String registeredChannelId = success.getChannelId(); Member member = event.getMember(); Guild guild = event.getGuild(); @@ -148,7 +149,7 @@ public void onGuildMemberUpdateBoostTime(@NonNull GuildMemberUpdateBoostTimeEven MessageEmbed mb = eb.build(); TextChannel sendingChannel = event.getGuild().getTextChannelById(registeredChannelId); - if(sendingChannel!=null && sendingChannel.canTalk()) { + if (sendingChannel != null && sendingChannel.canTalk()) { sendingChannel.sendMessageEmbeds(mb).queue(); } }); diff --git a/src/main/java/org/papertrail/listeners/audit/event/GuildMemberJoinAndLeaveEventListener.java b/src/main/java/org/papertrail/listeners/audit/event/GuildMemberJoinAndLeaveEventListener.java index f83f0627..607c0469 100644 --- a/src/main/java/org/papertrail/listeners/audit/event/GuildMemberJoinAndLeaveEventListener.java +++ b/src/main/java/org/papertrail/listeners/audit/event/GuildMemberJoinAndLeaveEventListener.java @@ -1,6 +1,7 @@ package org.papertrail.listeners.audit.event; -import io.vavr.control.Either; +import io.github.eggy03.papertrail.sdk.client.AuditLogRegistrationClient; +import io.github.eggy03.papertrail.sdk.entity.AuditLogRegistrationEntity; import net.dv8tion.jda.api.EmbedBuilder; import net.dv8tion.jda.api.entities.Guild; import net.dv8tion.jda.api.entities.Member; @@ -11,24 +12,23 @@ import net.dv8tion.jda.api.events.guild.member.GuildMemberRemoveEvent; import net.dv8tion.jda.api.hooks.ListenerAdapter; import org.jetbrains.annotations.NotNull; -import org.papertrail.commons.sdk.client.AuditLogClient; -import org.papertrail.commons.sdk.model.AuditLogObject; -import org.papertrail.commons.sdk.model.ErrorObject; import org.papertrail.commons.utilities.BooleanFormatter; import org.papertrail.commons.utilities.DurationFormatter; +import org.papertrail.commons.utilities.EnvConfig; import java.awt.Color; import java.time.Instant; +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 public class GuildMemberJoinAndLeaveEventListener extends ListenerAdapter { + private static final AuditLogRegistrationClient client = new AuditLogRegistrationClient(EnvConfig.get("API_URL")); private final Executor vThreadPool; public GuildMemberJoinAndLeaveEventListener(Executor vThreadPool) { - this.vThreadPool = vThreadPool; } @@ -38,10 +38,10 @@ public void onGuildMemberJoin(@NotNull GuildMemberJoinEvent event) { vThreadPool.execute(()->{ // guild member join and leave events are mapped to audit log table // Call the API and see if the event came from a registered Guild - Either response = AuditLogClient.getRegisteredGuild(event.getGuild().getId()); - response.peek(success -> { + Optional response = client.getRegisteredGuild(event.getGuild().getId()); + response.ifPresent(success -> { - String registeredChannelId = success.channelId(); + String registeredChannelId = success.getChannelId(); Guild guild = event.getGuild(); User user = event.getUser(); @@ -76,10 +76,10 @@ public void onGuildMemberRemove(@NotNull GuildMemberRemoveEvent event) { vThreadPool.execute(() -> { // Call the API and see if the event came from a registered Guild - Either response = AuditLogClient.getRegisteredGuild(event.getGuild().getId()); - response.peek(success -> { + Optional response = client.getRegisteredGuild(event.getGuild().getId()); + response.ifPresent(success -> { - String registeredChannelId = success.channelId(); + String registeredChannelId = success.getChannelId(); Guild guild = event.getGuild(); User user = event.getUser(); diff --git a/src/main/java/org/papertrail/listeners/audit/event/GuildPollEventListener.java b/src/main/java/org/papertrail/listeners/audit/event/GuildPollEventListener.java index 9ca0746f..59f99bfa 100644 --- a/src/main/java/org/papertrail/listeners/audit/event/GuildPollEventListener.java +++ b/src/main/java/org/papertrail/listeners/audit/event/GuildPollEventListener.java @@ -1,6 +1,7 @@ package org.papertrail.listeners.audit.event; -import io.vavr.control.Either; +import io.github.eggy03.papertrail.sdk.client.AuditLogRegistrationClient; +import io.github.eggy03.papertrail.sdk.entity.AuditLogRegistrationEntity; import net.dv8tion.jda.api.EmbedBuilder; import net.dv8tion.jda.api.entities.MessageEmbed; import net.dv8tion.jda.api.entities.channel.concrete.TextChannel; @@ -8,17 +9,17 @@ import net.dv8tion.jda.api.events.message.MessageReceivedEvent; import net.dv8tion.jda.api.hooks.ListenerAdapter; import org.jspecify.annotations.NonNull; -import org.papertrail.commons.sdk.client.AuditLogClient; -import org.papertrail.commons.sdk.model.AuditLogObject; -import org.papertrail.commons.sdk.model.ErrorObject; +import org.papertrail.commons.utilities.EnvConfig; import java.awt.Color; import java.time.Instant; import java.util.List; +import java.util.Optional; import java.util.concurrent.Executor; public class GuildPollEventListener extends ListenerAdapter { + private static final AuditLogRegistrationClient client = new AuditLogRegistrationClient(EnvConfig.get("API_URL")); private final Executor vThreadPool; public GuildPollEventListener(Executor vThreadPool) { @@ -39,11 +40,10 @@ public void onMessageReceived(@NonNull MessageReceivedEvent event) { // guild poll events are mapped to audit log table // Call the API and see if the event came from a registered Guild - Either response = AuditLogClient.getRegisteredGuild(event.getGuild().getId()); + Optional response = client.getRegisteredGuild(event.getGuild().getId()); + response.ifPresent(success -> { - response.peek(success -> { - - String registeredChannelId = success.channelId(); + String registeredChannelId = success.getChannelId(); StringBuilder answers = new StringBuilder(); List answerList = messagePoll.getAnswers(); diff --git a/src/main/java/org/papertrail/listeners/audit/event/GuildVoiceEventListener.java b/src/main/java/org/papertrail/listeners/audit/event/GuildVoiceEventListener.java index f13bd461..6b0f142d 100644 --- a/src/main/java/org/papertrail/listeners/audit/event/GuildVoiceEventListener.java +++ b/src/main/java/org/papertrail/listeners/audit/event/GuildVoiceEventListener.java @@ -1,6 +1,7 @@ package org.papertrail.listeners.audit.event; -import io.vavr.control.Either; +import io.github.eggy03.papertrail.sdk.client.AuditLogRegistrationClient; +import io.github.eggy03.papertrail.sdk.entity.AuditLogRegistrationEntity; import net.dv8tion.jda.api.EmbedBuilder; import net.dv8tion.jda.api.entities.Member; import net.dv8tion.jda.api.entities.MessageEmbed; @@ -9,18 +10,18 @@ import net.dv8tion.jda.api.events.guild.voice.GuildVoiceUpdateEvent; import net.dv8tion.jda.api.hooks.ListenerAdapter; import org.jetbrains.annotations.NotNull; -import org.papertrail.commons.sdk.client.AuditLogClient; -import org.papertrail.commons.sdk.model.AuditLogObject; -import org.papertrail.commons.sdk.model.ErrorObject; +import org.papertrail.commons.utilities.EnvConfig; import java.awt.Color; import java.time.Instant; +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 public class GuildVoiceEventListener extends ListenerAdapter { + private static final AuditLogRegistrationClient client = new AuditLogRegistrationClient(EnvConfig.get("API_URL")); private final Executor vThreadPool; public GuildVoiceEventListener(Executor vThreadPool) { @@ -34,11 +35,10 @@ public void onGuildVoiceUpdate(@NotNull GuildVoiceUpdateEvent event) { // guild voice events are mapped to audit log table // Call the API and see if the event came from a registered Guild - Either response = AuditLogClient.getRegisteredGuild(event.getGuild().getId()); + Optional response = client.getRegisteredGuild(event.getGuild().getId()); + response.ifPresent(success -> { - response.peek(success -> { - - String registeredChannelId = success.channelId(); + String registeredChannelId = success.getChannelId(); EmbedBuilder eb = new EmbedBuilder(); eb.setTitle("πŸ”Š Voice Activity Log"); diff --git a/src/main/java/org/papertrail/listeners/audit/setup/AuditLogSetupCommandListener.java b/src/main/java/org/papertrail/listeners/audit/setup/AuditLogSetupCommandListener.java index 147af747..11dbb0ee 100644 --- a/src/main/java/org/papertrail/listeners/audit/setup/AuditLogSetupCommandListener.java +++ b/src/main/java/org/papertrail/listeners/audit/setup/AuditLogSetupCommandListener.java @@ -1,22 +1,25 @@ package org.papertrail.listeners.audit.setup; -import io.vavr.control.Either; +import io.github.eggy03.papertrail.sdk.client.AuditLogRegistrationClient; +import io.github.eggy03.papertrail.sdk.entity.AuditLogRegistrationEntity; import net.dv8tion.jda.api.EmbedBuilder; 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.MessageEmbed; +import net.dv8tion.jda.api.entities.channel.Channel; 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 org.papertrail.commons.sdk.client.AuditLogClient; -import org.papertrail.commons.sdk.model.AuditLogObject; -import org.papertrail.commons.sdk.model.ErrorObject; +import org.papertrail.commons.utilities.EnvConfig; import java.awt.Color; -import java.util.Objects; +import java.util.Optional; public class AuditLogSetupCommandListener extends ListenerAdapter { + private static final AuditLogRegistrationClient client = new AuditLogRegistrationClient(EnvConfig.get("API_URL")); + @Override public void onSlashCommandInteraction(SlashCommandInteractionEvent event) { @@ -50,60 +53,68 @@ public void onSlashCommandInteraction(SlashCommandInteractionEvent event) { private void setAuditLogging(SlashCommandInteractionEvent event) { - // Only members with MANAGE_SERVER permissions should be able to use this command - Member member = event.getMember(); - if (member == null || !member.hasPermission(Permission.MANAGE_SERVER)) { + // Only members in a guild with MANAGE_SERVER permissions should be able to use this command + Member callerMember = event.getMember(); + Guild callerGuild = event.getGuild(); + Channel callerChannel = event.getChannel().asTextChannel(); + + if (callerMember == null || callerGuild == null) { + event.reply("❌ You can only use this command in a guild.").setEphemeral(true).queue(); + return; + } + + if (!callerMember.hasPermission(Permission.MANAGE_SERVER)) { event.reply("❌ You don't have the permission required to use this command.").setEphemeral(true).queue(); return; } // Call the API to register the guild and the channel - String guildId = Objects.requireNonNull(event.getGuild()).getId(); - String channelId = event.getChannel().asTextChannel().getId(); + boolean success = client.registerGuild(callerGuild.getId(), callerChannel.getId()); - Either response = AuditLogClient.registerGuild(guildId, channelId); - response.peek(success -> { + EmbedBuilder eb = new EmbedBuilder(); + eb.setTitle("πŸ“ Audit Log Configuration"); - EmbedBuilder eb = new EmbedBuilder(); - eb.setTitle("πŸ“ Audit Log Configuration"); + if (success) { eb.addField("βœ… Channel Registration Success", "β•°β”ˆβž€" + "All audit log info will be logged here", false); eb.setColor(Color.GREEN); - MessageEmbed mb = eb.build(); + MessageEmbed mb = eb.build(); event.replyEmbeds(mb).setEphemeral(false).queue(); - - }).peekLeft(failure -> { - - EmbedBuilder eb = new EmbedBuilder(); - eb.setTitle("πŸ“ Audit Log Configuration"); - eb.addField("❌ Channel Registration Failure", "β•°β”ˆβž€" + "Channel could not be registered", false); - eb.addField("\uD83C\uDF10 API Response", "β•°β”ˆβž€" + failure.message(), false); + } else { + eb.addField("❌ Channel Registration Failure", "β•°β”ˆβž€" + "Channel could not be registered.\nCheck if a channel in this guild is already registered for logging.", false); eb.setColor(Color.YELLOW); - MessageEmbed mb = eb.build(); + MessageEmbed mb = eb.build(); event.replyEmbeds(mb).setEphemeral(false).queue(); - }); + } + } private void retrieveAuditLoggingChannel(SlashCommandInteractionEvent event) { - - // Only members with MANAGE_SERVER permissions should be able to use this command - Member member = event.getMember(); - if (member == null || !member.hasPermission(Permission.MANAGE_SERVER)) { + + // Only members in a guild with MANAGE_SERVER permissions should be able to use this command + Member callerMember = event.getMember(); + Guild callerGuild = event.getGuild(); + + if (callerMember == null || callerGuild == null) { + event.reply("❌ You can only use this command in a guild.").setEphemeral(true).queue(); + return; + } + + if (!callerMember.hasPermission(Permission.MANAGE_SERVER)) { event.reply("❌ You don't have the permission required to use this command.").setEphemeral(true).queue(); return; } - String guildId = Objects.requireNonNull(event.getGuild()).getId(); // Call the API to retrieve the registered channel - Either response = AuditLogClient.getRegisteredGuild(guildId); + Optional response = client.getRegisteredGuild(callerGuild.getId()); // 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.peek(success -> { + response.ifPresentOrElse(success -> { - String registeredChannelId = success.channelId(); + String registeredChannelId = success.getChannelId(); GuildChannel registeredChannel = event.getJDA().getGuildChannelById(registeredChannelId); EmbedBuilder eb = new EmbedBuilder(); @@ -113,52 +124,51 @@ private void retrieveAuditLoggingChannel(SlashCommandInteractionEvent event) { MessageEmbed mb = eb.build(); event.replyEmbeds(mb).setEphemeral(false).queue(); - }).peekLeft(failure -> { - + }, () -> { EmbedBuilder eb = new EmbedBuilder(); eb.setTitle("πŸ“ Audit Log Configuration"); eb.addField("⚠️ Channel Registration Check", "β•°β”ˆβž€"+"No channel has been registered for audit logs", false); eb.setColor(Color.YELLOW); MessageEmbed mb = eb.build(); event.replyEmbeds(mb).setEphemeral(false).queue(); - }); } private void unsetAuditLogging(SlashCommandInteractionEvent event) { - - // Only members with MANAGE_SERVER permissions should be able to use this command - Member member = event.getMember(); - if (member == null || !member.hasPermission(Permission.MANAGE_SERVER)) { - event.reply("❌ You don't have the permission required to use this command.").setEphemeral(true).queue(); - return; - } - - String guildId = Objects.requireNonNull(event.getGuild()).getId(); + + // Only members in a guild with MANAGE_SERVER permissions should be able to use this command + Member callerMember = event.getMember(); + Guild callerGuild = event.getGuild(); + + if (callerMember == null || callerGuild == null) { + event.reply("❌ You can only use this command in a guild.").setEphemeral(true).queue(); + return; + } + + if (!callerMember.hasPermission(Permission.MANAGE_SERVER)) { + event.reply("❌ You don't have the permission required to use this command.").setEphemeral(true).queue(); + return; + } + // Call the API to unregister guild - Either response = AuditLogClient.deleteRegisteredGuild(guildId); - response.peek(success -> { + boolean success = client.deleteRegisteredGuild(callerGuild.getId()); - EmbedBuilder eb = new EmbedBuilder(); - eb.setTitle("πŸ“ Audit Log Configuration"); + EmbedBuilder eb = new EmbedBuilder(); + eb.setTitle("πŸ“ Audit Log Configuration"); + + if (success) { eb.addField("βœ… Channel Removal", "β•°β”ˆβž€"+"Channel successfully unset", false); eb.setColor(Color.GREEN); - MessageEmbed mb = eb.build(); + MessageEmbed mb = eb.build(); event.replyEmbeds(mb).setEphemeral(false).queue(); - - }).peekLeft(failure -> { - - EmbedBuilder eb = new EmbedBuilder(); - eb.setTitle("πŸ“ Audit Log Configuration"); - eb.addField("❌ Channel Removal Failure", "β•°β”ˆβž€"+"Channel could not be unset", false); - eb.addField("\uD83C\uDF10 API Response", "β•°β”ˆβž€"+failure.message(), false); + } else { + eb.addField("❌ Channel Removal Failure", "β•°β”ˆβž€"+"Channel could not be unset.\nThis may be because no channel has been registered in this guild yet.", false); eb.setColor(Color.YELLOW); - MessageEmbed mb = eb.build(); + MessageEmbed mb = eb.build(); event.replyEmbeds(mb).setEphemeral(false).queue(); - - }); + } } } diff --git a/src/main/java/org/papertrail/listeners/message/event/MessageLogListener.java b/src/main/java/org/papertrail/listeners/message/event/MessageLogListener.java index a3afad47..025d1bf1 100644 --- a/src/main/java/org/papertrail/listeners/message/event/MessageLogListener.java +++ b/src/main/java/org/papertrail/listeners/message/event/MessageLogListener.java @@ -1,8 +1,10 @@ package org.papertrail.listeners.message.event; import com.google.common.base.Splitter; -import com.google.common.util.concurrent.Striped; -import io.vavr.control.Either; +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 lombok.extern.slf4j.Slf4j; import net.dv8tion.jda.api.EmbedBuilder; import net.dv8tion.jda.api.entities.MessageEmbed; @@ -13,44 +15,26 @@ import net.dv8tion.jda.api.events.message.MessageUpdateEvent; import net.dv8tion.jda.api.hooks.ListenerAdapter; import org.jetbrains.annotations.NotNull; -import org.jspecify.annotations.NonNull; -import org.papertrail.commons.sdk.client.MessageContentLogClient; -import org.papertrail.commons.sdk.client.MessageLogClient; -import org.papertrail.commons.sdk.model.ErrorObject; -import org.papertrail.commons.sdk.model.MessageContentObject; -import org.papertrail.commons.sdk.model.MessageLogObject; -import org.papertrail.commons.utilities.MessageEncryption; +import org.papertrail.commons.utilities.EnvConfig; import java.awt.Color; import java.time.Instant; import java.util.List; +import java.util.Optional; import java.util.concurrent.Executor; -import java.util.concurrent.atomic.AtomicLong; -import java.util.concurrent.locks.Lock; @Slf4j public class MessageLogListener extends ListenerAdapter { - private final Executor vThreadPool; - private final Striped<@NonNull Lock> messageLocks = Striped.lock(8192); - private final AtomicLong activeLockCount = new AtomicLong(0); + private static final MessageLogRegistrationClient registrationClient = new MessageLogRegistrationClient(EnvConfig.get("API_URL")); + private static final MessageLogContentClient contentClient = new MessageLogContentClient(EnvConfig.get("API_URL")); + + private final Executor vThreadPool; public MessageLogListener(Executor vThreadPool) { this.vThreadPool = vThreadPool; } - private void withMessageLock (String messageId, Runnable task) { - Lock lock = messageLocks.get(messageId); - lock.lock(); - log.debug("Lock acquired for message id: {} . Active lock count: {}", messageId, activeLockCount.incrementAndGet()); - try{ - task.run(); - } finally { - lock.unlock(); - log.debug("Lock released for message id: {} . Active lock count: {}", messageId, activeLockCount.decrementAndGet()); - } - } - @Override public void onMessageReceived(MessageReceivedEvent event) { @@ -68,13 +52,13 @@ public void onMessageReceived(MessageReceivedEvent event) { // 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 - Either response = MessageLogClient.getRegisteredGuild(guildId); - response.peek(success -> { + Optional response = registrationClient.getRegisteredGuild(guildId); + response.ifPresent(success -> { String messageId = event.getMessageId(); - String encryptedMessage = MessageEncryption.encrypt(event.getMessage().getContentRaw()); + String messageContent = event.getMessage().getContentDisplay(); String authorId = event.getAuthor().getId(); - withMessageLock(messageId, ()-> MessageContentLogClient.logMessage(messageId, encryptedMessage, authorId)); + contentClient.logMessage(messageId, messageContent, authorId); }); }); } @@ -93,29 +77,29 @@ public void onMessageUpdate(MessageUpdateEvent event) { // get the message id of the message which was updated String messageId = event.getMessageId(); // Call the API to see if the guild is registered for Message Logging - Either response = MessageLogClient.getRegisteredGuild(guildId); - response.peek(success -> { + Optional response = registrationClient.getRegisteredGuild(guildId); + response.ifPresent(success -> { // retrieve the channel id where the logs must be sent - String channelIdToSendTo = success.channelId(); + String channelIdToSendTo = success.getChannelId(); // fetch the old message object from the API - Either updatedMessageObject = MessageContentLogClient.retrieveMessage(messageId); - updatedMessageObject.peek(content -> { - // Decrypt the fetched message - String decryptedMessage = MessageEncryption.decrypt(content.messageContent()); + Optional oldMessageContent = contentClient.retrieveMessage(messageId); + 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().getContentRaw(); + 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(decryptedMessage)) { + if(updatedMessage.equals(oldMessage)) { return; } // Splitting is required because each field in an embed can display only up-to 1024 characters - assert decryptedMessage != null; - List decryptedMessageSplits = Splitter.fixedLength(1024).splitToList(decryptedMessage); + // A full embed can display up-to 6000 characters + List oldMessageSplits = Splitter.fixedLength(1024).splitToList(oldMessage); List updatedMessageSplits = Splitter.fixedLength(1024).splitToList(updatedMessage); EmbedBuilder eb = new EmbedBuilder(); @@ -123,29 +107,22 @@ public void onMessageUpdate(MessageUpdateEvent event) { eb.setDescription("A message sent by "+event.getAuthor().getAsMention()+" has been edited in: "+event.getJumpUrl()); eb.setColor(Color.YELLOW); - decryptedMessageSplits.forEach(split -> eb.addField("Old Message", split, false)); // get only the message and not the author + oldMessageSplits.forEach(split -> eb.addField("Old Message", split, false)); updatedMessageSplits.forEach(split -> eb.addField("New Message", split, false)); eb.setFooter(event.getGuild().getName()); eb.setTimestamp(Instant.now()); - // update the database with the new message - withMessageLock(messageId, ()-> - MessageContentLogClient.updateMessage( - messageId, MessageEncryption.encrypt(updatedMessage), event.getAuthor().getId() - ) - ); - // the reason this is above the send queue is that in case where the user did not give sufficient permissions to - // the bot, the error responses wouldn't block the update of the message in the database. - - // fetch the channel id from the database - // this channel is where the logs will be sent to - // wrap the embed and send + MessageEmbed mb = eb.build(); + // send the old and updated message to the registered channel TextChannel sendingChannel = event.getGuild().getTextChannelById(channelIdToSendTo); if(sendingChannel!=null && sendingChannel.canTalk()) { sendingChannel.sendMessageEmbeds(mb).queue(); } + + // update the database with the new message + contentClient.updateMessage(messageId, updatedMessage, event.getAuthor().getId()); }); }); }); @@ -162,30 +139,29 @@ public void onMessageDelete(@NotNull MessageDeleteEvent event) { String messageId = event.getMessageId(); // Call the API to see if the guild is registered for Message Logging - Either response = MessageLogClient.getRegisteredGuild(guildId); - response.peek(success -> { + Optional response = registrationClient.getRegisteredGuild(guildId); + response.ifPresent(success -> { // retrieve the channel id where the logs must be sent - String channelIdToSendTo = success.channelId(); + String channelIdToSendTo = success.getChannelId(); // fetch the old message object from the API - Either deletedMessageObject = MessageContentLogClient.retrieveMessage(messageId); - deletedMessageObject.peek(content -> { + Optional oldMessageContent = contentClient.retrieveMessage(messageId); + oldMessageContent.ifPresent(contentEntity -> { // retrieve the stored message and author in the database which was deleted - String deletedMessage = MessageEncryption.decrypt(content.messageContent()); - String deletedMessageAuthorId = content.authorId(); + 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 - assert deletedMessage != null; List deletedMessageSplits = Splitter.fixedLength(1024).splitToList(deletedMessage); EmbedBuilder eb = new EmbedBuilder(); eb.setTitle("πŸ—‘οΈ Message Delete Event"); - eb.setDescription("A message sent by "+mentionableAuthor+" has been deleted"); + eb.setDescription("A message sent by "+mentionableAuthor+" has been deleted from "+ event.getChannel().getAsMention()); eb.setColor(Color.RED); deletedMessageSplits.forEach(split-> eb.addField("Deleted Message", split, false)); @@ -193,11 +169,6 @@ public void onMessageDelete(@NotNull MessageDeleteEvent event) { eb.setFooter(event.getGuild().getName()); eb.setTimestamp(Instant.now()); - // delete the message from the database - withMessageLock(messageId, ()-> MessageContentLogClient.deleteMessage(messageId)); - // the reason this is above the send queue is that, in case where the user did not give sufficient permissions to - // the bot, (such as no send message permissions) the exceptions wouldn't block the deletion in the database. - // send the fetched deleted message to the logging channel MessageEmbed mb = eb.build(); @@ -205,6 +176,9 @@ public void onMessageDelete(@NotNull MessageDeleteEvent event) { if(sendingChannel!=null && sendingChannel.canTalk()) { sendingChannel.sendMessageEmbeds(mb).queue(); } + + // delete the message from the database + contentClient.deleteMessage(messageId); }); }); }); diff --git a/src/main/java/org/papertrail/listeners/message/setup/MessageLogSetupCommandListener.java b/src/main/java/org/papertrail/listeners/message/setup/MessageLogSetupCommandListener.java index 630879ed..0eced335 100644 --- a/src/main/java/org/papertrail/listeners/message/setup/MessageLogSetupCommandListener.java +++ b/src/main/java/org/papertrail/listeners/message/setup/MessageLogSetupCommandListener.java @@ -1,22 +1,25 @@ package org.papertrail.listeners.message.setup; -import io.vavr.control.Either; +import io.github.eggy03.papertrail.sdk.client.MessageLogRegistrationClient; +import io.github.eggy03.papertrail.sdk.entity.MessageLogRegistrationEntity; import net.dv8tion.jda.api.EmbedBuilder; 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.MessageEmbed; +import net.dv8tion.jda.api.entities.channel.concrete.TextChannel; 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 org.papertrail.commons.sdk.client.MessageLogClient; -import org.papertrail.commons.sdk.model.ErrorObject; -import org.papertrail.commons.sdk.model.MessageLogObject; +import org.papertrail.commons.utilities.EnvConfig; import java.awt.Color; -import java.util.Objects; +import java.util.Optional; public class MessageLogSetupCommandListener extends ListenerAdapter { + private static final MessageLogRegistrationClient client = new MessageLogRegistrationClient(EnvConfig.get("API_URL")); + @Override public void onSlashCommandInteraction(SlashCommandInteractionEvent event) { @@ -48,58 +51,65 @@ public void onSlashCommandInteraction(SlashCommandInteractionEvent event) { } private void setMessageLogging(SlashCommandInteractionEvent event) { - - // Only members with MANAGE_SERVER permissions should be able to use this command - Member member = event.getMember(); - if (member == null || !member.hasPermission(Permission.ADMINISTRATOR)) { - event.reply("❌ You don't have the permission required to use this command.").setEphemeral(true).queue(); - return; - } - String guildId = Objects.requireNonNull(event.getGuild()).getId(); + // Only members in a guild with ADMINISTRATOR permissions should be able to use this command + Member callerMember = event.getMember(); + Guild callerGuild = event.getGuild(); + TextChannel callerChannel = event.getChannel().asTextChannel(); + + if (callerMember == null || callerGuild == null) { + event.reply("❌ You can only use this command in a guild.").setEphemeral(true).queue(); + return; + } + + if (!callerMember.hasPermission(Permission.ADMINISTRATOR)) { + event.reply("❌ You don't have the permission required to use this command.").setEphemeral(true).queue(); + return; + } // Call the API to register guild for message logging - Either response = MessageLogClient.registerGuild(guildId, event.getChannelId()); - response.peek(success -> { + boolean success = client.registerGuild(callerGuild.getId(), callerChannel.getId()); - EmbedBuilder eb = new EmbedBuilder(); - eb.setTitle("Message Log Registration"); + EmbedBuilder eb = new EmbedBuilder(); + eb.setTitle("Message Log Registration"); + + if (success) { eb.addField("βœ… Channel Registration Success","β•°β”ˆβž€"+"All edited and deleted messages will be logged here", false); eb.setColor(Color.GREEN); MessageEmbed mb = eb.build(); event.replyEmbeds(mb).setEphemeral(false).queue(); - - }).peekLeft(failure -> { - - EmbedBuilder eb = new EmbedBuilder(); - eb.setTitle("Message Log Registration"); - eb.addField("❌ Channel Registration Failure","β•°β”ˆβž€"+"Channel could not be registered", false); - eb.addField("\uD83C\uDF10 API Response", "β•°β”ˆβž€"+failure.message(), false); + } else { + eb.addField("❌ Channel Registration Failure", "β•°β”ˆβž€" + "Channel could not be registered.\nCheck if a channel in this guild is already registered for logging.", false); eb.setColor(Color.YELLOW); MessageEmbed mb = eb.build(); event.replyEmbeds(mb).setEphemeral(false).queue(); - }); + } - } + } private void retrieveMessageLoggingChannel(SlashCommandInteractionEvent event) { - - // Only members with MANAGE_SERVER permissions should be able to use this command - Member member = event.getMember(); - if (member == null || !member.hasPermission(Permission.ADMINISTRATOR)) { - event.reply("❌ You don't have the permission required to use this command.").setEphemeral(true).queue(); - return; - } - - String guildId = Objects.requireNonNull(event.getGuild()).getId(); + + // Only members in a guild with ADMINISTRATOR permissions should be able to use this command + Member callerMember = event.getMember(); + Guild callerGuild = event.getGuild(); + + if (callerMember == null || callerGuild == null) { + event.reply("❌ You can only use this command in a guild.").setEphemeral(true).queue(); + return; + } + + if (!callerMember.hasPermission(Permission.ADMINISTRATOR)) { + event.reply("❌ You don't have the permission required to use this command.").setEphemeral(true).queue(); + return; + } // Call the API to check for registered guild - Either response = MessageLogClient.getRegisteredGuild(guildId); - response.peek(success -> { + Optional response = client.getRegisteredGuild(callerGuild.getId()); + response.ifPresentOrElse(success -> { - String registeredChannelId = success.channelId(); + String registeredChannelId = success.getChannelId(); GuildChannel registeredChannel = event.getJDA().getGuildChannelById(registeredChannelId); EmbedBuilder eb = new EmbedBuilder(); @@ -109,8 +119,7 @@ private void retrieveMessageLoggingChannel(SlashCommandInteractionEvent event) { MessageEmbed mb = eb.build(); event.replyEmbeds(mb).setEphemeral(false).queue(); - }).peekLeft(failure -> { - + }, () -> { EmbedBuilder eb = new EmbedBuilder(); eb.setTitle("πŸ“ Message Log Configuration"); eb.addField("⚠️ Channel Registration Check", "β•°β”ˆβž€"+"No channel has been registered for message logs", false); @@ -122,39 +131,38 @@ private void retrieveMessageLoggingChannel(SlashCommandInteractionEvent event) { private void unsetMessageLogging(SlashCommandInteractionEvent event) { - // Only members with MANAGE_SERVER permissions should be able to use this command - Member member = event.getMember(); - if (member == null || !member.hasPermission(Permission.ADMINISTRATOR)) { + // Only members in a guild with ADMINISTRATOR permissions should be able to use this command + Member callerMember = event.getMember(); + Guild callerGuild = event.getGuild(); + + if (callerMember == null || callerGuild == null) { + event.reply("❌ You can only use this command in a guild.").setEphemeral(true).queue(); + return; + } + + if (!callerMember.hasPermission(Permission.ADMINISTRATOR)) { event.reply("❌ You don't have the permission required to use this command.").setEphemeral(true).queue(); return; } - String guildId = Objects.requireNonNull(event.getGuild()).getId(); + EmbedBuilder eb = new EmbedBuilder(); + eb.setTitle("πŸ“ Message Log Configuration"); - // Call the API to unregister guild - Either response = MessageLogClient.deleteRegisteredGuild(guildId); - response.peek(success -> { - EmbedBuilder eb = new EmbedBuilder(); - eb.setTitle("πŸ“ Message Log Configuration"); + // Call the API to unregister guild + boolean success = client.deleteRegisteredGuild(callerGuild.getId()); + if (success) { eb.addField("βœ… Channel Removal", "β•°β”ˆβž€" + "Channel successfully unset", false); eb.setColor(Color.GREEN); MessageEmbed mb = eb.build(); event.replyEmbeds(mb).setEphemeral(false).queue(); - - }).peekLeft(failure -> { - - EmbedBuilder eb = new EmbedBuilder(); - eb.setTitle("πŸ“ Message Log Configuration"); - eb.addField("❌ Channel Removal Failure", "β•°β”ˆβž€" + "Channel could not be unset", false); - eb.addField("\uD83C\uDF10 API Response", "β•°β”ˆβž€" + failure.message(), false); + } else { + eb.addField("❌ Channel Removal Failure", "β•°β”ˆβž€"+"Channel could not be unset.\nThis may be because no channel has been registered in this guild yet.", false); eb.setColor(Color.YELLOW); MessageEmbed mb = eb.build(); event.replyEmbeds(mb).setEphemeral(false).queue(); - - }); - + } } } diff --git a/src/main/java/org/papertrail/listeners/misc/SelfKickListener.java b/src/main/java/org/papertrail/listeners/misc/SelfKickListener.java index e9c31d97..f876a38a 100644 --- a/src/main/java/org/papertrail/listeners/misc/SelfKickListener.java +++ b/src/main/java/org/papertrail/listeners/misc/SelfKickListener.java @@ -1,11 +1,12 @@ package org.papertrail.listeners.misc; +import io.github.eggy03.papertrail.sdk.client.AuditLogRegistrationClient; +import io.github.eggy03.papertrail.sdk.client.MessageLogRegistrationClient; import net.dv8tion.jda.api.entities.Guild; import net.dv8tion.jda.api.events.guild.GuildLeaveEvent; import net.dv8tion.jda.api.hooks.ListenerAdapter; import org.jetbrains.annotations.NotNull; -import org.papertrail.commons.sdk.client.AuditLogClient; -import org.papertrail.commons.sdk.client.MessageLogClient; +import org.papertrail.commons.utilities.EnvConfig; import java.util.concurrent.Executor; @@ -14,6 +15,9 @@ */ public class SelfKickListener extends ListenerAdapter { + private static final AuditLogRegistrationClient alClient = new AuditLogRegistrationClient(EnvConfig.get("API_URL")); + private static final MessageLogRegistrationClient mlClient = new MessageLogRegistrationClient(EnvConfig.get("API_URL")); + private final Executor vThreadPool; public SelfKickListener(Executor vThreadPool) { @@ -25,8 +29,8 @@ public void onGuildLeave(@NotNull GuildLeaveEvent event) { Guild leftGuild = event.getGuild(); vThreadPool.execute(()->{ - AuditLogClient.deleteRegisteredGuild(leftGuild.getId()); - MessageLogClient.deleteRegisteredGuild(leftGuild.getId()); + alClient.deleteRegisteredGuild(leftGuild.getId()); + mlClient.deleteRegisteredGuild(leftGuild.getId()); }); } } diff --git a/src/main/java/org/papertrail/listeners/misc/ServerStatCommandListener.java b/src/main/java/org/papertrail/listeners/misc/ServerStatCommandListener.java index 55bcf2c1..7e031346 100644 --- a/src/main/java/org/papertrail/listeners/misc/ServerStatCommandListener.java +++ b/src/main/java/org/papertrail/listeners/misc/ServerStatCommandListener.java @@ -22,9 +22,12 @@ public void onSlashCommandInteraction(SlashCommandInteractionEvent event) { if(event.getName().equals("stats")) { Guild guild = event.getGuild(); + if (guild == null) { + event.reply("You can only use this command in Guilds").setEphemeral(true).queue(); + return; + } - assert guild != null; - List members = Objects.requireNonNull(guild).getMemberCache().asList(); + List members = guild.getMemberCache().asList(); int botCount = 0; int userCount = 0; int onlineUserCount = 0; diff --git a/src/main/java/org/papertrail/main/FireRun.java b/src/main/java/org/papertrail/main/Start.java similarity index 83% rename from src/main/java/org/papertrail/main/FireRun.java rename to src/main/java/org/papertrail/main/Start.java index 6a247ce7..699dfcf8 100644 --- a/src/main/java/org/papertrail/main/FireRun.java +++ b/src/main/java/org/papertrail/main/Start.java @@ -4,7 +4,6 @@ import com.sun.net.httpserver.HttpHandler; import com.sun.net.httpserver.HttpServer; import net.dv8tion.jda.api.sharding.ShardManager; -import org.bouncycastle.jce.provider.BouncyCastleProvider; import org.papertrail.listeners.audit.event.AuditLogEventListener; import org.papertrail.listeners.audit.event.GuildBoostEventListener; import org.papertrail.listeners.audit.event.GuildMemberJoinAndLeaveEventListener; @@ -16,34 +15,20 @@ import org.papertrail.listeners.misc.BotSetupInstructionCommandListener; import org.papertrail.listeners.misc.SelfKickListener; import org.papertrail.listeners.misc.ServerStatCommandListener; -import org.tinylog.Logger; import java.io.IOException; import java.net.InetSocketAddress; -import java.security.Security; import java.util.concurrent.Executor; import java.util.concurrent.Executors; /* * The main class of the bot */ -public class FireRun { +public class Start { // All I/O blocking operations run inside the vThreadPool private static final Executor vThreadPool = Executors.newVirtualThreadPerTaskExecutor(); - // Register Bouncy Castle as a security provider - // Required for the PBEWITHSHA256AND256BITAES-CBC-BC encryption algorithm - private static void registerBouncyCastle() { - - if (Security.getProvider(BouncyCastleProvider.PROVIDER_NAME) == null) { - Security.addProvider(new BouncyCastleProvider()); - Logger.info("Bouncy Castle Security Provider Registered."); - } - } - public static void main(String[] args) throws IOException { - - registerBouncyCastle(); ConnectionInitializer ci = new ConnectionInitializer(); ShardManager manager = ci.getManager(); diff --git a/src/main/resources/tinylog.properties b/src/main/resources/tinylog.properties index 22ba864e..bf8c7dda 100644 --- a/src/main/resources/tinylog.properties +++ b/src/main/resources/tinylog.properties @@ -1,5 +1,5 @@ writer = console writer.format = {level}: {class}.{method}()\n{message} -writer.level = info +writer.level = debug writingthread = true \ No newline at end of file