Skip to content

Commit

Permalink
Merge pull request #96 from Softawii/feature/listener-exception-handler
Browse files Browse the repository at this point in the history
feat: handle discord listener exceptions
  • Loading branch information
yaansz authored Dec 18, 2023
2 parents f02af55 + a54c2c9 commit d31873d
Show file tree
Hide file tree
Showing 3 changed files with 94 additions and 17 deletions.
27 changes: 16 additions & 11 deletions src/main/java/com/softawii/capivara/config/SpringConfig.java
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import net.dv8tion.jda.api.utils.cache.CacheFlag;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
Expand Down Expand Up @@ -77,23 +78,27 @@ public JDA jda() {
}

@Bean
public Curupira curupira(JDA jda) {
String pkg = "com.softawii.capivara.listeners";
String resetEnv = env.getProperty("curupira.reset", "false");
boolean reset = Boolean.parseBoolean(resetEnv);
LOGGER.info("curupira.reset: " + reset);


CapivaraExceptionHandler exceptionHandler = null;
String logChannelId = env.getProperty("log.channel.id");
String logDirectory = env.getProperty("log_directory");
public CapivaraExceptionHandler capivaraExceptionHandler() {
String logChannelId = env.getProperty("log.channel.id");
String logDirectory = env.getProperty("log_directory");
if (logChannelId != null) {
Path logPath = null;
if (logDirectory != null) {
logPath = Path.of(logDirectory);
}
exceptionHandler = new CapivaraExceptionHandler(logChannelId, logPath);
return new CapivaraExceptionHandler(logChannelId, logPath);
}

return null;
}

@Bean
public Curupira curupira(JDA jda, @Autowired(required = false) CapivaraExceptionHandler exceptionHandler) {
String pkg = "com.softawii.capivara.listeners";
String resetEnv = env.getProperty("curupira.reset", "false");
boolean reset = Boolean.parseBoolean(resetEnv);
LOGGER.info("curupira.reset: " + reset);

return new Curupira(jda, reset, exceptionHandler, pkg);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,14 @@
import com.softawii.capivara.core.VoiceManager;
import com.softawii.capivara.entity.VoiceHive;
import com.softawii.capivara.exceptions.KeyNotFoundException;
import com.softawii.capivara.utils.CapivaraExceptionHandler;
import net.dv8tion.jda.api.JDA;
import net.dv8tion.jda.api.entities.Member;
import net.dv8tion.jda.api.entities.channel.ChannelType;
import net.dv8tion.jda.api.entities.channel.concrete.Category;
import net.dv8tion.jda.api.entities.channel.concrete.VoiceChannel;
import net.dv8tion.jda.api.entities.channel.middleman.GuildMessageChannel;
import net.dv8tion.jda.api.events.Event;
import net.dv8tion.jda.api.events.channel.ChannelDeleteEvent;
import net.dv8tion.jda.api.events.channel.update.ChannelUpdateParentEvent;
import net.dv8tion.jda.api.events.channel.update.GenericChannelUpdateEvent;
Expand All @@ -28,15 +30,15 @@ public class VoiceEvents extends ListenerAdapter {
private final DroneManager droneManager;

private final Logger LOGGER = LogManager.getLogger(VoiceEvents.class);
private final JDA jda;
private final CapivaraExceptionHandler exceptionHandler;

public VoiceEvents(JDA jda, VoiceManager voiceManager, DroneManager droneManager) {
public VoiceEvents(JDA jda, VoiceManager voiceManager, DroneManager droneManager, CapivaraExceptionHandler exceptionHandler) {
this.voiceManager = voiceManager;
this.droneManager = droneManager;
this.jda = jda;
this.exceptionHandler = exceptionHandler;
this.droneManager.checkEmptyDrones();
this.voiceManager.checkRemovedHives();
this.jda.addEventListener(this);
jda.addEventListener(this);
}

//region Voice Events
Expand Down Expand Up @@ -69,6 +71,7 @@ public void onGuildVoiceUpdate(@NotNull GuildVoiceUpdateEvent event) {
}
} catch (Exception e) {
LOGGER.error("Error on onGuildVoiceUpdate", e);
handleException(e, event);
}
}

Expand Down Expand Up @@ -114,6 +117,7 @@ public void onChannelDelete(@NotNull ChannelDeleteEvent event) {
}
} catch (Exception e) {
LOGGER.error("Error on ChannelDeleteEvent", e);
handleException(e, event);
}
}

Expand Down Expand Up @@ -141,6 +145,7 @@ public void onChannelUpdateParent(@NotNull ChannelUpdateParentEvent event) {
}
} catch (Exception e) {
LOGGER.error("Error on ChannelUpdateParentEvent", e);
handleException(e, event);
}
}

