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 */ } 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);
};
}
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;
}
Aggregations