From ab66cf37ad4972d48942b7310b6ae65d0e819693 Mon Sep 17 00:00:00 2001 From: Jeff Date: Mon, 30 Oct 2023 20:45:06 -0400 Subject: [PATCH] Fix error handling for subscribed events so they do not stop processing if an error condition is encountered Instead they will gracefully log the error condition and continue to process events. Added better error handling to the Clan compare interaction --- .../discordbot/v3/bot/GuildCreateHandler.java | 9 +-- .../discordbot/v3/bot/MemberJoinHandler.java | 6 +- .../discordbot/v3/bot/MemberLeftHandler.java | 15 +++-- .../v3/bot/MemberUpdateHandler.java | 5 +- .../rs/discordbot/v3/bot/SoaDiscordBot.java | 63 +++++++++++-------- .../v3/commands/ClanCompareInteraction.java | 20 +++--- .../v3/usertrack/UserTrackGuildCreate.java | 6 +- 7 files changed, 74 insertions(+), 50 deletions(-) diff --git a/soa-discord/src/main/java/com/soa/rs/discordbot/v3/bot/GuildCreateHandler.java b/soa-discord/src/main/java/com/soa/rs/discordbot/v3/bot/GuildCreateHandler.java index 1301ee77..7924c10e 100644 --- a/soa-discord/src/main/java/com/soa/rs/discordbot/v3/bot/GuildCreateHandler.java +++ b/soa-discord/src/main/java/com/soa/rs/discordbot/v3/bot/GuildCreateHandler.java @@ -9,6 +9,7 @@ import com.soa.rs.discordbot.v3.usertrack.UserTrackGuildCreate; import discord4j.core.event.domain.guild.GuildCreateEvent; +import reactor.core.publisher.Mono; public class GuildCreateHandler { @@ -22,19 +23,19 @@ public GuildCreateHandler() { this.guildCreate.setRecentActionUtility(new RecentActionUtility()); } - public void handleGuildCreate(GuildCreateEvent event) { + public Mono handleGuildCreate(GuildCreateEvent event) { if (DiscordCfgFactory.getConfig().getUserTrackingEvent() != null && DiscordCfgFactory.getConfig() .getUserTrackingEvent().isEnabled()) { - guildCreate.handleJoinedGuild(event); + return Mono.fromRunnable(()->guildCreate.handleJoinedGuild(event)).then(); } + return Mono.empty(); } public void setLastSeenCache(RecentCache cache) { this.guildCreate.setLastSeenCache(cache); } - public void setLastActiveCache(RecentCache cache) - { + public void setLastActiveCache(RecentCache cache) { this.guildCreate.setLastActiveCache(cache); } } diff --git a/soa-discord/src/main/java/com/soa/rs/discordbot/v3/bot/MemberJoinHandler.java b/soa-discord/src/main/java/com/soa/rs/discordbot/v3/bot/MemberJoinHandler.java index e6640b83..98096bd8 100644 --- a/soa-discord/src/main/java/com/soa/rs/discordbot/v3/bot/MemberJoinHandler.java +++ b/soa-discord/src/main/java/com/soa/rs/discordbot/v3/bot/MemberJoinHandler.java @@ -7,6 +7,7 @@ import com.soa.rs.discordbot.v3.usertrack.UserTrackMemberJoin; import discord4j.core.event.domain.guild.MemberJoinEvent; +import reactor.core.publisher.Mono; public class MemberJoinHandler { @@ -19,9 +20,10 @@ public MemberJoinHandler() { this.userTrackMemberJoin.setRecentActionUtility(new RecentActionUtility()); } - public void handle(MemberJoinEvent event) { + public Mono handle(MemberJoinEvent event) { if (DiscordCfgFactory.getInstance().isUserTrackingEnabled() && !event.getMember().isBot()) { - userTrackMemberJoin.handleAddUser(event.getMember()); + return Mono.fromRunnable(()->userTrackMemberJoin.handleAddUser(event.getMember())); } + return Mono.empty(); } } diff --git a/soa-discord/src/main/java/com/soa/rs/discordbot/v3/bot/MemberLeftHandler.java b/soa-discord/src/main/java/com/soa/rs/discordbot/v3/bot/MemberLeftHandler.java index 00134207..083e3620 100644 --- a/soa-discord/src/main/java/com/soa/rs/discordbot/v3/bot/MemberLeftHandler.java +++ b/soa-discord/src/main/java/com/soa/rs/discordbot/v3/bot/MemberLeftHandler.java @@ -10,6 +10,7 @@ import discord4j.core.event.domain.guild.BanEvent; import discord4j.core.event.domain.guild.MemberLeaveEvent; import discord4j.core.object.entity.channel.MessageChannel; +import reactor.core.publisher.Mono; public class MemberLeftHandler { @@ -21,7 +22,7 @@ public MemberLeftHandler() { this.memberLeft.setRecentActionUtility(new RecentActionUtility()); } - public void handle(MemberLeaveEvent memberLeaveEvent) { + public Mono handle(MemberLeaveEvent memberLeaveEvent) { if (DiscordCfgFactory.getInstance().isUserTrackingEnabled() && memberLeaveEvent.getMember().isPresent()) { if (!memberLeaveEvent.getMember().get().isBot()) { this.memberLeft.handleMemberLeft(memberLeaveEvent.getMember().get()); @@ -29,14 +30,15 @@ public void handle(MemberLeaveEvent memberLeaveEvent) { } if(memberLeaveEvent.getGuildId().asLong() == 133922153010692096L) { - memberLeaveEvent.getGuild().flatMap(guild -> guild.getChannelById(Snowflake.of(974413726063132793L))) + return memberLeaveEvent.getGuild().flatMap(guild -> guild.getChannelById(Snowflake.of(974413726063132793L))) .flatMap(guildChannel -> ((MessageChannel) guildChannel).createMessage( memberLeaveEvent.getUser().getUsername() + "#" + memberLeaveEvent.getUser() - .getDiscriminator() + " has left the server.")).subscribe(); + .getDiscriminator() + " has left the server.")).then(); } + return Mono.empty(); } - public void handle(BanEvent banEvent) { + public Mono handle(BanEvent banEvent) { if (DiscordCfgFactory.getInstance().isUserTrackingEnabled()) { SoaLogging.getLogger(this) .debug("Member [@" + banEvent.getUser().getUsername() + "#" + banEvent.getUser().getDiscriminator() @@ -44,11 +46,12 @@ public void handle(BanEvent banEvent) { + "] was banned, marking as left server"); this.memberLeft.handleUserBanned(banEvent.getUser().getId().asLong(), banEvent.getGuildId().asLong()); if (banEvent.getGuildId().asLong() == 133922153010692096L) { - banEvent.getGuild().flatMap(guild -> guild.getChannelById(Snowflake.of(974413726063132793L))).flatMap( + return banEvent.getGuild().flatMap(guild -> guild.getChannelById(Snowflake.of(974413726063132793L))).flatMap( guildChannel -> ((MessageChannel) guildChannel).createMessage( banEvent.getUser().getUsername() + "#" + banEvent.getUser().getDiscriminator() - + " was banned from the server.")).subscribe(); + + " was banned from the server.")).then(); } } + return Mono.empty(); } } diff --git a/soa-discord/src/main/java/com/soa/rs/discordbot/v3/bot/MemberUpdateHandler.java b/soa-discord/src/main/java/com/soa/rs/discordbot/v3/bot/MemberUpdateHandler.java index 22023370..229ac891 100644 --- a/soa-discord/src/main/java/com/soa/rs/discordbot/v3/bot/MemberUpdateHandler.java +++ b/soa-discord/src/main/java/com/soa/rs/discordbot/v3/bot/MemberUpdateHandler.java @@ -32,10 +32,11 @@ public Mono handle(MemberUpdateEvent event) { .flatMap(member -> Mono.fromRunnable(() -> userTrackMemberUpdated.handleMemberUpdate(member))).then(); } - public void handle(UserUpdateEvent event) { + public Mono handle(UserUpdateEvent event) { if (DiscordCfgFactory.getInstance().isUserTrackingEnabled() && !event.getCurrent().isBot()) { - userTrackMemberUpdated.handleUserUpdate(event.getCurrent()); + return Mono.fromRunnable(()->userTrackMemberUpdated.handleUserUpdate(event.getCurrent())).then(); } + return Mono.empty(); } public Mono handle(PresenceUpdateEvent event) { diff --git a/soa-discord/src/main/java/com/soa/rs/discordbot/v3/bot/SoaDiscordBot.java b/soa-discord/src/main/java/com/soa/rs/discordbot/v3/bot/SoaDiscordBot.java index 623d9db3..e5e5b6e8 100644 --- a/soa-discord/src/main/java/com/soa/rs/discordbot/v3/bot/SoaDiscordBot.java +++ b/soa-discord/src/main/java/com/soa/rs/discordbot/v3/bot/SoaDiscordBot.java @@ -144,47 +144,56 @@ private void registerEvents(GatewayDiscordClient gatewayDiscordClient) { gatewayDiscordClient.on(MessageCreateEvent.class).flatMap(event -> messageCreateHandler.handle(event) .onErrorResume(err -> Mono.fromRunnable(() -> SoaLogging.getLogger(this) - .error("Unexpected error occurred during message create event.", err) - ))).subscribe(); + .error("Unexpected error occurred during message create event.", err)))).subscribe(); - gatewayDiscordClient.on(ChatInputInteractionEvent.class).flatMap(interactionProcessor::processInteraction).subscribe(null, - err -> SoaLogging.getLogger(this) - .error("Unexpected error occurred while processing interaction.", err)); + gatewayDiscordClient.on(ChatInputInteractionEvent.class).flatMap(interactionProcessor::processInteraction) + .onErrorResume(err -> Mono.fromRunnable(() -> SoaLogging.getLogger(this) + .error("Unexpected error occurred while processing interaction.", err))).subscribe(); - gatewayDiscordClient.on(ModalSubmitInteractionEvent.class).flatMap(interactionProcessor::processModal).subscribe(null, - err -> SoaLogging.getLogger(this) - .error("Unexpected error occurred while processing interaction.", err)); + gatewayDiscordClient.on(ModalSubmitInteractionEvent.class).flatMap(interactionProcessor::processModal) + .onErrorResume(err -> Mono.fromRunnable(() -> SoaLogging.getLogger(this) + .error("Unexpected error occurred while processing interaction.", err))).subscribe(); - gatewayDiscordClient.on(GuildCreateEvent.class).subscribe(guildCreateHandler::handleGuildCreate, - err -> SoaLogging.getLogger(this).error("Unexpected error occurred during guild create event.", err)); + gatewayDiscordClient.on(GuildCreateEvent.class).flatMap(guildCreateHandler::handleGuildCreate).onErrorResume( + err -> Mono.fromRunnable(() -> SoaLogging.getLogger(this) + .error("Unexpected error occurred during guild create event.", err))).subscribe(); - gatewayDiscordClient.on(MemberJoinEvent.class).subscribe(memberJoinHandler::handle, - err -> SoaLogging.getLogger(this).error("Unexpected error occurred during member join event.", err)); + gatewayDiscordClient.on(MemberJoinEvent.class).flatMap(memberJoinHandler::handle).onErrorResume( + err -> Mono.fromRunnable(() -> SoaLogging.getLogger(this) + .error("Unexpected error occurred during member join event.", err))).subscribe(); - gatewayDiscordClient.on(MemberLeaveEvent.class).subscribe(memberLeftHandler::handle, - err -> SoaLogging.getLogger(this).error("Unexpected error occurred during member leave event.", err)); + gatewayDiscordClient.on(MemberLeaveEvent.class).flatMap(memberLeftHandler::handle).onErrorResume( + err -> Mono.fromRunnable(() -> SoaLogging.getLogger(this) + .error("Unexpected error occurred during member leave event.", err))).subscribe(); - gatewayDiscordClient.on(BanEvent.class).subscribe(memberLeftHandler::handle, - err -> SoaLogging.getLogger(this).error("Unexpected error occurred during member leave event.", err)); + gatewayDiscordClient.on(BanEvent.class).flatMap(memberLeftHandler::handle).onErrorResume( + err -> Mono.fromRunnable(() -> SoaLogging.getLogger(this) + .error("Unexpected error occurred during member leave event.", err))).subscribe(); - gatewayDiscordClient.on(MemberUpdateEvent.class).flatMap(memberUpdateHandler::handle).subscribe(null, - err -> SoaLogging.getLogger(this).error("Unexpected error during member update event.", err)); + gatewayDiscordClient.on(MemberUpdateEvent.class).flatMap(memberUpdateHandler::handle).onErrorResume( + err -> Mono.fromRunnable(() -> SoaLogging.getLogger(this) + .error("Unexpected error occurred during member update event.", err))).subscribe(); - gatewayDiscordClient.on(UserUpdateEvent.class).subscribe(memberUpdateHandler::handle, - err -> SoaLogging.getLogger(this).error("Unexpected error during user update event.", err)); + gatewayDiscordClient.on(UserUpdateEvent.class).flatMap(memberUpdateHandler::handle).onErrorResume( + err -> Mono.fromRunnable(() -> SoaLogging.getLogger(this) + .error("Unexpected error occurred during user update event.", err))).subscribe(); - gatewayDiscordClient.on(PresenceUpdateEvent.class).flatMap(memberUpdateHandler::handle).subscribe(null, - err -> SoaLogging.getLogger(this).error("Unexpected error during presence update event.", err)); + gatewayDiscordClient.on(PresenceUpdateEvent.class).flatMap(memberUpdateHandler::handle).onErrorResume( + err -> Mono.fromRunnable(() -> SoaLogging.getLogger(this) + .error("Unexpected error occurred during presence update event.", err))).subscribe(); - gatewayDiscordClient.on(VoiceStateUpdateEvent.class).flatMap(voiceStateUpdateHandler::handle).subscribe(null, - err -> SoaLogging.getLogger(this).error("Unexpected error during voice state update event.", err)); + gatewayDiscordClient.on(VoiceStateUpdateEvent.class).flatMap(voiceStateUpdateHandler::handle).onErrorResume( + err -> Mono.fromRunnable(() -> SoaLogging.getLogger(this) + .error("Unexpected error occurred during voice state update event.", err))).subscribe(); - gatewayDiscordClient.on(ReactionAddEvent.class).flatMap(reactionAddEventHandler::handle).subscribe(null, - err -> SoaLogging.getLogger(this).error("Unexpected error during reaction add event.", err)); + gatewayDiscordClient.on(ReactionAddEvent.class).flatMap(reactionAddEventHandler::handle).onErrorResume( + err -> Mono.fromRunnable(() -> SoaLogging.getLogger(this) + .error("Unexpected error occurred during reaction add event.", err))).subscribe(); if (DiscordCfgFactory.getInstance().isUserTrackingEnabled()) { gatewayDiscordClient.on(TypingStartEvent.class).flatMap(typingStartHandler::handleTypingStart) - .subscribe(null, err -> SoaLogging.getLogger(this).error("Error processing typing event", err)); + .onErrorResume(err -> Mono.fromRunnable(() -> SoaLogging.getLogger(this) + .error("Unexpected error occurred during Typing Start event.", err))).subscribe(); } } diff --git a/soa-discord/src/main/java/com/soa/rs/discordbot/v3/commands/ClanCompareInteraction.java b/soa-discord/src/main/java/com/soa/rs/discordbot/v3/commands/ClanCompareInteraction.java index 07ed0b90..953c4107 100644 --- a/soa-discord/src/main/java/com/soa/rs/discordbot/v3/commands/ClanCompareInteraction.java +++ b/soa-discord/src/main/java/com/soa/rs/discordbot/v3/commands/ClanCompareInteraction.java @@ -8,6 +8,7 @@ import com.soa.rs.discordbot.v3.api.command.AbstractCommand; import com.soa.rs.discordbot.v3.cfg.DiscordCfgFactory; import com.soa.rs.discordbot.v3.jdbi.SettingsUtility; +import com.soa.rs.discordbot.v3.util.SoaLogging; import discord4j.core.event.domain.interaction.ChatInputInteractionEvent; import discord4j.core.event.domain.interaction.ModalSubmitInteractionEvent; @@ -45,12 +46,17 @@ public Mono execute(MessageCreateEvent event) { @Override public Mono execute(ChatInputInteractionEvent event) { - return event.deferReply().withEphemeral(true).then(Mono.fromCallable(() -> settingsUtility.getValueForKey("clancompare.altId")) - .map(Integer::parseInt) - .flatMap(i -> Mono.fromCallable(() -> processClanCompare(i))) - .flatMapMany(Flux::fromIterable) - .flatMapSequential(s -> event.createFollowup(s).withEphemeral(true)).then()) - .then(); + return event.deferReply().withEphemeral(true) + .then(Mono.fromCallable(() -> settingsUtility.getValueForKey("clancompare.altId")) + .map(Integer::parseInt).flatMap(i -> Mono.fromCallable(() -> processClanCompare(i))) + .onErrorResume(err -> { + String error = "Error encountered during clan compare operation."; + List e = new ArrayList<>(); + e.add(error); + SoaLogging.getLogger(this).error(error, err); + return Mono.just(e); + }).flatMapMany(Flux::fromIterable) + .flatMapSequential(s -> event.createFollowup(s).withEphemeral(true)).then()).then(); } @Override @@ -65,7 +71,7 @@ public List processClanCompare(int altId) List response = new ArrayList<>(); - if(processResult.size() == 0) + if(processResult.isEmpty()) { response.add("Clan Compare found no deltas between the forums and the in-game clan."); return response; diff --git a/soa-discord/src/main/java/com/soa/rs/discordbot/v3/usertrack/UserTrackGuildCreate.java b/soa-discord/src/main/java/com/soa/rs/discordbot/v3/usertrack/UserTrackGuildCreate.java index a3662aba..0b166aa5 100644 --- a/soa-discord/src/main/java/com/soa/rs/discordbot/v3/usertrack/UserTrackGuildCreate.java +++ b/soa-discord/src/main/java/com/soa/rs/discordbot/v3/usertrack/UserTrackGuildCreate.java @@ -13,6 +13,7 @@ import discord4j.core.event.domain.guild.GuildCreateEvent; import discord4j.core.object.entity.Guild; +import reactor.core.publisher.Mono; public class UserTrackGuildCreate { @@ -63,8 +64,9 @@ public void handleJoinedGuild(GuildCreateEvent event) { reviewer.setAllUsers(userUtility.getUsersCurrentlyInGuildForGuildId(guild.getId().asLong())); reviewer.setLeftUsers(userUtility.getLeftUsersInGuildForGuildId(guild.getId().asLong())); guild.getMembers().filter(member -> !member.isBot()).flatMap(reviewer::reviewMember) - .doOnComplete(reviewer::submitUsers).doOnComplete(reviewer::removeRemainingUsers).subscribe(null, - err -> SoaLogging.getLogger(this).error("Unexpected error occurred during guild create event.", err)); + .doOnComplete(reviewer::submitUsers).doOnComplete(reviewer::removeRemainingUsers).onErrorResume( + err -> Mono.fromRunnable(() -> SoaLogging.getLogger(this) + .error("Unexpected error occurred during guild create event.", err))).subscribe(); }