Expand All @@ -157,10 +162,12 @@ public void onGenericPermissionOverride(@NotNull GenericPermissionOverrideEvent
} catch (KeyNotFoundException e) {
// Not Found...
LOGGER.debug(method + " : error : " + e.getMessage());
handleException(e, event);
}
}
} catch (Exception e) {
LOGGER.error("Error on " + method, e);
handleException(e, event);
}
}

Expand All @@ -175,14 +182,20 @@ public void onGenericChannelUpdate(@NotNull GenericChannelUpdateEvent<?> event)
} catch (KeyNotFoundException e) {
// Not Found...
LOGGER.debug("onGenericChannelUpdate : error : " + e.getMessage());
handleException(e, event);
}
}
} catch (Exception e) {
LOGGER.error("Error on GenericChannelUpdateEvent", e);
handleException(e, event);
}
}


//endregion

private void handleException(Exception exception, Event event) {
if (exceptionHandler != null) {
exceptionHandler.handle(exception, event);
}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@
import net.dv8tion.jda.api.JDA;
import net.dv8tion.jda.api.entities.MessageEmbed;
import net.dv8tion.jda.api.entities.channel.concrete.TextChannel;
import net.dv8tion.jda.api.events.Event;
import net.dv8tion.jda.api.events.channel.GenericChannelEvent;
import net.dv8tion.jda.api.events.guild.GenericGuildEvent;
import net.dv8tion.jda.api.interactions.Interaction;
import net.dv8tion.jda.api.requests.restaction.MessageCreateAction;
import net.dv8tion.jda.api.utils.FileUpload;
Expand Down Expand Up @@ -68,6 +71,62 @@ public void handle(Throwable throwable, Interaction interaction) {
}
}

public void handle(Throwable throwable, Event event) {
InputStream logFileBytes = null;
if (logDirectory != null) {
Path logFile = logDirectory.resolve("capivara.log");
if (Files.isDirectory(logDirectory) && Files.exists(logFile) && Files.isRegularFile(logFile)) {
try {
logFileBytes = Files.newInputStream(logFile);
} catch (IOException e) {
LOGGER.warn(e.getMessage(), e);
}
}
}
JDA jda = event.getJDA();
TextChannel channel = jda.getTextChannelById(channelId);
if (channel != null) {
String stackTrace = getStackTrace(throwable);
String now = OffsetDateTime.now(ZoneId.of("America/Sao_Paulo")).format(DateTimeFormatter.ISO_OFFSET_DATE_TIME);
String stackTraceFileName = String.format("capivara-stacktrace-%s.log", now);
String logFileName = String.format("capivara-log-%s.log", now);
MessageEmbed interactionContext = getContext(event);
try {
MessageCreateAction messageAction = channel.sendFiles(FileUpload.fromData(stackTrace.getBytes(StandardCharsets.UTF_8), stackTraceFileName)).setEmbeds(interactionContext);
if (logFileBytes != null) {
messageAction = messageAction.addFiles(FileUpload.fromData(logFileBytes, logFileName));
}
messageAction.submit();
} catch (IllegalArgumentException e) {
LOGGER.warn(e.getMessage(), e);
channel.sendMessage(getStackTrace(e)).submit();
}
}
}

private MessageEmbed getContext(Event event) {
EmbedBuilder builder = new EmbedBuilder();
builder.setColor(Color.RED)
.setTitle("Unhandled Exception");

if (event instanceof GenericChannelEvent channelEvent) {
if (channelEvent.isFromGuild()) {
builder.addField("Guild ID", channelEvent.getGuild().getId(), true)
.addField("Guild Name", channelEvent.getGuild().getName(), true)
.addField("Guild Members", String.valueOf(channelEvent.getGuild().getMembers().size()), true);
}
builder.addField("Channel Type", channelEvent.getChannelType().toString(), true)
.addField("Channel ID", channelEvent.getChannel().getId(), true)
.addField("Channel Name", channelEvent.getChannel().getName(), true);
} else if (event instanceof GenericGuildEvent guildEvent) {
builder.addField("Guild ID", guildEvent.getGuild().getId(), true)
.addField("Guild Name", guildEvent.getGuild().getName(), true)
.addField("Guild Members", String.valueOf(guildEvent.getGuild().getMembers().size()), true);
}

return builder.build();
}

private String getStackTrace(Throwable throwable) {
StringWriter stringWriter = new StringWriter();
PrintWriter printWriter = new PrintWriter(stringWriter);
Expand Down

0 comments on commit d31873d

Please sign in to comment.