From a4b05d7155c3ae2a86b4774d0dd21b44c269410d Mon Sep 17 00:00:00 2001
From: Egg-03 <111327101+Egg-03@users.noreply.github.com>
Date: Mon, 15 Sep 2025 01:22:55 +0530
Subject: [PATCH] refactor(api): replace unirest with spring restclient and
vavr
Replaces the Unirest HTTP client library with Spring's RestClient
and introduces Vavr's Either for functional error handling.
This change refactors the HttpServiceEngine, all API clients,
and updates DTOs and API response handling in listeners.
Benefits:
- Improves error handling with explicit success/failure states using Either.
- Adopts a modern and actively maintained HTTP client.
- Enhances consistency and maintainability of API interactions.
---
pom.xml | 13 +-
.../AuditLogSetupCommandListener.java | 64 ++---
.../MessageLogSetupCommandListener.java | 54 +++--
.../guildlisteners/ServerBoostListener.java | 65 +++---
.../loglisteners/AuditLogListener.java | 15 +-
.../loglisteners/MessageLogListener.java | 218 ++++++++----------
.../GuildMemberJoinAndLeaveListener.java | 119 +++++-----
.../voicelisteners/GuildVoiceListener.java | 89 +++----
.../java/org/papertrail/main/FireRun.java | 7 +-
.../papertrail/sdk/client/AuditLogClient.java | 71 +++---
.../sdk/client/MessageContentLogClient.java | 71 +++---
.../sdk/client/MessageLogClient.java | 71 +++---
.../sdk/http/HttpServiceEngine.java | 105 ++++++---
.../sdk/http/HttpServiceResponse.java | 7 -
.../papertrail/sdk/model/AuditLogObject.java | 5 +
.../sdk/model/AuditLogResponse.java | 5 -
.../{ErrorResponse.java => ErrorObject.java} | 2 +-
.../sdk/model/MessageContentObject.java | 4 +
.../sdk/model/MessageContentResponse.java | 4 -
.../sdk/model/MessageLogObject.java | 5 +
.../sdk/model/MessageLogResponse.java | 5 -
.../org/papertrail/version/ProjectInfo.java | 2 +-
22 files changed, 521 insertions(+), 480 deletions(-)
delete mode 100644 src/main/java/org/papertrail/sdk/http/HttpServiceResponse.java
create mode 100644 src/main/java/org/papertrail/sdk/model/AuditLogObject.java
delete mode 100644 src/main/java/org/papertrail/sdk/model/AuditLogResponse.java
rename src/main/java/org/papertrail/sdk/model/{ErrorResponse.java => ErrorObject.java} (83%)
create mode 100644 src/main/java/org/papertrail/sdk/model/MessageContentObject.java
delete mode 100644 src/main/java/org/papertrail/sdk/model/MessageContentResponse.java
create mode 100644 src/main/java/org/papertrail/sdk/model/MessageLogObject.java
delete mode 100644 src/main/java/org/papertrail/sdk/model/MessageLogResponse.java
diff --git a/pom.xml b/pom.xml
index 261c5788..c4cbf78d 100644
--- a/pom.xml
+++ b/pom.xml
@@ -58,10 +58,17 @@
guava
33.4.8-jre
+
- com.konghq
- unirest-java-core
- 4.5.0
+ org.springframework.boot
+ spring-boot-restclient
+ 4.0.0-M2
+
+
+
+ io.vavr
+ vavr
+ 0.10.7
com.google.code.gson
diff --git a/src/main/java/org/papertrail/listeners/commandlisteners/AuditLogSetupCommandListener.java b/src/main/java/org/papertrail/listeners/commandlisteners/AuditLogSetupCommandListener.java
index fd07bb25..0aeeefc6 100644
--- a/src/main/java/org/papertrail/listeners/commandlisteners/AuditLogSetupCommandListener.java
+++ b/src/main/java/org/papertrail/listeners/commandlisteners/AuditLogSetupCommandListener.java
@@ -3,10 +3,10 @@
import java.awt.Color;
import java.util.Objects;
-import org.papertrail.sdk.http.HttpServiceResponse;
-import org.papertrail.sdk.model.ErrorResponse;
+import io.vavr.control.Either;
+import org.papertrail.sdk.model.ErrorObject;
import org.papertrail.sdk.client.AuditLogClient;
-import org.papertrail.sdk.model.AuditLogResponse;
+import org.papertrail.sdk.model.AuditLogObject;
import net.dv8tion.jda.api.EmbedBuilder;
import net.dv8tion.jda.api.Permission;
@@ -50,38 +50,41 @@ 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)) {
- event.reply("â You don't have the permission required to use this command.").setEphemeral(true).queue();
- return;
- }
+
+ // 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;
+ }
// Call the API to register the guild and the channel
- String channelIdToRegister = event.getChannel().asTextChannel().getId();
- HttpServiceResponse guildRegistration = AuditLogClient.registerGuild(Objects.requireNonNull(event.getGuild()).getId(), channelIdToRegister);
- if(guildRegistration.requestSuccess()){
+ String guildId = Objects.requireNonNull(event.getGuild()).getId();
+ String channelId = event.getChannel().asTextChannel().getId();
+
+ Either response = AuditLogClient.registerGuild(guildId, channelId);
+ response.peek(success -> {
EmbedBuilder eb = new EmbedBuilder();
eb.setTitle("đ Audit Log Configuration");
- eb.addField("â
Channel Registration Success","â°ââ¤"+"All audit log info will be logged here", false);
+ eb.addField("â
Channel Registration Success", "â°ââ¤" + "All audit log info will be logged here", false);
eb.setColor(Color.GREEN);
MessageEmbed mb = eb.build();
event.replyEmbeds(mb).setEphemeral(false).queue();
- } else {
+
+ }).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", "â°ââ¤"+guildRegistration.error().message(), false);
+ eb.addField("\uD83C\uDF10 API Response", "â°ââ¤" + failure.message(), false);
eb.setColor(Color.YELLOW);
MessageEmbed mb = eb.build();
- event.replyEmbeds(mb).setEphemeral(false).queue();
- }
- }
+ event.replyEmbeds(mb).setEphemeral(false).queue();
+ });
+ }
private void retrieveAuditLoggingChannel(SlashCommandInteractionEvent event) {
@@ -95,13 +98,13 @@ private void retrieveAuditLoggingChannel(SlashCommandInteractionEvent event) {
String guildId = Objects.requireNonNull(event.getGuild()).getId();
// Call the API to retrieve the registered channel
- HttpServiceResponse guildRegistrationCheck = AuditLogClient.getRegisteredGuild(guildId);
+ Either response = AuditLogClient.getRegisteredGuild(guildId);
// 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
- if (guildRegistrationCheck.requestSuccess()) {
+ response.peek(success -> {
- String registeredChannelId = guildRegistrationCheck.success().channelId();
+ String registeredChannelId = success.channelId();
GuildChannel registeredChannel = event.getJDA().getGuildChannelById(registeredChannelId);
EmbedBuilder eb = new EmbedBuilder();
@@ -110,7 +113,8 @@ private void retrieveAuditLoggingChannel(SlashCommandInteractionEvent event) {
eb.addField("â
Channel Registration Check", "â°ââ¤"+(registeredChannel!=null ? registeredChannel.getAsMention() : registeredChannelId)+ " is found to be registered as the audit log channel", false);
MessageEmbed mb = eb.build();
event.replyEmbeds(mb).setEphemeral(false).queue();
- } else {
+
+ }).peekLeft(failure -> {
EmbedBuilder eb = new EmbedBuilder();
eb.setTitle("đ Audit Log Configuration");
@@ -118,7 +122,8 @@ private void retrieveAuditLoggingChannel(SlashCommandInteractionEvent event) {
eb.setColor(Color.YELLOW);
MessageEmbed mb = eb.build();
event.replyEmbeds(mb).setEphemeral(false).queue();
- }
+
+ });
}
private void unsetAuditLogging(SlashCommandInteractionEvent event) {
@@ -132,8 +137,8 @@ private void unsetAuditLogging(SlashCommandInteractionEvent event) {
String guildId = Objects.requireNonNull(event.getGuild()).getId();
// Call the API to unregister guild
- HttpServiceResponse guildUnregistration = AuditLogClient.deleteRegisteredGuild(guildId);
- if(guildUnregistration.requestSuccess()) {
+ Either response = AuditLogClient.deleteRegisteredGuild(guildId);
+ response.peek(success -> {
EmbedBuilder eb = new EmbedBuilder();
eb.setTitle("đ Audit Log Configuration");
@@ -143,17 +148,18 @@ private void unsetAuditLogging(SlashCommandInteractionEvent event) {
event.replyEmbeds(mb).setEphemeral(false).queue();
- } else {
+ }).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", "â°ââ¤"+guildUnregistration.error().message(), false);
+ eb.addField("\uD83C\uDF10 API Response", "â°ââ¤"+failure.message(), false);
eb.setColor(Color.YELLOW);
MessageEmbed mb = eb.build();
event.replyEmbeds(mb).setEphemeral(false).queue();
- }
+ });
+
}
}
diff --git a/src/main/java/org/papertrail/listeners/commandlisteners/MessageLogSetupCommandListener.java b/src/main/java/org/papertrail/listeners/commandlisteners/MessageLogSetupCommandListener.java
index 11bfc3f1..484f1fd7 100644
--- a/src/main/java/org/papertrail/listeners/commandlisteners/MessageLogSetupCommandListener.java
+++ b/src/main/java/org/papertrail/listeners/commandlisteners/MessageLogSetupCommandListener.java
@@ -3,14 +3,13 @@
import java.awt.Color;
import java.util.Objects;
-import org.papertrail.sdk.http.HttpServiceResponse;
-import org.papertrail.sdk.model.ErrorResponse;
+import io.vavr.control.Either;
+import org.papertrail.sdk.model.ErrorObject;
import org.papertrail.sdk.client.MessageLogClient;
-import org.papertrail.sdk.model.MessageLogResponse;
+import org.papertrail.sdk.model.MessageLogObject;
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.middleman.GuildChannel;
@@ -57,13 +56,12 @@ private void setMessageLogging(SlashCommandInteractionEvent event) {
event.reply("â You don't have the permission required to use this command.").setEphemeral(true).queue();
return;
}
-
- Guild guild = event.getGuild();
- String guildId = Objects.requireNonNull(guild).getId();
+
+ String guildId = Objects.requireNonNull(event.getGuild()).getId();
// Call the API to register guild for message logging
- HttpServiceResponse guildRegistration = MessageLogClient.registerGuild(guildId, event.getChannelId());
- if(guildRegistration.requestSuccess()) {
+ Either response = MessageLogClient.registerGuild(guildId, event.getChannelId());
+ response.peek(success -> {
EmbedBuilder eb = new EmbedBuilder();
eb.setTitle("Message Log Registration");
@@ -72,17 +70,19 @@ private void setMessageLogging(SlashCommandInteractionEvent event) {
MessageEmbed mb = eb.build();
event.replyEmbeds(mb).setEphemeral(false).queue();
- } else {
+
+ }).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", "â°ââ¤"+guildRegistration.error().message(), false);
+ eb.addField("\uD83C\uDF10 API Response", "â°ââ¤"+failure.message(), false);
eb.setColor(Color.YELLOW);
MessageEmbed mb = eb.build();
event.replyEmbeds(mb).setEphemeral(false).queue();
- }
+ });
+
}
private void retrieveMessageLoggingChannel(SlashCommandInteractionEvent event) {
@@ -94,15 +94,13 @@ private void retrieveMessageLoggingChannel(SlashCommandInteractionEvent event) {
return;
}
- Guild guild = event.getGuild();
- String guildId = Objects.requireNonNull(guild).getId();
+ String guildId = Objects.requireNonNull(event.getGuild()).getId();
// Call the API to check for registered guild
- HttpServiceResponse guildRegistrationCheck = MessageLogClient.getRegisteredGuild(guildId);
-
- if(guildRegistrationCheck.requestSuccess()){
+ Either response = MessageLogClient.getRegisteredGuild(guildId);
+ response.peek(success -> {
- String registeredChannelId = guildRegistrationCheck.success().channelId();
+ String registeredChannelId = success.channelId();
GuildChannel registeredChannel = event.getJDA().getGuildChannelById(registeredChannelId);
EmbedBuilder eb = new EmbedBuilder();
@@ -112,7 +110,7 @@ private void retrieveMessageLoggingChannel(SlashCommandInteractionEvent event) {
MessageEmbed mb = eb.build();
event.replyEmbeds(mb).setEphemeral(false).queue();
- } else {
+ }).peekLeft(failure -> {
EmbedBuilder eb = new EmbedBuilder();
eb.setTitle("đ Message Log Configuration");
@@ -120,8 +118,7 @@ private void retrieveMessageLoggingChannel(SlashCommandInteractionEvent event) {
eb.setColor(Color.YELLOW);
MessageEmbed mb = eb.build();
event.replyEmbeds(mb).setEphemeral(false).queue();
-
- }
+ });
}
private void unsetMessageLogging(SlashCommandInteractionEvent event) {
@@ -133,12 +130,11 @@ private void unsetMessageLogging(SlashCommandInteractionEvent event) {
return;
}
- Guild guild = event.getGuild();
- String guildId = Objects.requireNonNull(guild).getId();
+ String guildId = Objects.requireNonNull(event.getGuild()).getId();
// Call the API to unregister guild
- HttpServiceResponse guildUnregistration = MessageLogClient.deleteRegisteredGuild(guildId);
- if (guildUnregistration.requestSuccess()) {
+ Either response = MessageLogClient.deleteRegisteredGuild(guildId);
+ response.peek(success -> {
EmbedBuilder eb = new EmbedBuilder();
eb.setTitle("đ Message Log Configuration");
@@ -147,17 +143,19 @@ private void unsetMessageLogging(SlashCommandInteractionEvent event) {
MessageEmbed mb = eb.build();
event.replyEmbeds(mb).setEphemeral(false).queue();
- } else {
+
+ }).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", "â°ââ¤" + guildUnregistration.error().message(), false);
+ eb.addField("\uD83C\uDF10 API Response", "â°ââ¤" + failure.message(), false);
eb.setColor(Color.YELLOW);
MessageEmbed mb = eb.build();
event.replyEmbeds(mb).setEphemeral(false).queue();
- }
+ });
+
}
}
diff --git a/src/main/java/org/papertrail/listeners/guildlisteners/ServerBoostListener.java b/src/main/java/org/papertrail/listeners/guildlisteners/ServerBoostListener.java
index 407810a9..9a9737fb 100644
--- a/src/main/java/org/papertrail/listeners/guildlisteners/ServerBoostListener.java
+++ b/src/main/java/org/papertrail/listeners/guildlisteners/ServerBoostListener.java
@@ -6,6 +6,7 @@
import java.util.Objects;
import java.util.concurrent.Executor;
+import io.vavr.control.Either;
import org.jetbrains.annotations.NotNull;
import net.dv8tion.jda.api.EmbedBuilder;
@@ -15,9 +16,8 @@
import net.dv8tion.jda.api.events.guild.member.update.GuildMemberUpdateBoostTimeEvent;
import net.dv8tion.jda.api.hooks.ListenerAdapter;
import org.papertrail.sdk.client.AuditLogClient;
-import org.papertrail.sdk.http.HttpServiceResponse;
-import org.papertrail.sdk.model.AuditLogResponse;
-import org.papertrail.sdk.model.ErrorResponse;
+import org.papertrail.sdk.model.AuditLogObject;
+import org.papertrail.sdk.model.ErrorObject;
public class ServerBoostListener extends ListenerAdapter {
@@ -33,44 +33,43 @@ public void onGuildMemberUpdateBoostTime(@NotNull GuildMemberUpdateBoostTimeEven
vThreadPool.execute(()->{
// server boost logs are mapped to audit log table
// Call the API and see if the event came from a registered Guild
- HttpServiceResponse guildCheck = AuditLogClient.getRegisteredGuild(event.getGuild().getId());
+ Either response = AuditLogClient.getRegisteredGuild(event.getGuild().getId());
+ response.peek(success -> {
+ String registeredChannelId= success.channelId();
- if(!guildCheck.requestSuccess()){
- return;
- }
- String registeredChannelId= guildCheck.success().channelId();
+ Member member = event.getMember();
+ Guild guild = event.getGuild();
- Member member = event.getMember();
- Guild guild = event.getGuild();
+ String mentionableMember = member.getAsMention();
- String mentionableMember = member.getAsMention();
+ OffsetDateTime newBoostTime = event.getNewTimeBoosted(); // Will be null if the member stopped boosting
- OffsetDateTime newBoostTime = event.getNewTimeBoosted(); // Will be null if the member stopped boosting
+ EmbedBuilder eb = new EmbedBuilder();
+ eb.setTitle("đ Server Boost Event ");
+ eb.setThumbnail(guild.getIconUrl());
- EmbedBuilder eb = new EmbedBuilder();
- eb.setTitle("đ Server Boost Event ");
- eb.setThumbnail(guild.getIconUrl());
+ if (newBoostTime != null) {
+ eb.setDescription("đ **" + guild.getName() + "** has been boosted!");
+ eb.setColor(Color.PINK);
+ eb.addField("đ Booster Gained", "â°ââ¤"+mentionableMember+" has started boosting your server", false);
+ eb.addField("đ Total Boosts In The Server", "â°ââ¤"+guild.getBoostCount(), false);
+ eb.addField("đī¸ Current Boost Tier", "â°ââ¤"+ guild.getBoostTier(), false);
+ } else {
+ eb.setDescription("â ī¸ **" + guild.getName() + "** has lost a boost.");
+ eb.setColor(Color.GRAY);
+ eb.addField("đĒĢ Booster Lost", "â°ââ¤"+mentionableMember+" has removed their boost from your server", false);
+ eb.addField("đ Remaining Boosts In The Server", "â°ââ¤"+guild.getBoostCount(), false);
+ eb.addField("đī¸ Current Boost Tier", "â°ââ¤"+ guild.getBoostTier(), false);
+ eb.addField("Notice", "Boosts remain active for a period even after a member stops boosting, so the server's boost count doesn't update immediately.", false);
+ }
- if (newBoostTime != null) {
- eb.setDescription("đ **" + guild.getName() + "** has been boosted!");
- eb.setColor(Color.PINK);
- eb.addField("đ Booster Gained", "â°ââ¤"+mentionableMember+" has started boosting your server", false);
- eb.addField("đ Total Boosts In The Server", "â°ââ¤"+guild.getBoostCount(), false);
- eb.addField("đī¸ Current Boost Tier", "â°ââ¤"+ guild.getBoostTier(), false);
- } else {
- eb.setDescription("â ī¸ **" + guild.getName() + "** has lost a boost.");
- eb.setColor(Color.GRAY);
- eb.addField("đĒĢ Booster Lost", "â°ââ¤"+mentionableMember+" has removed their boost from your server", false);
- eb.addField("đ Remaining Boosts In The Server", "â°ââ¤"+guild.getBoostCount(), false);
- eb.addField("đī¸ Current Boost Tier", "â°ââ¤"+ guild.getBoostTier(), false);
- eb.addField("Notice", "Boosts remain active for a period even after a member stops boosting, so the server's boost count doesn't update immediately.", false);
- }
+ eb.setFooter("Server Boost Detection");
+ eb.setTimestamp(Instant.now());
- eb.setFooter("Server Boost Detection");
- eb.setTimestamp(Instant.now());
+ MessageEmbed mb = eb.build();
+ Objects.requireNonNull(event.getGuild().getTextChannelById(registeredChannelId)).sendMessageEmbeds(mb).queue();
+ });
- MessageEmbed mb = eb.build();
- Objects.requireNonNull(event.getGuild().getTextChannelById(registeredChannelId)).sendMessageEmbeds(mb).queue();
});
}
}
diff --git a/src/main/java/org/papertrail/listeners/loglisteners/AuditLogListener.java b/src/main/java/org/papertrail/listeners/loglisteners/AuditLogListener.java
index b7f88b9e..93705e76 100644
--- a/src/main/java/org/papertrail/listeners/loglisteners/AuditLogListener.java
+++ b/src/main/java/org/papertrail/listeners/loglisteners/AuditLogListener.java
@@ -6,12 +6,12 @@
import java.util.Objects;
import java.util.concurrent.Executor;
+import io.vavr.control.Either;
import org.apache.commons.lang3.StringUtils;
import org.jetbrains.annotations.NotNull;
import org.papertrail.sdk.client.AuditLogClient;
-import org.papertrail.sdk.http.HttpServiceResponse;
-import org.papertrail.sdk.model.AuditLogResponse;
-import org.papertrail.sdk.model.ErrorResponse;
+import org.papertrail.sdk.model.AuditLogObject;
+import org.papertrail.sdk.model.ErrorObject;
import org.papertrail.utilities.ColorFormatter;
import org.papertrail.utilities.DurationFormatter;
import org.papertrail.utilities.GuildSystemChannelFlagResolver;
@@ -50,12 +50,11 @@ public void onGuildAuditLogEntryCreate(@NotNull GuildAuditLogEntryCreateEvent ev
vThreadPool.execute(()->{
// Call the API and see if the event came from a registered Guild
- HttpServiceResponse guildCheck = AuditLogClient.getRegisteredGuild(event.getGuild().getId());
-
- if(guildCheck.requestSuccess()){
+ Either response = AuditLogClient.getRegisteredGuild(event.getGuild().getId());
+ response.peek(success -> {
AuditLogEntry ale = event.getEntry();
- auditLogParser(event, ale, guildCheck.success().channelId());
- }
+ auditLogParser(event, ale, success.channelId());
+ });
});
}
diff --git a/src/main/java/org/papertrail/listeners/loglisteners/MessageLogListener.java b/src/main/java/org/papertrail/listeners/loglisteners/MessageLogListener.java
index 626cf2fe..dd91339f 100644
--- a/src/main/java/org/papertrail/listeners/loglisteners/MessageLogListener.java
+++ b/src/main/java/org/papertrail/listeners/loglisteners/MessageLogListener.java
@@ -10,6 +10,7 @@
import com.google.common.base.Splitter;
import com.google.common.util.concurrent.Striped;
+import io.vavr.control.Either;
import org.jetbrains.annotations.NotNull;
import org.jspecify.annotations.NonNull;
@@ -22,10 +23,9 @@
import net.dv8tion.jda.api.hooks.ListenerAdapter;
import org.papertrail.sdk.client.MessageContentLogClient;
import org.papertrail.sdk.client.MessageLogClient;
-import org.papertrail.sdk.http.HttpServiceResponse;
-import org.papertrail.sdk.model.ErrorResponse;
-import org.papertrail.sdk.model.MessageContentResponse;
-import org.papertrail.sdk.model.MessageLogResponse;
+import org.papertrail.sdk.model.ErrorObject;
+import org.papertrail.sdk.model.MessageContentObject;
+import org.papertrail.sdk.model.MessageLogObject;
import org.papertrail.utilities.MessageEncryption;
import org.tinylog.Logger;
@@ -68,22 +68,15 @@ 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
- HttpServiceResponse guildRegistrationCheck = MessageLogClient.getRegisteredGuild(guildId);
-
- // if not registered, exit
- if(!guildRegistrationCheck.requestSuccess()) {
- return;
- }
-
- // else log the message with its ID and author
- String messageId = event.getMessageId();
- String encryptedMessage = MessageEncryption.encrypt(event.getMessage().getContentRaw());
- String authorId = event.getAuthor().getId();
-
- withMessageLock(messageId, ()-> MessageContentLogClient.logMessage(messageId, encryptedMessage, authorId));
+ Either response = MessageLogClient.getRegisteredGuild(guildId);
+ response.peek(success -> {
+ String messageId = event.getMessageId();
+ String encryptedMessage = MessageEncryption.encrypt(event.getMessage().getContentRaw());
+ String authorId = event.getAuthor().getId();
+
+ withMessageLock(messageId, ()-> MessageContentLogClient.logMessage(messageId, encryptedMessage, authorId));
+ });
});
-
-
}
@Override
@@ -95,66 +88,62 @@ public void onMessageUpdate(MessageUpdateEvent event) {
vThreadPool.execute(()->{
+ // Get the guild id for which the event was fired
String guildId = event.getGuild().getId();
+ // 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
- HttpServiceResponse guildRegistrationCheck = MessageLogClient.getRegisteredGuild(guildId);
-
- // if not registered, exit
- if(!guildRegistrationCheck.requestSuccess()) {
- return;
- }
-
- // get the message id of the message which was updated
- String messageId = event.getMessageId();
-
- // fetch the old message object from the API
- HttpServiceResponse loggedMessageResponse = MessageContentLogClient.retrieveMessage(messageId);
- if(!loggedMessageResponse.requestSuccess()){ // if message does not exist (it wasn't logged), then return
- return;
- }
- // Decrypt the fetched message
- assert loggedMessageResponse.success() != null;
- String decryptedMessage = MessageEncryption.decrypt(loggedMessageResponse.success().messageContent());
- // fetch the updated message and its author from the event
- String updatedMessage = event.getMessage().getContentRaw();
-
- // 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)) {
- 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);
- List updatedMessageSplits = Splitter.fixedLength(1024).splitToList(updatedMessage);
-
- EmbedBuilder eb = new EmbedBuilder();
- eb.setTitle("đ Message Edit 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
- 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();
- assert guildRegistrationCheck.success() != null;
- String channelIdToSendTo = guildRegistrationCheck.success().channelId();
- Objects.requireNonNull(event.getGuild().getTextChannelById(channelIdToSendTo)).sendMessageEmbeds(mb).queue();
+ Either response = MessageLogClient.getRegisteredGuild(guildId);
+ response.peek(success -> {
+
+ // retrieve the channel id where the logs must be sent
+ String channelIdToSendTo = success.channelId();
+
+ // 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());
+ // fetch the updated message and its author from the event
+ String updatedMessage = event.getMessage().getContentRaw();
+
+ // 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)) {
+ 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);
+ List updatedMessageSplits = Splitter.fixedLength(1024).splitToList(updatedMessage);
+
+ EmbedBuilder eb = new EmbedBuilder();
+ eb.setTitle("đ Message Edit 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
+ 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();
+ Objects.requireNonNull(event.getGuild().getTextChannelById(channelIdToSendTo)).sendMessageEmbeds(mb).queue();
+ });
+ });
});
}
@@ -163,58 +152,53 @@ public void onMessageDelete(@NotNull MessageDeleteEvent event) {
vThreadPool.execute(()-> {
+ // Get the guild id for which the event was fired
String guildId = event.getGuild().getId();
- // Call the API to see if the guild is registered for Message Logging
- HttpServiceResponse guildRegistrationCheck = MessageLogClient.getRegisteredGuild(guildId);
+ // get the message id of the message which was deleted
+ String messageId = event.getMessageId();
- // if not registered, exit
- if(!guildRegistrationCheck.requestSuccess()) {
- return;
- }
-
- // get the message id of the message which was deleted
- 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 -> {
- // fetch the old message object from the API
- HttpServiceResponse loggedMessageResponse = MessageContentLogClient.retrieveMessage(messageId);
- if(!loggedMessageResponse.requestSuccess()){ // if message does not exist (it wasn't logged), then return
- return;
- }
+ // retrieve the channel id where the logs must be sent
+ String channelIdToSendTo = success.channelId();
- // retrieve the channel id where the logs must be sent
- assert guildRegistrationCheck.success() != null;
- String channelIdToSendTo = guildRegistrationCheck.success().channelId();
+ // fetch the old message object from the API
+ Either deletedMessageObject = MessageContentLogClient.retrieveMessage(messageId);
+ deletedMessageObject.peek(content -> {
- // retrieve the stored message and author in the database which was deleted
- assert loggedMessageResponse.success() != null;
- String deletedMessage = MessageEncryption.decrypt(loggedMessageResponse.success().messageContent());
- String deletedMessageAuthorId = loggedMessageResponse.success().authorId();
+ // retrieve the stored message and author in the database which was deleted
+ String deletedMessage = MessageEncryption.decrypt(content.messageContent());
+ String deletedMessageAuthorId = content.authorId();
- User author = event.getJDA().getUserById(deletedMessageAuthorId);
- String mentionableAuthor = (author !=null ? author.getAsMention() : deletedMessageAuthorId);
+ 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);
+ // 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.setColor(Color.RED);
+ EmbedBuilder eb = new EmbedBuilder();
+ eb.setTitle("đī¸ Message Delete Event");
+ eb.setDescription("A message sent by "+mentionableAuthor+" has been deleted");
+ eb.setColor(Color.RED);
- deletedMessageSplits.forEach(split-> eb.addField("Deleted Message", split, false));
+ deletedMessageSplits.forEach(split-> eb.addField("Deleted Message", split, false));
- eb.setFooter(event.getGuild().getName());
- eb.setTimestamp(Instant.now());
+ 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.
+ // 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();
- Objects.requireNonNull(event.getGuild().getTextChannelById(channelIdToSendTo)).sendMessageEmbeds(mb).queue();
+ // send the fetched deleted message to the logging channel
+ MessageEmbed mb = eb.build();
+ Objects.requireNonNull(event.getGuild().getTextChannelById(channelIdToSendTo)).sendMessageEmbeds(mb).queue();
+ });
+ });
});
}
}
diff --git a/src/main/java/org/papertrail/listeners/memberlisteners/GuildMemberJoinAndLeaveListener.java b/src/main/java/org/papertrail/listeners/memberlisteners/GuildMemberJoinAndLeaveListener.java
index 552a7d8e..21e4afba 100644
--- a/src/main/java/org/papertrail/listeners/memberlisteners/GuildMemberJoinAndLeaveListener.java
+++ b/src/main/java/org/papertrail/listeners/memberlisteners/GuildMemberJoinAndLeaveListener.java
@@ -1,5 +1,6 @@
package org.papertrail.listeners.memberlisteners;
+import io.vavr.control.Either;
import net.dv8tion.jda.api.EmbedBuilder;
import net.dv8tion.jda.api.entities.Guild;
import net.dv8tion.jda.api.entities.Member;
@@ -10,9 +11,8 @@
import net.dv8tion.jda.api.hooks.ListenerAdapter;
import org.jetbrains.annotations.NotNull;
import org.papertrail.sdk.client.AuditLogClient;
-import org.papertrail.sdk.http.HttpServiceResponse;
-import org.papertrail.sdk.model.AuditLogResponse;
-import org.papertrail.sdk.model.ErrorResponse;
+import org.papertrail.sdk.model.AuditLogObject;
+import org.papertrail.sdk.model.ErrorObject;
import org.papertrail.utilities.DurationFormatter;
import java.awt.Color;
@@ -35,33 +35,32 @@ 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
- HttpServiceResponse guildCheck = AuditLogClient.getRegisteredGuild(event.getGuild().getId());
+ Either response = AuditLogClient.getRegisteredGuild(event.getGuild().getId());
+ response.peek(success -> {
- if(!guildCheck.requestSuccess()){
- return;
- }
- String registeredChannelId = guildCheck.success().channelId();
+ String registeredChannelId = success.channelId();
- Guild guild = event.getGuild();
- User user = event.getUser();
+ Guild guild = event.getGuild();
+ User user = event.getUser();
- EmbedBuilder eb = new EmbedBuilder();
- eb.setTitle("đŦ Member Join Event");
- eb.setDescription("A Member has joined "+guild.getName());
- eb.setColor(Color.GREEN);
+ EmbedBuilder eb = new EmbedBuilder();
+ eb.setTitle("đŦ Member Join Event");
+ eb.setDescription("A Member has joined "+guild.getName());
+ eb.setColor(Color.GREEN);
- eb.addField("đˇī¸ Member Name", "â°ââ¤"+user.getName(), false);
- eb.setThumbnail(user.getEffectiveAvatarUrl());
- eb.addField("âšī¸ Member Mention", "â°ââ¤"+user.getAsMention(), false);
- eb.addField("đ Member ID", "â°ââ¤"+user.getId(), false);
- eb.addField("đ
Account Created", "â°ââ¤"+DurationFormatter.isoToLocalTimeCounter(user.getTimeCreated()), false);
- eb.addField("đ¤ Is Application ?", "â°ââ¤"+((user.isBot()) ? "â
" : "â"), false);
- eb.setFooter("Member Join Detection");
- eb.setTimestamp(Instant.now());
+ eb.addField("đˇī¸ Member Name", "â°ââ¤"+user.getName(), false);
+ eb.setThumbnail(user.getEffectiveAvatarUrl());
+ eb.addField("âšī¸ Member Mention", "â°ââ¤"+user.getAsMention(), false);
+ eb.addField("đ Member ID", "â°ââ¤"+user.getId(), false);
+ eb.addField("đ
Account Created", "â°ââ¤"+DurationFormatter.isoToLocalTimeCounter(user.getTimeCreated()), false);
+ eb.addField("đ¤ Is Application ?", "â°ââ¤"+((user.isBot()) ? "â
" : "â"), false);
+ eb.setFooter("Member Join Detection");
+ eb.setTimestamp(Instant.now());
- MessageEmbed mb = eb.build();
+ MessageEmbed mb = eb.build();
- Objects.requireNonNull(event.getGuild().getTextChannelById(registeredChannelId)).sendMessageEmbeds(mb).queue();
+ Objects.requireNonNull(event.getGuild().getTextChannelById(registeredChannelId)).sendMessageEmbeds(mb).queue();
+ });
});
}
@@ -70,42 +69,42 @@ public void onGuildMemberRemove(@NotNull GuildMemberRemoveEvent event) {
vThreadPool.execute(() -> {
// Call the API and see if the event came from a registered Guild
- HttpServiceResponse guildCheck = AuditLogClient.getRegisteredGuild(event.getGuild().getId());
-
- if(!guildCheck.requestSuccess()){
- return;
- }
- String registeredChannelId = guildCheck.success().channelId();
-
- Guild guild = event.getGuild();
- User user = event.getUser();
- Member member = event.getMember();
-
- String memberJoinDate = "Member Not Cached";
- boolean memberJoinDateTrustable = false;
- if(member!=null){
- memberJoinDate = "";
- memberJoinDateTrustable = member.hasTimeJoined();
- }
-
- EmbedBuilder eb = new EmbedBuilder();
- eb.setTitle("đĢ Member Leave Event");
- eb.setDescription("A Member has left "+guild.getName());
- eb.setColor(Color.RED);
-
- eb.addField("đˇī¸ Member Name", "â°ââ¤"+user.getName(), false);
- eb.setThumbnail(user.getEffectiveAvatarUrl());
- eb.addField("đ Member ID", "â°ââ¤"+user.getId(), false);
- eb.addField("â Member Joined The Server On","â°ââ¤"+memberJoinDate, false);
- eb.addField("â Member Join Date Accurate?", memberJoinDateTrustable ? "â
" : "â" , false);
-
- eb.setFooter("Join timestamp may fall back to guild creation time if not provided by Discord during lazy loading of members. " +
- "Accuracy of the timestamp can be determined by the extra field provided.");
- eb.setTimestamp(Instant.now());
-
- MessageEmbed mb = eb.build();
-
- Objects.requireNonNull(event.getGuild().getTextChannelById(registeredChannelId)).sendMessageEmbeds(mb).queue();
+ Either response = AuditLogClient.getRegisteredGuild(event.getGuild().getId());
+ response.peek(success -> {
+
+ String registeredChannelId = success.channelId();
+
+ Guild guild = event.getGuild();
+ User user = event.getUser();
+ Member member = event.getMember();
+
+ String memberJoinDate = "Member Not Cached";
+ boolean memberJoinDateTrustable = false;
+ if(member!=null){
+ memberJoinDate = "";
+ memberJoinDateTrustable = member.hasTimeJoined();
+ }
+
+ EmbedBuilder eb = new EmbedBuilder();
+ eb.setTitle("đĢ Member Leave Event");
+ eb.setDescription("A Member has left "+guild.getName());
+ eb.setColor(Color.RED);
+
+ eb.addField("đˇī¸ Member Name", "â°ââ¤"+user.getName(), false);
+ eb.setThumbnail(user.getEffectiveAvatarUrl());
+ eb.addField("đ Member ID", "â°ââ¤"+user.getId(), false);
+ eb.addField("â Member Joined The Server On","â°ââ¤"+memberJoinDate, false);
+ eb.addField("â Member Join Date Accurate?", memberJoinDateTrustable ? "â
" : "â" , false);
+
+ eb.setFooter("Join timestamp may fall back to guild creation time if not provided by Discord during lazy loading of members. " +
+ "Accuracy of the timestamp can be determined by the extra field provided.");
+ eb.setTimestamp(Instant.now());
+
+ MessageEmbed mb = eb.build();
+
+ Objects.requireNonNull(event.getGuild().getTextChannelById(registeredChannelId)).sendMessageEmbeds(mb).queue();
+ });
+
});
}
diff --git a/src/main/java/org/papertrail/listeners/voicelisteners/GuildVoiceListener.java b/src/main/java/org/papertrail/listeners/voicelisteners/GuildVoiceListener.java
index 8c31f85b..e9ee04d3 100644
--- a/src/main/java/org/papertrail/listeners/voicelisteners/GuildVoiceListener.java
+++ b/src/main/java/org/papertrail/listeners/voicelisteners/GuildVoiceListener.java
@@ -5,6 +5,7 @@
import java.util.Objects;
import java.util.concurrent.Executor;
+import io.vavr.control.Either;
import org.jetbrains.annotations.NotNull;
import net.dv8tion.jda.api.EmbedBuilder;
import net.dv8tion.jda.api.entities.Member;
@@ -13,9 +14,8 @@
import net.dv8tion.jda.api.events.guild.voice.GuildVoiceUpdateEvent;
import net.dv8tion.jda.api.hooks.ListenerAdapter;
import org.papertrail.sdk.client.AuditLogClient;
-import org.papertrail.sdk.http.HttpServiceResponse;
-import org.papertrail.sdk.model.AuditLogResponse;
-import org.papertrail.sdk.model.ErrorResponse;
+import org.papertrail.sdk.model.AuditLogObject;
+import org.papertrail.sdk.model.ErrorObject;
public class GuildVoiceListener extends ListenerAdapter {
@@ -32,47 +32,48 @@ 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
- HttpServiceResponse guildCheck = AuditLogClient.getRegisteredGuild(event.getGuild().getId());
-
- if(!guildCheck.requestSuccess()){
- return ;
- }
- String registeredChannelId = guildCheck.success().channelId();
-
- EmbedBuilder eb = new EmbedBuilder();
- eb.setTitle("đ Voice Activity Log");
-
- Member member = event.getMember();
- AudioChannel left = event.getOldValue(); // can be null if user joined for first time
- AudioChannel joined = event.getNewValue(); // can be null if user left
-
- if(left==null && joined!=null) {
- // User has joined a vc
- eb.setDescription("A Member has joined a voice channel");
- eb.setColor(Color.GREEN);
- eb.addField("â
Member Joined", "â°ââ¤"+member.getAsMention()+" joined the voice channel "+joined.getAsMention(), false);
- }
-
- if (left != null && joined != null) {
- // Moved from one channel to another
- eb.setDescription("A Member has switched voice channels");
- eb.setColor(Color.YELLOW);
- eb.addField("đ Member Switched Channels", "â°ââ¤"+member.getAsMention()+" joined the switched from channel "+left.getAsMention()+ " to "+joined.getAsMention(), false);
- }
-
- if (left!=null && joined==null) {
- // User disconnected voluntarily (or was disconnected by a moderator)
- eb.setDescription("A Member has left a voice channel");
- eb.setColor(Color.RED);
- eb.addField("â Member Left A Voice Channel", "â°ââ¤"+member.getAsMention()+" left the voice channel "+left.getAsMention(), false);
- }
-
- eb.setFooter("Voice Activity Detection");
- eb.setTimestamp(Instant.now());
-
- MessageEmbed mb = eb.build();
-
- Objects.requireNonNull(event.getGuild().getTextChannelById(registeredChannelId)).sendMessageEmbeds(mb).queue();
+ Either response = AuditLogClient.getRegisteredGuild(event.getGuild().getId());
+
+ response.peek(success -> {
+
+ String registeredChannelId = success.channelId();
+
+ EmbedBuilder eb = new EmbedBuilder();
+ eb.setTitle("đ Voice Activity Log");
+
+ Member member = event.getMember();
+ AudioChannel left = event.getOldValue(); // can be null if user joined for first time
+ AudioChannel joined = event.getNewValue(); // can be null if user left
+
+ if(left==null && joined!=null) {
+ // User has joined a vc
+ eb.setDescription("A Member has joined a voice channel");
+ eb.setColor(Color.GREEN);
+ eb.addField("â
Member Joined", "â°ââ¤"+member.getAsMention()+" joined the voice channel "+joined.getAsMention(), false);
+ }
+
+ if (left != null && joined != null) {
+ // Moved from one channel to another
+ eb.setDescription("A Member has switched voice channels");
+ eb.setColor(Color.YELLOW);
+ eb.addField("đ Member Switched Channels", "â°ââ¤"+member.getAsMention()+" joined the switched from channel "+left.getAsMention()+ " to "+joined.getAsMention(), false);
+ }
+
+ if (left!=null && joined==null) {
+ // User disconnected voluntarily (or was disconnected by a moderator)
+ eb.setDescription("A Member has left a voice channel");
+ eb.setColor(Color.RED);
+ eb.addField("â Member Left A Voice Channel", "â°ââ¤"+member.getAsMention()+" left the voice channel "+left.getAsMention(), false);
+ }
+
+ eb.setFooter("Voice Activity Detection");
+ eb.setTimestamp(Instant.now());
+
+ MessageEmbed mb = eb.build();
+
+ Objects.requireNonNull(event.getGuild().getTextChannelById(registeredChannelId)).sendMessageEmbeds(mb).queue();
+ });
+
});
}
}
diff --git a/src/main/java/org/papertrail/main/FireRun.java b/src/main/java/org/papertrail/main/FireRun.java
index 54ab73b3..28bf507f 100644
--- a/src/main/java/org/papertrail/main/FireRun.java
+++ b/src/main/java/org/papertrail/main/FireRun.java
@@ -65,11 +65,8 @@ public static void main(String[] args) throws IOException {
manager.addEventListener(new BotInfoCommandListener());
manager.addEventListener(new BotSetupCommandListener());
manager.addEventListener(new RequiredPermissionCheckCommandListener());
-
- /*
- * This is required only to set up a cron-job to periodically ping this end-point so that
- * hosting services that spin down after inactivity don't do that anymore
- */
+
+ // Custom health check endpoint
HttpServer server = HttpServer.create(new InetSocketAddress(8080), 0);
server.createContext("/ping", new PingHandler());
server.setExecutor(null); // creates a default executor
diff --git a/src/main/java/org/papertrail/sdk/client/AuditLogClient.java b/src/main/java/org/papertrail/sdk/client/AuditLogClient.java
index 6ad91257..1b168ce1 100644
--- a/src/main/java/org/papertrail/sdk/client/AuditLogClient.java
+++ b/src/main/java/org/papertrail/sdk/client/AuditLogClient.java
@@ -1,67 +1,72 @@
package org.papertrail.sdk.client;
-import kong.unirest.core.HttpMethod;
+import io.vavr.control.Either;
+import org.jetbrains.annotations.NotNull;
import org.papertrail.sdk.http.HttpServiceEngine;
-import org.papertrail.sdk.http.HttpServiceResponse;
-import org.papertrail.sdk.model.ErrorResponse;
-import org.papertrail.sdk.model.AuditLogResponse;
+import org.papertrail.sdk.model.AuditLogObject;
+import org.papertrail.sdk.model.ErrorObject;
import org.papertrail.utilities.EnvConfig;
-import java.util.Map;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.HttpMethod;
+
+import java.util.List;
public class AuditLogClient {
- private AuditLogClient(){
- throw new IllegalStateException("Utility Class");
+ 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 static final String BASE_URL = EnvConfig.get("API_URL");
- private static final Map CONTENT_HEADER = Map.of("Content-Type", "application/json");
+ private AuditLogClient() {
+ throw new IllegalStateException("Client class");
+ }
- public static HttpServiceResponse registerGuild(String guildId, String channelId){
+ @NotNull
+ public static Either registerGuild(String guildId, String channelId){
- return HttpServiceEngine.makeRequest(
+ return engine.makeRequestWithBody(
HttpMethod.POST,
BASE_URL +"api/v1/log/audit",
- CONTENT_HEADER,
- new AuditLogResponse(guildId, channelId),
- AuditLogResponse.class,
- ErrorResponse.class
+ httpHeaders,
+ new AuditLogObject(guildId, channelId),
+ AuditLogObject.class
);
}
- public static HttpServiceResponse getRegisteredGuild(String guildId){
+ @NotNull
+ public static Either getRegisteredGuild(String guildId){
- return HttpServiceEngine.makeRequest(
+ return engine.makeRequest(
HttpMethod.GET,
BASE_URL +"api/v1/log/audit/"+guildId,
- CONTENT_HEADER,
- null,
- AuditLogResponse.class,
- ErrorResponse.class
+ httpHeaders,
+ AuditLogObject.class
);
}
- public static HttpServiceResponse updateRegisteredGuild(String guildId, String channelId){
+ @NotNull
+ public static Either updateRegisteredGuild(String guildId, String channelId){
- return HttpServiceEngine.makeRequest(
+ return engine.makeRequestWithBody(
HttpMethod.PUT,
BASE_URL +"api/v1/log/audit",
- CONTENT_HEADER,
- new AuditLogResponse(guildId, channelId),
- AuditLogResponse.class,
- ErrorResponse.class
+ httpHeaders,
+ new AuditLogObject(guildId, channelId),
+ AuditLogObject.class
);
}
- public static HttpServiceResponse deleteRegisteredGuild(String guildId){
+ public static Either deleteRegisteredGuild(String guildId){
- return HttpServiceEngine.makeRequest(
+ return engine.makeRequest(
HttpMethod.DELETE,
BASE_URL +"api/v1/log/audit/"+guildId,
- CONTENT_HEADER,
- null,
- Void.class,
- ErrorResponse.class
+ httpHeaders,
+ Void.class
);
}
}
diff --git a/src/main/java/org/papertrail/sdk/client/MessageContentLogClient.java b/src/main/java/org/papertrail/sdk/client/MessageContentLogClient.java
index d8ac1aa4..4f609f15 100644
--- a/src/main/java/org/papertrail/sdk/client/MessageContentLogClient.java
+++ b/src/main/java/org/papertrail/sdk/client/MessageContentLogClient.java
@@ -1,69 +1,74 @@
package org.papertrail.sdk.client;
-import kong.unirest.core.HttpMethod;
+import io.vavr.control.Either;
+import org.jetbrains.annotations.NotNull;
import org.papertrail.sdk.http.HttpServiceEngine;
-import org.papertrail.sdk.http.HttpServiceResponse;
-import org.papertrail.sdk.model.ErrorResponse;
-import org.papertrail.sdk.model.MessageContentResponse;
+import org.papertrail.sdk.model.ErrorObject;
+import org.papertrail.sdk.model.MessageContentObject;
import org.papertrail.utilities.EnvConfig;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.HttpMethod;
-import java.util.Map;
+import java.util.List;
public class MessageContentLogClient {
- private MessageContentLogClient(){
- throw new IllegalStateException("Utility Class");
+ 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 static final String BASE_URL = EnvConfig.get("API_URL")+"api/v1/content/message";
- private static final Map CONTENT_HEADER = Map.of("Content-Type", "application/json");
+ private MessageContentLogClient() {
+ throw new IllegalStateException("Client class");
+ }
- public static HttpServiceResponse logMessage(String messageId, String messageContent, String authorId){
+ @NotNull
+ public static Either logMessage(String messageId, String messageContent, String authorId){
- return HttpServiceEngine.makeRequest(
+ return engine.makeRequestWithBody(
HttpMethod.POST,
BASE_URL,
- CONTENT_HEADER,
- new MessageContentResponse(messageId, messageContent, authorId),
- MessageContentResponse.class,
- ErrorResponse.class
+ httpHeaders,
+ new MessageContentObject(messageId, messageContent, authorId),
+ MessageContentObject.class
);
}
- public static HttpServiceResponse retrieveMessage(String messageId){
+ @NotNull
+ public static Either retrieveMessage(String messageId){
- return HttpServiceEngine.makeRequest(
+ return engine.makeRequest(
HttpMethod.GET,
BASE_URL+"/"+messageId,
- CONTENT_HEADER,
- null,
- MessageContentResponse.class,
- ErrorResponse.class
+ httpHeaders,
+ MessageContentObject.class
);
}
- public static HttpServiceResponse updateMessage(String messageId, String messageContent, String authorId){
+ @NotNull
+ public static Either updateMessage(String messageId, String messageContent, String authorId){
- return HttpServiceEngine.makeRequest(
+ return engine.makeRequestWithBody(
HttpMethod.PUT,
BASE_URL,
- CONTENT_HEADER,
- new MessageContentResponse(messageId, messageContent, authorId),
- MessageContentResponse.class,
- ErrorResponse.class
+ httpHeaders,
+ new MessageContentObject(messageId, messageContent, authorId),
+ MessageContentObject.class
);
}
- public static HttpServiceResponse deleteMessage(String messageId) {
+ @NotNull
+ public static Either deleteMessage(String messageId) {
- return HttpServiceEngine.makeRequest(
+ return engine.makeRequest(
HttpMethod.DELETE,
BASE_URL+"/"+messageId,
- CONTENT_HEADER,
- null,
- Void.class,
- ErrorResponse.class
+ httpHeaders,
+ Void.class
);
}
diff --git a/src/main/java/org/papertrail/sdk/client/MessageLogClient.java b/src/main/java/org/papertrail/sdk/client/MessageLogClient.java
index 5ec4750b..0e95224b 100644
--- a/src/main/java/org/papertrail/sdk/client/MessageLogClient.java
+++ b/src/main/java/org/papertrail/sdk/client/MessageLogClient.java
@@ -1,69 +1,72 @@
package org.papertrail.sdk.client;
-import kong.unirest.core.HttpMethod;
+import io.vavr.control.Either;
+import org.jetbrains.annotations.NotNull;
import org.papertrail.sdk.http.HttpServiceEngine;
-import org.papertrail.sdk.http.HttpServiceResponse;
-import org.papertrail.sdk.model.ErrorResponse;
-import org.papertrail.sdk.model.MessageLogResponse;
+import org.papertrail.sdk.model.ErrorObject;
+import org.papertrail.sdk.model.MessageLogObject;
import org.papertrail.utilities.EnvConfig;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.HttpMethod;
+
+import java.util.List;
-import java.util.Map;
public class MessageLogClient {
- private MessageLogClient(){
- throw new IllegalStateException("Utility Class");
+ 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 static final String BASE_URL = EnvConfig.get("API_URL");
- private static final Map CONTENT_HEADER = Map.of("Content-Type", "application/json");
+ private MessageLogClient(){
+ throw new IllegalStateException("Client class");
+ }
- public static HttpServiceResponse registerGuild(String guildId, String channelId){
+ @NotNull
+ public static Either registerGuild(String guildId, String channelId){
- return HttpServiceEngine.makeRequest(
+ return engine.makeRequestWithBody(
HttpMethod.POST,
BASE_URL +"api/v1/log/message",
- CONTENT_HEADER,
- new MessageLogResponse(guildId, channelId),
- MessageLogResponse.class,
- ErrorResponse.class
+ httpHeaders,
+ new MessageLogObject(guildId, channelId),
+ MessageLogObject.class
);
}
- public static HttpServiceResponse getRegisteredGuild(String guildId){
+ public static Either getRegisteredGuild(String guildId){
- return HttpServiceEngine.makeRequest(
+ return engine.makeRequest(
HttpMethod.GET,
BASE_URL +"api/v1/log/message/"+guildId,
- CONTENT_HEADER,
- null,
- MessageLogResponse.class,
- ErrorResponse.class
+ httpHeaders,
+ MessageLogObject.class
);
}
- public static HttpServiceResponse updateRegisteredGuild(String guildId, String channelId){
+ public static Either updateRegisteredGuild(String guildId, String channelId){
- return HttpServiceEngine.makeRequest(
+ return HttpServiceEngine.getInstance().makeRequestWithBody(
HttpMethod.PUT,
- BASE_URL +"api/v1/log/message",
- CONTENT_HEADER,
- new MessageLogResponse(guildId, channelId),
- MessageLogResponse.class,
- ErrorResponse.class
+ BASE_URL + "api/v1/log/message",
+ httpHeaders,
+ new MessageLogObject(guildId, channelId),
+ MessageLogObject.class
);
}
- public static HttpServiceResponse deleteRegisteredGuild(String guildId){
+ public static Either deleteRegisteredGuild(String guildId){
- return HttpServiceEngine.makeRequest(
+ return engine.makeRequest(
HttpMethod.DELETE,
BASE_URL +"api/v1/log/message/"+guildId,
- CONTENT_HEADER,
- null,
- Void.class,
- ErrorResponse.class
+ httpHeaders,
+ Void.class
);
}
}
diff --git a/src/main/java/org/papertrail/sdk/http/HttpServiceEngine.java b/src/main/java/org/papertrail/sdk/http/HttpServiceEngine.java
index 110efa94..69dcdfb8 100644
--- a/src/main/java/org/papertrail/sdk/http/HttpServiceEngine.java
+++ b/src/main/java/org/papertrail/sdk/http/HttpServiceEngine.java
@@ -1,47 +1,92 @@
package org.papertrail.sdk.http;
-import com.google.gson.Gson;
-import kong.unirest.core.HttpMethod;
-import kong.unirest.core.HttpRequestWithBody;
-import kong.unirest.core.HttpResponse;
-import kong.unirest.core.Unirest;
+import io.vavr.control.Either;
import org.jetbrains.annotations.NotNull;
+import org.papertrail.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 org.tinylog.Logger;
-import java.util.Map;
+import java.net.URI;
+import java.time.Instant;
public class HttpServiceEngine {
+ private final RestClient client;
+ private static final HttpServiceEngine INSTANCE = new HttpServiceEngine();
+
private HttpServiceEngine() {
- throw new IllegalStateException("Utility Class");
+ client = RestClient.builder().build();
+ }
+
+ public static HttpServiceEngine getInstance() {
+ return INSTANCE;
}
- public static HttpServiceResponse makeRequest (
+ public Either makeRequest (
@NotNull HttpMethod httpMethod,
- @NotNull String url, Map headerMap,
- Object requestBody,
- @NotNull Class successResponseClass,
- @NotNull Class errorResponseClass) {
-
- HttpRequestWithBody request = Unirest
- .request(httpMethod.toString(), url)
- .headers(headerMap);
-
- Gson gson = new Gson();
- HttpResponse response;
- if (requestBody != null) {
- String jsonBody = gson.toJson(requestBody);
- response = request.body(jsonBody).asString();
- } else {
- response = request.asString();
+ @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) {
+ Logger.trace("Client error when calling {} {}: {}", httpMethod, url, e.getMessage(), e);
+ ErrorObject error = e.getResponseBodyAs(ErrorObject.class);
+ return Either.left(error);
+ } catch (HttpServerErrorException e) {
+ Logger.error("Server error when calling {} {}: {}", httpMethod, url, e.getMessage(), e);
+ ErrorObject error = e.getResponseBodyAs(ErrorObject.class);
+ return Either.left(error);
+ } catch (ResourceAccessException e) {
+ Logger.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();
- if(response.isSuccess()) {
- S success = gson.fromJson(response.getBody(), successResponseClass);
- return new HttpServiceResponse<>(success, null, true);
+ return Either.right(body);
- } else {
- E error = gson.fromJson(response.getBody(), errorResponseClass);
- return new HttpServiceResponse<>(null, error, false);
+ } catch (HttpClientErrorException e) {
+ Logger.trace("Client error when calling {} {}: {}", httpMethod, url, e.getMessage(), e);
+ ErrorObject error = e.getResponseBodyAs(ErrorObject.class);
+ return Either.left(error);
+ } catch (HttpServerErrorException e) {
+ Logger.error("Server error when calling {} {}: {}", httpMethod, url, e.getMessage(), e);
+ ErrorObject error = e.getResponseBodyAs(ErrorObject.class);
+ return Either.left(error);
+ } catch (ResourceAccessException e) {
+ Logger.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/sdk/http/HttpServiceResponse.java b/src/main/java/org/papertrail/sdk/http/HttpServiceResponse.java
deleted file mode 100644
index af5ef724..00000000
--- a/src/main/java/org/papertrail/sdk/http/HttpServiceResponse.java
+++ /dev/null
@@ -1,7 +0,0 @@
-package org.papertrail.sdk.http;
-
-import org.jspecify.annotations.Nullable;
-
-public record HttpServiceResponse(@Nullable S success, @Nullable E error, boolean requestSuccess) {
-
-}
diff --git a/src/main/java/org/papertrail/sdk/model/AuditLogObject.java b/src/main/java/org/papertrail/sdk/model/AuditLogObject.java
new file mode 100644
index 00000000..8c4df960
--- /dev/null
+++ b/src/main/java/org/papertrail/sdk/model/AuditLogObject.java
@@ -0,0 +1,5 @@
+package org.papertrail.sdk.model;
+
+public record AuditLogObject(String guildId, String channelId) {
+
+}
diff --git a/src/main/java/org/papertrail/sdk/model/AuditLogResponse.java b/src/main/java/org/papertrail/sdk/model/AuditLogResponse.java
deleted file mode 100644
index 1e421975..00000000
--- a/src/main/java/org/papertrail/sdk/model/AuditLogResponse.java
+++ /dev/null
@@ -1,5 +0,0 @@
-package org.papertrail.sdk.model;
-
-public record AuditLogResponse(String guildId, String channelId) {
-
-}
diff --git a/src/main/java/org/papertrail/sdk/model/ErrorResponse.java b/src/main/java/org/papertrail/sdk/model/ErrorObject.java
similarity index 83%
rename from src/main/java/org/papertrail/sdk/model/ErrorResponse.java
rename to src/main/java/org/papertrail/sdk/model/ErrorObject.java
index 41ce3abe..a0ca5257 100644
--- a/src/main/java/org/papertrail/sdk/model/ErrorResponse.java
+++ b/src/main/java/org/papertrail/sdk/model/ErrorObject.java
@@ -1,6 +1,6 @@
package org.papertrail.sdk.model;
-public record ErrorResponse(
+public record ErrorObject(
int status,
String error,
String message,
diff --git a/src/main/java/org/papertrail/sdk/model/MessageContentObject.java b/src/main/java/org/papertrail/sdk/model/MessageContentObject.java
new file mode 100644
index 00000000..2d1cc70b
--- /dev/null
+++ b/src/main/java/org/papertrail/sdk/model/MessageContentObject.java
@@ -0,0 +1,4 @@
+package org.papertrail.sdk.model;
+
+public record MessageContentObject(String messageId, String messageContent, String authorId) {
+}
diff --git a/src/main/java/org/papertrail/sdk/model/MessageContentResponse.java b/src/main/java/org/papertrail/sdk/model/MessageContentResponse.java
deleted file mode 100644
index 478f1161..00000000
--- a/src/main/java/org/papertrail/sdk/model/MessageContentResponse.java
+++ /dev/null
@@ -1,4 +0,0 @@
-package org.papertrail.sdk.model;
-
-public record MessageContentResponse(String messageId, String messageContent, String authorId) {
-}
diff --git a/src/main/java/org/papertrail/sdk/model/MessageLogObject.java b/src/main/java/org/papertrail/sdk/model/MessageLogObject.java
new file mode 100644
index 00000000..f07c8a11
--- /dev/null
+++ b/src/main/java/org/papertrail/sdk/model/MessageLogObject.java
@@ -0,0 +1,5 @@
+package org.papertrail.sdk.model;
+
+public record MessageLogObject(String guildId, String channelId) {
+
+}
diff --git a/src/main/java/org/papertrail/sdk/model/MessageLogResponse.java b/src/main/java/org/papertrail/sdk/model/MessageLogResponse.java
deleted file mode 100644
index 2d1b9b53..00000000
--- a/src/main/java/org/papertrail/sdk/model/MessageLogResponse.java
+++ /dev/null
@@ -1,5 +0,0 @@
-package org.papertrail.sdk.model;
-
-public record MessageLogResponse(String guildId, String channelId) {
-
-}
diff --git a/src/main/java/org/papertrail/version/ProjectInfo.java b/src/main/java/org/papertrail/version/ProjectInfo.java
index 36076784..b5bc3e21 100644
--- a/src/main/java/org/papertrail/version/ProjectInfo.java
+++ b/src/main/java/org/papertrail/version/ProjectInfo.java
@@ -7,7 +7,7 @@ private ProjectInfo() {
}
public static final String APPNAME = "PaperTrail";
- public static final String VERSION = "v2.0.0-beta";
+ public static final String VERSION = "v2.0.0";
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";