Search in sources :

Example 1 with DiscordApi

use of org.javacord.api.DiscordApi in project Javacord by BtoBastian.

the class TextChannel method typeContinuouslyAfter.

/**
 * Displays the "xyz is typing..." message continuously, starting delayed.
 * The message is continuously displayed if not quit using the returned {@code AutoCloseable}.
 * Sending a message will make the message go away shortly, but it will return immediately if not cancelled using
 * the {@code AutoCloseable}. This can be used in a try-with-resources block like
 * <code>try (NonThrowingAutoCloseable typingIndicator = textChannel.typeContinuouslyAfter(500,
 * TimeUnit.MILLISECONDS, ExceptionLogger.getConsumer(RatelimitException.class)))
 * { /* do lengthy stuff &#42;/ } sendReply();</code>.
 *
 * <p>The typing indicator will be shown delayed. This can be useful if the task you do can be finished in very
 * short time which could cause the typing indicator and the response message being sent at the same time and the
 * typing indicator could be shown for 10 seconds even if the message was sent already. With the delay this is
 * compensated, because if the returned {@code AutoCloseable} is closed before the delay is over, no typing
 * indicator will be sent at all.
 *
 * <p>Any occurring exceptions including ratelimit exceptions are given to the provided {@code exceptionHandler} or
 * ignored if it is {@code null}.
 *
 * @param exceptionHandler The handler that exceptions are given to.
 * @param delay The delay to wait until the first typing indicator is sent.
 * @param timeUnit The time unit of the delay value.
 * @return An auto-closable to stop sending the typing indicator.
 * @see #type()
 * @see #typeContinuously()
 * @see #typeContinuously(Consumer)
 * @see #typeContinuouslyAfter(long, TimeUnit)
 */
default NonThrowingAutoCloseable typeContinuouslyAfter(long delay, TimeUnit timeUnit, Consumer<Throwable> exceptionHandler) {
    // the delegate that does the actual type indicator sending and error handling
    Runnable typeRunnable = () -> {
        try {
            CompletableFuture<?> typeFuture = type();
            if (exceptionHandler != null) {
                typeFuture.exceptionally(throwable -> {
                    exceptionHandler.accept(throwable);
                    return null;
                });
            }
        } catch (Throwable t) {
            ExceptionLogger.getConsumer().accept(t);
        }
    };
    DiscordApi api = getApi();
    // schedule regular type indicator sending
    Future<?> typingIndicator = api.getThreadPool().getScheduler().scheduleWithFixedDelay(typeRunnable, TimeUnit.NANOSECONDS.convert(delay, timeUnit), 8_000_000_000L, TimeUnit.NANOSECONDS);
    // prevent messages from other commands to interrupt the typing indicator too long
    ListenerManager<MessageCreateListener> typingInterruptedListenerManager = api.addMessageCreateListener(event -> {
        if (event.getMessage().getAuthor().isYourself()) {
            typeRunnable.run();
        }
    });
    // auto-closable to cancel the continuously typing indicator
    return () -> {
        typingInterruptedListenerManager.remove();
        typingIndicator.cancel(true);
    };
}
Also used : MessageSet(org.javacord.api.entity.message.MessageSet) Arrays(java.util.Arrays) CompletableFuture(java.util.concurrent.CompletableFuture) MessageCache(org.javacord.api.util.cache.MessageCache) IncomingWebhook(org.javacord.api.entity.webhook.IncomingWebhook) Future(java.util.concurrent.Future) ListenerManager(org.javacord.api.util.event.ListenerManager) ExceptionLogger(org.javacord.api.util.logging.ExceptionLogger) StreamSupport(java.util.stream.StreamSupport) NoSuchElementException(java.util.NoSuchElementException) MessageCreateListener(org.javacord.api.listener.message.MessageCreateListener) PermissionType(org.javacord.api.entity.permission.PermissionType) Webhook(org.javacord.api.entity.webhook.Webhook) Messageable(org.javacord.api.entity.message.Messageable) Predicate(java.util.function.Predicate) TextChannelAttachableListenerManager(org.javacord.api.listener.channel.TextChannelAttachableListenerManager) Message(org.javacord.api.entity.message.Message) TimeUnit(java.util.concurrent.TimeUnit) Consumer(java.util.function.Consumer) List(java.util.List) Stream(java.util.stream.Stream) User(org.javacord.api.entity.user.User) DiscordApi(org.javacord.api.DiscordApi) Optional(java.util.Optional) NonThrowingAutoCloseable(org.javacord.api.util.NonThrowingAutoCloseable) CompletableFuture(java.util.concurrent.CompletableFuture) MessageCreateListener(org.javacord.api.listener.message.MessageCreateListener) DiscordApi(org.javacord.api.DiscordApi)

Example 2 with DiscordApi

use of org.javacord.api.DiscordApi in project Javacord by BtoBastian.

the class DiscordApiBuilderDelegateImpl method loginShards.

@Override
public Collection<CompletableFuture<DiscordApi>> loginShards(int... shards) {
    Objects.requireNonNull(shards);
    if (shards.length == 0) {
        return Collections.emptyList();
    }
    if (Arrays.stream(shards).distinct().count() != shards.length) {
        throw new IllegalArgumentException("shards cannot be started multiple times!");
    }
    if (Arrays.stream(shards).max().orElseThrow(AssertionError::new) >= getTotalShards()) {
        throw new IllegalArgumentException("shard cannot be greater or equal than totalShards!");
    }
    if (Arrays.stream(shards).min().orElseThrow(AssertionError::new) < 0) {
        throw new IllegalArgumentException("shard cannot be less than 0!");
    }
    if (shards.length == getTotalShards()) {
        logger.info("Creating {} {}", getTotalShards(), (getTotalShards() == 1) ? "shard" : "shards");
    } else {
        logger.info("Creating {} out of {} shards ({})", shards.length, getTotalShards(), shards);
    }
    Collection<CompletableFuture<DiscordApi>> result = new ArrayList<>(shards.length);
    int currentShard = getCurrentShard();
    for (int shard : shards) {
        if (currentShard != 0) {
            CompletableFuture<DiscordApi> future = new CompletableFuture<>();
            future.completeExceptionally(new IllegalArgumentException("You cannot use loginShards or loginAllShards after setting the current shard!"));
            result.add(future);
            continue;
        }
        setCurrentShard(shard);
        result.add(login());
    }
    setCurrentShard(currentShard);
    return result;
}
Also used : CompletableFuture(java.util.concurrent.CompletableFuture) ArrayList(java.util.ArrayList) CopyOnWriteArrayList(java.util.concurrent.CopyOnWriteArrayList) DiscordApi(org.javacord.api.DiscordApi) RestEndpoint(org.javacord.core.util.rest.RestEndpoint)

Aggregations

CompletableFuture (java.util.concurrent.CompletableFuture)2 DiscordApi (org.javacord.api.DiscordApi)2 ArrayList (java.util.ArrayList)1 Arrays (java.util.Arrays)1 List (java.util.List)1 NoSuchElementException (java.util.NoSuchElementException)1 Optional (java.util.Optional)1 CopyOnWriteArrayList (java.util.concurrent.CopyOnWriteArrayList)1 Future (java.util.concurrent.Future)1 TimeUnit (java.util.concurrent.TimeUnit)1 Consumer (java.util.function.Consumer)1 Predicate (java.util.function.Predicate)1 Stream (java.util.stream.Stream)1 StreamSupport (java.util.stream.StreamSupport)1 Message (org.javacord.api.entity.message.Message)1 MessageSet (org.javacord.api.entity.message.MessageSet)1 Messageable (org.javacord.api.entity.message.Messageable)1 PermissionType (org.javacord.api.entity.permission.PermissionType)1 User (org.javacord.api.entity.user.User)1 IncomingWebhook (org.javacord.api.entity.webhook.IncomingWebhook)1