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

net.neoforged.camelot.util.Utils Maven / Gradle / Ivy

There is a newer version: 1.0.177
Show newest version
package net.neoforged.camelot.util;

import net.dv8tion.jda.api.entities.User;
import net.dv8tion.jda.api.entities.channel.concrete.PrivateChannel;
import net.dv8tion.jda.api.exceptions.ErrorHandler;
import net.dv8tion.jda.api.exceptions.ErrorResponseException;
import net.dv8tion.jda.api.hooks.EventListener;
import net.dv8tion.jda.api.requests.ErrorResponse;
import net.dv8tion.jda.api.requests.RestAction;
import net.neoforged.camelot.BotMain;
import org.jetbrains.annotations.Nullable;

import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ThreadFactory;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Supplier;

/**
 * General utility methods.
 */
public class Utils {
    /**
     * Returns a new CompletableFuture that is completed when all of
     * the given CompletableFutures complete.  If any of the given
     * CompletableFutures complete exceptionally, then the returned
     * CompletableFuture also does so, with a CompletionException
     * holding this exception as its cause.  Otherwise, the results,
     * if any, of the given CompletableFutures are not reflected in
     * the returned CompletableFuture, but may be obtained by
     * inspecting them individually. If no CompletableFutures are
     * provided, returns a CompletableFuture completed with the value
     * {@code null}.
     *
     * 

Unlike {@link CompletableFuture#allOf(CompletableFuture[])}, this future does not return {@link Void}, * but the values of all completed futures.

* * @param futuresList the CompletableFutures * @return a new CompletableFuture that is completed when all of the * given CompletableFutures complete * @throws NullPointerException if the array or any of its elements are * {@code null} */ public static CompletableFuture> allOf(List> futuresList) { return CompletableFuture.allOf(futuresList.toArray(CompletableFuture[]::new)).thenApply(v -> futuresList.stream() .map(future -> future.getNow(null)) // The future had already been completed, so `getNow` will result the future's value .toList() ); } public static CompletableFuture whenComplete(@Nullable CompletableFuture existing, Supplier> cf) { if (existing == null) return cf.get(); final CompletableFuture newCf = new CompletableFuture<>(); existing.whenComplete((o, throwable) -> { if (throwable == null) { cf.get().whenComplete((o1, throwable1) -> { if (throwable1 == null) { newCf.complete(null); } else { newCf.completeExceptionally(throwable1); } }); } else { newCf.completeExceptionally(throwable); } }); return newCf; } /** * Converts the given {@code rbg} colour to a string. */ public static String rgbToString(int rgb) { return String.format("#%06X", (0xFFFFFF & rgb)); } /** * Truncates the given string if it exceeds the {@code limit}, adding an ellipsis if so. */ public static String truncate(final String str, int limit) { return str.length() > (limit - 3) ? str.substring(0, limit - 3) + "..." : str; } /** * Sneakily throws the given exception, bypassing compile-time checks for * checked exceptions. * *

* This method will never return normally. The exception passed * to the method is always rethrown. *

* * @param ex the exception to sneakily rethrow */ @SuppressWarnings("unchecked") public static void sneakyThrow(Throwable ex) throws E { throw (E) ex; } /** * {@return the username of the {@code user}, appending the discriminator if they have one} */ public static String getName(User user) { return user.getDiscriminator().equals("0000") ? user.getName() : user.getAsTag(); } /** * Creates a {@link EventListener} listening for events of the given {@code type}. */ public static EventListener listenerFor(Class type, Consumer listener) { return event -> { if (type.isInstance(event)) { listener.accept(type.cast(event)); } }; } /** * {@return a thread factory which creates daemon threads that are part of a group with the give {@code name}} */ public static ThreadFactory daemonGroup(String name) { final var group = new ThreadGroup(name); return r -> { final Thread thread = new Thread(group, r, name + " #" + group.activeCount()); thread.setDaemon(true); thread.setUncaughtExceptionHandler((t, e) -> BotMain.LOGGER.error("Encountered exception on thread {}: ", t.getName(), e)); return thread; }; } /** * Attempts to DM the {@code user}, ignoring a {@link ErrorResponse#CANNOT_SEND_TO_USER} exception. */ public static RestAction attemptDM(final User user, final Function> action) { return user.openPrivateChannel() .flatMap(ch -> action.apply(ch).map(_ -> (Void) null)) .onErrorMap(ErrorResponse.CANNOT_SEND_TO_USER::test, _ -> null); } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy