Search in sources :

Example 1 with Message

use of org.javacord.api.entity.message.Message in project Javacord by BtoBastian.

the class MessageBuilderBaseDelegateImpl method checkForAttachmentsAndExecuteRequest.

// //////////////////////////////////////////////////////////////////////////////
// Internal MessageBuilder utility methods
// //////////////////////////////////////////////////////////////////////////////
private CompletableFuture<Message> checkForAttachmentsAndExecuteRequest(TextChannel channel, ObjectNode body, RestRequest<Message> request, boolean clearAttachmentsIfAppropriate) {
    if (attachments.isEmpty() && embeds.stream().noneMatch(EmbedBuilder::requiresAttachments)) {
        if (clearAttachmentsIfAppropriate) {
            body.set("attachments", JsonNodeFactory.instance.objectNode().arrayNode());
        }
        return executeRequestWithoutAttachments(channel, body, request);
    }
    CompletableFuture<Message> future = new CompletableFuture<>();
    // We access files etc. so this should be async
    channel.getApi().getThreadPool().getExecutorService().submit(() -> {
        try {
            List<FileContainer> tempAttachments = new ArrayList<>(attachments);
            // Add the attachments required for the embeds
            for (EmbedBuilder embed : embeds) {
                tempAttachments.addAll(((EmbedBuilderDelegateImpl) embed.getDelegate()).getRequiredAttachments());
            }
            addMultipartBodyToRequest(request, body, tempAttachments, channel.getApi());
            request.execute(result -> ((DiscordApiImpl) channel.getApi()).getOrCreateMessage(channel, result.getJsonBody())).whenComplete((newMessage, throwable) -> {
                if (throwable != null) {
                    future.completeExceptionally(throwable);
                } else {
                    future.complete(newMessage);
                }
            });
        } catch (Throwable t) {
            future.completeExceptionally(t);
        }
    });
    return future;
}
Also used : MessageAttachment(org.javacord.api.entity.message.MessageAttachment) Arrays(java.util.Arrays) Member(org.javacord.core.entity.user.Member) URL(java.net.URL) RestMethod(org.javacord.core.util.rest.RestMethod) FileContainer(org.javacord.core.util.FileContainer) HighLevelComponent(org.javacord.api.entity.message.component.HighLevelComponent) RestRequest(org.javacord.core.util.rest.RestRequest) EmbedBuilderDelegateImpl(org.javacord.core.entity.message.embed.EmbedBuilderDelegateImpl) JsonNode(com.fasterxml.jackson.databind.JsonNode) ComponentType(org.javacord.api.entity.message.component.ComponentType) MediaType(okhttp3.MediaType) ActionRowBuilder(org.javacord.api.entity.message.component.ActionRowBuilder) MessageBuilderBaseDelegate(org.javacord.api.entity.message.internal.MessageBuilderBaseDelegate) BufferedImage(java.awt.image.BufferedImage) Messageable(org.javacord.api.entity.message.Messageable) Collection(java.util.Collection) Set(java.util.Set) EmbedBuilder(org.javacord.api.entity.message.embed.EmbedBuilder) AllowedMentions(org.javacord.api.entity.message.mention.AllowedMentions) Message(org.javacord.api.entity.message.Message) ArrayNode(com.fasterxml.jackson.databind.node.ArrayNode) RestEndpoint(org.javacord.core.util.rest.RestEndpoint) List(java.util.List) Logger(org.apache.logging.log4j.Logger) MultipartBody(okhttp3.MultipartBody) Mentionable(org.javacord.api.entity.Mentionable) JsonNodeFactory(com.fasterxml.jackson.databind.node.JsonNodeFactory) AllowedMentionsImpl(org.javacord.core.entity.message.mention.AllowedMentionsImpl) CompletableFuture(java.util.concurrent.CompletableFuture) ComponentImpl(org.javacord.core.entity.message.component.ComponentImpl) ObjectNode(com.fasterxml.jackson.databind.node.ObjectNode) IncomingWebhook(org.javacord.api.entity.webhook.IncomingWebhook) RequestBody(okhttp3.RequestBody) ArrayList(java.util.ArrayList) HashSet(java.util.HashSet) MessageDecoration(org.javacord.api.entity.message.MessageDecoration) URLConnection(java.net.URLConnection) Icon(org.javacord.api.entity.Icon) TextChannel(org.javacord.api.entity.channel.TextChannel) DiscordApiImpl(org.javacord.core.DiscordApiImpl) ActionRow(org.javacord.api.entity.message.component.ActionRow) LowLevelComponent(org.javacord.api.entity.message.component.LowLevelComponent) File(java.io.File) LoggerUtil(org.javacord.core.util.logging.LoggerUtil) User(org.javacord.api.entity.user.User) DiscordApi(org.javacord.api.DiscordApi) Collections(java.util.Collections) InputStream(java.io.InputStream) CompletableFuture(java.util.concurrent.CompletableFuture) EmbedBuilder(org.javacord.api.entity.message.embed.EmbedBuilder) Message(org.javacord.api.entity.message.Message) DiscordApiImpl(org.javacord.core.DiscordApiImpl) ArrayList(java.util.ArrayList) FileContainer(org.javacord.core.util.FileContainer)

Example 2 with Message

use of org.javacord.api.entity.message.Message in project Javacord by BtoBastian.

the class MessageBuilderBaseDelegateImpl method send.

/**
 * Send a message to an incoming webhook.
 *
 * @param webhookId The id of the webhook to send the message to
 * @param webhookToken The token of the webhook to send the message to
 * @param displayName The display name the webhook should use
 * @param avatarUrl The avatar the webhook should use
 * @param wait If the completable future will be completed
 * @param api The api instance needed to send and return the message
 * @return The sent message
 */
protected CompletableFuture<Message> send(String webhookId, String webhookToken, String displayName, URL avatarUrl, boolean wait, DiscordApi api) {
    ObjectNode body = JsonNodeFactory.instance.objectNode();
    prepareCommonWebhookMessageBodyParts(body);
    if (displayName != null) {
        body.put("username", displayName);
    }
    if (avatarUrl != null) {
        body.put("avatar_url", avatarUrl.toExternalForm());
    }
    prepareComponents(body);
    if (strBuilder.length() != 0) {
        body.put("content", strBuilder.toString());
    }
    RestRequest<Message> request = new RestRequest<Message>(api, RestMethod.POST, RestEndpoint.WEBHOOK_SEND).addQueryParameter("wait", Boolean.toString(wait)).setUrlParameters(webhookId, webhookToken);
    CompletableFuture<Message> future = new CompletableFuture<>();
    if (!attachments.isEmpty() || embeds.stream().anyMatch(EmbedBuilder::requiresAttachments)) {
        // We access files etc. so this should be async
        api.getThreadPool().getExecutorService().submit(() -> {
            try {
                List<FileContainer> tempAttachments = new ArrayList<>(attachments);
                // Add the attachments required for the embeds
                for (EmbedBuilder embed : embeds) {
                    tempAttachments.addAll(((EmbedBuilderDelegateImpl) embed.getDelegate()).getRequiredAttachments());
                }
                addMultipartBodyToRequest(request, body, tempAttachments, api);
                executeWebhookRest(request, wait, future, api);
            } catch (Throwable t) {
                future.completeExceptionally(t);
            }
        });
    } else {
        request.setBody(body);
        executeWebhookRest(request, wait, future, api);
    }
    return future;
}
Also used : CompletableFuture(java.util.concurrent.CompletableFuture) EmbedBuilder(org.javacord.api.entity.message.embed.EmbedBuilder) RestRequest(org.javacord.core.util.rest.RestRequest) ObjectNode(com.fasterxml.jackson.databind.node.ObjectNode) Message(org.javacord.api.entity.message.Message) ArrayList(java.util.ArrayList) FileContainer(org.javacord.core.util.FileContainer)

Example 3 with Message

use of org.javacord.api.entity.message.Message in project Javacord by BtoBastian.

the class UncachedMessageUtilImpl method edit.

@Override
public CompletableFuture<Message> edit(long channelId, long messageId, String content, boolean updateContent, List<EmbedBuilder> embeds, boolean updateEmbed) {
    ObjectNode body = JsonNodeFactory.instance.objectNode();
    if (updateContent) {
        if (content == null || content.isEmpty()) {
            body.putNull("content");
        } else {
            body.put("content", content);
        }
    }
    if (updateEmbed) {
        ArrayNode embedArray = body.putArray("embeds");
        embeds.stream().map(embedBuilder -> ((EmbedBuilderDelegateImpl) embedBuilder.getDelegate()).toJsonNode()).forEach(embedArray::add);
    }
    return new RestRequest<Message>(api, RestMethod.PATCH, RestEndpoint.MESSAGE).setUrlParameters(Long.toUnsignedString(channelId), Long.toUnsignedString(messageId)).setBody(body).execute(result -> new MessageImpl(api, api.getTextChannelById(channelId).orElseThrow(() -> new IllegalStateException("TextChannel is missing.")), result.getJsonBody()));
}
Also used : Arrays(java.util.Arrays) CompletableFuture(java.util.concurrent.CompletableFuture) UncachedMessageUtil(org.javacord.api.entity.message.UncachedMessageUtil) RestMethod(org.javacord.core.util.rest.RestMethod) ObjectNode(com.fasterxml.jackson.databind.node.ObjectNode) ArrayList(java.util.ArrayList) DiscordEntity(org.javacord.api.entity.DiscordEntity) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) Map(java.util.Map) RestRequest(org.javacord.core.util.rest.RestRequest) Emoji(org.javacord.api.entity.emoji.Emoji) EmbedBuilderDelegateImpl(org.javacord.core.entity.message.embed.EmbedBuilderDelegateImpl) JsonNode(com.fasterxml.jackson.databind.JsonNode) StreamSupport(java.util.stream.StreamSupport) UserImpl(org.javacord.core.entity.user.UserImpl) MemberImpl(org.javacord.core.entity.user.MemberImpl) EmbedBuilder(org.javacord.api.entity.message.embed.EmbedBuilder) CustomEmoji(org.javacord.api.entity.emoji.CustomEmoji) DiscordApiImpl(org.javacord.core.DiscordApiImpl) Instant(java.time.Instant) Message(org.javacord.api.entity.message.Message) Collectors(java.util.stream.Collectors) InternalUncachedMessageAttachableListenerManager(org.javacord.core.listener.message.InternalUncachedMessageAttachableListenerManager) ArrayNode(com.fasterxml.jackson.databind.node.ArrayNode) RestEndpoint(org.javacord.core.util.rest.RestEndpoint) List(java.util.List) ChronoUnit(java.time.temporal.ChronoUnit) Stream(java.util.stream.Stream) User(org.javacord.api.entity.user.User) JsonNodeFactory(com.fasterxml.jackson.databind.node.JsonNodeFactory) DiscordApi(org.javacord.api.DiscordApi) Collections(java.util.Collections) ObjectNode(com.fasterxml.jackson.databind.node.ObjectNode) Message(org.javacord.api.entity.message.Message) ArrayNode(com.fasterxml.jackson.databind.node.ArrayNode) EmbedBuilderDelegateImpl(org.javacord.core.entity.message.embed.EmbedBuilderDelegateImpl)

Example 4 with Message

use of org.javacord.api.entity.message.Message in project Javacord by BtoBastian.

the class UncachedMessageUtilImpl method delete.

@Override
public CompletableFuture<Void> delete(long channelId, long... messageIds) {
    // split by younger than two weeks / older than two weeks
    Instant twoWeeksAgo = Instant.now().minus(14, ChronoUnit.DAYS);
    Map<Boolean, List<Long>> messageIdsByAge = Arrays.stream(messageIds).distinct().boxed().collect(Collectors.groupingBy(messageId -> DiscordEntity.getCreationTimestamp(messageId).isAfter(twoWeeksAgo)));
    AtomicInteger batchCounter = new AtomicInteger();
    return CompletableFuture.allOf(Stream.concat(// for messages younger than 2 weeks
    messageIdsByAge.getOrDefault(true, Collections.emptyList()).stream().collect(Collectors.groupingBy(messageId -> batchCounter.getAndIncrement() / 100)).values().stream().map(messageIdBatch -> {
        // do not use batch deletion for a single message
        if (messageIdBatch.size() == 1) {
            return Message.delete(api, channelId, messageIdBatch.get(0));
        }
        ObjectNode body = JsonNodeFactory.instance.objectNode();
        ArrayNode messages = body.putArray("messages");
        messageIdBatch.stream().map(Long::toUnsignedString).forEach(messages::add);
        return new RestRequest<Void>(api, RestMethod.POST, RestEndpoint.MESSAGES_BULK_DELETE).setUrlParameters(Long.toUnsignedString(channelId)).setBody(body).execute(result -> null);
    }), // for messages older than 2 weeks use single message deletion
    messageIdsByAge.getOrDefault(false, Collections.emptyList()).stream().map(messageId -> Message.delete(api, channelId, messageId))).toArray(CompletableFuture[]::new));
}
Also used : Arrays(java.util.Arrays) CompletableFuture(java.util.concurrent.CompletableFuture) UncachedMessageUtil(org.javacord.api.entity.message.UncachedMessageUtil) RestMethod(org.javacord.core.util.rest.RestMethod) ObjectNode(com.fasterxml.jackson.databind.node.ObjectNode) ArrayList(java.util.ArrayList) DiscordEntity(org.javacord.api.entity.DiscordEntity) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) Map(java.util.Map) RestRequest(org.javacord.core.util.rest.RestRequest) Emoji(org.javacord.api.entity.emoji.Emoji) EmbedBuilderDelegateImpl(org.javacord.core.entity.message.embed.EmbedBuilderDelegateImpl) JsonNode(com.fasterxml.jackson.databind.JsonNode) StreamSupport(java.util.stream.StreamSupport) UserImpl(org.javacord.core.entity.user.UserImpl) MemberImpl(org.javacord.core.entity.user.MemberImpl) EmbedBuilder(org.javacord.api.entity.message.embed.EmbedBuilder) CustomEmoji(org.javacord.api.entity.emoji.CustomEmoji) DiscordApiImpl(org.javacord.core.DiscordApiImpl) Instant(java.time.Instant) Message(org.javacord.api.entity.message.Message) Collectors(java.util.stream.Collectors) InternalUncachedMessageAttachableListenerManager(org.javacord.core.listener.message.InternalUncachedMessageAttachableListenerManager) ArrayNode(com.fasterxml.jackson.databind.node.ArrayNode) RestEndpoint(org.javacord.core.util.rest.RestEndpoint) List(java.util.List) ChronoUnit(java.time.temporal.ChronoUnit) Stream(java.util.stream.Stream) User(org.javacord.api.entity.user.User) JsonNodeFactory(com.fasterxml.jackson.databind.node.JsonNodeFactory) DiscordApi(org.javacord.api.DiscordApi) Collections(java.util.Collections) CompletableFuture(java.util.concurrent.CompletableFuture) RestRequest(org.javacord.core.util.rest.RestRequest) ObjectNode(com.fasterxml.jackson.databind.node.ObjectNode) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) Instant(java.time.Instant) ArrayList(java.util.ArrayList) List(java.util.List) ArrayNode(com.fasterxml.jackson.databind.node.ArrayNode)

Example 5 with Message

use of org.javacord.api.entity.message.Message 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)

Aggregations

Message (org.javacord.api.entity.message.Message)14 ObjectNode (com.fasterxml.jackson.databind.node.ObjectNode)7 ArrayList (java.util.ArrayList)7 List (java.util.List)7 CompletableFuture (java.util.concurrent.CompletableFuture)7 JsonNode (com.fasterxml.jackson.databind.JsonNode)6 RestRequest (org.javacord.core.util.rest.RestRequest)6 Arrays (java.util.Arrays)5 Collections (java.util.Collections)5 TextChannel (org.javacord.api.entity.channel.TextChannel)5 EmbedBuilder (org.javacord.api.entity.message.embed.EmbedBuilder)5 DiscordApiImpl (org.javacord.core.DiscordApiImpl)5 RestEndpoint (org.javacord.core.util.rest.RestEndpoint)5 RestMethod (org.javacord.core.util.rest.RestMethod)5 ArrayNode (com.fasterxml.jackson.databind.node.ArrayNode)4 JsonNodeFactory (com.fasterxml.jackson.databind.node.JsonNodeFactory)4 Stream (java.util.stream.Stream)4 StreamSupport (java.util.stream.StreamSupport)4 DiscordApi (org.javacord.api.DiscordApi)4 Emoji (org.javacord.api.entity.emoji.Emoji)4