diff --git a/PRIVACY.md b/PRIVACY.md new file mode 100644 index 00000000..ff9fd2ca --- /dev/null +++ b/PRIVACY.md @@ -0,0 +1,92 @@ +# Privacy Policy + +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. + +--- + +## Information Collection and Use + +The bot only stores data when specific features are explicitly enabled by server administrators: + +### If **Message Logging** is enabled: +- Encrypted message content (not readable by us) +- Message ID +- Author ID (Discord user ID) +- Channel ID +- Guild ID +- Timestamp (created_at) + +Message content is encrypted before storage and cannot be decrypted by the bot operator. + +### If **only Audit Logging** is enabled: +- Guild ID +- Channel ID where audit logs should be sent (one per guild) + +No message content or user data is stored in this case. + +The stored data is used solely for server moderation purposes. + +--- + +## Data Retention + +- All stored message data is automatically deleted after **30 days**. +- 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. + +--- + +## Log Data + +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. + +--- + +## Security + +We take data protection seriously: +- All sensitive data (e.g., message content) is encrypted before being saved. +- No decryption keys are stored on our servers. +- The database is securely hosted using Aiven PostgreSQL wiht UpCloud as it's provider. + +However, no method of transmission over the internet or method of electronic storage is 100% secure, and we cannot guarantee absolute security. + +--- + +## 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. + +--- + +## User Rights (GDPR Compliance) + +If you are located in the EU/EEA, you have the following rights under the General Data Protection Regulation (GDPR): + +- **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 request access or deletion, please contact us using the method below. + +--- + +## Contact + +For privacy-related questions or GDPR requests: +- GitHub: [Submit an issue or discussion](https://github.com/Egg-03/PaperTrailBot/issues) +- Email: `eggzerothree@proton.me` + +--- + +## Changes to This Privacy Policy + +This policy may be updated from time to time. Changes will be posted here and are effective immediately once published. + +--- + diff --git a/README.md b/README.md new file mode 100644 index 00000000..d516be1f --- /dev/null +++ b/README.md @@ -0,0 +1,179 @@ +# Overview +PaperTrail is a free and open source, self-hostable 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). + +Key Features: + +- πŸ” Full audit log integration (supports over 50+ event types) and generic support for unknown types +- πŸ’¬ Message logging (edit, delete) +- πŸ‘€ Member activity tracking (joins, leaves, kicks, bans, updates) +- πŸ”Š Voice activity logging (join/leave, move) +- πŸš€ Server boost tracking +- 🧱 Minimalist PostgreSQL schema with auto-cleanup support via `pg_cron` + +> πŸ” While PaperTrail is designed to be self-hosted for maximum data ownership, a public instance is also available if preferred. +> +> πŸ“Ž Invite Link: [TODO] + +# Self-Hosting Guide + +## 1) Setting up the bot +### Step 1: Get Required Secrets + +You will need two environment variables to run the bot: + +- `TOKEN` – Your Discord bot token from the [Discord Developer Portal](https://discord.com/developers/applications) +- `DATABASEURL` – A PostgreSQL connection URL (format: `jdbc:postgresql://host:port/dbname`) +- `MESSAGE_SECRET` - A randomly generated secret that will be used as a passphrase for encrypting and decrypting all the messages sent to and from the database respectively +> πŸ’‘ You will receive the DATABASEURL from your database hosting provider once you've set up your database. This value is essential and should be kept secure. +> +> πŸ’‘ You can use any passphrase generator to generate a MESSAGE_SECRET. Make sure to store it in a secure place. + +Create a `.env` file with the following: + +```env +# .env file +TOKEN=your-discord-application-token +DATABASEURL=jdbc:postgresql://your-database-url +MESSAGE_SECRET=your-secret +``` + +> ⚠️ Never commit your `.env` file to version control. Add it to `.gitignore`: + +```gitignore +.env +``` + + +### 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. +#### A. Cloud Platforms with GitHub + Docker Support + +- These can auto-deploy using the included `Dockerfile` + +#### B. Platforms with GitHub + Java Support (No Docker) + +- These can build the project using the `pom.xml` if JDK 21+ is available + +#### Build and Run (for local/manual deployment) + +If deploying manually or running locally: + +**Build the JAR:** + +```sh +./mvnw clean package # If using Maven Wrapper +``` + OR +```sh +mvn clean package # If Maven is installed globally +``` +This creates a runnable JAR file in the `target/` folder, named `paper-trail-bot.jar`. + +**Run the JAR:** + +```sh +java -jar target/paper-trail-bot.jar +``` + +> Ensure you have JDK 21 or later installed. + +> For local deployments, make sure your `.env` file containing the secrets is placed in the project's base directory + + +## 2) Setting up the database + +You’ll need a PostgreSQL database with the following tables: +![image](https://github.com/user-attachments/assets/5e56e80c-70e0-4bde-8bcf-0b48933a72af) + +Assuming you have a default public schema, use the following SQL Queries to create the required tables: + +```SQL +CREATE TABLE public.audit_log_table ( + guild_id int8 NOT NULL, + channel_id int8 NOT NULL, + CONSTRAINT audit_log_table_pk PRIMARY KEY (guild_id), + CONSTRAINT audit_log_table_unique UNIQUE (channel_id) +); + +CREATE TABLE public.message_log_content_table ( + message_id int8 NOT NULL, + message_content text NULL, + author_id int8 NOT NULL, + created_at timestamp DEFAULT (CURRENT_TIMESTAMP AT TIME ZONE 'UTC'::text) NOT NULL, + CONSTRAINT message_log_content_table_pk PRIMARY KEY (message_id) +); +CREATE INDEX message_log_content_table_created_at_idx ON public.message_log_content_table USING btree (created_at); + +CREATE TABLE public.message_log_registration_table ( + guild_id int8 NOT NULL, + channel_id int8 NOT NULL, + CONSTRAINT message_log_registration_table_pk PRIMARY KEY (guild_id), + CONSTRAINT message_log_registration_table_unique UNIQUE (channel_id) +); +``` +### Optional: Automatic Message Cleanup with `pg_cron` + +NOTE: The following requires the `pg_cron` extension to be available. + +Check with your database provider to see if it is supported + +You can also set up a cron-job via the `pg_cron` extension to auto-delete messages older than 30 days or your preferred time interval +```SQL +CREATE EXTENSION IF NOT EXISTS pg_cron; + +SELECT cron.schedule( + 'daily_log_cleanup', + '0 2 * * *', -- 2:00 AM UTC daily + $$DELETE FROM message_log_content_table WHERE created_at < CURRENT_TIMESTAMP AT TIME ZONE 'UTC' - INTERVAL '30 days';$$ +); +``` + +To check your cron-job runs +```SQL +SELECT * FROM cron.job_run_details +``` + +> If `pg_cron` is not supported, consider using a scheduled task in your app or CI/CD platform to run cleanup logic. + +--- + +# 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. + +[Read the full Privacy Policy](./PRIVACY.md) + +# Security + +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** +- 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). + +# License + +PaperTrail is licensed under the [Apache License 2.0](./LICENSE). + +You are free to: +- Use, modify, and redistribute the code +- Self-host or publicly host your own instance +- Build on top of this bot for your own projects + +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! + diff --git a/SECURITY.md b/SECURITY.md new file mode 100644 index 00000000..efb7ec42 --- /dev/null +++ b/SECURITY.md @@ -0,0 +1,23 @@ +# Security Policy + +## Supported Versions + +Currently, only the `main` branch of PaperTrail is actively maintained. Bug fixes and security patches are applied there. + +## Reporting a Vulnerability + +If you discover a security vulnerability in PaperTrail, please **do not open a GitHub issue**. Instead, report it responsibly by contacting: + +πŸ“§ **eggzerothree@proton.me** + +Please include: + +- A clear description of the issue +- Steps to reproduce, if possible +- Any known workarounds + +We aim to acknowledge your report within **48 hours** and will keep you updated through the resolution process. + +Once a fix is ready and released, we will credit reporters (if desired) and may publish a GitHub Security Advisory summarizing the issue and patch. + +Thank you for helping keep PaperTrail safe and secure! diff --git a/TERMS.md b/TERMS.md new file mode 100644 index 00000000..a88f620b --- /dev/null +++ b/TERMS.md @@ -0,0 +1,48 @@ +# Terms of Service + +_Last updated: June 22, 2025_ + +Thank you for using **PaperTrail**, an open-source Discord logging bot. + +By using this software (either self-hosted or via the public instance), you agree to the following terms: + +--- + +## 1. Usage + +You may use this bot for free, either: +- By hosting it yourself +- Or by using the public hosted instance (if one is available) + +You agree to use the bot responsibly, and not for any of the following: +- Harassment, abuse, or spamming users +- Illegal activity under applicable laws +- Violating Discord’s [Terms of Service](https://discord.com/terms) + +--- + +## 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. + +--- + +## 3. 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. + +--- + +## 4. 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. + +--- + +## 5. Changes + +We may update these terms as the project evolves. You are encouraged to check this document periodically. + +--- + +If you have any questions or concerns, please open an issue on the [GitHub repository](https://github.com/Egg-03/PaperTrailBot/issues). diff --git a/src/main/java/org/papertrail/listeners/customlisteners/BotInfoListener.java b/src/main/java/org/papertrail/listeners/customlisteners/BotInfoListener.java index b51a574b..e5e2aaa2 100644 --- a/src/main/java/org/papertrail/listeners/customlisteners/BotInfoListener.java +++ b/src/main/java/org/papertrail/listeners/customlisteners/BotInfoListener.java @@ -4,7 +4,7 @@ import java.time.Instant; import org.papertrail.version.AuthorInfo; -import org.papertrail.version.VersionInfo; +import org.papertrail.version.ProjectInfo; import net.dv8tion.jda.api.EmbedBuilder; import net.dv8tion.jda.api.entities.MessageEmbed; @@ -19,18 +19,18 @@ public void onSlashCommandInteraction(SlashCommandInteractionEvent event) { if(event.getName().equals("about")) { EmbedBuilder eb = new EmbedBuilder(); - eb.setTitle("πŸ“Š About "+VersionInfo.APPNAME+" πŸ“Š"); + eb.setTitle("πŸ“Š About "+ProjectInfo.APPNAME+" πŸ“Š"); eb.setDescription("πŸ‘€ Developed By: **"+AuthorInfo.AUTHOR_NAME+"**"); eb.setThumbnail(AuthorInfo.AUTHOR_AVATAR_URL); eb.setColor(Color.PINK); - eb.addField("🏷️ App Name", "β•°β”ˆβž€"+VersionInfo.APPNAME, false); - eb.addField("βš™οΈ App Version", "β•°β”ˆβž€"+VersionInfo.VERSION, false); - eb.addField("πŸ“ƒ App Source Code", VersionInfo.PROJECT_LINK, false); - eb.addField("πŸ–§ App Server", "β•°β”ˆβž€"+VersionInfo.SERVER_LOCATION, false); - eb.addField("πŸ›’ App Database", "β•°β”ˆβž€"+VersionInfo.DATABASE_LOCATION, false); - - eb.setFooter(VersionInfo.APPNAME+" "+VersionInfo.VERSION); + eb.addField("🏷️ App Name", "β•°β”ˆβž€"+ProjectInfo.APPNAME, false); + eb.addField("βš™οΈ App Version", "β•°β”ˆβž€"+ProjectInfo.VERSION, false); + eb.addField("πŸ“ƒ App Source Code", "β•°β”ˆβž€"+"[GitHub]("+ProjectInfo.PROJECT_LINK+")", false); + eb.addField("πŸ” Privacy Policy", "β•°β”ˆβž€"+"[Privacy.md]("+ProjectInfo.PRIVACY+")", false); + eb.addField("🀝 Terms of Use", "β•°β”ˆβž€"+"[Terms.md]("+ProjectInfo.TERMS+")", false); + + eb.setFooter(ProjectInfo.APPNAME+" "+ProjectInfo.VERSION); eb.setTimestamp(Instant.now()); MessageEmbed mb = eb.build(); diff --git a/src/main/java/org/papertrail/listeners/customlisteners/BotSetupListener.java b/src/main/java/org/papertrail/listeners/customlisteners/BotSetupListener.java index b717a000..7a50786f 100644 --- a/src/main/java/org/papertrail/listeners/customlisteners/BotSetupListener.java +++ b/src/main/java/org/papertrail/listeners/customlisteners/BotSetupListener.java @@ -3,7 +3,7 @@ import java.awt.Color; import java.time.Instant; -import org.papertrail.version.VersionInfo; +import org.papertrail.version.ProjectInfo; import net.dv8tion.jda.api.EmbedBuilder; import net.dv8tion.jda.api.entities.MessageEmbed; @@ -18,8 +18,8 @@ public void onSlashCommandInteraction(SlashCommandInteractionEvent event) { if (event.getName().equals("setup")) { EmbedBuilder eb = new EmbedBuilder(); - eb.setTitle("πŸ› οΈ Setup Guide for " + VersionInfo.APPNAME); - eb.setDescription("Welcome to **" + VersionInfo.APPNAME + "**!\nHere's how to get started using the bot in your server."); + eb.setTitle("πŸ› οΈ Setup Guide for " + ProjectInfo.APPNAME); + eb.setDescription("Welcome to **" + ProjectInfo.APPNAME + "**!\nHere's how to get started using the bot in your server."); eb.setColor(Color.decode("#38e8bc")); eb.addField("1️⃣ Register Audit Log Channel", @@ -62,11 +62,11 @@ public void onSlashCommandInteraction(SlashCommandInteractionEvent event) { - Make sure the bot has view and message send permissions for the logging channel. - Commands only work in servers (guilds), not in DMs. - The bot will lose its configuration if kicked from the server. - - By default, all messages are stored in the database for 30 days, after which the newer ones will replace the older ones."""; + - By default, all messages are encrypted and stored in the database for 30 days, after which the newer ones will replace the older ones."""; eb.addField("πŸ’‘ Tips",tips,false); - eb.addField("πŸ“¬ Need help?", "Create an issue on [GitHub](" + VersionInfo.PROJECT_ISSUE_LINK+")", false); - eb.setFooter(VersionInfo.APPNAME+" "+VersionInfo.VERSION); + 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(); diff --git a/src/main/java/org/papertrail/version/VersionInfo.java b/src/main/java/org/papertrail/version/ProjectInfo.java similarity index 60% rename from src/main/java/org/papertrail/version/VersionInfo.java rename to src/main/java/org/papertrail/version/ProjectInfo.java index 85cea726..d74f4f59 100644 --- a/src/main/java/org/papertrail/version/VersionInfo.java +++ b/src/main/java/org/papertrail/version/ProjectInfo.java @@ -1,8 +1,8 @@ package org.papertrail.version; -public class VersionInfo { +public class ProjectInfo { - private VersionInfo() { + private ProjectInfo() { throw new IllegalStateException("Utility Class"); } @@ -11,6 +11,6 @@ private VersionInfo() { public static final String PROJECT_LINK = "https://github.com/Egg-03/PaperTrailBot"; public static final String PROJECT_ISSUE_LINK="https://github.com/Egg-03/PaperTrailBot/issues"; - public static final String SERVER_LOCATION = "Render: Frankfurt(Germany, Europe)"; - public static final String DATABASE_LOCATION = "Aiven: England(UK, Europe)"; + public static final String PRIVACY = "https://github.com/Egg-03/PaperTrailBot/blob/main/PRIVACY.md"; + public static final String TERMS = "https://github.com/Egg-03/PaperTrailBot/blob/main/TERMS.md"; }