All Downloads are FREE. Search and download functionalities are using the official Maven repository.

net.dv8tion.jda.api.exceptions.ErrorHandler Maven / Gradle / Ivy

Go to download

Java wrapper for the popular chat & VOIP service: Discord https://discord.com

There is a newer version: 5.1.0
Show newest version
/*
 * Copyright 2015 Austin Keener, Michael Ritter, Florian Spieß, and the JDA contributors
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package net.dv8tion.jda.api.exceptions;

import net.dv8tion.jda.api.requests.ErrorResponse;
import net.dv8tion.jda.api.requests.RestAction;
import net.dv8tion.jda.internal.utils.Checks;

import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.util.*;
import java.util.function.Consumer;
import java.util.function.Predicate;

/**
 * Utility class to simplify error handling with {@link RestAction RestActions} and {@link ErrorResponse ErrorResponses}.
 *
 * 

Example
*

{@code
 * // Send message to user and delete it 30 seconds later, handles blocked messages in context channel.
 * public void sendMessage(TextChannel context, User user, String content) {
 *     user.openPrivateChannel()
 *         .flatMap(channel -> channel.sendMessage(content))
 *         .delay(Duration.ofSeconds(30))
 *         .flatMap(Message::delete) // delete after 30 seconds
 *         .queue(null, new ErrorHandler()
 *             .ignore(ErrorResponse.UNKNOWN_MESSAGE) // if delete fails that's fine
 *             .handle(
 *                 ErrorResponse.CANNOT_SEND_TO_USER,  // Fallback handling for blocked messages
 *                 (e) -> context.sendMessage("Failed to send message, you block private messages!").queue()));
 * }
 * }
* * @see ErrorResponse * @see ErrorResponseException * @see RestAction#queue(Consumer, Consumer) * * @since 4.2.0 */ public class ErrorHandler implements Consumer { private static final Consumer empty = (e) -> {}; private final Consumer base; private final Map, Consumer> cases = new LinkedHashMap<>(); /** * Create an ErrorHandler with {@link RestAction#getDefaultFailure()} as base consumer. *
If none of the provided ignore/handle cases apply, the base consumer is applied instead. */ public ErrorHandler() { this(RestAction.getDefaultFailure()); } /** * Create an ErrorHandler with the specified consumer as base consumer. *
If none of the provided ignore/handle cases apply, the base consumer is applied instead. * * @param base * The base {@link Consumer} */ public ErrorHandler(@Nonnull Consumer base) { Checks.notNull(base, "Consumer"); this.base = base; } /** * Ignore the specified set of error responses. * *

Example
*

{@code
     * // Creates a message with the provided content and deletes it 30 seconds later
     * public static void selfDestruct(MessageChannel channel, String content) {
     *     channel.sendMessage(content)
     *         .delay(Duration.ofSeconds(30))
     *         .flatMap(Message::delete)
     *         .queue(null, new ErrorHandler().ignore(UNKNOWN_MESSAGE));
     * }
     * }
* * @param ignored * Ignored error response * @param errorResponses * Additional error responses to ignore * * @throws IllegalArgumentException * If provided with null * * @return This ErrorHandler with the applied ignore cases */ @Nonnull public ErrorHandler ignore(@Nonnull ErrorResponse ignored, @Nonnull ErrorResponse... errorResponses) { Checks.notNull(ignored, "ErrorResponse"); Checks.noneNull(errorResponses, "ErrorResponse"); return ignore(EnumSet.of(ignored, errorResponses)); } /** * Ignore the specified set of error responses. * *

Example
*

{@code
     * // Creates a message with the provided content and deletes it 30 seconds later
     * public static void selfDestruct(User user, String content) {
     *     user.openPrivateChannel()
     *         .flatMap(channel -> channel.sendMessage(content))
     *         .delay(Duration.ofSeconds(30))
     *         .flatMap(Message::delete)
     *         .queue(null, new ErrorHandler().ignore(EnumSet.of(UNKNOWN_MESSAGE, CANNOT_SEND_TO_USER)));
     * }
     * }
* * @param errorResponses * The error responses to ignore * * @throws IllegalArgumentException * If provided with null * * @return This ErrorHandler with the applied ignore cases */ @Nonnull public ErrorHandler ignore(@Nonnull Collection errorResponses) { return handle(errorResponses, empty); } /** * Ignore exceptions of the specified types. * *

Example
*

{@code
     * // Ignore SocketTimeoutException
     * public static void ban(Guild guild, String userId) {
     *     guild.ban(userId).queue(null, new ErrorHandler().ignore(SocketTimeoutException.class);
     * }
     * }
* * @param clazz * The class to ignore * @param classes * Additional classes to ignore * * @throws IllegalArgumentException * If provided with null * * @return This ErrorHandler with the applied ignore case * * @see java.net.SocketTimeoutException */ @Nonnull public ErrorHandler ignore(@Nonnull Class clazz, @Nonnull Class... classes) { Checks.notNull(clazz, "Classes"); Checks.noneNull(classes, "Classes"); return ignore(it -> { if (clazz.isInstance(it)) return true; for (Class e : classes) { if (e.isInstance(it)) return true; } return false; }); } /** * Ignore exceptions on specific conditions. * *

Example
*

{@code
     * // Ignore all exceptions except for ErrorResponseException
     * public static void ban(Guild guild, String userId) {
     *     guild.ban(userId).queue(null, new ErrorHandler().ignore((ex) -> !(ex instanceof ErrorResponseException));
     * }
     * }
* * @param condition * The condition to check * * @throws IllegalArgumentException * If provided with null * * @return This ErrorHandler with the applied ignore case * * @see ErrorResponseException */ @Nonnull public ErrorHandler ignore(@Nonnull Predicate condition) { return handle(condition, empty); } /** * Handle specific {@link ErrorResponse ErrorResponses}. *
This will apply the specified handler to use instead of the base consumer if one of the provided ErrorResponses happens. * *

Example
*

{@code
     * public static void sendMessage(TextChannel context, User user, String content) {
     *     user.openPrivateChannel()
     *         .flatMap(channel -> channel.sendMessage(content))
     *         .queue(null, new ErrorHandler()
     *             .handle(ErrorResponse.CANNOT_SEND_TO_USER,
     *                 (ex) -> context.sendMessage("Cannot send direct message, please enable direct messages from server members!").queue()));
     * }
     * }
* * @param response * The first {@link ErrorResponse} to match * @param handler * The alternative handler * * @throws IllegalArgumentException * If provided with null * * @return This ErrorHandler with the applied handler */ @Nonnull public ErrorHandler handle(@Nonnull ErrorResponse response, @Nonnull Consumer handler) { Checks.notNull(response, "ErrorResponse"); return handle(EnumSet.of(response), handler); } /** * Handle specific {@link ErrorResponse ErrorResponses}. *
This will apply the specified handler to use instead of the base consumer if one of the provided ErrorResponses happens. * *

Example
*

{@code
     * public static void sendMessage(TextChannel context, User user, String content) {
     *     user.openPrivateChannel()
     *         .flatMap(channel -> channel.sendMessage(content))
     *         .queue(null, new ErrorHandler()
     *             .handle(EnumSet.of(ErrorResponse.CANNOT_SEND_TO_USER),
     *                 (ex) -> context.sendMessage("Cannot send direct message, please enable direct messages from server members!").queue()));
     * }
     * }
* * @param errorResponses * The {@link ErrorResponse ErrorResponses} to match * @param handler * The alternative handler * * @throws IllegalArgumentException * If provided with null * * @return This ErrorHandler with the applied handler */ @Nonnull public ErrorHandler handle(@Nonnull Collection errorResponses, @Nonnull Consumer handler) { Checks.notNull(handler, "Handler"); Checks.noneNull(errorResponses, "ErrorResponse"); return handle(ErrorResponseException.class, (it) -> errorResponses.contains(it.getErrorResponse()), handler); } /** * Handle specific throwable types. *
This will apply the specified handler if the throwable is of the specified type. The check is done using {@link Class#isInstance(Object)}. * *

Example
*

{@code
     * public static void logErrorResponse(RestAction action) {
     *     action.queue(null, new ErrorHandler()
     *         .handle(ErrorResponseException.class,
     *             (ex) -> System.out.println(ex.getErrorResponse())));
     * }
     * }
* * @param clazz * The throwable type * @param handler * The alternative handler * * @param * The type * * @return This ErrorHandler with the applied handler */ @Nonnull public ErrorHandler handle(@Nonnull Class clazz, @Nonnull Consumer handler) { Checks.notNull(clazz, "Class"); Checks.notNull(handler, "Handler"); return handle(clazz::isInstance, (ex) -> handler.accept(clazz.cast(ex))); } /** * Handle specific throwable types. *
This will apply the specified handler if the throwable is of the specified type. The check is done using {@link Class#isInstance(Object)}. * *

Example
*

{@code
     * public static void logErrorResponse(RestAction action) {
     *     action.queue(null, new ErrorHandler()
     *         .handle(ErrorResponseException.class,
     *             ErrorResponseException::isServerError,
     *             (ex) -> System.out.println(ex.getErrorCode() + ": " + ex.getMeaning())));
     * }
     * }
* * @param clazz * The throwable type * @param condition * Additional condition that must apply to use this handler * @param handler * The alternative handler * * @param * The type * * @return This ErrorHandler with the applied handler */ @Nonnull public ErrorHandler handle(@Nonnull Class clazz, @Nonnull Predicate condition, @Nonnull Consumer handler) { Checks.notNull(clazz, "Class"); Checks.notNull(handler, "Handler"); return handle( (it) -> clazz.isInstance(it) && condition.test(clazz.cast(it)), (ex) -> handler.accept(clazz.cast(ex))); } /** * Handle specific throwable types. *
This will apply the specified handler if the throwable is of the specified type. The check is done using {@link Class#isInstance(Object)}. * *

Example
*

{@code
     * public static void logErrorResponse(RestAction action) {
     *     action.queue(null, new ErrorHandler()
     *         .handle(Arrays.asList(Throwable.class),
     *             (ex) -> ex instanceof Error,
     *             (ex) -> ex.printStackTrace()));
     * }
     * }
* * @param clazz * The throwable types * @param condition * Additional condition that must apply to use this handler, or null to apply no additional condition * @param handler * The alternative handler * * @return This ErrorHandler with the applied handler */ @Nonnull public ErrorHandler handle(@Nonnull Collection> clazz, @Nullable Predicate condition, @Nonnull Consumer handler) { Checks.noneNull(clazz, "Class"); Checks.notNull(handler, "Handler"); List> classes = new ArrayList<>(clazz); Predicate check = (it) -> classes.stream().anyMatch(c -> c.isInstance(it)) && (condition == null || condition.test(it)); return handle(check, handler); } /** * Handle specific conditions. * *

Example
*

{@code
     * public static void logErrorResponse(RestAction action) {
     *     action.queue(null, new ErrorHandler()
     *         .handle(
     *             (ex) -> !(ex instanceof ErrorResponseException),
     *             Throwable::printStackTrace));
     * }
     * }
* * @param condition * Condition that must apply to use this handler * @param handler * The alternative handler * * @return This ErrorHandler with the applied handler */ @Nonnull public ErrorHandler handle(@Nonnull Predicate condition, @Nonnull Consumer handler) { Checks.notNull(condition, "Condition"); Checks.notNull(handler, "Handler"); cases.put(condition, handler); return this; } @Override public void accept(Throwable t) { for (Map.Entry, Consumer> entry : cases.entrySet()) { Predicate condition = entry.getKey(); Consumer callback = entry.getValue(); if (condition.test(t)) { callback.accept(t); return; } } base.accept(t); } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy