From 9fc38fec2a304db37ec5ca49d35161ba8a271b0c Mon Sep 17 00:00:00 2001 From: freya02 <41875020+freya022@users.noreply.github.com> Date: Sun, 30 Jun 2024 11:28:12 +0200 Subject: [PATCH] Improve Unknown Interaction error responses (#2687) --- .../exceptions/ErrorResponseException.java | 18 ++++++++- .../jda/api/requests/ErrorResponse.java | 1 + .../interactions/InteractionCallbackImpl.java | 38 +++++++++++++++++-- 3 files changed, 52 insertions(+), 5 deletions(-) diff --git a/src/main/java/net/dv8tion/jda/api/exceptions/ErrorResponseException.java b/src/main/java/net/dv8tion/jda/api/exceptions/ErrorResponseException.java index 291acd6971..8bc64197de 100644 --- a/src/main/java/net/dv8tion/jda/api/exceptions/ErrorResponseException.java +++ b/src/main/java/net/dv8tion/jda/api/exceptions/ErrorResponseException.java @@ -64,7 +64,18 @@ private ErrorResponseException(ErrorResponse errorResponse, Response response, i this.errorResponse = errorResponse; this.code = code; this.meaning = meaning; - this.schemaErrors = schemaErrors; + this.schemaErrors = Collections.unmodifiableList(schemaErrors); + } + + private ErrorResponseException(String message, ErrorResponseException cause) + { + super(cause.code + ": " + message, cause); + + this.response = cause.response; + this.errorResponse = cause.errorResponse; + this.code = cause.code; + this.meaning = cause.meaning; + this.schemaErrors = cause.schemaErrors; } /** @@ -134,6 +145,11 @@ public List getSchemaErrors() return schemaErrors; } + public static ErrorResponseException create(String message, ErrorResponseException cause) + { + return new ErrorResponseException(message, cause); + } + public static ErrorResponseException create(ErrorResponse errorResponse, Response response) { String meaning = errorResponse.getMeaning(); diff --git a/src/main/java/net/dv8tion/jda/api/requests/ErrorResponse.java b/src/main/java/net/dv8tion/jda/api/requests/ErrorResponse.java index 49de2c3448..92cdf78601 100644 --- a/src/main/java/net/dv8tion/jda/api/requests/ErrorResponse.java +++ b/src/main/java/net/dv8tion/jda/api/requests/ErrorResponse.java @@ -118,6 +118,7 @@ public enum ErrorResponse USER_NOT_CONNECTED( 40032, "Target user is not connected to voice."), ALREADY_CROSSPOSTED( 40033, "This message has already been crossposted."), APPLICATION_COMMAND_NAME_ALREADY_EXISTS( 40041, "An application command with that name already exists"), + INTERACTION_ALREADY_ACKNOWLEDGED( 40060, "Interaction has already been acknowledged"), MISSING_ACCESS( 50001, "Missing Access"), INVALID_ACCOUNT_TYPE( 50002, "Invalid Account Type"), INVALID_DM_ACTION( 50003, "Cannot execute action on a DM channel"), diff --git a/src/main/java/net/dv8tion/jda/internal/requests/restaction/interactions/InteractionCallbackImpl.java b/src/main/java/net/dv8tion/jda/internal/requests/restaction/interactions/InteractionCallbackImpl.java index f89f4ed9b4..5e9ab4fa12 100644 --- a/src/main/java/net/dv8tion/jda/internal/requests/restaction/interactions/InteractionCallbackImpl.java +++ b/src/main/java/net/dv8tion/jda/internal/requests/restaction/interactions/InteractionCallbackImpl.java @@ -16,10 +16,8 @@ package net.dv8tion.jda.internal.requests.restaction.interactions; -import net.dv8tion.jda.api.requests.Request; -import net.dv8tion.jda.api.requests.Response; -import net.dv8tion.jda.api.requests.RestAction; -import net.dv8tion.jda.api.requests.Route; +import net.dv8tion.jda.api.exceptions.ErrorResponseException; +import net.dv8tion.jda.api.requests.*; import net.dv8tion.jda.api.requests.restaction.interactions.InteractionCallbackAction; import net.dv8tion.jda.internal.interactions.InteractionImpl; import net.dv8tion.jda.internal.requests.RestActionImpl; @@ -36,6 +34,38 @@ public InteractionCallbackImpl(InteractionImpl interaction) { super(interaction.getJDA(), Route.Interactions.CALLBACK.compile(interaction.getId(), interaction.getToken())); this.interaction = interaction; + setErrorMapper(this::handleUnknownInteraction); + } + + private Throwable handleUnknownInteraction(Response response, Request request, ErrorResponseException exception) + { + // While this error response has existed since at least 2022 (https://github.com/discord/discord-api-docs/pull/4484), + // Discord does not always report this error correctly and instead sends a 'UNKNOWN_INTERACTION'. + // That's why we also have a similar exception at the end of this method. + if (exception.getErrorResponse() == ErrorResponse.INTERACTION_ALREADY_ACKNOWLEDGED) + return ErrorResponseException.create( + "This interaction was acknowledged by another process running for the same bot.\n" + + "To resolve this, try stopping all current processes for the bot that could be responsible, or resetting your bot token.\n" + + "You can reset your token at https://discord.com/developers/applications/" + getJDA().getSelfUser().getApplicationId() + "/bot", + exception + ); + + // Time synchronization issues prevent us from checking the exact nature of the issue, + // and storing a local Instant would be invalid in case the WS thread is blocked, + // as it will be created when the thread is released. + // Send a message for both issues instead. + if (exception.getErrorResponse() == ErrorResponse.UNKNOWN_INTERACTION) + return ErrorResponseException.create( + "Failed to acknowledge this interaction, this can be due to 2 reasons:\n" + + "1. This interaction took longer than 3 seconds to be acknowledged, see https://jda.wiki/using-jda/troubleshooting/#the-interaction-took-longer-than-3-seconds-to-be-acknowledged\n" + + "2. This interaction could have been acknowledged by another process running for the same bot\n" + + "You can confirm this by checking if your bot replied, or the three dots in a button disappeared without saying 'This interaction failed', or you see '[Bot] is thinking...' for more than 3 seconds.\n" + + "To resolve this, try stopping all current processes for the bot that could be responsible, or resetting your bot token.\n" + + "You can reset your token at https://discord.com/developers/applications/" + getJDA().getSelfUser().getApplicationId() + "/bot", + exception + ); + + return null; } @Nonnull