diff --git a/src/main/java/net/dv8tion/jda/api/EmbedBuilder.java b/src/main/java/net/dv8tion/jda/api/EmbedBuilder.java
index c8c6be38a8..2516fa5aa9 100644
--- a/src/main/java/net/dv8tion/jda/api/EmbedBuilder.java
+++ b/src/main/java/net/dv8tion/jda/api/EmbedBuilder.java
@@ -432,7 +432,7 @@ public EmbedBuilder setColor(int color)
*
*
Uploading images with Embeds
* When uploading an image
- * (using {@link net.dv8tion.jda.api.entities.MessageChannel#sendFile(java.io.File, net.dv8tion.jda.api.utils.AttachmentOption...) MessageChannel.sendFile(...)})
+ * (using {@link net.dv8tion.jda.api.entities.MessageChannel#sendFiles(net.dv8tion.jda.api.utils.FileUpload...) MessageChannel.sendFiles(...)})
* you can reference said image using the specified filename as URI {@code attachment://filename.ext}.
*
*
Example
@@ -442,7 +442,7 @@ public EmbedBuilder setColor(int color)
* InputStream file = new URL("https://http.cat/500").openStream();
* embed.setThumbnail("attachment://cat.png") // we specify this in sendFile as "cat.png"
* .setDescription("This is a cute cat :3");
- * channel.sendFile(file, "cat.png").setEmbeds(embed.build()).queue();
+ * channel.sendFiles(FileUpload.fromData(file, "cat.png")).setEmbeds(embed.build()).queue();
*
*
* @param url
@@ -479,7 +479,7 @@ public EmbedBuilder setThumbnail(@Nullable String url)
*
*
Uploading images with Embeds
* When uploading an image
- * (using {@link net.dv8tion.jda.api.entities.MessageChannel#sendFile(java.io.File, net.dv8tion.jda.api.utils.AttachmentOption...) MessageChannel.sendFile(...)})
+ * (using {@link net.dv8tion.jda.api.entities.MessageChannel#sendFiles(net.dv8tion.jda.api.utils.FileUpload...) MessageChannel.sendFiles(...)})
* you can reference said image using the specified filename as URI {@code attachment://filename.ext}.
*
*
Example
@@ -489,7 +489,7 @@ public EmbedBuilder setThumbnail(@Nullable String url)
* InputStream file = new URL("https://http.cat/500").openStream();
* embed.setImage("attachment://cat.png") // we specify this in sendFile as "cat.png"
* .setDescription("This is a cute cat :3");
- * channel.sendFile(file, "cat.png").setEmbeds(embed.build()).queue();
+ * channel.sendFiles(FileUpload.fromData(file, "cat.png")).setEmbeds(embed.build()).queue();
*
*
* @param url
@@ -504,7 +504,7 @@ public EmbedBuilder setThumbnail(@Nullable String url)
*
* @return the builder after the image has been set
*
- * @see net.dv8tion.jda.api.entities.MessageChannel#sendFile(java.io.File, String, net.dv8tion.jda.api.utils.AttachmentOption...) MessageChannel.sendFile(...)
+ * @see net.dv8tion.jda.api.entities.MessageChannel#sendFiles(net.dv8tion.jda.api.utils.FileUpload...) MessageChannel.sendFiles(...)
*/
@Nonnull
public EmbedBuilder setImage(@Nullable String url)
@@ -580,7 +580,7 @@ public EmbedBuilder setAuthor(@Nullable String name, @Nullable String url)
*
*
Uploading images with Embeds
* When uploading an image
- * (using {@link net.dv8tion.jda.api.entities.MessageChannel#sendFile(java.io.File, net.dv8tion.jda.api.utils.AttachmentOption...) MessageChannel.sendFile(...)})
+ * (using {@link net.dv8tion.jda.api.entities.MessageChannel#sendFiles(net.dv8tion.jda.api.utils.FileUpload...) MessageChannel.sendFiles(...)})
* you can reference said image using the specified filename as URI {@code attachment://filename.ext}.
*
*
Example
@@ -590,7 +590,7 @@ public EmbedBuilder setAuthor(@Nullable String name, @Nullable String url)
* InputStream file = new URL("https://http.cat/500").openStream();
* embed.setAuthor("Minn", null, "attachment://cat.png") // we specify this in sendFile as "cat.png"
* .setDescription("This is a cute cat :3");
- * channel.sendFile(file, "cat.png").setEmbeds(embed.build()).queue();
+ * channel.sendFiles(FileUpload.fromData(file, "cat.png")).setEmbeds(embed.build()).queue();
*
*
* @param name
@@ -660,7 +660,7 @@ public EmbedBuilder setFooter(@Nullable String text)
*
*
Uploading images with Embeds
* When uploading an image
- * (using {@link net.dv8tion.jda.api.entities.MessageChannel#sendFile(java.io.File, net.dv8tion.jda.api.utils.AttachmentOption...) MessageChannel.sendFile(...)})
+ * (using {@link net.dv8tion.jda.api.entities.MessageChannel#sendFiles(net.dv8tion.jda.api.utils.FileUpload...) MessageChannel.sendFiles(...)})
* you can reference said image using the specified filename as URI {@code attachment://filename.ext}.
*
*
Example
@@ -670,7 +670,7 @@ public EmbedBuilder setFooter(@Nullable String text)
* InputStream file = new URL("https://http.cat/500").openStream();
* embed.setFooter("Cool footer!", "attachment://cat.png") // we specify this in sendFile as "cat.png"
* .setDescription("This is a cute cat :3");
- * channel.sendFile(file, "cat.png").setEmbeds(embed.build()).queue();
+ * channel.sendFiles(FileUpload.fromData(file, "cat.png")).setEmbeds(embed.build()).queue();
*
*
* @param text
diff --git a/src/main/java/net/dv8tion/jda/api/JDAInfo.java b/src/main/java/net/dv8tion/jda/api/JDAInfo.java
index a4504b2509..dca0d2d4ba 100644
--- a/src/main/java/net/dv8tion/jda/api/JDAInfo.java
+++ b/src/main/java/net/dv8tion/jda/api/JDAInfo.java
@@ -20,7 +20,7 @@
*/
public class JDAInfo
{
- public static final int DISCORD_GATEWAY_VERSION = 10;
+ public static final int DISCORD_GATEWAY_VERSION = 9;
public static final int DISCORD_REST_VERSION = 10;
public static final int AUDIO_GATEWAY_VERSION = 4;
public static final String GITHUB = "https://github.com/DV8FromTheWorld/JDA";
diff --git a/src/main/java/net/dv8tion/jda/api/MessageBuilder.java b/src/main/java/net/dv8tion/jda/api/MessageBuilder.java
deleted file mode 100644
index ac2d79d653..0000000000
--- a/src/main/java/net/dv8tion/jda/api/MessageBuilder.java
+++ /dev/null
@@ -1,1281 +0,0 @@
-/*
- * 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;
-
-import net.dv8tion.jda.api.entities.*;
-import net.dv8tion.jda.api.entities.sticker.Sticker;
-import net.dv8tion.jda.api.entities.sticker.StickerSnowflake;
-import net.dv8tion.jda.api.interactions.components.ActionRow;
-import net.dv8tion.jda.api.interactions.components.LayoutComponent;
-import net.dv8tion.jda.api.requests.restaction.MessageAction;
-import net.dv8tion.jda.internal.entities.DataMessage;
-import net.dv8tion.jda.internal.utils.Checks;
-import net.dv8tion.jda.internal.utils.Helpers;
-
-import javax.annotation.Nonnull;
-import javax.annotation.Nullable;
-import java.util.*;
-import java.util.stream.Collectors;
-
-/**
- * Builder system used to build {@link net.dv8tion.jda.api.entities.Message Messages}.
- * Internally the builder uses a {@link java.lang.StringBuilder} to take advantage of the efficiencies offered by the
- * StringBuilder, and the methods provided by this class are a combination of those offered by the StringBuilder and
- * {@link String#format(String, Object...)}.
- *
- * @since 1.0
- * @author Michael Ritter
- * @author Aljoscha Grebe
- */
-public class MessageBuilder implements Appendable
-{
- protected final StringBuilder builder = new StringBuilder();
-
- protected final List embeds = new ArrayList<>();
- protected final List components = new ArrayList<>();
- protected final List stickers = new ArrayList<>();
- protected boolean isTTS = false;
- protected String nonce;
- protected EnumSet allowedMentions = null;
- protected Set mentionedUsers = new HashSet<>();
- protected Set mentionedRoles = new HashSet<>();
-
- public MessageBuilder() {}
-
- public MessageBuilder(@Nullable CharSequence content)
- {
- if (content != null)
- builder.append(content);
- }
-
- public MessageBuilder(@Nullable Message message)
- {
- if (message != null)
- {
- isTTS = message.isTTS();
- builder.append(message.getContentRaw());
- List embeds = message.getEmbeds();
- if (embeds != null)
- embeds.stream().filter(it -> it.getType() == EmbedType.RICH).forEach(this.embeds::add);
- components.addAll(message.getActionRows());
- if (message instanceof DataMessage)
- {
- DataMessage data = (DataMessage) message;
- if (data.getAllowedMentions() != null)
- this.allowedMentions = Helpers.copyEnumSet(Message.MentionType.class, data.getAllowedMentions());
- Collections.addAll(this.mentionedUsers, data.getMentionedUsersWhitelist());
- Collections.addAll(this.mentionedRoles, data.getMentionedRolesWhitelist());
- stickers.addAll(data.getStickerSnowflakes());
- }
- else
- {
- stickers.addAll(message.getStickers().stream()
- .map(Sticker::getId)
- .map(Sticker::fromId)
- .collect(Collectors.toList()));
- }
- }
- }
-
- public MessageBuilder(@Nullable MessageBuilder builder)
- {
- if (builder != null)
- {
- this.isTTS = builder.isTTS;
- this.builder.append(builder.builder);
- this.nonce = builder.nonce;
- this.embeds.addAll(builder.embeds);
- this.components.addAll(builder.components);
- this.stickers.addAll(builder.stickers);
- if (builder.allowedMentions != null)
- this.allowedMentions = Helpers.copyEnumSet(Message.MentionType.class, builder.allowedMentions);
- this.mentionedRoles.addAll(builder.mentionedRoles);
- this.mentionedUsers.addAll(builder.mentionedUsers);
- }
- }
-
- public MessageBuilder(@Nullable EmbedBuilder builder)
- {
- if (builder != null)
- this.embeds.add(builder.build());
- }
-
- public MessageBuilder(@Nullable MessageEmbed embed)
- {
- if (embed != null)
- this.embeds.add(embed);
- }
-
- /**
- * Makes the created Message a TTS message.
- * TTS stands for Text-To-Speech. When a TTS method is received by the Discord client,
- * it is vocalized so long as the user has not disabled TTS.
- *
- * @param tts
- * whether the created Message should be a tts message
- *
- * @return The MessageBuilder instance. Useful for chaining.
- */
- @Nonnull
- public MessageBuilder setTTS(boolean tts)
- {
- this.isTTS = tts;
- return this;
- }
-
- /**
- * Adds up to {@value Message#MAX_EMBED_COUNT} {@link net.dv8tion.jda.api.entities.MessageEmbed MessageEmbeds} to the Message. Embeds can be built using
- * the {@link net.dv8tion.jda.api.EmbedBuilder} and offer specialized formatting.
- *
- * @param embeds
- * the embeds to add, or empty array to remove
- *
- * @throws java.lang.IllegalArgumentException
- * If any of the provided MessageEmbeds is null or not sendable according to {@link net.dv8tion.jda.api.entities.MessageEmbed#isSendable() MessageEmbed.isSendable()}!
- * The sum of all {@link MessageEmbed#getLength()} must not be greater than {@link MessageEmbed#EMBED_MAX_LENGTH_BOT}!
- *
- * @return The MessageBuilder instance. Useful for chaining.
- */
- @Nonnull
- public MessageBuilder setEmbeds(@Nonnull MessageEmbed... embeds)
- {
- Checks.noneNull(embeds, "MessageEmbeds");
- return setEmbeds(Arrays.asList(embeds));
- }
-
- /**
- * Adds up to {@value Message#MAX_EMBED_COUNT} {@link net.dv8tion.jda.api.entities.MessageEmbed MessageEmbeds} to the Message. Embeds can be built using
- * the {@link net.dv8tion.jda.api.EmbedBuilder} and offer specialized formatting.
- *
- * @param embeds
- * the embeds to add, or empty list to remove
- *
- * @throws java.lang.IllegalArgumentException
- * If any of the provided MessageEmbeds is null or not sendable according to {@link net.dv8tion.jda.api.entities.MessageEmbed#isSendable() MessageEmbed.isSendable()}!
- * The sum of all {@link MessageEmbed#getLength()} must not be greater than {@link MessageEmbed#EMBED_MAX_LENGTH_BOT}!
- *
- * @return The MessageBuilder instance. Useful for chaining.
- */
- @Nonnull
- public MessageBuilder setEmbeds(@Nonnull Collection extends MessageEmbed> embeds)
- {
-
- Checks.noneNull(embeds, "MessageEmbeds");
- embeds.forEach(embed ->
- Checks.check(embed.isSendable(),
- "Provided Message contains an empty embed or an embed with a length greater than %d characters, which is the max for bot accounts!",
- MessageEmbed.EMBED_MAX_LENGTH_BOT)
- );
- Checks.check(embeds.size() <= Message.MAX_EMBED_COUNT, "Cannot have more than %d embeds in a message!", Message.MAX_EMBED_COUNT);
- Checks.check(embeds.stream().mapToInt(MessageEmbed::getLength).sum() <= MessageEmbed.EMBED_MAX_LENGTH_BOT, "The sum of all MessageEmbeds may not exceed %d!", MessageEmbed.EMBED_MAX_LENGTH_BOT);
- this.embeds.clear();
- this.embeds.addAll(embeds);
- return this;
- }
-
- /**
- * Set the action rows for the message.
- *
- * @param rows
- * The new action rows, or null to reset the components
- *
- * @throws IllegalArgumentException
- * If null is provided in the collection or more than 5 actions rows are provided
- *
- * @return The MessageBuilder instance. Useful for chaining.
- */
- @Nonnull
- public MessageBuilder setActionRows(@Nullable Collection extends ActionRow> rows)
- {
- if (rows == null)
- {
- this.components.clear();
- return this;
- }
- Checks.noneNull(rows, "ActionRows");
- Checks.check(rows.size() <= 5, "Can only have 5 action rows per message!");
- this.components.clear();
- this.components.addAll(rows);
- return this;
- }
-
- /**
- * Set the action rows for the message.
- *
- * @param rows
- * The new action rows, or null to reset the components
- *
- * @throws IllegalArgumentException
- * If null is provided in the array or more than 5 actions rows are provided
- *
- * @return The MessageBuilder instance. Useful for chaining.
- */
- @Nonnull
- public MessageBuilder setActionRows(@Nullable ActionRow... rows)
- {
- if (rows == null)
- {
- this.components.clear();
- return this;
- }
- return setActionRows(Arrays.asList(rows));
- }
-
- /**
- * Set the stickers to send alongside this message.
- * This is not supported for message edits.
- *
- * @param stickers
- * The stickers to send, or null to not send any stickers
- *
- * @throws IllegalArgumentException
- * If more than {@value Message#MAX_STICKER_COUNT} stickers or null stickers are provided
- *
- * @return The MessageBuilder instance. Useful for chaining.
- *
- * @see Sticker#fromId(long)
- */
- @Nonnull
- public MessageBuilder setStickers(@Nullable Collection extends StickerSnowflake> stickers)
- {
- this.stickers.clear();
- if (stickers == null || stickers.isEmpty())
- return this;
- Checks.noneNull(stickers, "Stickers");
- Checks.check(stickers.size() <= Message.MAX_STICKER_COUNT,
- "Cannot send more than %d stickers in a message!", Message.MAX_STICKER_COUNT);
-
- stickers.stream()
- .map(StickerSnowflake::getId)
- .map(StickerSnowflake::fromId)
- .forEach(this.stickers::add);
- return this;
- }
-
- /**
- * Set the stickers to send alongside this message.
- * This is not supported for message edits.
- *
- * @param stickers
- * The stickers to send, or null to not send any stickers
- *
- * @throws IllegalArgumentException
- * If more than {@value Message#MAX_STICKER_COUNT} stickers or null stickers are provided
- *
- * @return The MessageBuilder instance. Useful for chaining.
- *
- * @see Sticker#fromId(long)
- */
- @Nonnull
- public MessageBuilder setStickers(@Nullable StickerSnowflake... stickers)
- {
- if (stickers != null)
- Checks.noneNull(stickers, "Stickers");
- return setStickers(stickers == null ? null : Arrays.asList(stickers));
- }
-
- /**
- * Sets the nonce
- * of the built message(s). It is recommended to have only 100% unique strings to validate messages via this nonce.
- * The nonce will be available from the resulting message via {@link net.dv8tion.jda.api.entities.Message#getNonce() Message.getNonce()}
- * in message received by events and RestAction responses.
- * When {@code null} is provided no nonce will be used.
- *
- * @param nonce
- * Validation nonce string
- *
- * @return The MessageBuilder instance. Useful for chaining.
- *
- * @see net.dv8tion.jda.api.entities.Message#getNonce()
- * @see Cryptographic Nonce - Wikipedia
- */
- @Nonnull
- public MessageBuilder setNonce(@Nullable String nonce)
- {
- this.nonce = nonce;
- return this;
- }
-
- /**
- * Sets the content of the resulting Message
- * This will replace already added content.
- *
- * @param content
- * The content to use, or {@code null} to reset the content
- *
- * @return The MessageBuilder instance. Useful for chaining.
- *
- * @see net.dv8tion.jda.api.entities.Message#getContentRaw()
- */
- @Nonnull
- public MessageBuilder setContent(@Nullable String content)
- {
- if (content == null)
- {
- builder.setLength(0);
- }
- else
- {
- final int newLength = Math.max(builder.length(), content.length());
- builder.replace(0, newLength, content);
- }
- return this;
- }
-
- @Nonnull
- @Override
- public MessageBuilder append(@Nullable CharSequence text)
- {
- builder.append(text);
- return this;
- }
-
- @Nonnull
- @Override
- public MessageBuilder append(@Nullable CharSequence text, int start, int end)
- {
- builder.append(text, start, end);
- return this;
- }
-
- @Nonnull
- @Override
- public MessageBuilder append(char c)
- {
- builder.append(c);
- return this;
- }
-
- /**
- * Appends the string representation of an object to the Message.
- * This is the same as {@link #append(CharSequence) append(String.valueOf(object))}
- *
- * @param object
- * the object to append
- *
- * @return The MessageBuilder instance. Useful for chaining.
- */
- @Nonnull
- public MessageBuilder append(@Nullable Object object)
- {
- return append(String.valueOf(object));
- }
-
- /**
- * Appends a mention to the Message.
- * Typical usage would be providing an {@link net.dv8tion.jda.api.entities.IMentionable IMentionable} like
- * {@link net.dv8tion.jda.api.entities.User User} or {@link net.dv8tion.jda.api.entities.TextChannel TextChannel}.
- *
- * This will not add a rule to mention a {@link User} or {@link Role}. You have to use {@link #mention(IMentionable...)}
- * in addition to this method.
- *
- * @param mention
- * the mention to append
- *
- * @throws java.lang.IllegalArgumentException
- * If provided with null
- *
- * @return The MessageBuilder instance. Useful for chaining.
- */
- @Nonnull
- public MessageBuilder append(@Nonnull IMentionable mention)
- {
- Checks.notNull(mention, "Mentionable");
- builder.append(mention.getAsMention());
- return this;
- }
-
- /**
- * Appends a String using the specified chat {@link net.dv8tion.jda.api.MessageBuilder.Formatting Formatting(s)}.
- *
- * @param text
- * the text to append.
- * @param format
- * the format(s) to apply to the text.
- *
- * @return The MessageBuilder instance. Useful for chaining.
- */
- @Nonnull
- public MessageBuilder append(@Nullable CharSequence text, @Nonnull Formatting... format)
- {
- boolean blockPresent = false;
- for (Formatting formatting : format)
- {
- if (formatting == Formatting.BLOCK)
- {
- blockPresent = true;
- continue;
- }
- builder.append(formatting.getTag());
- }
- if (blockPresent)
- builder.append(Formatting.BLOCK.getTag());
-
- builder.append(text);
-
- if (blockPresent)
- builder.append(Formatting.BLOCK.getTag());
- for (int i = format.length - 1; i >= 0; i--)
- {
- if (format[i] == Formatting.BLOCK) continue;
- builder.append(format[i].getTag());
- }
- return this;
- }
-
- /**
- * This method is an extended form of {@link String#format(String, Object...)}. It allows for all of
- * the token replacement functionality that String.format(String, Object...) supports.
- * A lot of JDA entities implement {@link java.util.Formattable Formattable} and will provide
- * specific format outputs for their specific type.
- *
- * {@link net.dv8tion.jda.api.entities.IMentionable IMentionable}
- * These will output their {@link net.dv8tion.jda.api.entities.IMentionable#getAsMention() getAsMention} by default,
- * some implementations have alternatives such as {@link net.dv8tion.jda.api.entities.User User} and {@link net.dv8tion.jda.api.entities.TextChannel TextChannel}.
- * {@link net.dv8tion.jda.api.entities.MessageChannel MessageChannel}
- * All message channels format to {@code "#" + getName()} by default, TextChannel has special handling
- * and uses the getAsMention output by default and the MessageChannel output as alternative ({@code #} flag).
- * {@link net.dv8tion.jda.api.entities.Message Message}
- * Messages by default output their {@link net.dv8tion.jda.api.entities.Message#getContentDisplay() getContentDisplay()} value and
- * as alternative use the {@link net.dv8tion.jda.api.entities.Message#getContentRaw() getContentRaw()} value
- *
- *
- * Example:
- * If you placed the following code in an method handling a
- * {@link net.dv8tion.jda.api.events.message.MessageReceivedEvent MessageReceivedEvent}
- *
{@code
- * User user = event.getAuthor();
- * MessageBuilder builder = new MessageBuilder();
- * builder.appendFormat("%#s is really cool!", user);
- * builder.build();
- * }
- *
- * It would build a message that mentions the author and says that he is really cool!. If the user's
- * name was "Minn" and his discriminator "6688", it would say:
- * "Minn#6688 is really cool!"
- * Note that this uses the {@code #} flag to utilize the alternative format for {@link net.dv8tion.jda.api.entities.User User}.
- * By default it would fallback to {@link net.dv8tion.jda.api.entities.IMentionable#getAsMention()}
- *
- * @param format
- * a format string.
- * @param args
- * an array objects that will be used to replace the tokens, they must be
- * provided in the order that the tokens appear in the provided format string.
- *
- * @throws java.lang.IllegalArgumentException
- * If the provided format string is {@code null} or empty
- * @throws java.util.IllegalFormatException
- * If a format string contains an illegal syntax,
- * a format specifier that is incompatible with the given arguments,
- * insufficient arguments given the format string, or other illegal conditions.
- * For specification of all possible formatting errors,
- * see the Details
- * section of the formatter class specification.
- *
- * @return The MessageBuilder instance. Useful for chaining.
- */
- @Nonnull
- public MessageBuilder appendFormat(@Nonnull String format, @Nonnull Object... args)
- {
- Checks.notEmpty(format, "Format String");
- this.append(String.format(format, args));
- return this;
- }
-
- /**
- * Appends a code-line to the Message.
- * Code Lines are similar to code-blocks, however they are displayed in-line and do not support language specific highlighting.
- *
- * @param text
- * the code to append
- *
- * @return The MessageBuilder instance. Useful for chaining.
- */
- @Nonnull
- public MessageBuilder appendCodeLine(@Nullable CharSequence text)
- {
- this.append(text, Formatting.BLOCK);
- return this;
- }
-
- /**
- * Appends a code-block to the Message.
- * Discord uses Highlight.js for its language highlighting support. You can find out what
- * specific languages are supported here .
- *
- * @param text
- * the code to append
- * @param language
- * the language of the code. If unknown use an empty string
- *
- * @return The MessageBuilder instance. Useful for chaining.
- */
- @Nonnull
- public MessageBuilder appendCodeBlock(@Nullable CharSequence text, @Nullable CharSequence language)
- {
- builder.append("```").append(language).append('\n').append(text).append("\n```");
- return this;
- }
-
- /**
- * Returns the current length of the content that will be built into a {@link net.dv8tion.jda.api.entities.Message Message}
- * when {@link #build()} is called.
- * If this value is {@code 0} (and there is no embed) or greater than {@code 2000} when {@link #build()} is called, an exception
- * will be raised as you cannot send an empty message to Discord and Discord has a hard limit of 2000 characters per message.
- *
- * Hint: You can use {@link #build(int, int)} or
- * {@link #buildAll(net.dv8tion.jda.api.MessageBuilder.SplitPolicy...) buildAll(SplitPolicy...)} as possible ways to
- * deal with the 2000 character cap.
- *
- * @return the current length of the content that will be built into a Message.
- */
- public int length()
- {
- return builder.length();
- }
-
- /**
- * Checks if the message contains any contend. This includes text as well as embeds.
- *
- * @return whether the message contains content
- */
- public boolean isEmpty() {
- return builder.length() == 0 && embeds.isEmpty();
- }
-
- /**
- * Replaces each substring that matches the target string with the specified replacement string.
- * The replacement proceeds from the beginning of the string to the end, for example, replacing
- * "aa" with "b" in the message "aaa" will result in "ba" rather than "ab".
- *
- * @param target
- * the sequence of char values to be replaced
- * @param replacement
- * the replacement sequence of char values
- *
- * @return The MessageBuilder instance. Useful for chaining.
- */
- @Nonnull
- public MessageBuilder replace(@Nonnull String target, @Nonnull String replacement)
- {
- int index = builder.indexOf(target);
- while (index != -1)
- {
- builder.replace(index, index + target.length(), replacement);
- index = builder.indexOf(target, index + replacement.length());
- }
- return this;
- }
-
- /**
- * Replaces the first substring that matches the target string with the specified replacement string.
- *
- * @param target
- * the sequence of char values to be replaced
- * @param replacement
- * the replacement sequence of char values
- *
- * @return The MessageBuilder instance. Useful for chaining.
- */
- @Nonnull
- public MessageBuilder replaceFirst(@Nonnull String target, @Nonnull String replacement)
- {
- int index = builder.indexOf(target);
- if (index != -1)
- {
- builder.replace(index, index + target.length(), replacement);
- }
- return this;
- }
-
- /**
- * Replaces the last substring that matches the target string with the specified replacement string.
- *
- * @param target
- * the sequence of char values to be replaced
- * @param replacement
- * the replacement sequence of char values
- *
- * @return The MessageBuilder instance. Useful for chaining.
- */
- @Nonnull
- public MessageBuilder replaceLast(@Nonnull String target, @Nonnull String replacement)
- {
- int index = builder.lastIndexOf(target);
- if (index != -1)
- {
- builder.replace(index, index + target.length(), replacement);
- }
- return this;
- }
-
- /**
- * Removes the whitelist of mentioned users.
- * If {@link #setAllowedMentions(Collection)} does not contain {@link net.dv8tion.jda.api.entities.Message.MentionType#USER MentionType.USER}
- * then no user will be mentioned.
- *
- * @return The MessageBuilder instance. Useful for chaining.
- */
- @Nonnull
- public MessageBuilder clearMentionedUsers()
- {
- mentionedUsers.clear();
- return this;
- }
-
- /**
- * Removes the whitelist of mentioned roles.
- * If {@link #setAllowedMentions(Collection)} does not contain {@link net.dv8tion.jda.api.entities.Message.MentionType#ROLE MentionType.ROLE}
- * then no role will be mentioned.
- *
- * @return The MessageBuilder instance. Useful for chaining.
- */
- @Nonnull
- public MessageBuilder clearMentionedRoles()
- {
- mentionedRoles.clear();
- return this;
- }
-
- /**
- * Combination of {@link #clearMentionedRoles()} and {@link #clearMentionedUsers()}.
- *
- *
This will not affect {@link #setAllowedMentions(Collection)}. You can reset those to default
- * by using {@code setAllowedMentions(null)}.
- *
- * @return The MessageBuilder instance. Useful for chaining.
- */
- @Nonnull
- public MessageBuilder clearMentions()
- {
- return clearMentionedUsers().clearMentionedRoles();
- }
-
- /**
- * Sets which {@link net.dv8tion.jda.api.entities.Message.MentionType MentionTypes} should be parsed from
- * the input. This will use {@link MessageAction#getDefaultMentions()} by default, or if {@code null} is provided.
- *
- * @param mentionTypes
- * Collection of allowed mention types, or null to use {@link MessageAction#getDefaultMentions()}.
- *
- * @return The MessageBuilder instance. Useful for chaining.
- */
- @Nonnull
- public MessageBuilder setAllowedMentions(@Nullable Collection mentionTypes)
- {
- this.allowedMentions = mentionTypes == null
- ? MessageAction.getDefaultMentions()
- : Helpers.copyEnumSet(Message.MentionType.class, mentionTypes);
- return this;
- }
-
- /**
- * Adds the provided {@link net.dv8tion.jda.api.entities.Message.MentionType MentionTypes} to the whitelist.
- *
- * @param types
- * The mention types to allow
- *
- * @throws IllegalArgumentException
- * If null is provided
- *
- * @return The MessageBuilder instance. Useful for chaining.
- */
- @Nonnull
- public MessageBuilder allowMentions(@Nonnull Message.MentionType... types)
- {
- Checks.noneNull(types, "MentionTypes");
- if (types.length > 0)
- {
- if (allowedMentions == null)
- allowedMentions = MessageAction.getDefaultMentions();
- Collections.addAll(allowedMentions, types);
- }
- return this;
- }
-
- /**
- * Removes the provided {@link net.dv8tion.jda.api.entities.Message.MentionType MentionTypes} from the whitelist.
- *
- * @param types
- * The mention types to deny
- *
- * @throws IllegalArgumentException
- * If null is provided
- *
- * @return The MessageBuilder instance. Useful for chaining.
- */
- @Nonnull
- public MessageBuilder denyMentions(@Nonnull Message.MentionType... types)
- {
- Checks.noneNull(types, "MentionTypes");
- if (types.length > 0)
- {
- if (allowedMentions == null)
- allowedMentions = MessageAction.getDefaultMentions();
- for (Message.MentionType type : types)
- allowedMentions.remove(type);
- }
- return this;
- }
-
- /**
- * Adds the provided {@link IMentionable IMentionable} instance to the whitelist of mentions.
- * This will only affect instances of {@link User}, {@link Member}, and {@link Role}.
- * The content will not be affected by this. To append a mention use {@link #append(IMentionable)}.
- *
- * See {@link MessageAction#mention(IMentionable...)} for more details.
- *
- * @param mentions
- * Whitelist of mentions to apply
- *
- * @throws IllegalArgumentException
- * If null is provided
- *
- * @return The MessageBuilder instance. Useful for chaining.
- *
- * @see #clearMentions()
- * @see MessageAction#mention(IMentionable...)
- */
- @Nonnull
- public MessageBuilder mention(@Nonnull IMentionable... mentions)
- {
- Checks.noneNull(mentions, "Mentions");
-
- for (IMentionable mention : mentions)
- {
- if (mention instanceof User || mention instanceof Member)
- mentionedUsers.add(mention.getId());
- else if (mention instanceof Role)
- mentionedRoles.add(mention.getId());
- }
- return this;
- }
-
- /**
- * Adds the provided {@link IMentionable IMentionable} instance to the whitelist of mentions.
- * This will only affect instances of {@link User}, {@link Member}, and {@link Role}.
- * The content will not be affected by this. To append a mention use {@link #append(IMentionable)}.
- *
- *
See {@link MessageAction#mention(IMentionable...)} for more details.
- *
- * @param mentions
- * Whitelist of mentions to apply
- *
- * @throws IllegalArgumentException
- * If null is provided
- *
- * @return The MessageBuilder instance. Useful for chaining.
- *
- * @see #clearMentions()
- * @see MessageAction#mention(IMentionable...)
- */
- @Nonnull
- public MessageBuilder mention(@Nonnull Collection extends IMentionable> mentions)
- {
- Checks.noneNull(mentions, "Mentions");
- return mention(mentions.toArray(new IMentionable[0]));
- }
-
- /**
- * Adds the provided {@link User Users} to the whitelist of mentions.
- * The provided list must only contain IDs of users.
- * The content will not be affected by this.
- * To append a mention use {@code append("<@").append(id).append(">")}.
- *
- *
See {@link MessageAction#mentionUsers(String...)} for more details.
- *
- * @param users
- * Whitelist of user IDs to apply
- *
- * @throws IllegalArgumentException
- * If null is provided
- *
- * @return The MessageBuilder instance. Useful for chaining.
- *
- * @see #clearMentionedUsers()
- * @see MessageAction#mentionUsers(String...)
- */
- @Nonnull
- public MessageBuilder mentionUsers(@Nonnull String... users)
- {
- Checks.noneNull(users, "Users");
- Collections.addAll(mentionedUsers, users);
- return this;
- }
-
- /**
- * Adds the provided {@link Role Roles} to the whitelist of mentions.
- * The provided list must only contain IDs of roles.
- * The content will not be affected by this.
- * To append a mention use {@code append("<@&").append(id).append(">")}.
- *
- *
See {@link MessageAction#mentionRoles(String...)} for more details.
- *
- * @param roles
- * Whitelist of role IDs to apply
- *
- * @throws IllegalArgumentException
- * If null is provided
- *
- * @return The MessageBuilder instance. Useful for chaining.
- *
- * @see #clearMentionedRoles()
- * @see MessageAction#mentionRoles(String...)
- */
- @Nonnull
- public MessageBuilder mentionRoles(@Nonnull String... roles)
- {
- Checks.noneNull(roles, "Roles");
- Collections.addAll(mentionedRoles, roles);
- return this;
- }
-
- /**
- * Adds the provided {@link User Users} to the whitelist of mentions.
- * The provided list must only contain IDs of users.
- * The content will not be affected by this.
- * To append a mention use {@code append("<@").append(id).append(">")}.
- *
- *
See {@link MessageAction#mentionUsers(long...)} for more details.
- *
- * @param users
- * Whitelist of user IDs to apply
- *
- * @throws IllegalArgumentException
- * If null is provided
- *
- * @return The MessageBuilder instance. Useful for chaining.
- *
- * @see #clearMentionedUsers()
- * @see MessageAction#mentionUsers(long...)
- */
- @Nonnull
- public MessageBuilder mentionUsers(@Nonnull long... users)
- {
- Checks.notNull(users, "Users");
- return mentionUsers(toStringArray(users));
- }
-
- /**
- * Adds the provided {@link Role Roles} to the whitelist of mentions.
- * The provided list must only contain IDs of roles.
- * The content will not be affected by this.
- * To append a mention use {@code append("<@&").append(id).append(">")}.
- *
- *
See {@link MessageAction#mentionRoles(long...)} for more details.
- *
- * @param roles
- * Whitelist of role IDs to apply
- *
- * @throws IllegalArgumentException
- * If null is provided
- *
- * @return The MessageBuilder instance. Useful for chaining.
- *
- * @see #clearMentionedRoles()
- * @see MessageAction#mentionRoles(long...)
- */
- @Nonnull
- public MessageBuilder mentionRoles(@Nonnull long... roles)
- {
- Checks.notNull(roles, "Roles");
- return mentionRoles(toStringArray(roles));
- }
-
- /**
- * Returns the underlying {@link StringBuilder}.
- *
- * @return The {@link StringBuilder} used by this {@link MessageBuilder}
- */
- @Nonnull
- public StringBuilder getStringBuilder()
- {
- return this.builder;
- }
-
- /**
- * Clears the current builder. Useful for mass message creation.
- *
- *
This will not clear the allowed mentions.
- *
- * @return The MessageBuilder instance. Useful for chaining.
- */
- @Nonnull
- public MessageBuilder clear() {
- this.builder.setLength(0);
- this.embeds.clear();
- this.isTTS = false;
- return this;
- }
-
- /**
- * Returns the index within this string of the first occurrence of the
- * specified substring between the specified indices.
- *
- *
If no such value of {@code target} exists, then {@code -1} is returned.
- *
- * @param target
- * the substring to search for.
- * @param fromIndex
- * the index from which to start the search.
- * @param endIndex
- * the index at which to end the search.
- *
- * @throws java.lang.IndexOutOfBoundsException
- *
- * If the {@code fromIndex} is outside of the range of {@code 0} to {@link #length()}
- * If the {@code endIndex} is outside of the range of {@code 0} to {@link #length()}
- * If the {@code fromIndex} is greater than {@code endIndex}
- *
- *
- * @return the index of the first occurrence of the specified substring between
- * the specified indices or {@code -1} if there is no such occurrence.
- */
- public int indexOf(@Nonnull CharSequence target, int fromIndex, int endIndex)
- {
- if (fromIndex < 0)
- throw new IndexOutOfBoundsException("index out of range: " + fromIndex);
- if (endIndex < 0)
- throw new IndexOutOfBoundsException("index out of range: " + endIndex);
- if (fromIndex > length())
- throw new IndexOutOfBoundsException("fromIndex > length()");
- if (fromIndex > endIndex)
- throw new IndexOutOfBoundsException("fromIndex > endIndex");
-
- if (endIndex >= builder.length())
- {
- endIndex = builder.length() - 1;
- }
-
- int targetCount = target.length();
- if (targetCount == 0)
- {
- return fromIndex;
- }
-
- char strFirstChar = target.charAt(0);
- int max = endIndex + targetCount - 1;
-
- lastCharSearch:
- for (int i = fromIndex; i <= max; i++)
- {
- if (builder.charAt(i) == strFirstChar)
- {
- for (int j = 1; j < targetCount; j++)
- {
- if (builder.charAt(i + j) != target.charAt(j))
- {
- continue lastCharSearch;
- }
- }
- return i;
- }
- }
- return -1;
- }
-
- /**
- * Returns the index within this string of the last occurrence of the
- * specified substring between the specified indices.
- *
- * If no such value of {@code target} exists, then {@code -1} is returned.
- *
- * @param target
- * the substring to search for.
- * @param fromIndex
- * the index from which to start the search.
- * @param endIndex
- * the index at which to end the search.
- *
- * @throws java.lang.IndexOutOfBoundsException
- *
- * If the {@code fromIndex} is outside of the range of {@code 0} to {@link #length()}
- * If the {@code endIndex} is outside of the range of {@code 0} to {@link #length()}
- * If the {@code fromIndex} is greater than {@code endIndex}
- *
- *
- * @return the index of the last occurrence of the specified substring between
- * the specified indices or {@code -1} if there is no such occurrence.
- */
- public int lastIndexOf(@Nonnull CharSequence target, int fromIndex, int endIndex)
- {
- if (fromIndex < 0)
- throw new IndexOutOfBoundsException("index out of range: " + fromIndex);
- if (endIndex < 0)
- throw new IndexOutOfBoundsException("index out of range: " + endIndex);
- if (fromIndex > length())
- throw new IndexOutOfBoundsException("fromIndex > length()");
- if (fromIndex > endIndex)
- throw new IndexOutOfBoundsException("fromIndex > endIndex");
-
- if (endIndex >= builder.length())
- {
- endIndex = builder.length() - 1;
- }
-
- int targetCount = target.length();
- if (targetCount == 0)
- {
- return endIndex;
- }
-
- int rightIndex = endIndex - targetCount;
-
- if (fromIndex > rightIndex)
- {
- fromIndex = rightIndex;
- }
-
- int strLastIndex = targetCount - 1;
- char strLastChar = target.charAt(strLastIndex);
-
- int min = fromIndex + targetCount - 1;
-
- lastCharSearch:
- for (int i = endIndex; i >= min; i--)
- {
- if (builder.charAt(i) == strLastChar)
- {
- for (int j = strLastIndex - 1, k = 1; j >= 0; j--, k++)
- {
- if (builder.charAt(i - k) != target.charAt(j))
- {
- continue lastCharSearch;
- }
- }
- return i - target.length() + 1;
- }
- }
- return -1;
- }
-
- /**
- * Creates a {@link net.dv8tion.jda.api.entities.Message Message} object from this MessageBuilder
- *
- * Hint: You can use {@link #build(int, int)} or
- * {@link #buildAll(net.dv8tion.jda.api.MessageBuilder.SplitPolicy...) buildAll(SplitPolicy...)} as possible ways to
- * deal with the 2000 character cap.
- *
- * @throws java.lang.IllegalStateException
- *
- * If you attempt to build() an empty Message ({@link #length()} is {@code 0} and no
- * {@link net.dv8tion.jda.api.entities.MessageEmbed} was provided to {@link #setEmbeds(MessageEmbed...)}
- * If you attempt to build() a Message with more than 2000 characters of content.
- *
- *
- * @return the created {@link net.dv8tion.jda.api.entities.Message Message}
- */
- @Nonnull
- public Message build()
- {
- String message = builder.toString();
- if (this.isEmpty())
- throw new IllegalStateException("Cannot build a Message with no content. (You never added any content to the message)");
- if (message.length() > Message.MAX_CONTENT_LENGTH)
- throw new IllegalStateException("Cannot build a Message with more than " + Message.MAX_CONTENT_LENGTH + " characters. Please limit your input.");
-
- String[] ids = new String[0];
- return new DataMessage(isTTS, message, nonce, embeds,
- allowedMentions, mentionedUsers.toArray(ids), mentionedRoles.toArray(ids),
- components.toArray(new LayoutComponent[0]),
- new ArrayList<>(stickers));
- }
-
- /**
- * Creates a {@link java.util.Queue Queue} of {@link net.dv8tion.jda.api.entities.Message Message} objects from this MessageBuilder.
- *
- * This method splits the content if it exceeds 2000 chars. The splitting behaviour can be customized using {@link SplitPolicy SplitPolicies}.
- * The method will try the policies in the order they are passed to it.
- * If no SplitPolicy is provided each message will be split after exactly 2000 chars.
- *
- *
This is not Markdown safe. An easy workaround is to include Zero Width Spaces
- * as predetermined breaking points to the message and only split on them.
- *
- * @param policy
- * The {@link net.dv8tion.jda.api.MessageBuilder.SplitPolicy} defining how to split the text in the
- * MessageBuilder into different, individual messages.
- *
- * @return the created {@link net.dv8tion.jda.api.entities.Message Messages}
- */
- @Nonnull
- public Queue buildAll(@Nullable SplitPolicy... policy)
- {
- if (this.isEmpty())
- throw new UnsupportedOperationException("Cannot build a Message with no content. (You never added any content to the message)");
-
- LinkedList messages = new LinkedList<>();
-
- if (builder.length() <= Message.MAX_CONTENT_LENGTH)
- {
- messages.add(this.build());
- return messages;
- }
-
- if (policy == null || policy.length == 0)
- policy = new SplitPolicy[]{ SplitPolicy.ANYWHERE };
-
- int currentBeginIndex = 0;
-
- messageLoop:
- while (currentBeginIndex < builder.length() - Message.MAX_CONTENT_LENGTH)
- {
- for (SplitPolicy splitPolicy : policy)
- {
- int currentEndIndex = splitPolicy.nextMessage(currentBeginIndex, this);
- if (currentEndIndex != -1)
- {
- messages.add(build(currentBeginIndex, currentEndIndex));
- currentBeginIndex = currentEndIndex;
- continue messageLoop;
- }
- }
- throw new IllegalStateException("Failed to split the messages");
- }
-
- if (currentBeginIndex < builder.length())
- messages.add(build(currentBeginIndex, builder.length()));
-
- if (!this.embeds.isEmpty())
- ((DataMessage) messages.get(messages.size() - 1)).setEmbeds(embeds);
-
- return messages;
- }
-
- @Nonnull
- protected DataMessage build(int beginIndex, int endIndex)
- {
- String[] ids = new String[0];
- return new DataMessage(isTTS, builder.substring(beginIndex, endIndex), null, null,
- allowedMentions, mentionedUsers.toArray(ids), mentionedRoles.toArray(ids),
- components.toArray(new LayoutComponent[0]),
- new ArrayList<>(stickers));
- }
-
- private String[] toStringArray(long[] users)
- {
- String[] ids = new String[users.length];
- for (int i = 0; i < ids.length; i++)
- ids[i] = Long.toUnsignedString(users[i]);
- return ids;
- }
-
- /**
- * Interface to allow custom implementation of Splitting rules for
- * {@link #buildAll(net.dv8tion.jda.api.MessageBuilder.SplitPolicy...) MessageBuilder.buildAll(SplitPolicy...)}.
- */
- public interface SplitPolicy
- {
- /**
- * Splits on newline chars {@code `\n`}.
- */
- SplitPolicy NEWLINE = new CharSequenceSplitPolicy("\n", true);
-
- /**
- * Splits on space chars {@code `\u0020`}.
- */
- SplitPolicy SPACE = new CharSequenceSplitPolicy(" ", true);
-
- /**
- * Splits exactly after 2000 chars.
- */
- SplitPolicy ANYWHERE = (i, b) -> Math.min(i + Message.MAX_CONTENT_LENGTH, b.length());
-
- /**
- * Creates a new {@link SplitPolicy} splitting on the specified chars.
- *
- * @param chars
- * the chars to split on
- * @param remove
- * whether to remove the chars when splitting on them
- *
- * @return a new {@link SplitPolicy}
- */
- @Nonnull
- static SplitPolicy onChars(@Nonnull CharSequence chars, boolean remove)
- {
- return new CharSequenceSplitPolicy(chars, remove);
- }
-
- /**
- * Default {@link SplitPolicy} implementation. Splits on a specified {@link CharSequence}.
- */
- class CharSequenceSplitPolicy implements SplitPolicy
- {
- private final boolean remove;
- private final CharSequence chars;
-
- private CharSequenceSplitPolicy(@Nonnull final CharSequence chars, final boolean remove)
- {
- this.chars = chars;
- this.remove = remove;
- }
-
- @Override
- public int nextMessage(final int currentBeginIndex, final MessageBuilder builder)
- {
- int currentEndIndex = builder.lastIndexOf(this.chars, currentBeginIndex, currentBeginIndex + 2000 - (this.remove ? this.chars.length() : 0));
- if (currentEndIndex < 0)
- {
- return -1;
- }
- else
- {
- return currentEndIndex + this.chars.length();
- }
- }
- }
-
- /**
- * Calculates the endIndex for the next {@link net.dv8tion.jda.api.entities.Message Message}.
- *
- * @param currentBeginIndex
- * the index the next {@link net.dv8tion.jda.api.entities.Message Message} should start from
- * @param builder
- * the {@link net.dv8tion.jda.api.MessageBuilder MessageBuilder}
- *
- * @return the end Index of the next {@link net.dv8tion.jda.api.entities.Message Message}
- *
- * @throws java.lang.IllegalStateException when splitting fails
- *
- */
- int nextMessage(int currentBeginIndex, MessageBuilder builder);
- }
-
- /**
- * Holds the available formatting used in {@link MessageBuilder#append(java.lang.CharSequence, net.dv8tion.jda.api.MessageBuilder.Formatting...)}
- */
- public enum Formatting
- {
- ITALICS("*"),
- BOLD("**"),
- STRIKETHROUGH("~~"),
- UNDERLINE("__"),
- BLOCK("`");
-
- private final String tag;
-
- Formatting(String tag)
- {
- this.tag = tag;
- }
-
- @Nonnull
- private String getTag()
- {
- return tag;
- }
- }
-}
diff --git a/src/main/java/net/dv8tion/jda/api/entities/GuildMessageChannel.java b/src/main/java/net/dv8tion/jda/api/entities/GuildMessageChannel.java
index baccecaf76..43d7747512 100644
--- a/src/main/java/net/dv8tion/jda/api/entities/GuildMessageChannel.java
+++ b/src/main/java/net/dv8tion/jda/api/entities/GuildMessageChannel.java
@@ -8,7 +8,7 @@
import net.dv8tion.jda.api.exceptions.InsufficientPermissionException;
import net.dv8tion.jda.api.exceptions.MissingAccessException;
import net.dv8tion.jda.api.requests.RestAction;
-import net.dv8tion.jda.api.requests.restaction.MessageAction;
+import net.dv8tion.jda.api.requests.restaction.MessageCreateAction;
import net.dv8tion.jda.internal.utils.Checks;
import javax.annotation.CheckReturnValue;
@@ -423,13 +423,13 @@ default RestAction clearReactionsById(long messageId, @Nonnull Emoji emoji
* If null is provided
*
*
- * @return {@link MessageAction}
+ * @return {@link MessageCreateAction}
*
* @see Sticker#fromId(long)
*/
@Nonnull
@CheckReturnValue
- MessageAction sendStickers(@Nonnull Collection extends StickerSnowflake> stickers);
+ MessageCreateAction sendStickers(@Nonnull Collection extends StickerSnowflake> stickers);
/**
* Send up to 3 stickers in this channel.
@@ -454,13 +454,13 @@ default RestAction clearReactionsById(long messageId, @Nonnull Emoji emoji
* If null is provided
*
*
- * @return {@link MessageAction}
+ * @return {@link MessageCreateAction}
*
* @see Sticker#fromId(long)
*/
@Nonnull
@CheckReturnValue
- default MessageAction sendStickers(@Nonnull StickerSnowflake... stickers)
+ default MessageCreateAction sendStickers(@Nonnull StickerSnowflake... stickers)
{
Checks.notEmpty(stickers, "Stickers");
return sendStickers(Arrays.asList(stickers));
diff --git a/src/main/java/net/dv8tion/jda/api/entities/Message.java b/src/main/java/net/dv8tion/jda/api/entities/Message.java
index e477101bf9..6b9225173a 100644
--- a/src/main/java/net/dv8tion/jda/api/entities/Message.java
+++ b/src/main/java/net/dv8tion/jda/api/entities/Message.java
@@ -18,7 +18,6 @@
import net.dv8tion.jda.annotations.ForRemoval;
import net.dv8tion.jda.annotations.ReplaceWith;
import net.dv8tion.jda.api.JDA;
-import net.dv8tion.jda.api.MessageBuilder;
import net.dv8tion.jda.api.Permission;
import net.dv8tion.jda.api.entities.channel.unions.GuildMessageChannelUnion;
import net.dv8tion.jda.api.entities.channel.unions.MessageChannelUnion;
@@ -36,20 +35,26 @@
import net.dv8tion.jda.api.interactions.components.ActionRow;
import net.dv8tion.jda.api.interactions.components.LayoutComponent;
import net.dv8tion.jda.api.interactions.components.buttons.Button;
-import net.dv8tion.jda.api.interactions.components.selections.SelectMenu;
import net.dv8tion.jda.api.requests.RestAction;
import net.dv8tion.jda.api.requests.restaction.AuditableRestAction;
-import net.dv8tion.jda.api.requests.restaction.MessageAction;
+import net.dv8tion.jda.api.requests.restaction.MessageCreateAction;
+import net.dv8tion.jda.api.requests.restaction.MessageEditAction;
import net.dv8tion.jda.api.requests.restaction.ThreadChannelAction;
import net.dv8tion.jda.api.requests.restaction.pagination.ReactionPaginationAction;
-import net.dv8tion.jda.api.utils.AttachmentOption;
+import net.dv8tion.jda.api.utils.AttachedFile;
import net.dv8tion.jda.api.utils.AttachmentProxy;
+import net.dv8tion.jda.api.utils.FileUpload;
+import net.dv8tion.jda.api.utils.data.DataObject;
+import net.dv8tion.jda.api.utils.messages.MessageCreateData;
+import net.dv8tion.jda.api.utils.messages.MessageEditData;
+import net.dv8tion.jda.api.utils.messages.MessageRequest;
import net.dv8tion.jda.internal.JDAImpl;
import net.dv8tion.jda.internal.entities.ReceivedMessage;
import net.dv8tion.jda.internal.requests.FunctionalCallback;
import net.dv8tion.jda.internal.requests.Requester;
import net.dv8tion.jda.internal.utils.Checks;
import net.dv8tion.jda.internal.utils.IOUtil;
+import okhttp3.MultipartBody;
import okhttp3.OkHttpClient;
import okhttp3.Request;
@@ -72,7 +77,7 @@
* as {@link net.dv8tion.jda.api.events.message.MessageUpdateEvent MessageUpdateEvent} and similar.
*
* Message Differences
- * There are 3 implementations of this interface in JDA.
+ * There are 2 implementations of this interface in JDA.
*
* Received Message
* Messages received through events or history query.
@@ -82,10 +87,6 @@
* Specification of Received Messages that are generated by Discord
* on certain events. Commonly this is used in groups or to indicate a pin within a MessageChannel.
* The different types can be found in the {@link net.dv8tion.jda.api.entities.MessageType MessageType} enum.
- * Data Message
- * This type is produced by {@link MessageBuilder MessageBuilder}
- * and only holds sendable information such as content or nonce. These messages do not allow
- * any modifications via RestActions or information that is generated when sent such as the id to be used.
*
*
* When a feature is not available it will throw an {@link java.lang.UnsupportedOperationException UnsupportedOperationException}
@@ -116,9 +117,6 @@
*
*
More information on formatting syntax can be found in the {@link java.util.Formatter format syntax documentation}!
*
- * @see MessageBuilder MessageBuilder
- * @see MessageChannel#sendMessage(Message)
- *
* @see MessageChannel#getIterableHistory()
* @see MessageChannel#getHistory()
* @see MessageChannel#getHistoryAfter(String, int)
@@ -138,21 +136,21 @@ public interface Message extends ISnowflake, Formattable
/**
* The maximum sendable file size (8 MiB)
*
- * @see MessageAction#addFile(java.io.File, net.dv8tion.jda.api.utils.AttachmentOption...) MessageAction.addFile(...)
+ * @see MessageRequest#setFiles(Collection)
*/
int MAX_FILE_SIZE = 8 << 20;
/**
* The maximum sendable file size for nitro (50 MiB)
*
- * @see MessageAction#addFile(java.io.File, net.dv8tion.jda.api.utils.AttachmentOption...) MessageAction.addFile(...)
+ * @see MessageRequest#setFiles(Collection)
*/
int MAX_FILE_SIZE_NITRO = 50 << 20;
/**
* The maximum amount of files sendable within a single message ({@value})
*
- * @see MessageAction#addFile(java.io.File, net.dv8tion.jda.api.utils.AttachmentOption...) MessageAction.addFile(...)
+ * @see MessageRequest#setFiles(Collection)
*/
int MAX_FILE_AMOUNT = 10;
@@ -160,7 +158,7 @@ public interface Message extends ISnowflake, Formattable
* The maximum amount of characters sendable in one message. ({@value})
* This only applies to the raw content and not embeds!
*
- * @see MessageAction#append(CharSequence) MessageAction.append(...)
+ * @see MessageRequest#setContent(String)
*/
int MAX_CONTENT_LENGTH = 2000;
@@ -175,7 +173,7 @@ public interface Message extends ISnowflake, Formattable
* The maximum amount of Embeds that can be added to one message ({@value})
*
* @see MessageChannel#sendMessageEmbeds(Collection)
- * @see MessageAction#setEmbeds(Collection)
+ * @see MessageRequest#setEmbeds(Collection)
*/
int MAX_EMBED_COUNT = 10;
@@ -183,10 +181,20 @@ public interface Message extends ISnowflake, Formattable
* The maximum amount of {@link Sticker Stickers} that can be added to a message ({@value})
*
* @see GuildMessageChannel#sendStickers(StickerSnowflake...)
- * @see MessageAction#setStickers(StickerSnowflake...)
+ * @see MessageCreateAction#setStickers(StickerSnowflake...)
*/
int MAX_STICKER_COUNT = 3;
+ /**
+ * The maximum amount of {@link LayoutComponent LayoutComponents} that can be added to a message ({@value})
+ */
+ int MAX_COMPONENT_COUNT = 5;
+
+ /**
+ * The maximum character length for a {@link #getNonce() nonce} ({@value})
+ */
+ int MAX_NONCE_LENGTH = 25;
+
/**
* Pattern used to find instant invites in strings.
*
@@ -299,9 +307,6 @@ default Message getReferencedMessage()
* System.out.println("Message used these custom emojis: " + message.getMentions().getCustomEmojis());
* }
*
- * @throws UnsupportedOperationException
- * If this is a Data Message (output of {@link MessageBuilder MessageBuilder})
- *
* @return {@link Mentions} for this message.
*/
@Nonnull
@@ -310,9 +315,6 @@ default Message getReferencedMessage()
/**
* Returns whether or not this Message has been edited before.
*
- * @throws UnsupportedOperationException
- * If this is a Data Message (output of {@link MessageBuilder MessageBuilder})
- *
* @return True if this message has been edited.
*/
boolean isEdited();
@@ -322,9 +324,6 @@ default Message getReferencedMessage()
* edited. If this Message has not been edited ({@link #isEdited()} is {@code false}), then this method
* will return {@code null}.
*
- * @throws UnsupportedOperationException
- * If this is a Data Message (output of {@link MessageBuilder MessageBuilder})
- *
* @return Time of the most recent edit, or {@code null} if the Message has never been edited.
*/
@Nullable
@@ -333,9 +332,6 @@ default Message getReferencedMessage()
/**
* The author of this Message
*
- * @throws UnsupportedOperationException
- * If this is a Data Message (output of {@link MessageBuilder MessageBuilder})
- *
* @return Message author
*/
@Nonnull
@@ -351,9 +347,6 @@ default Message getReferencedMessage()
* This will return null if the message was retrieved through {@link MessageChannel#retrieveMessageById(long)} or similar means,
* unless the member is already cached.
*
- * @throws UnsupportedOperationException
- * If this is a Data Message (output of {@link MessageBuilder MessageBuilder})
- *
* @return Message author, or {@code null} if the message was not sent in a GuildMessageChannel, or if the message was sent by a Webhook.
*
* @see #isWebhookMessage()
@@ -365,9 +358,6 @@ default Message getReferencedMessage()
* Returns the jump-to URL for the received message. Clicking this URL in the Discord client will cause the client to
* jump to the specified message.
*
- * @throws java.lang.UnsupportedOperationException
- * If this is a data message
- *
* @return A String representing the jump-to URL for the message
*/
@Nonnull
@@ -389,9 +379,6 @@ default Message getReferencedMessage()
*
*
Requires {@link net.dv8tion.jda.api.requests.GatewayIntent#MESSAGE_CONTENT GatewayIntent.MESSAGE_CONTENT}
*
- * @throws UnsupportedOperationException
- * If this is a Data Message (output of {@link MessageBuilder MessageBuilder})
- *
* @return The textual content of the message with mentions resolved to be visually like the Discord client.
*/
@Nonnull
@@ -417,9 +404,6 @@ default Message getReferencedMessage()
*
*
Requires {@link net.dv8tion.jda.api.requests.GatewayIntent#MESSAGE_CONTENT GatewayIntent.MESSAGE_CONTENT}
*
- * @throws UnsupportedOperationException
- * If this is a Data Message (output of {@link MessageBuilder MessageBuilder})
- *
* @return The textual content from {@link #getContentDisplay()} with all text formatting characters removed or escaped.
*/
@Nonnull
@@ -435,9 +419,6 @@ default Message getReferencedMessage()
*
You can use the codes to retrieve/validate invites via
* {@link net.dv8tion.jda.api.entities.Invite#resolve(JDA, String) Invite.resolve(JDA, String)}
*
- * @throws UnsupportedOperationException
- * If this is a Data Message (output of {@link MessageBuilder MessageBuilder})
- *
* @return Immutable list of invite codes
*/
@Nonnull
@@ -446,13 +427,11 @@ default Message getReferencedMessage()
/**
* Validation nonce for this Message
* This can be used to validate that a Message was properly sent to the Discord Service.
- * To set a nonce before sending you may use {@link MessageBuilder#setNonce(String) MessageBuilder.setNonce(String)}!
+ * To set a nonce before sending you may use {@link MessageCreateAction#setNonce(String) MessageCreateAction.setNonce(String)}!
*
* @return The validation nonce
*
- * @since 3.4.0
- *
- * @see MessageBuilder#setNonce(String)
+ * @see MessageCreateAction#setNonce(String)
* @see Cryptographic Nonce - Wikipedia
*/
@Nullable
@@ -461,17 +440,12 @@ default Message getReferencedMessage()
/**
* Used to determine if this Message was received from a {@link net.dv8tion.jda.api.entities.MessageChannel MessageChannel}
* of the {@link net.dv8tion.jda.api.entities.ChannelType ChannelType} specified.
- * This will always be false for {@link net.dv8tion.jda.api.entities.ChannelType#VOICE} as Messages can't be sent to
- * {@link net.dv8tion.jda.api.entities.VoiceChannel VoiceChannels}.
*
*
Useful for restricting functionality to a certain type of channels.
*
* @param type
* The {@link net.dv8tion.jda.api.entities.ChannelType ChannelType} to check against.
*
- * @throws UnsupportedOperationException
- * If this is a Data Message (output of {@link MessageBuilder MessageBuilder})
- *
* @return True if the {@link net.dv8tion.jda.api.entities.ChannelType ChannelType} which this message was received
* from is the same as the one specified by {@code type}.
*/
@@ -481,9 +455,6 @@ default Message getReferencedMessage()
* Whether this message was sent in a {@link net.dv8tion.jda.api.entities.Guild Guild}.
* If this is {@code false} then {@link #getGuild()} will throw an {@link java.lang.IllegalStateException}.
*
- * @throws UnsupportedOperationException
- * If this is a Data Message (output of {@link MessageBuilder MessageBuilder})
- *
* @return True, if {@link #getChannelType()}.{@link ChannelType#isGuild() isGuild()} is true.
*/
default boolean isFromGuild()
@@ -493,11 +464,6 @@ default boolean isFromGuild()
/**
* Gets the {@link net.dv8tion.jda.api.entities.ChannelType ChannelType} that this message was received from.
- * This will never be {@link net.dv8tion.jda.api.entities.ChannelType#VOICE} as Messages can't be sent to
- * {@link net.dv8tion.jda.api.entities.VoiceChannel VoiceChannels}.
- *
- * @throws UnsupportedOperationException
- * If this is a Data Message (output of {@link MessageBuilder MessageBuilder})
*
* @return The ChannelType which this message was received from.
*/
@@ -509,9 +475,6 @@ default boolean isFromGuild()
* {@link User User}.
* Useful if you want to ignore non-users.
*
- * @throws UnsupportedOperationException
- * If this is a Data Message (output of {@link MessageBuilder MessageBuilder})
- *
* @return True if this message was sent by a {@link net.dv8tion.jda.api.entities.Webhook Webhook}.
*/
boolean isWebhookMessage();
@@ -519,9 +482,6 @@ default boolean isFromGuild()
/**
* Returns the {@link net.dv8tion.jda.api.entities.MessageChannel MessageChannel} that this message was sent in.
*
- * @throws UnsupportedOperationException
- * If this is a Data Message (output of {@link MessageBuilder MessageBuilder})
- *
* @return The MessageChannel of this Message
*/
@Nonnull
@@ -531,8 +491,6 @@ default boolean isFromGuild()
* Returns the {@link net.dv8tion.jda.api.entities.GuildMessageChannel GuildMessageChannel} that this message was sent in
* if it was sent in a Guild.
*
- * @throws UnsupportedOperationException
- * If this is a Data Message (output of {@link MessageBuilder MessageBuilder})
* @throws java.lang.IllegalStateException
* If this was not sent in a {@link net.dv8tion.jda.api.entities.Guild}.
*
@@ -546,9 +504,6 @@ default boolean isFromGuild()
* message was sent in. This will always be {@code null} for DMs.
* Equivalent to {@code getGuildChannel().getParentCategory()} if this was sent in a {@link GuildMessageChannel}.
*
- * @throws UnsupportedOperationException
- * If this is a Data Message (output of {@link MessageBuilder MessageBuilder})
- *
* @return {@link net.dv8tion.jda.api.entities.Category Category} for this message
*/
@Nullable
@@ -560,8 +515,6 @@ default boolean isFromGuild()
* This is only valid if the Message was actually sent in a GuildMessageChannel.
* You can check the type of channel this message was sent from using {@link #isFromType(ChannelType)} or {@link #getChannelType()}.
*
- * @throws UnsupportedOperationException
- * If this is a Data Message (output of {@link MessageBuilder MessageBuilder})
* @throws java.lang.IllegalStateException
* If this was not sent in a {@link net.dv8tion.jda.api.entities.GuildChannel}.
*
@@ -580,9 +533,6 @@ default boolean isFromGuild()
*
*
Requires {@link net.dv8tion.jda.api.requests.GatewayIntent#MESSAGE_CONTENT GatewayIntent.MESSAGE_CONTENT}
*
- * @throws UnsupportedOperationException
- * If this is a Data Message (output of {@link MessageBuilder MessageBuilder})
- *
* @return Immutable list of {@link net.dv8tion.jda.api.entities.Message.Attachment Attachments}.
*/
@Nonnull
@@ -598,9 +548,24 @@ default boolean isFromGuild()
@Nonnull
List getEmbeds();
+ /**
+ * Layouts of interactive components, usually {@link ActionRow ActionRows}.
+ * You can use {@link MessageRequest#setComponents(LayoutComponent...)} to update these.
+ *
+ * Requires {@link net.dv8tion.jda.api.requests.GatewayIntent#MESSAGE_CONTENT GatewayIntent.MESSAGE_CONTENT}
+ *
+ * @return Immutable {@link List} of {@link LayoutComponent}
+ *
+ * @see #getActionRows()
+ * @see #getButtons()
+ * @see #getButtonById(String)
+ */
+ @Nonnull
+ List getComponents();
+
/**
* Rows of interactive components such as {@link Button Buttons}.
- * You can use {@link MessageAction#setActionRows(ActionRow...)} to update these.
+ * You can use {@link MessageRequest#setComponents(LayoutComponent...)} to update these.
*
* Requires {@link net.dv8tion.jda.api.requests.GatewayIntent#MESSAGE_CONTENT GatewayIntent.MESSAGE_CONTENT}
*
@@ -610,7 +575,14 @@ default boolean isFromGuild()
* @see #getButtonById(String)
*/
@Nonnull
- List getActionRows();
+ default List getActionRows()
+ {
+ return getComponents()
+ .stream()
+ .filter(ActionRow.class::isInstance)
+ .map(ActionRow.class::cast)
+ .collect(Collectors.toList());
+ }
/**
* All {@link Button Buttons} attached to this message.
@@ -622,8 +594,8 @@ default boolean isFromGuild()
@Nonnull
default List getButtons()
{
- return getActionRows().stream()
- .map(ActionRow::getButtons)
+ return getComponents().stream()
+ .map(LayoutComponent::getButtons)
.flatMap(List::stream)
.collect(Collectors.toList());
}
@@ -682,9 +654,6 @@ default List getButtonsByLabel(@Nonnull String label, boolean ignoreCase
/**
* All {@link MessageReaction MessageReactions} that are on this Message.
*
- * @throws UnsupportedOperationException
- * If this is a Data Message (output of {@link MessageBuilder MessageBuilder})
- *
* @return Immutable list of all MessageReactions on this message.
*
* @see MessageReaction
@@ -696,9 +665,6 @@ default List getButtonsByLabel(@Nonnull String label, boolean ignoreCase
* All {@link StickerItem StickerItems} that are in this Message.
* The returned StickerItems may only contain necessary information such as the sticker id, format type, name, and icon url.
*
- * @throws UnsupportedOperationException
- * If this is a Data Message (output of {@link MessageBuilder MessageBuilder})
- *
* @return Immutable list of all StickerItems in this message.
*/
@Nonnull
@@ -714,271 +680,289 @@ default List getButtonsByLabel(@Nonnull String label, boolean ignoreCase
/**
* A {@link net.dv8tion.jda.api.entities.MessageActivity MessageActivity} that contains its type and party id.
*
- * @throws UnsupportedOperationException
- * If this is a Data Message (output of {@link MessageBuilder MessageBuilder})
- *
* @return The activity, or {@code null} if no activity was added to the message.
*/
@Nullable
MessageActivity getActivity();
/**
- * Edits this Message's content to the provided String.
- * Messages can only be edited by the account that sent them! .
- *
- * This message instance will not be updated by this operation, please use the response message instead.
+ * Edits this message and updates the content.
+ * Any other fields of the message will remain unchanged,
+ * you can use {@link net.dv8tion.jda.api.utils.messages.MessageEditRequest#setReplace(boolean) replace(true)} to remove everything else (embeds/attachments/components).
*
*
The following {@link net.dv8tion.jda.api.requests.ErrorResponse ErrorResponses} are possible:
*
* {@link net.dv8tion.jda.api.requests.ErrorResponse#MISSING_ACCESS MISSING_ACCESS}
- * The edit was attempted after the account lost access to the {@link net.dv8tion.jda.api.entities.Guild Guild}
- * typically due to being kicked or removed.
- *
- * {@link net.dv8tion.jda.api.requests.ErrorResponse#MISSING_PERMISSIONS MISSING_PERMISSIONS}
- * The edit was attempted after the account lost {@link Permission#MESSAGE_SEND Permission.MESSAGE_SEND} in
- * the {@link net.dv8tion.jda.api.entities.GuildMessageChannel GuildMessageChannel}.
+ * The request was attempted after the account lost access to the {@link net.dv8tion.jda.api.entities.Guild Guild}
+ * typically due to being kicked or removed, or after {@link net.dv8tion.jda.api.Permission#VIEW_CHANNEL Permission.VIEW_CHANNEL}
+ * was revoked in the {@link net.dv8tion.jda.api.entities.GuildMessageChannel GuildMessageChannel}
*
* {@link net.dv8tion.jda.api.requests.ErrorResponse#UNKNOWN_MESSAGE UNKNOWN_MESSAGE}
- * If the message has already been deleted. This might also be triggered for ephemeral messages.
+ * The provided {@code messageId} is unknown in this MessageChannel, either due to the id being invalid, or
+ * the message it referred to has already been deleted.
+ *
+ * {@link net.dv8tion.jda.api.requests.ErrorResponse#UNKNOWN_CHANNEL UNKNOWN_CHANNEL}
+ * The request was attempted after the channel was deleted.
*
*
* @param newContent
- * the new content of the Message
+ * The new content of the message, or empty string to remove content (assumes other fields exist like embeds)
*
- * @throws java.lang.UnsupportedOperationException
- * If this is a system message, or data message (output of {@link MessageBuilder MessageBuilder})
- * @throws java.lang.IllegalStateException
- * If the message attempting to be edited was not created by the currently logged in account, or if
- * {@code newContent}'s length is 0 or greater than 2000.
+ * @throws UnsupportedOperationException
+ * If this is a system message
+ * @throws IllegalStateException
+ * If the message is not authored by this bot
+ * @throws IllegalArgumentException
+ * If null is provided or the new content is longer than {@value #MAX_CONTENT_LENGTH} characters
+ *
+ * @return {@link MessageEditAction}
*
- * @return {@link MessageAction MessageAction}
- * The {@link net.dv8tion.jda.api.entities.Message Message} with the updated content
+ * @see MessageChannel#editMessageById(long, CharSequence)
*/
@Nonnull
@CheckReturnValue
- MessageAction editMessage(@Nonnull CharSequence newContent);
+ MessageEditAction editMessage(@Nonnull CharSequence newContent);
/**
- * Edits this Message's content to the provided {@link net.dv8tion.jda.api.entities.MessageEmbed MessageEmbeds}.
- * Messages can only be edited by the account that sent them! .
- *
- * This message instance will not be updated by this operation, please use the response message instead.
+ * Edits this message using the provided {@link MessageEditData}.
+ * You can use {@link net.dv8tion.jda.api.utils.messages.MessageEditBuilder MessageEditBuilder} to create a {@link MessageEditData} instance.
*
*
The following {@link net.dv8tion.jda.api.requests.ErrorResponse ErrorResponses} are possible:
*
* {@link net.dv8tion.jda.api.requests.ErrorResponse#MISSING_ACCESS MISSING_ACCESS}
- * The edit was attempted after the account lost access to the {@link net.dv8tion.jda.api.entities.Guild Guild}
- * typically due to being kicked or removed.
+ * The request was attempted after the account lost access to the {@link net.dv8tion.jda.api.entities.Guild Guild}
+ * typically due to being kicked or removed, or after {@link net.dv8tion.jda.api.Permission#VIEW_CHANNEL Permission.VIEW_CHANNEL}
+ * was revoked in the {@link net.dv8tion.jda.api.entities.GuildMessageChannel GuildMessageChannel}
*
- * {@link net.dv8tion.jda.api.requests.ErrorResponse#MISSING_PERMISSIONS MISSING_PERMISSIONS}
- * The edit was attempted after the account lost {@link Permission#MESSAGE_SEND Permission.MESSAGE_SEND} in
- * the {@link GuildChannel}.
+ * {@link net.dv8tion.jda.api.requests.ErrorResponse#UNKNOWN_MESSAGE UNKNOWN_MESSAGE}
+ * The provided {@code messageId} is unknown in this MessageChannel, either due to the id being invalid, or
+ * the message it referred to has already been deleted.
+ *
+ * {@link net.dv8tion.jda.api.requests.ErrorResponse#UNKNOWN_CHANNEL UNKNOWN_CHANNEL}
+ * The request was attempted after the channel was deleted.
+ *
+ *
+ * @param data
+ * The {@link MessageEditData} used to update the message
+ *
+ * @throws UnsupportedOperationException
+ * If this is a system message
+ * @throws IllegalStateException
+ * If the message is not authored by this bot
+ * @throws IllegalArgumentException
+ * If null is provided
+ *
+ * @return {@link MessageEditAction}
+ *
+ * @see net.dv8tion.jda.api.utils.messages.MessageEditBuilder MessageEditBuilder
+ * @see MessageChannel#editMessageById(long, MessageEditData)
+ */
+ @Nonnull
+ @CheckReturnValue
+ MessageEditAction editMessage(@Nonnull MessageEditData data);
+
+ /**
+ * Edits this message using the provided {@link MessageEmbed MessageEmbeds}.
+ * You can use {@link net.dv8tion.jda.api.EmbedBuilder EmbedBuilder} to create a {@link MessageEmbed} instance.
+ *
+ * The following {@link net.dv8tion.jda.api.requests.ErrorResponse ErrorResponses} are possible:
+ *
+ * {@link net.dv8tion.jda.api.requests.ErrorResponse#MISSING_ACCESS MISSING_ACCESS}
+ * The request was attempted after the account lost access to the {@link net.dv8tion.jda.api.entities.Guild Guild}
+ * typically due to being kicked or removed, or after {@link net.dv8tion.jda.api.Permission#VIEW_CHANNEL Permission.VIEW_CHANNEL}
+ * was revoked in the {@link net.dv8tion.jda.api.entities.GuildMessageChannel GuildMessageChannel}
*
* {@link net.dv8tion.jda.api.requests.ErrorResponse#UNKNOWN_MESSAGE UNKNOWN_MESSAGE}
- * If the message has already been deleted. This might also be triggered for ephemeral messages.
+ * The provided {@code messageId} is unknown in this MessageChannel, either due to the id being invalid, or
+ * the message it referred to has already been deleted.
+ *
+ * {@link net.dv8tion.jda.api.requests.ErrorResponse#UNKNOWN_CHANNEL UNKNOWN_CHANNEL}
+ * The request was attempted after the channel was deleted.
*
*
* @param embeds
- * the new embeds of the Message (up to 10)
+ * The new {@link MessageEmbed MessageEmbeds} of the message, empty list to remove embeds
*
- * @throws java.lang.UnsupportedOperationException
- * If this is a system message, or data message (output of {@link MessageBuilder MessageBuilder})
- * @throws java.lang.IllegalStateException
- * If the message attempting to be edited was not created by the currently logged in account
+ * @throws UnsupportedOperationException
+ * If this is a system message
+ * @throws IllegalStateException
+ * If the message is not authored by this bot
* @throws IllegalArgumentException
- * if any of the passed-in embeds is {@code null} or not {@link net.dv8tion.jda.api.entities.MessageEmbed#isSendable() sendable}.
+ *
+ * If {@code null} is provided
+ * If more than {@value Message#MAX_EMBED_COUNT} embeds are provided
+ *
+ *
+ * @return {@link MessageEditAction}
*
- * @return {@link MessageAction MessageAction}
- * The {@link net.dv8tion.jda.api.entities.Message Message} with the updated content
+ * @see net.dv8tion.jda.api.EmbedBuilder EmbedBuilder
+ * @see MessageChannel#editMessageEmbedsById(long, Collection)
*/
@Nonnull
@CheckReturnValue
- MessageAction editMessageEmbeds(@Nonnull Collection extends MessageEmbed> embeds);
+ MessageEditAction editMessageEmbeds(@Nonnull Collection extends MessageEmbed> embeds);
/**
- * Edits this Message's content to the provided {@link net.dv8tion.jda.api.entities.MessageEmbed MessageEmbeds}.
- * Messages can only be edited by the account that sent them! .
- *
- * This message instance will not be updated by this operation, please use the response message instead.
+ * Edits this message using the provided {@link MessageEmbed MessageEmbeds}.
+ * You can use {@link net.dv8tion.jda.api.EmbedBuilder EmbedBuilder} to create a {@link MessageEmbed} instance.
*
*
The following {@link net.dv8tion.jda.api.requests.ErrorResponse ErrorResponses} are possible:
*
* {@link net.dv8tion.jda.api.requests.ErrorResponse#MISSING_ACCESS MISSING_ACCESS}
- * The edit was attempted after the account lost access to the {@link net.dv8tion.jda.api.entities.Guild Guild}
- * typically due to being kicked or removed.
- *
- * {@link net.dv8tion.jda.api.requests.ErrorResponse#MISSING_PERMISSIONS MISSING_PERMISSIONS}
- * The edit was attempted after the account lost {@link Permission#MESSAGE_SEND Permission.MESSAGE_SEND} in
- * the {@link GuildChannel}.
+ * The request was attempted after the account lost access to the {@link net.dv8tion.jda.api.entities.Guild Guild}
+ * typically due to being kicked or removed, or after {@link net.dv8tion.jda.api.Permission#VIEW_CHANNEL Permission.VIEW_CHANNEL}
+ * was revoked in the {@link net.dv8tion.jda.api.entities.GuildMessageChannel GuildMessageChannel}
*
* {@link net.dv8tion.jda.api.requests.ErrorResponse#UNKNOWN_MESSAGE UNKNOWN_MESSAGE}
- * If the message has already been deleted. This might also be triggered for ephemeral messages.
+ * The provided {@code messageId} is unknown in this MessageChannel, either due to the id being invalid, or
+ * the message it referred to has already been deleted.
+ *
+ * {@link net.dv8tion.jda.api.requests.ErrorResponse#UNKNOWN_CHANNEL UNKNOWN_CHANNEL}
+ * The request was attempted after the channel was deleted.
*
*
* @param embeds
- * the new embeds of the Message (up to 10)
+ * The new {@link MessageEmbed MessageEmbeds} of the message, or an empty list to remove all embeds
*
- * @throws java.lang.UnsupportedOperationException
- * If this is a system message, or data message (output of {@link MessageBuilder MessageBuilder})
- * @throws java.lang.IllegalStateException
- * If the message attempting to be edited was not created by the currently logged in account
+ * @throws UnsupportedOperationException
+ * If this is a system message
+ * @throws IllegalStateException
+ * If the message is not authored by this bot
* @throws IllegalArgumentException
- * if any of the passed-in embeds is {@code null} or not {@link net.dv8tion.jda.api.entities.MessageEmbed#isSendable() sendable}.
+ *
+ * If {@code null} is provided
+ * If more than {@value Message#MAX_EMBED_COUNT} embeds are provided
+ *
+ *
+ * @return {@link MessageEditAction}
*
- * @return {@link MessageAction MessageAction}
- * The {@link net.dv8tion.jda.api.entities.Message Message} with the updated content
+ * @see net.dv8tion.jda.api.EmbedBuilder EmbedBuilder
+ * @see MessageChannel#editMessageEmbedsById(long, Collection)
*/
@Nonnull
@CheckReturnValue
- default MessageAction editMessageEmbeds(@Nonnull MessageEmbed... embeds)
+ default MessageEditAction editMessageEmbeds(@Nonnull MessageEmbed... embeds)
{
Checks.noneNull(embeds, "MessageEmbeds");
return editMessageEmbeds(Arrays.asList(embeds));
}
/**
- * Edits this Message's content to the provided {@link LayoutComponent LayoutComponents}.
- * Messages can only be edited by the account that sent them! .
- * This will replace all the current {@link net.dv8tion.jda.api.interactions.components.Component Components},
- * such as {@link Button Buttons} or {@link SelectMenu SelectMenus} on this message.
- * The provided parameters are {@link LayoutComponent LayoutComponent} such as {@link ActionRow} which contain a list of components to arrange in the respective layout.
- *
- * This message instance will not be updated by this operation, please use the response message instead.
+ * Edits this message using the provided {@link LayoutComponent LayoutComponents}.
*
*
The following {@link net.dv8tion.jda.api.requests.ErrorResponse ErrorResponses} are possible:
*
- * {@link net.dv8tion.jda.api.requests.ErrorResponse#INVALID_AUTHOR_EDIT INVALID_AUTHOR_EDIT}
- * Attempted to edit a message that was not sent by the currently logged in account.
- * Discord does not allow editing of other users' Messages!
- *
* {@link net.dv8tion.jda.api.requests.ErrorResponse#MISSING_ACCESS MISSING_ACCESS}
* The request was attempted after the account lost access to the {@link net.dv8tion.jda.api.entities.Guild Guild}
- * typically due to being kicked or removed, or after {@link Permission#VIEW_CHANNEL Permission.VIEW_CHANNEL}
- * was revoked in the {@link GuildChannel}
+ * typically due to being kicked or removed, or after {@link net.dv8tion.jda.api.Permission#VIEW_CHANNEL Permission.VIEW_CHANNEL}
+ * was revoked in the {@link net.dv8tion.jda.api.entities.GuildMessageChannel GuildMessageChannel}
*
* {@link net.dv8tion.jda.api.requests.ErrorResponse#UNKNOWN_MESSAGE UNKNOWN_MESSAGE}
- * If the message has already been deleted. This might also be triggered for ephemeral messages.
+ * The provided {@code messageId} is unknown in this MessageChannel, either due to the id being invalid, or
+ * the message it referred to has already been deleted.
*
* {@link net.dv8tion.jda.api.requests.ErrorResponse#UNKNOWN_CHANNEL UNKNOWN_CHANNEL}
* The request was attempted after the channel was deleted.
*
*
- * Example
- *
{@code
- * List rows = Arrays.asList(
- * ActionRow.of(Button.success("prompt:accept", "Accept"), Button.danger("prompt:reject", "Reject")), // 1st row below message
- * ActionRow.of(Button.link(url, "Help")) // 2nd row below message
- * );
- * message.editMessageComponents(rows).queue();
- * }
- *
* @param components
- * Up to 5 new {@link LayoutComponent LayoutComponents} for the edited message, such as {@link ActionRow}
+ * The new {@link LayoutComponent LayoutComponents} of the message, or an empty list to remove all components
*
- * @throws java.lang.UnsupportedOperationException
- * If this is a system message, or data message (output of {@link MessageBuilder MessageBuilder})
- * or any of the component layouts is a custom implementation that is not supported by this interface
+ * @throws UnsupportedOperationException
+ * If this is a system message
+ * @throws IllegalStateException
+ * If the message is not authored by this bot
* @throws IllegalArgumentException
- * If null is provided, or more than 5 layouts are added
- * @throws java.lang.IllegalStateException
- * If the message attempting to be edited was not created by the currently logged in account
+ *
+ * If {@code null} is provided
+ * If any of the components is not {@link LayoutComponent#isMessageCompatible() message compatible}
+ * If more than {@value Message#MAX_COMPONENT_COUNT} components are provided
+ *
*
- * @return {@link MessageAction MessageAction}
- * The {@link net.dv8tion.jda.api.entities.Message Message} with the updated components
+ * @return {@link MessageEditAction}
+ *
+ * @see MessageChannel#editMessageComponentsById(long, Collection)
*/
@Nonnull
@CheckReturnValue
- MessageAction editMessageComponents(@Nonnull Collection extends LayoutComponent> components);
+ MessageEditAction editMessageComponents(@Nonnull Collection extends LayoutComponent> components);
/**
- * Edits this Message's content to the provided {@link LayoutComponent LayoutComponents}.
- * Messages can only be edited by the account that sent them! .
- * This will replace all the current {@link net.dv8tion.jda.api.interactions.components.Component Components},
- * such as {@link Button Buttons} or {@link SelectMenu SelectMenus} on this message.
- * The provided parameters are {@link LayoutComponent LayoutComponent} such as {@link ActionRow} which contain a list of components to arrange in the respective layout.
- *
- * This message instance will not be updated by this operation, please use the response message instead.
+ * Edits this message using the provided {@link LayoutComponent LayoutComponents}.
*
*
The following {@link net.dv8tion.jda.api.requests.ErrorResponse ErrorResponses} are possible:
*
- * {@link net.dv8tion.jda.api.requests.ErrorResponse#INVALID_AUTHOR_EDIT INVALID_AUTHOR_EDIT}
- * Attempted to edit a message that was not sent by the currently logged in account.
- * Discord does not allow editing of other users' Messages!
- *
* {@link net.dv8tion.jda.api.requests.ErrorResponse#MISSING_ACCESS MISSING_ACCESS}
* The request was attempted after the account lost access to the {@link net.dv8tion.jda.api.entities.Guild Guild}
- * typically due to being kicked or removed, or after {@link Permission#VIEW_CHANNEL Permission.VIEW_CHANNEL}
- * was revoked in the {@link GuildChannel}
+ * typically due to being kicked or removed, or after {@link net.dv8tion.jda.api.Permission#VIEW_CHANNEL Permission.VIEW_CHANNEL}
+ * was revoked in the {@link net.dv8tion.jda.api.entities.GuildMessageChannel GuildMessageChannel}
*
* {@link net.dv8tion.jda.api.requests.ErrorResponse#UNKNOWN_MESSAGE UNKNOWN_MESSAGE}
- * If the message has already been deleted. This might also be triggered for ephemeral messages.
+ * The provided {@code messageId} is unknown in this MessageChannel, either due to the id being invalid, or
+ * the message it referred to has already been deleted.
*
* {@link net.dv8tion.jda.api.requests.ErrorResponse#UNKNOWN_CHANNEL UNKNOWN_CHANNEL}
* The request was attempted after the channel was deleted.
*
*
- * Example
- *
{@code
- * message.editMessageComponents(
- * ActionRow.of(Button.success("prompt:accept", "Accept"), Button.danger("prompt:reject", "Reject")), // 1st row below message
- * ActionRow.of(Button.link(url, "Help")) // 2nd row below message
- * ).queue();
- * }
- *
* @param components
- * Up to 5 new {@link LayoutComponent LayoutComponents} for the edited message, such as {@link ActionRow}
+ * The new {@link LayoutComponent LayoutComponents} of the message, empty list to remove all components
*
- * @throws java.lang.UnsupportedOperationException
- * If this is a system message, or data message (output of {@link MessageBuilder MessageBuilder})
- * or any of the component layouts is a custom implementation that is not supported by this interface
+ * @throws UnsupportedOperationException
+ * If this is a system message
+ * @throws IllegalStateException
+ * If the message is not authored by this bot
* @throws IllegalArgumentException
- * If null is provided, or more than 5 layouts are added
- * @throws java.lang.IllegalStateException
- * If the message attempting to be edited was not created by the currently logged in account
+ *
+ * If {@code null} is provided
+ * If any of the components is not {@link LayoutComponent#isMessageCompatible() message compatible}
+ * If more than {@value Message#MAX_COMPONENT_COUNT} components are provided
+ *
*
- * @return {@link MessageAction MessageAction}
- * The {@link net.dv8tion.jda.api.entities.Message Message} with the updated components
+ * @return {@link MessageEditAction}
+ *
+ * @see MessageChannel#editMessageComponentsById(long, Collection)
*/
@Nonnull
@CheckReturnValue
- default MessageAction editMessageComponents(@Nonnull LayoutComponent... components)
+ default MessageEditAction editMessageComponents(@Nonnull LayoutComponent... components)
{
Checks.noneNull(components, "Components");
return editMessageComponents(Arrays.asList(components));
}
/**
- * Edits this Message's content to the provided format.
- * Shortcut for {@link MessageBuilder#appendFormat(String, Object...)}.
- * Messages can only be edited by the account that sent them! .
- *
- * This message instance will not be updated by this operation, please use the response message instead.
+ * Edits this message using the provided format arguments.
*
*
The following {@link net.dv8tion.jda.api.requests.ErrorResponse ErrorResponses} are possible:
*
* {@link net.dv8tion.jda.api.requests.ErrorResponse#MISSING_ACCESS MISSING_ACCESS}
- * The edit was attempted after the account lost access to the {@link net.dv8tion.jda.api.entities.Guild Guild}
- * typically due to being kicked or removed.
- *
- * {@link net.dv8tion.jda.api.requests.ErrorResponse#MISSING_PERMISSIONS MISSING_PERMISSIONS}
- * The edit was attempted after the account lost {@link Permission#MESSAGE_SEND Permission.MESSAGE_SEND} in
- * the {@link GuildChannel}.
+ * The request was attempted after the account lost access to the {@link net.dv8tion.jda.api.entities.Guild Guild}
+ * typically due to being kicked or removed, or after {@link net.dv8tion.jda.api.Permission#VIEW_CHANNEL Permission.VIEW_CHANNEL}
+ * was revoked in the {@link net.dv8tion.jda.api.entities.GuildMessageChannel GuildMessageChannel}
*
* {@link net.dv8tion.jda.api.requests.ErrorResponse#UNKNOWN_MESSAGE UNKNOWN_MESSAGE}
- * If the message has already been deleted. This might also be triggered for ephemeral messages.
+ * The provided {@code messageId} is unknown in this MessageChannel, either due to the id being invalid, or
+ * the message it referred to has already been deleted.
+ *
+ * {@link net.dv8tion.jda.api.requests.ErrorResponse#UNKNOWN_CHANNEL UNKNOWN_CHANNEL}
+ * The request was attempted after the channel was deleted.
*
*
* @param format
- * Format String used to generate the Message's content via
- * {@link MessageBuilder#appendFormat(String, Object...)} specification
+ * Format String used to generate new Content
* @param args
- * The arguments to use in order to be converted in the format string
+ * The arguments which should be used to format the given format String
*
- * @throws java.lang.UnsupportedOperationException
- * If this is a system message, or data message (output of {@link MessageBuilder MessageBuilder})
* @throws IllegalArgumentException
- * If the provided format String is {@code null} or blank, or if
- * the created message exceeds the 2000 character limit
+ * If provided {@code format} is {@code null} or blank.
+ * @throws UnsupportedOperationException
+ * If this is a system message
+ * @throws IllegalStateException
+ * If the message is not authored by this bot
+ * @throws net.dv8tion.jda.api.exceptions.InsufficientPermissionException
+ * If this is a {@link net.dv8tion.jda.api.entities.GuildMessageChannel GuildMessageChannel} and this account does not have
+ * {@link net.dv8tion.jda.api.Permission#VIEW_CHANNEL Permission.VIEW_CHANNEL}
* @throws java.util.IllegalFormatException
* If a format string contains an illegal syntax,
* a format specifier that is incompatible with the given arguments,
@@ -986,63 +970,117 @@ default MessageAction editMessageComponents(@Nonnull LayoutComponent... componen
* For specification of all possible formatting errors,
* see the Details
* section of the formatter class specification.
- * @throws IllegalStateException
- * If the message attempting to be edited was not created by the currently logged in account
*
- * @return {@link MessageAction MessageAction}
- * The {@link net.dv8tion.jda.api.entities.Message Message} with the updated content
+ * @return {@link MessageEditAction}
+ *
+ * @see MessageChannel#editMessageFormatById(long, String, Object...)
*/
@Nonnull
@CheckReturnValue
- MessageAction editMessageFormat(@Nonnull String format, @Nonnull Object... args);
+ MessageEditAction editMessageFormat(@Nonnull String format, @Nonnull Object... args);
/**
- * Edits this Message's content to the provided {@link net.dv8tion.jda.api.entities.Message Message}.
- * Messages can only be edited by the account that sent them! .
- *
- * This message instance will not be updated by this operation, please use the response message instead.
+ * Edits this message using the provided files.
*
*
The following {@link net.dv8tion.jda.api.requests.ErrorResponse ErrorResponses} are possible:
*
+ * {@link net.dv8tion.jda.api.requests.ErrorResponse#REQUEST_ENTITY_TOO_LARGE REQUEST_ENTITY_TOO_LARGE}
+ * If any of the provided files is bigger than {@link Guild#getMaxFileSize()}
+ *
* {@link net.dv8tion.jda.api.requests.ErrorResponse#MISSING_ACCESS MISSING_ACCESS}
- * The edit was attempted after the account lost access to the {@link net.dv8tion.jda.api.entities.Guild Guild}
- * typically due to being kicked or removed.
+ * The request was attempted after the account lost access to the {@link net.dv8tion.jda.api.entities.Guild Guild}
+ * typically due to being kicked or removed, or after {@link net.dv8tion.jda.api.Permission#VIEW_CHANNEL Permission.VIEW_CHANNEL}
+ * was revoked in the {@link net.dv8tion.jda.api.entities.GuildMessageChannel GuildMessageChannel}
*
- * {@link net.dv8tion.jda.api.requests.ErrorResponse#MISSING_PERMISSIONS MISSING_PERMISSIONS}
- * The edit was attempted after the account lost {@link Permission#MESSAGE_SEND Permission.MESSAGE_SEND} in
- * the {@link GuildChannel}.
+ * {@link net.dv8tion.jda.api.requests.ErrorResponse#UNKNOWN_MESSAGE UNKNOWN_MESSAGE}
+ * The provided {@code messageId} is unknown in this MessageChannel, either due to the id being invalid, or
+ * the message it referred to has already been deleted. This might also be triggered for ephemeral messages.
+ *
+ * {@link net.dv8tion.jda.api.requests.ErrorResponse#UNKNOWN_CHANNEL UNKNOWN_CHANNEL}
+ * The request was attempted after the channel was deleted.
+ *
+ *
+ * Resource Handling Note: Once the request is handed off to the requester, for example when you call {@link RestAction#queue()},
+ * the requester will automatically clean up all opened files by itself. You are only responsible to close them yourself if it is never handed off properly.
+ * For instance, if an exception occurs after using {@link FileUpload#fromData(File)}, before calling {@link RestAction#queue()}.
+ * You can safely use a try-with-resources to handle this, since {@link FileUpload#close()} becomes ineffective once the request is handed off.
+ *
+ * @param attachments
+ * The new attachments of the message (Can be {@link FileUpload FileUploads} or {@link net.dv8tion.jda.api.utils.AttachmentUpdate AttachmentUpdates})
+ *
+ * @throws UnsupportedOperationException
+ * If this is a system message
+ * @throws IllegalStateException
+ * If the message is not authored by this bot
+ * @throws IllegalArgumentException
+ * If {@code null} is provided
+ *
+ * @return {@link MessageEditAction} that can be used to further update the message
+ *
+ * @see AttachedFile#fromAttachment(Message.Attachment)
+ * @see FileUpload#fromData(InputStream, String)
+ */
+ @Nonnull
+ @CheckReturnValue
+ MessageEditAction editMessageAttachments(@Nonnull Collection extends AttachedFile> attachments);
+
+ /**
+ * Edits this message using the provided files.
+ *
+ *
The following {@link net.dv8tion.jda.api.requests.ErrorResponse ErrorResponses} are possible:
+ *
+ * {@link net.dv8tion.jda.api.requests.ErrorResponse#REQUEST_ENTITY_TOO_LARGE REQUEST_ENTITY_TOO_LARGE}
+ * If any of the provided files is bigger than {@link Guild#getMaxFileSize()}
+ *
+ * {@link net.dv8tion.jda.api.requests.ErrorResponse#MISSING_ACCESS MISSING_ACCESS}
+ * The request was attempted after the account lost access to the {@link net.dv8tion.jda.api.entities.Guild Guild}
+ * typically due to being kicked or removed, or after {@link net.dv8tion.jda.api.Permission#VIEW_CHANNEL Permission.VIEW_CHANNEL}
+ * was revoked in the {@link net.dv8tion.jda.api.entities.GuildMessageChannel GuildMessageChannel}
*
* {@link net.dv8tion.jda.api.requests.ErrorResponse#UNKNOWN_MESSAGE UNKNOWN_MESSAGE}
- * If the message has already been deleted. This might also be triggered for ephemeral messages.
+ * The provided {@code messageId} is unknown in this MessageChannel, either due to the id being invalid, or
+ * the message it referred to has already been deleted. This might also be triggered for ephemeral messages.
+ *
+ * {@link net.dv8tion.jda.api.requests.ErrorResponse#UNKNOWN_CHANNEL UNKNOWN_CHANNEL}
+ * The request was attempted after the channel was deleted.
*
*
- * @param newContent
- * the new content of the Message
+ * Resource Handling Note: Once the request is handed off to the requester, for example when you call {@link RestAction#queue()},
+ * the requester will automatically clean up all opened files by itself. You are only responsible to close them yourself if it is never handed off properly.
+ * For instance, if an exception occurs after using {@link FileUpload#fromData(File)}, before calling {@link RestAction#queue()}.
+ * You can safely use a try-with-resources to handle this, since {@link FileUpload#close()} becomes ineffective once the request is handed off.
*
- * @throws java.lang.UnsupportedOperationException
- * If this is a system message, or data message (output of {@link MessageBuilder MessageBuilder})
- * @throws java.lang.IllegalStateException
- *
- * If the message attempting to be edited was not created by the currently logged in account
- * If the message contains a MessageEmbed that is not
- * {@link net.dv8tion.jda.api.entities.MessageEmbed#isSendable() sendable}
- *
+ * @param attachments
+ * The new attachments of the message (Can be {@link FileUpload FileUploads} or {@link net.dv8tion.jda.api.utils.AttachmentUpdate AttachmentUpdates})
+ *
+ * @throws UnsupportedOperationException
+ * If this is a system message
+ * @throws IllegalStateException
+ * If the message is not authored by this bot
+ * @throws IllegalArgumentException
+ * If {@code null} is provided
*
- * @return {@link MessageAction MessageAction}
- * The {@link net.dv8tion.jda.api.entities.Message Message} with the updated content
+ * @return {@link MessageEditAction} that can be used to further update the message
+ *
+ * @see AttachedFile#fromAttachment(Message.Attachment)
+ * @see FileUpload#fromData(InputStream, String)
*/
@Nonnull
@CheckReturnValue
- MessageAction editMessage(@Nonnull Message newContent);
+ default MessageEditAction editMessageAttachments(@Nonnull AttachedFile... attachments)
+ {
+ Checks.noneNull(attachments, "Attachments");
+ return editMessageAttachments(Arrays.asList(attachments));
+ }
/**
* Replies and references this message.
* This is identical to {@code message.getGuildChannel().sendStickers(stickers).reference(message)}.
- * You can use {@link MessageAction#mentionRepliedUser(boolean) mentionRepliedUser(false)} to not mention the author of the message.
+ * You can use {@link MessageCreateAction#mentionRepliedUser(boolean) mentionRepliedUser(false)} to not mention the author of the message.
* By default there won't be any error thrown if the referenced message does not exist.
- * This behavior can be changed with {@link MessageAction#failOnInvalidReply(boolean)}.
+ * This behavior can be changed with {@link MessageCreateAction#failOnInvalidReply(boolean)}.
*
- * For further info, see {@link GuildMessageChannel#sendStickers(Collection)} and {@link MessageAction#reference(Message)}.
+ *
For further info, see {@link GuildMessageChannel#sendStickers(Collection)} and {@link MessageCreateAction#setMessageReference(Message)}.
*
* @param stickers
* The 1-3 stickers to send
@@ -1064,25 +1102,25 @@ default MessageAction editMessageComponents(@Nonnull LayoutComponent... componen
* @throws IllegalStateException
* If this message was not sent in a {@link Guild}
*
- * @return {@link MessageAction}
+ * @return {@link MessageCreateAction}
*
* @see Sticker#fromId(long)
*/
@Nonnull
@CheckReturnValue
- default MessageAction replyStickers(@Nonnull Collection extends StickerSnowflake> stickers)
+ default MessageCreateAction replyStickers(@Nonnull Collection extends StickerSnowflake> stickers)
{
- return getGuildChannel().sendStickers(stickers).reference(this);
+ return getGuildChannel().sendStickers(stickers).setMessageReference(this);
}
/**
* Replies and references this message.
* This is identical to {@code message.getGuildChannel().sendStickers(stickers).reference(message)}.
- * You can use {@link MessageAction#mentionRepliedUser(boolean) mentionRepliedUser(false)} to not mention the author of the message.
+ * You can use {@link MessageCreateAction#mentionRepliedUser(boolean) mentionRepliedUser(false)} to not mention the author of the message.
* By default there won't be any error thrown if the referenced message does not exist.
- * This behavior can be changed with {@link MessageAction#failOnInvalidReply(boolean)}.
+ * This behavior can be changed with {@link MessageCreateAction#failOnInvalidReply(boolean)}.
*
- *
For further info, see {@link GuildMessageChannel#sendStickers(Collection)} and {@link MessageAction#reference(Message)}.
+ *
For further info, see {@link GuildMessageChannel#sendStickers(Collection)} and {@link MessageCreateAction#setMessageReference(Message)}.
*
* @param stickers
* The 1-3 stickers to send
@@ -1104,313 +1142,164 @@ default MessageAction replyStickers(@Nonnull Collection extends StickerSnowfla
* @throws IllegalStateException
* If this message was not sent in a {@link Guild}
*
- * @return {@link MessageAction}
+ * @return {@link MessageCreateAction}
*
* @see Sticker#fromId(long)
*/
@Nonnull
@CheckReturnValue
- default MessageAction replyStickers(@Nonnull StickerSnowflake... stickers)
+ default MessageCreateAction replyStickers(@Nonnull StickerSnowflake... stickers)
{
- return getGuildChannel().sendStickers(stickers).reference(this);
+ return getGuildChannel().sendStickers(stickers).setMessageReference(this);
}
/**
- * Replies and references this message.
- * This is identical to {@code message.getChannel().sendMessage(content).reference(message)}.
- * You can use {@link MessageAction#mentionRepliedUser(boolean) mentionRepliedUser(false)} to not mention the author of the message.
- * By default there won't be any error thrown if the referenced message does not exist.
- * This behavior can be changed with {@link MessageAction#failOnInvalidReply(boolean)}.
- *
- *
For further info, see {@link MessageChannel#sendMessage(CharSequence)} and {@link MessageAction#reference(Message)}.
+ * Shortcut for {@code getChannel().sendMessage(content).setMessageReference(this)}-
*
* @param content
- * The content of the reply message
+ * The reply content
*
- * @throws UnsupportedOperationException
- * If this is a Data Message (output of {@link MessageBuilder})
- * @throws net.dv8tion.jda.api.exceptions.InsufficientPermissionException
- * If this is a {@link GuildChannel} and the logged in account does
- * not have {@link Permission#MESSAGE_SEND Permission.MESSAGE_SEND}
- * @throws java.lang.IllegalArgumentException
- * if the provided text is null, empty or longer than 2000 characters
+ * @throws InsufficientPermissionException
+ * If {@link MessageChannel#sendMessage(CharSequence)} throws
+ * @throws IllegalArgumentException
+ * If {@link MessageChannel#sendMessage(CharSequence)} throws
*
- * @return {@link MessageAction} Providing the {@link Message} created from this upload.
+ * @return {@link MessageCreateAction}
*/
@Nonnull
@CheckReturnValue
- default MessageAction reply(@Nonnull CharSequence content)
+ default MessageCreateAction reply(@Nonnull CharSequence content)
{
- return getChannel().sendMessage(content).reference(this);
+ return getChannel().sendMessage(content).setMessageReference(this);
}
/**
- * Replies and references this message.
- * This is identical to {@code message.getChannel().sendMessageEmbeds(embeds).reference(message)}.
- * You can use {@link MessageAction#mentionRepliedUser(boolean) mentionRepliedUser(false)} to not mention the author of the message.
- * By default there won't be any error thrown if the referenced message does not exist.
- * This behavior can be changed with {@link MessageAction#failOnInvalidReply(boolean)}.
+ * Shortcut for {@code getChannel().sendMessage(data).setMessageReference(this)}-
*
- *
For further info, see {@link MessageChannel#sendMessageEmbeds(MessageEmbed, MessageEmbed...)} and {@link MessageAction#reference(Message)}.
+ * @param msg
+ * The {@link MessageCreateData} to send
*
- * @param embed
- * The embed to reply with
- * @param other
- * Additional embeds to reply with
- *
- * @throws UnsupportedOperationException
- * If this is a Data Message (output of {@link MessageBuilder})
- * @throws net.dv8tion.jda.api.exceptions.InsufficientPermissionException
- * If this is a {@link GuildChannel} and the logged in account does
- * not have {@link Permission#MESSAGE_SEND Permission.MESSAGE_SEND}
+ * @throws InsufficientPermissionException
+ * If {@link MessageChannel#sendMessage(MessageCreateData)} throws
* @throws IllegalArgumentException
- * If null is provided, any of the embeds are not {@link MessageEmbed#isSendable() sendable}, more than {@value Message#MAX_EMBED_COUNT} embeds are provided,
- * or the sum of {@link MessageEmbed#getLength()} is greater than {@link MessageEmbed#EMBED_MAX_LENGTH_BOT}
+ * If {@link MessageChannel#sendMessage(MessageCreateData)} throws
*
- * @return {@link MessageAction} Providing the {@link Message} created from this upload.
+ * @return {@link MessageCreateAction}
*/
@Nonnull
@CheckReturnValue
- default MessageAction replyEmbeds(@Nonnull MessageEmbed embed, @Nonnull MessageEmbed... other)
+ default MessageCreateAction reply(@Nonnull MessageCreateData msg)
{
- Checks.notNull(embed, "MessageEmbeds");
- Checks.noneNull(other, "MessageEmbeds");
- List embeds = new ArrayList<>(1 + other.length);
- embeds.add(embed);
- Collections.addAll(embeds, other);
- return replyEmbeds(embeds);
+ return getChannel().sendMessage(msg).setMessageReference(this);
}
/**
- * Replies and references this message.
- * This is identical to {@code message.getChannel().sendMessageEmbeds(embeds).reference(message)}.
- * You can use {@link MessageAction#mentionRepliedUser(boolean) mentionRepliedUser(false)} to not mention the author of the message.
- * By default there won't be any error thrown if the referenced message does not exist.
- * This behavior can be changed with {@link MessageAction#failOnInvalidReply(boolean)}.
- *
- * For further info, see {@link MessageChannel#sendMessageEmbeds(MessageEmbed, MessageEmbed...)} and {@link MessageAction#reference(Message)}.
+ * Shortcut for {@code getChannel().sendMessageEmbeds(embed, other).setMessageReference(this)}-
*
- * @param embeds
- * The embeds to reply with
+ * @param embed
+ * The {@link MessageEmbed} to send
+ * @param other
+ * Any addition {@link MessageEmbed MessageEmbeds} to send
*
- * @throws UnsupportedOperationException
- * If this is a Data Message (output of {@link MessageBuilder})
- * @throws net.dv8tion.jda.api.exceptions.InsufficientPermissionException
- * If this is a {@link GuildChannel} and the logged in account does
- * not have {@link Permission#MESSAGE_SEND Permission.MESSAGE_SEND}
+ * @throws InsufficientPermissionException
+ * If {@link MessageChannel#sendMessageEmbeds(MessageEmbed, MessageEmbed...)} throws
* @throws IllegalArgumentException
- * If null is provided, any of the embeds are not {@link MessageEmbed#isSendable() sendable}, more than {@value Message#MAX_EMBED_COUNT} embeds are provided,
- * or the sum of {@link MessageEmbed#getLength()} is greater than {@link MessageEmbed#EMBED_MAX_LENGTH_BOT}
+ * If {@link MessageChannel#sendMessageEmbeds(MessageEmbed, MessageEmbed...)} throws
*
- * @return {@link MessageAction} Providing the {@link Message} created from this upload.
+ * @return {@link MessageCreateAction}
*/
@Nonnull
@CheckReturnValue
- default MessageAction replyEmbeds(@Nonnull Collection extends MessageEmbed> embeds)
+ default MessageCreateAction replyEmbeds(@Nonnull MessageEmbed embed, @Nonnull MessageEmbed... other)
{
- return getChannel().sendMessageEmbeds(embeds).reference(this);
+ Checks.notNull(embed, "MessageEmbeds");
+ Checks.noneNull(other, "MessageEmbeds");
+ List embeds = new ArrayList<>(1 + other.length);
+ embeds.add(embed);
+ Collections.addAll(embeds, other);
+ return replyEmbeds(embeds);
}
/**
- * Replies and references this message.
- * This is identical to {@code message.getChannel().sendMessage(content).reference(message)}.
- * You can use {@link MessageAction#mentionRepliedUser(boolean) mentionRepliedUser(false)} to not mention the author of the message.
- * By default there won't be any error thrown if the referenced message does not exist.
- * This behavior can be changed with {@link MessageAction#failOnInvalidReply(boolean)}.
- *
- * For further info, see {@link MessageChannel#sendMessage(Message)} and {@link MessageAction#reference(Message)}.
+ * Shortcut for {@code getChannel().sendMessageEmbeds(embeds).setMessageReference(this)}-
*
- * @param content
- * The content of the reply message
+ * @param embeds
+ * The {@link MessageEmbed MessageEmbeds} to send
*
- * @throws UnsupportedOperationException
- * If this is a Data Message (output of {@link MessageBuilder})
- * @throws net.dv8tion.jda.api.exceptions.InsufficientPermissionException
- * If this is a {@link GuildChannel} and the logged in account does
- * not have {@link Permission#MESSAGE_SEND Permission.MESSAGE_SEND}
+ * @throws InsufficientPermissionException
+ * If {@link MessageChannel#sendMessageEmbeds(Collection)} throws
* @throws IllegalArgumentException
- * If null is provided
- *
- * @return {@link MessageAction} Providing the {@link Message} created from this upload.
+ * If {@link MessageChannel#sendMessageEmbeds(Collection)} throws
*
- * @since 4.2.1
+ * @return {@link MessageCreateAction}
*/
@Nonnull
@CheckReturnValue
- default MessageAction reply(@Nonnull Message content)
+ default MessageCreateAction replyEmbeds(@Nonnull Collection extends MessageEmbed> embeds)
{
- return getChannel().sendMessage(content).reference(this);
+ return getChannel().sendMessageEmbeds(embeds).setMessageReference(this);
}
/**
- * Replies and references this message.
- * This is identical to {@code message.getChannel().sendMessageFormat(content, args).reference(message)}.
- * You can use {@link MessageAction#mentionRepliedUser(boolean) mentionRepliedUser(false)} to not mention the author of the message.
- * By default there won't be any error thrown if the referenced message does not exist.
- * This behavior can be changed with {@link MessageAction#failOnInvalidReply(boolean)}.
- *
- *
For further info, see {@link MessageChannel#sendMessageFormat(String, Object...)} and {@link MessageAction#reference(Message)}.
+ * Shortcut for {@code getChannel().sendMessageFormat(format, args).setMessageReference(this)}-
*
* @param format
- * The string that should be formatted, if this is null or empty the content of the Message would be empty and cause a builder exception.
+ * The format string
* @param args
- * The arguments for your format
- *
- * @throws UnsupportedOperationException
- * If this is a Data Message (output of {@link MessageBuilder})
- * @throws net.dv8tion.jda.api.exceptions.InsufficientPermissionException
- * If this is a {@link GuildChannel} and the logged in account does
- * not have {@link Permission#MESSAGE_SEND Permission.MESSAGE_SEND}
- * @throws IllegalArgumentException
- * If null is provided
- *
- * @return {@link MessageAction} Providing the {@link Message} created from this upload.
- *
- * @since 4.2.1
- */
- @Nonnull
- @CheckReturnValue
- default MessageAction replyFormat(@Nonnull String format, @Nonnull Object... args)
- {
- return getChannel().sendMessageFormat(format, args).reference(this);
- }
-
- /**
- * Replies and references this message.
- * This is identical to {@code message.getChannel().sendFile(file, options).reference(message)}.
- * You can use {@link MessageAction#mentionRepliedUser(boolean) mentionRepliedUser(false)} to not mention the author of the message.
- * By default there won't be any error thrown if the referenced message does not exist.
- * This behavior can be changed with {@link MessageAction#failOnInvalidReply(boolean)}.
- *
- *
For further info, see {@link MessageChannel#sendFile(File, net.dv8tion.jda.api.utils.AttachmentOption...)} and {@link MessageAction#reference(Message)}.
+ * The arguments to use in the format string
*
- * @param file
- * The file to upload to the channel in the reply
- * @param options
- * Possible options to apply to this attachment, such as marking it as spoiler image
- *
- * @throws UnsupportedOperationException
- * If this is a Data Message (output of {@link MessageBuilder})
- * @throws net.dv8tion.jda.api.exceptions.InsufficientPermissionException
- * If this is a {@link GuildChannel} and the logged in account does
- * not have {@link Permission#MESSAGE_SEND Permission.MESSAGE_SEND}
+ * @throws InsufficientPermissionException
+ * If {@link MessageChannel#sendMessageFormat(String, Object...)} throws
* @throws IllegalArgumentException
- * If null is provided
+ * If {@link MessageChannel#sendMessageFormat(String, Object...)} throws
*
- * @return {@link MessageAction} Providing the {@link Message} created from this upload.
- *
- * @since 4.2.1
+ * @return {@link MessageCreateAction}
*/
@Nonnull
@CheckReturnValue
- default MessageAction reply(@Nonnull File file, @Nonnull AttachmentOption... options)
+ default MessageCreateAction replyFormat(@Nonnull String format, @Nonnull Object... args)
{
- return getChannel().sendFile(file, options).reference(this);
+ return getChannel().sendMessageFormat(format, args).setMessageReference(this);
}
/**
- * Replies and references this message.
- * This is identical to {@code message.getChannel().sendFile(data, name, options).reference(message)}.
- * You can use {@link MessageAction#mentionRepliedUser(boolean) mentionRepliedUser(false)} to not mention the author of the message.
- * By default there won't be any error thrown if the referenced message does not exist.
- * This behavior can be changed with {@link MessageAction#failOnInvalidReply(boolean)}.
- *
- *
For further info, see {@link MessageChannel#sendFile(File, String, net.dv8tion.jda.api.utils.AttachmentOption...)} and {@link MessageAction#reference(Message)}.
- *
- * @param data
- * The data to upload to the channel in the reply
- * @param name
- * The name that should be sent to discord
- * @param options
- * Possible options to apply to this attachment, such as marking it as spoiler image
- *
- * @throws UnsupportedOperationException
- * If this is a Data Message (output of {@link MessageBuilder})
- * @throws net.dv8tion.jda.api.exceptions.InsufficientPermissionException
- * If this is a {@link GuildChannel} and the logged in account does
- * not have {@link Permission#MESSAGE_SEND Permission.MESSAGE_SEND}
- * @throws IllegalArgumentException
- * If null is provided
+ * Shortcut for {@code getChannel().sendFiles(files).setMessageReference(this)}-
*
- * @return {@link MessageAction} Providing the {@link Message} created from this upload.
+ * @param files
+ * The {@link FileUpload FileUploads} to send
*
- * @since 4.2.1
- */
- @Nonnull
- @CheckReturnValue
- default MessageAction reply(@Nonnull File data, @Nonnull String name, @Nonnull AttachmentOption... options)
- {
- return getChannel().sendFile(data, name, options).reference(this);
- }
-
- /**
- * Replies and references this message.
- * This is identical to {@code message.getChannel().sendFile(data, name, options).reference(message)}.
- * You can use {@link MessageAction#mentionRepliedUser(boolean) mentionRepliedUser(false)} to not mention the author of the message.
- * By default there won't be any error thrown if the referenced message does not exist.
- * This behavior can be changed with {@link MessageAction#failOnInvalidReply(boolean)}.
- *
- *
For further info, see {@link MessageChannel#sendFile(InputStream, String, net.dv8tion.jda.api.utils.AttachmentOption...)} and {@link MessageAction#reference(Message)}.
- *
- * @param data
- * The data to upload to the channel in the reply
- * @param name
- * The name that should be sent to discord
- * @param options
- * Possible options to apply to this attachment, such as marking it as spoiler image
- *
- * @throws UnsupportedOperationException
- * If this is a Data Message (output of {@link MessageBuilder})
- * @throws net.dv8tion.jda.api.exceptions.InsufficientPermissionException
- * If this is a {@link GuildChannel} and the logged in account does
- * not have {@link Permission#MESSAGE_SEND Permission.MESSAGE_SEND}
+ * @throws InsufficientPermissionException
+ * If {@link MessageChannel#sendFiles(FileUpload...)} throws
* @throws IllegalArgumentException
- * If null is provided
+ * If {@link MessageChannel#sendFiles(FileUpload...)} throws
*
- * @return {@link MessageAction} Providing the {@link Message} created from this upload.
- *
- * @since 4.2.1
+ * @return {@link MessageCreateAction}
*/
@Nonnull
@CheckReturnValue
- default MessageAction reply(@Nonnull InputStream data, @Nonnull String name, @Nonnull AttachmentOption... options)
+ default MessageCreateAction replyFiles(@Nonnull FileUpload... files)
{
- return getChannel().sendFile(data, name, options).reference(this);
+ return getChannel().sendFiles(files).setMessageReference(this);
}
/**
- * Replies and references this message.
- * This is identical to {@code message.getChannel().sendFile(data, name, options).reference(message)}.
- * You can use {@link MessageAction#mentionRepliedUser(boolean) mentionRepliedUser(false)} to not mention the author of the message.
- * By default there won't be any error thrown if the referenced message does not exist.
- * This behavior can be changed with {@link MessageAction#failOnInvalidReply(boolean)}.
- *
- *
For further info, see {@link MessageChannel#sendFile(byte[], String, net.dv8tion.jda.api.utils.AttachmentOption...)} and {@link MessageAction#reference(Message)}.
+ * Shortcut for {@code getChannel().sendFiles(files).setMessageReference(this)}-
*
- * @param data
- * The data to upload to the channel in the reply
- * @param name
- * The name that should be sent to discord
- * @param options
- * Possible options to apply to this attachment, such as marking it as spoiler image
+ * @param files
+ * The {@link FileUpload FileUploads} to send
*
- * @throws UnsupportedOperationException
- * If this is a Data Message (output of {@link MessageBuilder})
- * @throws net.dv8tion.jda.api.exceptions.InsufficientPermissionException
- * If this is a {@link GuildChannel} and the logged in account does
- * not have {@link Permission#MESSAGE_SEND Permission.MESSAGE_SEND}
+ * @throws InsufficientPermissionException
+ * If {@link MessageChannel#sendFiles(Collection)} throws
* @throws IllegalArgumentException
- * If null is provided
- *
- * @return {@link MessageAction} Providing the {@link Message} created from this upload.
+ * If {@link MessageChannel#sendFiles(Collection)} throws
*
- * @since 4.2.1
+ * @return {@link MessageCreateAction}
*/
@Nonnull
@CheckReturnValue
- default MessageAction reply(@Nonnull byte[] data, @Nonnull String name, @Nonnull AttachmentOption... options)
+ default MessageCreateAction replyFiles(@Nonnull Collection extends FileUpload> files)
{
- return getChannel().sendFile(data, name, options).reference(this);
+ return getChannel().sendFiles(files).setMessageReference(this);
}
/**
@@ -1439,8 +1328,6 @@ default MessageAction reply(@Nonnull byte[] data, @Nonnull String name, @Nonnull
* If the message has already been deleted. This might also be triggered for ephemeral messages.
*
*
- * @throws java.lang.UnsupportedOperationException
- * If this is a Data Message (output of {@link MessageBuilder MessageBuilder})
* @throws MissingAccessException
* If the currently logged in account does not have {@link Member#hasAccess(GuildChannel) access} in this channel.
* @throws net.dv8tion.jda.api.exceptions.InsufficientPermissionException
@@ -1468,9 +1355,6 @@ default MessageAction reply(@Nonnull byte[] data, @Nonnull String name, @Nonnull
/**
* Returns the {@link net.dv8tion.jda.api.JDA JDA} instance related to this Message.
*
- * @throws java.lang.UnsupportedOperationException
- * If this is a Data Message (output of {@link MessageBuilder MessageBuilder})
- *
* @return the corresponding JDA instance
*/
@Nonnull
@@ -1479,9 +1363,6 @@ default MessageAction reply(@Nonnull byte[] data, @Nonnull String name, @Nonnull
/**
* Whether or not this Message has been pinned in its parent channel.
*
- * @throws java.lang.UnsupportedOperationException
- * If this is a Data Message (output of {@link MessageBuilder MessageBuilder})
- *
* @return True - if this message has been pinned.
*/
boolean isPinned();
@@ -1508,8 +1389,6 @@ default MessageAction reply(@Nonnull byte[] data, @Nonnull String name, @Nonnull
* If the message has already been deleted. This might also be triggered for ephemeral messages.
*
*
- * @throws java.lang.UnsupportedOperationException
- * If this is a system message, or a Data Message (output of {@link MessageBuilder MessageBuilder})
* @throws net.dv8tion.jda.api.exceptions.InsufficientPermissionException
* If this Message is from a {@link GuildChannel} and:
*
@@ -1549,8 +1428,6 @@ default MessageAction reply(@Nonnull byte[] data, @Nonnull String name, @Nonnull
* If the message has already been deleted. This might also be triggered for ephemeral messages.
*
*
- * @throws java.lang.UnsupportedOperationException
- * If this is a system message, or a Data Message (output of {@link MessageBuilder MessageBuilder})
* @throws net.dv8tion.jda.api.exceptions.InsufficientPermissionException
* If this Message is from a {@link GuildChannel} and:
*
@@ -1606,8 +1483,6 @@ default MessageAction reply(@Nonnull byte[] data, @Nonnull String name, @Nonnull
* @param emoji
* The {@link Emoji} to add as a reaction to this Message.
*
- * @throws java.lang.UnsupportedOperationException
- * If this is a Data Message (output of {@link MessageBuilder MessageBuilder})
* @throws net.dv8tion.jda.api.exceptions.InsufficientPermissionException
* If the MessageChannel this message was sent in was a {@link GuildChannel}
* and the logged in account does not have
@@ -1654,8 +1529,6 @@ default MessageAction reply(@Nonnull byte[] data, @Nonnull String name, @Nonnull
* If the message has already been deleted. This might also be triggered for ephemeral messages.
*
*
- * @throws java.lang.UnsupportedOperationException
- * If this is a Data Message (output of {@link MessageBuilder MessageBuilder})
* @throws net.dv8tion.jda.api.exceptions.InsufficientPermissionException
* If the MessageChannel this message was sent in was a {@link GuildChannel}
* and the currently logged in account does not have {@link Permission#MESSAGE_MANAGE Permission.MESSAGE_MANAGE}
@@ -1694,8 +1567,6 @@ default MessageAction reply(@Nonnull byte[] data, @Nonnull String name, @Nonnull
* @param emoji
* The {@link Emoji} to remove reactions for
*
- * @throws java.lang.UnsupportedOperationException
- * If this is a Data Message (output of {@link MessageBuilder MessageBuilder})
* @throws InsufficientPermissionException
* If the currently logged in account does not have {@link Permission#MESSAGE_MANAGE} in the channel
* @throws IllegalArgumentException
@@ -1741,8 +1612,6 @@ default MessageAction reply(@Nonnull byte[] data, @Nonnull String name, @Nonnull
* @param emoji
* The {@link Emoji} reaction to remove as a reaction from this Message.
*
- * @throws java.lang.UnsupportedOperationException
- * If this is a Data Message (output of {@link MessageBuilder MessageBuilder})
* @throws net.dv8tion.jda.api.exceptions.InsufficientPermissionException
* If the MessageChannel this message was sent in was a {@link GuildChannel}
* and the logged in account does not have {@link Permission#MESSAGE_HISTORY Permission.MESSAGE_HISTORY}
@@ -1796,8 +1665,6 @@ default MessageAction reply(@Nonnull byte[] data, @Nonnull String name, @Nonnull
* @param user
* The {@link User} to remove the reaction for.
*
- * @throws java.lang.UnsupportedOperationException
- * If this is a Data Message (output of {@link MessageBuilder MessageBuilder})
* @throws net.dv8tion.jda.api.exceptions.InsufficientPermissionException
* If the MessageChannel this message was sent in was a {@link GuildChannel}
* and the logged in account does not have {@link Permission#MESSAGE_HISTORY Permission.MESSAGE_HISTORY}.
@@ -1848,8 +1715,6 @@ default MessageAction reply(@Nonnull byte[] data, @Nonnull String name, @Nonnull
* @param emoji
* The {@link Emoji} to retrieve users for.
*
- * @throws java.lang.UnsupportedOperationException
- * If this is a Data Message (output of {@link MessageBuilder MessageBuilder})
* @throws net.dv8tion.jda.api.exceptions.InsufficientPermissionException
* If the MessageChannel this message was sent in was a {@link GuildChannel} and the
* logged in account does not have {@link Permission#MESSAGE_HISTORY Permission.MESSAGE_HISTORY} in the channel.
@@ -1873,8 +1738,6 @@ default MessageAction reply(@Nonnull byte[] data, @Nonnull String name, @Nonnull
* @param emoji
* The unicode or custom emoji of the reaction emoji
*
- * @throws java.lang.UnsupportedOperationException
- * If this is a Data Message (output of {@link MessageBuilder MessageBuilder})
* @throws java.lang.IllegalArgumentException
* If the provided emoji is null
*
@@ -1905,9 +1768,8 @@ default MessageAction reply(@Nonnull byte[] data, @Nonnull String name, @Nonnull
*
*
* @param suppressed
- * Whether or not the embed should be suppressed
- * @throws java.lang.UnsupportedOperationException
- * If this is a Data Message (output of {@link MessageBuilder MessageBuilder})
+ * Whether the embed should be suppressed
+ *
* @throws net.dv8tion.jda.api.exceptions.InsufficientPermissionException
* If the MessageChannel this message was sent in was a {@link GuildChannel}
* and the currently logged in account does not have
@@ -1950,8 +1812,6 @@ default MessageAction reply(@Nonnull byte[] data, @Nonnull String name, @Nonnull
* The request was attempted after the channel was deleted.
*
*
- * @throws java.lang.UnsupportedOperationException
- * If this is a Data Message (output of {@link MessageBuilder MessageBuilder})
* @throws IllegalStateException
*
* If the channel is not a {@link NewsChannel}.
@@ -1978,9 +1838,6 @@ default MessageAction reply(@Nonnull byte[] data, @Nonnull String name, @Nonnull
* This is a shortcut method for checking if {@link #getFlags() getFlags()} contains
* {@link net.dv8tion.jda.api.entities.Message.MessageFlag#EMBEDS_SUPPRESSED MessageFlag#EMBEDS_SUPPRESSED}
*
- * @throws java.lang.UnsupportedOperationException
- * If this is a Data Message (output of {@link MessageBuilder MessageBuilder})
- *
* @return Whether or not Embeds are suppressed for this Message.
*
* @see #suppressEmbeds(boolean)
@@ -1990,9 +1847,6 @@ default MessageAction reply(@Nonnull byte[] data, @Nonnull String name, @Nonnull
/**
* Returns an EnumSet of all {@link Message.MessageFlag MessageFlags} present for this Message.
*
- * @throws java.lang.UnsupportedOperationException
- * If this is a Data Message (output of {@link MessageBuilder MessageBuilder})
- *
* @return Never-Null EnumSet of present {@link Message.MessageFlag MessageFlags}
*
* @see Message.MessageFlag
@@ -2003,9 +1857,6 @@ default MessageAction reply(@Nonnull byte[] data, @Nonnull String name, @Nonnull
/**
* Returns the raw message flags of this message
*
- * @throws java.lang.UnsupportedOperationException
- * If this is a Data Message (output of {@link MessageBuilder MessageBuilder})
- *
* @return The raw message flags
*
* @see #getFlags()
@@ -2017,9 +1868,6 @@ default MessageAction reply(@Nonnull byte[] data, @Nonnull String name, @Nonnull
* The message being ephemeral means it is only visible to the bot and the interacting user
* This is a shortcut method for checking if {@link #getFlags()} contains {@link MessageFlag#EPHEMERAL}
*
- * @throws java.lang.UnsupportedOperationException
- * If this is a Data Message (output of {@link MessageBuilder MessageBuilder})
- *
* @return Whether the message is ephemeral
*/
boolean isEphemeral();
@@ -2040,9 +1888,6 @@ default MessageAction reply(@Nonnull byte[] data, @Nonnull String name, @Nonnull
* inform about events that occur. Messages can either be {@link net.dv8tion.jda.api.entities.MessageType#DEFAULT default messages}
* or special messages like {@link net.dv8tion.jda.api.entities.MessageType#GUILD_MEMBER_JOIN welcome messages}.
*
- * @throws java.lang.UnsupportedOperationException
- * If this is a Data Message (output of {@link MessageBuilder MessageBuilder})
- *
* @return The {@link net.dv8tion.jda.api.entities.MessageType MessageType} of this message.
*/
@Nonnull
@@ -2053,9 +1898,6 @@ default MessageAction reply(@Nonnull byte[] data, @Nonnull String name, @Nonnull
*
* This means responses to Message Components do not include this property, instead including a message reference object as components always exist on preexisting messages.
*
- * @throws java.lang.UnsupportedOperationException
- * If this is a Data Message (output of {@link MessageBuilder MessageBuilder})
- *
* @return The {@link net.dv8tion.jda.api.entities.Message.Interaction Interaction} of this message.
*/
@Nullable
@@ -2116,7 +1958,7 @@ public Pattern getPattern()
/**
* The Key returned by this method is used to determine the group or parsable mention group they are part of.
- * It is used internally in methods like {@link net.dv8tion.jda.api.requests.restaction.MessageAction#allowedMentions(Collection) MessageAction#allowedMentions(Collection)}.
+ * It is used internally in methods like {@link MessageRequest#setAllowedMentions(Collection)}.
*
* Returns {@code null}, when they don't belong to any mention group.
*
@@ -2177,6 +2019,7 @@ enum MessageFlag
/**
* Returns the value of the MessageFlag as represented in the bitfield. It is always a power of 2 (single bit)
+ *
* @return Non-Zero bit value of the field
*/
public int getValue()
@@ -2224,7 +2067,7 @@ public static int toBitField(@Nonnull Collection coll)
/**
* Represents a {@link net.dv8tion.jda.api.entities.Message Message} file attachment.
*/
- class Attachment implements ISnowflake
+ class Attachment implements ISnowflake, AttachedFile
{
private static final Set IMAGE_EXTENSIONS = new HashSet<>(Arrays.asList("jpg",
"jpeg", "png", "gif", "webp", "tiff", "svg", "apng"));
@@ -2699,6 +2542,21 @@ public boolean isSpoiler()
return getFileName().startsWith("SPOILER_");
}
+ @Override
+ public void close() {}
+
+ @Override
+ public void forceClose() {}
+
+ @Override
+ public void addPart(@Nonnull MultipartBody.Builder builder, int index) {}
+
+ @Nonnull
+ @Override
+ public DataObject toAttachmentData(int index)
+ {
+ return DataObject.empty().put("id", id);
+ }
}
/**
diff --git a/src/main/java/net/dv8tion/jda/api/entities/MessageChannel.java b/src/main/java/net/dv8tion/jda/api/entities/MessageChannel.java
index 773f6d7648..d4d5eee6e7 100644
--- a/src/main/java/net/dv8tion/jda/api/entities/MessageChannel.java
+++ b/src/main/java/net/dv8tion/jda/api/entities/MessageChannel.java
@@ -24,19 +24,24 @@
import net.dv8tion.jda.api.interactions.components.selections.SelectMenu;
import net.dv8tion.jda.api.requests.RestAction;
import net.dv8tion.jda.api.requests.restaction.AuditableRestAction;
-import net.dv8tion.jda.api.requests.restaction.MessageAction;
+import net.dv8tion.jda.api.requests.restaction.MessageCreateAction;
+import net.dv8tion.jda.api.requests.restaction.MessageEditAction;
import net.dv8tion.jda.api.requests.restaction.pagination.MessagePaginationAction;
import net.dv8tion.jda.api.requests.restaction.pagination.PaginationAction;
import net.dv8tion.jda.api.requests.restaction.pagination.ReactionPaginationAction;
-import net.dv8tion.jda.api.utils.AttachmentOption;
+import net.dv8tion.jda.api.utils.AttachedFile;
+import net.dv8tion.jda.api.utils.FileUpload;
import net.dv8tion.jda.api.utils.MiscUtil;
import net.dv8tion.jda.api.utils.data.DataArray;
+import net.dv8tion.jda.api.utils.messages.MessageCreateData;
+import net.dv8tion.jda.api.utils.messages.MessageEditData;
import net.dv8tion.jda.internal.JDAImpl;
import net.dv8tion.jda.internal.entities.EntityBuilder;
import net.dv8tion.jda.internal.requests.RestActionImpl;
import net.dv8tion.jda.internal.requests.Route;
import net.dv8tion.jda.internal.requests.restaction.AuditableRestActionImpl;
-import net.dv8tion.jda.internal.requests.restaction.MessageActionImpl;
+import net.dv8tion.jda.internal.requests.restaction.MessageCreateActionImpl;
+import net.dv8tion.jda.internal.requests.restaction.MessageEditActionImpl;
import net.dv8tion.jda.internal.requests.restaction.pagination.MessagePaginationActionImpl;
import net.dv8tion.jda.internal.requests.restaction.pagination.ReactionPaginationActionImpl;
import net.dv8tion.jda.internal.utils.Checks;
@@ -44,7 +49,8 @@
import javax.annotation.CheckReturnValue;
import javax.annotation.Nonnull;
-import java.io.*;
+import java.io.File;
+import java.io.InputStream;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.function.Function;
@@ -279,511 +285,345 @@ default List> purgeMessagesById(@Nonnull long... message
}
/**
- * Sends a plain text message to this channel.
- * This will fail if this channel is an instance of {@link net.dv8tion.jda.api.entities.GuildMessageChannel GuildMessageChannel} and
- * the currently logged in account does not have permissions to send a message to this channel.
- * To determine if you are able to send a message in a {@link net.dv8tion.jda.api.entities.GuildMessageChannel GuildMessageChannel} use
- * {@link net.dv8tion.jda.api.entities.Member#hasPermission(GuildChannel, net.dv8tion.jda.api.Permission...)
- * guild.getSelfMember().hasPermission(channel, Permission.MESSAGE_SEND)}.
+ * Send a message to this channel.
*
- * For {@link net.dv8tion.jda.api.requests.ErrorResponse} information, refer to {@link #sendMessage(Message)}.
- *
- * @param text
- * the text to send to the MessageChannel.
- *
- * @throws net.dv8tion.jda.api.exceptions.InsufficientPermissionException
- * If this is a {@link net.dv8tion.jda.api.entities.GuildMessageChannel GuildMessageChannel} and the logged in account does
- * not have {@link net.dv8tion.jda.api.Permission#MESSAGE_SEND Permission.MESSAGE_SEND}
- * @throws java.lang.IllegalArgumentException
- * if the provided text is null, empty or longer than 2000 characters
- * @throws java.lang.UnsupportedOperationException
- * If this is a {@link net.dv8tion.jda.api.entities.PrivateChannel PrivateChannel}
- * and both the currently logged in account and the target user are bots.
- *
- * @return {@link MessageAction MessageAction}
- * The newly created Message after it has been sent to Discord.
- *
- * @see net.dv8tion.jda.api.MessageBuilder
- */
- @Nonnull
- @CheckReturnValue
- default MessageAction sendMessage(@Nonnull CharSequence text)
- {
- Checks.notEmpty(text, "Provided text for message");
- Checks.check(text.length() <= Message.MAX_CONTENT_LENGTH, "Provided text for message must be less than %d characters in length", Message.MAX_CONTENT_LENGTH);
-
- if (text instanceof StringBuilder)
- return new MessageActionImpl(getJDA(), null, this, (StringBuilder) text);
- else
- return new MessageActionImpl(getJDA(), null, this).append(text);
- }
-
- /**
- * Sends a formatted text message to this channel.
- * This will fail if this channel is an instance of {@link net.dv8tion.jda.api.entities.GuildMessageChannel GuildMessageChannel} and
- * the currently logged in account does not have permissions to send a message to this channel.
- * To determine if you are able to send a message in a {@link net.dv8tion.jda.api.entities.GuildMessageChannel GuildMessageChannel} use
- * {@link net.dv8tion.jda.api.entities.Member#hasPermission(GuildChannel, net.dv8tion.jda.api.Permission...)
- * guild.getSelfMember().hasPermission(channel, Permission.MESSAGE_SEND)}.
+ *
Possible {@link net.dv8tion.jda.api.requests.ErrorResponse ErrorResponses} include:
+ *
+ * {@link net.dv8tion.jda.api.requests.ErrorResponse#UNKNOWN_CHANNEL UNKNOWN_CHANNEL}
+ * if this channel was deleted
*
- * For {@link net.dv8tion.jda.api.requests.ErrorResponse} information, refer to {@link #sendMessage(Message)}.
+ *
{@link net.dv8tion.jda.api.requests.ErrorResponse#CANNOT_SEND_TO_USER CANNOT_SEND_TO_USER}
+ * If this is a {@link net.dv8tion.jda.api.entities.PrivateChannel PrivateChannel} and the currently logged in account
+ * does not share any Guilds with the recipient User
+ *
*
- * @param format
- * The string that should be formatted, if this is {@code null} or empty
- * the content of the Message would be empty and cause a builder exception.
- * @param args
- * The arguments for your format
+ * @param text
+ * The message content
*
+ * @throws UnsupportedOperationException
+ * If this is a {@link PrivateChannel} and the recipient is a bot
+ * @throws IllegalArgumentException
+ * If the content is null or longer than {@value Message#MAX_CONTENT_LENGTH} characters
* @throws net.dv8tion.jda.api.exceptions.InsufficientPermissionException
- * If this is a {@link net.dv8tion.jda.api.entities.GuildMessageChannel GuildMessageChannel} and the logged in account does
- * not have
- *
- * {@link net.dv8tion.jda.api.Permission#VIEW_CHANNEL Permission.VIEW_CHANNEL}
- * {@link net.dv8tion.jda.api.Permission#MESSAGE_SEND Permission.MESSAGE_SEND}
- *
- * @throws java.lang.IllegalArgumentException
- * If the provided format text is {@code null}, empty or longer than 2000 characters
- * @throws java.lang.UnsupportedOperationException
- * If this is a {@link net.dv8tion.jda.api.entities.PrivateChannel PrivateChannel}
- * and both the currently logged in account and the target user are bots.
- * @throws java.util.IllegalFormatException
- * If a format string contains an illegal syntax,
- * a format specifier that is incompatible with the given arguments,
- * insufficient arguments given the format string, or other illegal conditions.
- * For specification of all possible formatting errors,
- * see the Details
- * section of the formatter class specification.
+ * If this is a {@link net.dv8tion.jda.api.entities.GuildMessageChannel GuildMessageChannel} and this account does not have
+ * {@link net.dv8tion.jda.api.Permission#VIEW_CHANNEL Permission.VIEW_CHANNEL} or {@link net.dv8tion.jda.api.Permission#MESSAGE_SEND Permission.MESSAGE_SEND}
*
- * @return {@link MessageAction MessageAction}
- * The newly created Message after it has been sent to Discord.
+ * @return {@link MessageCreateAction}
*/
@Nonnull
@CheckReturnValue
- default MessageAction sendMessageFormat(@Nonnull String format, @Nonnull Object... args)
+ default MessageCreateAction sendMessage(@Nonnull CharSequence text)
{
- Checks.notEmpty(format, "Format");
- return sendMessage(String.format(format, args));
+ Checks.notNull(text, "Content");
+ return new MessageCreateActionImpl(this).setContent(text.toString());
}
/**
- * Sends up to {@value Message#MAX_EMBED_COUNT} specified {@link net.dv8tion.jda.api.entities.MessageEmbed MessageEmbeds} as a {@link net.dv8tion.jda.api.entities.Message Message}
- * to this channel.
- * This will fail if this channel is an instance of {@link net.dv8tion.jda.api.entities.GuildMessageChannel GuildMessageChannel} and
- * the currently logged in account does not have permissions to send a message to this channel.
- * To determine if you are able to send a message in a {@link net.dv8tion.jda.api.entities.GuildMessageChannel GuildMessageChannel} use
- * {@link net.dv8tion.jda.api.entities.Member#hasPermission(GuildChannel, net.dv8tion.jda.api.Permission...)
- * guild.getSelfMember().hasPermission(channel, Permission.MESSAGE_SEND)}.
- *
- * For {@link net.dv8tion.jda.api.requests.ErrorResponse} information, refer to {@link #sendMessage(Message)}.
- *
- * @param embed
- * The {@link MessageEmbed MessageEmbed} to send
- * @param other
- * Additional {@link net.dv8tion.jda.api.entities.MessageEmbed MessageEmbeds} to send
+ * Send a message to this channel.
*
- * @throws net.dv8tion.jda.api.exceptions.InsufficientPermissionException
- * If this is a {@link net.dv8tion.jda.api.entities.GuildMessageChannel GuildMessageChannel} and the logged in account does
- * not have
- *
- * {@link net.dv8tion.jda.api.Permission#VIEW_CHANNEL Permission.VIEW_CHANNEL}
- * {@link net.dv8tion.jda.api.Permission#MESSAGE_SEND Permission.MESSAGE_SEND}
- * {@link net.dv8tion.jda.api.Permission#MESSAGE_EMBED_LINKS Permission.MESSAGE_EMBED_LINKS}
- *
- * @throws java.lang.IllegalArgumentException
- * If null is provided, any of the embeds are not {@link MessageEmbed#isSendable() sendable}, more than {@value Message#MAX_EMBED_COUNT} embeds are provided,
- * or the sum of {@link MessageEmbed#getLength()} is greater than {@link MessageEmbed#EMBED_MAX_LENGTH_BOT}
- * @throws java.lang.UnsupportedOperationException
- * If this is a {@link net.dv8tion.jda.api.entities.PrivateChannel PrivateChannel}
- * and both the currently logged in account and the target user are bots.
- *
- * @return {@link MessageAction MessageAction}
- * The newly created Message after it has been sent to Discord.
- *
- * @see net.dv8tion.jda.api.MessageBuilder
- * @see net.dv8tion.jda.api.EmbedBuilder
- */
- @Nonnull
- @CheckReturnValue
- default MessageAction sendMessageEmbeds(@Nonnull MessageEmbed embed, @Nonnull MessageEmbed... other)
- {
- Checks.notNull(embed, "MessageEmbeds");
- Checks.noneNull(other, "MessageEmbeds");
- List embeds = new ArrayList<>(1 + other.length);
- embeds.add(embed);
- Collections.addAll(embeds, other);
- return new MessageActionImpl(getJDA(), null, this).setEmbeds(embeds);
- }
-
- /**
- * Sends up to {@value Message#MAX_EMBED_COUNT} specified {@link net.dv8tion.jda.api.entities.MessageEmbed MessageEmbeds} as a {@link net.dv8tion.jda.api.entities.Message Message}
- * to this channel.
- * This will fail if this channel is an instance of {@link net.dv8tion.jda.api.entities.GuildMessageChannel GuildMessageChannel} and
- * the currently logged in account does not have permissions to send a message to this channel.
- * To determine if you are able to send a message in a {@link net.dv8tion.jda.api.entities.GuildMessageChannel GuildMessageChannel} use
- * {@link net.dv8tion.jda.api.entities.Member#hasPermission(GuildChannel, net.dv8tion.jda.api.Permission...)
- * guild.getSelfMember().hasPermission(channel, Permission.MESSAGE_SEND)}.
+ * Possible {@link net.dv8tion.jda.api.requests.ErrorResponse ErrorResponses} include:
+ *
+ * {@link net.dv8tion.jda.api.requests.ErrorResponse#UNKNOWN_CHANNEL UNKNOWN_CHANNEL}
+ * if this channel was deleted
*
- * For {@link net.dv8tion.jda.api.requests.ErrorResponse} information, refer to {@link #sendMessage(Message)}.
+ *
{@link net.dv8tion.jda.api.requests.ErrorResponse#CANNOT_SEND_TO_USER CANNOT_SEND_TO_USER}
+ * If this is a {@link net.dv8tion.jda.api.entities.PrivateChannel PrivateChannel} and the currently logged in account
+ * does not share any Guilds with the recipient User
+ *
*
- * @param embeds
- * The {@link net.dv8tion.jda.api.entities.MessageEmbed MessageEmbeds} to send
+ * @param msg
+ * The {@link MessageCreateData} to send
*
+ * @throws UnsupportedOperationException
+ * If this is a {@link PrivateChannel} and the recipient is a bot
+ * @throws IllegalArgumentException
+ * If null is provided
* @throws net.dv8tion.jda.api.exceptions.InsufficientPermissionException
- * If this is a {@link net.dv8tion.jda.api.entities.GuildMessageChannel GuildMessageChannel} and the logged in account does
- * not have
- *
- * {@link net.dv8tion.jda.api.Permission#VIEW_CHANNEL Permission.VIEW_CHANNEL}
- * {@link net.dv8tion.jda.api.Permission#MESSAGE_SEND Permission.MESSAGE_SEND}
- * {@link net.dv8tion.jda.api.Permission#MESSAGE_EMBED_LINKS Permission.MESSAGE_EMBED_LINKS}
- *
- * @throws java.lang.IllegalArgumentException
- * If any of the provided embeds is {@code null} or if the provided {@link net.dv8tion.jda.api.entities.MessageEmbed MessageEmbed}
- * is not {@link net.dv8tion.jda.api.entities.MessageEmbed#isSendable() sendable}
- * @throws java.lang.UnsupportedOperationException
- * If this is a {@link net.dv8tion.jda.api.entities.PrivateChannel PrivateChannel}
- * and both the currently logged in account and the target user are bots.
+ * If this is a {@link net.dv8tion.jda.api.entities.GuildMessageChannel GuildMessageChannel} and this account does not have
+ * {@link net.dv8tion.jda.api.Permission#VIEW_CHANNEL Permission.VIEW_CHANNEL} or {@link net.dv8tion.jda.api.Permission#MESSAGE_SEND Permission.MESSAGE_SEND}
*
- * @return {@link MessageAction MessageAction}
- * The newly created Message after it has been sent to Discord.
+ * @return {@link MessageCreateAction}
*
- * @see net.dv8tion.jda.api.MessageBuilder
- * @see net.dv8tion.jda.api.EmbedBuilder
+ * @see net.dv8tion.jda.api.utils.messages.MessageCreateBuilder MessageCreateBuilder
*/
@Nonnull
@CheckReturnValue
- default MessageAction sendMessageEmbeds(@Nonnull Collection extends MessageEmbed> embeds)
+ default MessageCreateAction sendMessage(@Nonnull MessageCreateData msg)
{
- return new MessageActionImpl(getJDA(), null, this).setEmbeds(embeds);
+ Checks.notNull(msg, "Message");
+ return new MessageCreateActionImpl(this).applyData(msg);
}
/**
- * Sends a specified {@link net.dv8tion.jda.api.entities.Message Message} to this channel.
- * This will fail if this channel is an instance of {@link net.dv8tion.jda.api.entities.GuildMessageChannel GuildMessageChannel} and
- * the currently logged in account does not have permissions to send a message to this channel.
- * To determine if you are able to send a message in a {@link net.dv8tion.jda.api.entities.GuildMessageChannel GuildMessageChannel} use
- * {@link net.dv8tion.jda.api.entities.Member#hasPermission(GuildChannel, net.dv8tion.jda.api.Permission...)
- * guild.getSelfMember().hasPermission(channel, Permission.MESSAGE_SEND)}.
+ * Send a message to this channel.
*
- * The following {@link net.dv8tion.jda.api.requests.ErrorResponse ErrorResponses} are possible:
+ *
Possible {@link net.dv8tion.jda.api.requests.ErrorResponse ErrorResponses} include:
*
- * {@link net.dv8tion.jda.api.requests.ErrorResponse#MISSING_ACCESS MISSING_ACCESS}
- * The request was attempted after the account lost access to the {@link net.dv8tion.jda.api.entities.Guild Guild}
- * typically due to being kicked or removed, or after {@link net.dv8tion.jda.api.Permission#VIEW_CHANNEL Permission.VIEW_CHANNEL}
- * was revoked in the {@link net.dv8tion.jda.api.entities.GuildMessageChannel GuildMessageChannel}
- *
- * {@link net.dv8tion.jda.api.requests.ErrorResponse#MISSING_PERMISSIONS MISSING_PERMISSIONS}
- * The send request was attempted after the account lost {@link net.dv8tion.jda.api.Permission#MESSAGE_SEND Permission.MESSAGE_SEND} in
- * the {@link net.dv8tion.jda.api.entities.GuildMessageChannel GuildMessageChannel}.
+ * {@link net.dv8tion.jda.api.requests.ErrorResponse#UNKNOWN_CHANNEL UNKNOWN_CHANNEL}
+ * if this channel was deleted
*
* {@link net.dv8tion.jda.api.requests.ErrorResponse#CANNOT_SEND_TO_USER CANNOT_SEND_TO_USER}
* If this is a {@link net.dv8tion.jda.api.entities.PrivateChannel PrivateChannel} and the currently logged in account
* does not share any Guilds with the recipient User
- *
- * {@link net.dv8tion.jda.api.requests.ErrorResponse#UNKNOWN_CHANNEL UNKNOWN_CHANNEL}
- * The send request was attempted after the channel was deleted.
*
*
- * @param msg
- * the {@link net.dv8tion.jda.api.entities.Message Message} to send
+ * @param format
+ * Format string for the message content
+ * @param args
+ * Format arguments for the content
*
+ * @throws UnsupportedOperationException
+ * If this is a {@link PrivateChannel} and the recipient is a bot
+ * @throws IllegalArgumentException
+ * If the format string is null or the resulting content is longer than {@value Message#MAX_CONTENT_LENGTH} characters
* @throws net.dv8tion.jda.api.exceptions.InsufficientPermissionException
- * If this is a {@link net.dv8tion.jda.api.entities.GuildMessageChannel GuildMessageChannel} and the logged in account does
- * not have
- *
- * {@link net.dv8tion.jda.api.Permission#VIEW_CHANNEL Permission.VIEW_CHANNEL}
- * {@link net.dv8tion.jda.api.Permission#MESSAGE_SEND Permission.MESSAGE_SEND}
- * {@link net.dv8tion.jda.api.Permission#MESSAGE_EMBED_LINKS Permission.MESSAGE_EMBED_LINKS} (if this message is only an embed)
- *
- * @throws java.lang.IllegalArgumentException
- * If the provided message is {@code null} or the provided {@link net.dv8tion.jda.api.entities.Message Message}
- * contains a {@link net.dv8tion.jda.api.entities.MessageEmbed MessageEmbed}
- * that is not {@link net.dv8tion.jda.api.entities.MessageEmbed#isSendable() sendable}
- * @throws java.lang.UnsupportedOperationException
- * If this is a {@link net.dv8tion.jda.api.entities.PrivateChannel PrivateChannel}
- * and both the currently logged in account and the target user are bots.
- *
- * @return {@link MessageAction MessageAction}
- * The newly created Message after it has been sent to Discord.
- *
- * @see net.dv8tion.jda.api.MessageBuilder
+ * If this is a {@link net.dv8tion.jda.api.entities.GuildMessageChannel GuildMessageChannel} and this account does not have
+ * {@link net.dv8tion.jda.api.Permission#VIEW_CHANNEL Permission.VIEW_CHANNEL} or {@link net.dv8tion.jda.api.Permission#MESSAGE_SEND Permission.MESSAGE_SEND}
+ * @throws java.util.IllegalFormatException
+ * If a format string contains an illegal syntax, a format
+ * specifier that is incompatible with the given arguments,
+ * insufficient arguments given the format string, or other
+ * illegal conditions. For specification of all possible
+ * formatting errors, see the Details section of the
+ * formatter class specification.
+ *
+ * @return {@link MessageCreateAction}
*/
@Nonnull
@CheckReturnValue
- default MessageAction sendMessage(@Nonnull Message msg)
+ default MessageCreateAction sendMessageFormat(@Nonnull String format, @Nonnull Object... args)
{
- Checks.notNull(msg, "Message");
- return new MessageActionImpl(getJDA(), null, this).apply(msg);
+ Checks.notEmpty(format, "Format");
+ return sendMessage(String.format(format, args));
}
/**
- * Uploads a file to the Discord servers and sends it to this {@link net.dv8tion.jda.api.entities.MessageChannel MessageChannel}.
- * Sends the provided {@link net.dv8tion.jda.api.entities.Message Message} with the uploaded file.
- * If you want to send a Message with the uploaded file, you can add the file to the {@link net.dv8tion.jda.api.requests.restaction.MessageAction}
- * returned by {@link #sendMessage(Message)}.
+ * Send a message to this channel.
*
- * This is a shortcut to {@link #sendFile(java.io.File, String, AttachmentOption...)} by way of using {@link java.io.File#getName()}.
- *
sendFile(file, file.getName())
- *
- * Uploading images with Embeds
- * When uploading an image you can reference said image using the specified filename as URI {@code attachment://filename.ext}.
+ *
Possible {@link net.dv8tion.jda.api.requests.ErrorResponse ErrorResponses} include:
+ *
+ * {@link net.dv8tion.jda.api.requests.ErrorResponse#UNKNOWN_CHANNEL UNKNOWN_CHANNEL}
+ * if this channel was deleted
*
- * Example
- *
- * MessageChannel channel; // = reference of a MessageChannel
- * EmbedBuilder embed = new EmbedBuilder();
- * File file = new File("cat.gif");
- * embed.setImage("attachment://cat.gif")
- * .setDescription("This is a cute cat :3");
- * channel.sendFile(file).setEmbeds(embed.build()).queue();
- *
+ * {@link net.dv8tion.jda.api.requests.ErrorResponse#CANNOT_SEND_TO_USER CANNOT_SEND_TO_USER}
+ * If this is a {@link net.dv8tion.jda.api.entities.PrivateChannel PrivateChannel} and the currently logged in account
+ * does not share any Guilds with the recipient User
+ *
*
- * For {@link net.dv8tion.jda.api.requests.ErrorResponse} information, refer to the documentation for {@link #sendFile(java.io.File, String, AttachmentOption...)}.
+ *
Example: Attachment Images
+ *
{@code
+ * // Make a file upload instance which refers to a local file called "myFile.png"
+ * // The second parameter "image.png" is the filename we tell discord to use for the attachment
+ * FileUpload file = FileUpload.fromData(new File("myFile.png"), "image.png");
+ *
+ * // Build a message embed which refers to this attachment by the given name.
+ * // Note that this must be the same name as configured for the attachment, not your local filename.
+ * MessageEmbed embed = new EmbedBuilder()
+ * .setDescription("This is my cute cat :)")
+ * .setImage("attachment://image.png") // refer to the file by using the "attachment://" schema with the filename we gave it above
+ * .build();
+ *
+ * channel.sendMessageEmbeds(embed) // send the embed
+ * .addFiles(file) // add the file as attachment
+ * .queue();
+ * }
*
- * @param file
- * The file to upload to the {@link net.dv8tion.jda.api.entities.MessageChannel MessageChannel}.
- * @param options
- * Possible options to apply to this attachment, such as marking it as spoiler image
+ * @param embed
+ * {@link MessageEmbed} to send
+ * @param other
+ * Additional {@link MessageEmbed MessageEmbeds} to use (up to {@value Message#MAX_EMBED_COUNT})
*
- * @throws java.lang.IllegalArgumentException
- *
- * Provided {@code file} is null.
- * Provided {@code file} does not exist.
- * Provided {@code file} is unreadable.
- * Provided {@code file} is greater than 8 MiB on a normal or 50 MiB on a nitro account.
- *
+ * @throws UnsupportedOperationException
+ * If this is a {@link PrivateChannel} and the recipient is a bot
+ * @throws IllegalArgumentException
+ * If any of the embeds are null, more than {@value Message#MAX_EMBED_COUNT}, or longer than {@link MessageEmbed#EMBED_MAX_LENGTH_BOT}.
* @throws net.dv8tion.jda.api.exceptions.InsufficientPermissionException
- * If this is a {@link net.dv8tion.jda.api.entities.GuildMessageChannel GuildMessageChannel} and the logged in account does not have
- *
- * {@link net.dv8tion.jda.api.Permission#VIEW_CHANNEL Permission.VIEW_CHANNEL}
- * {@link net.dv8tion.jda.api.Permission#MESSAGE_SEND Permission.MESSAGE_SEND}
- * {@link net.dv8tion.jda.api.Permission#MESSAGE_ATTACH_FILES Permission.MESSAGE_ATTACH_FILES}
- *
- * @throws java.lang.UnsupportedOperationException
- * If this is a {@link net.dv8tion.jda.api.entities.PrivateChannel PrivateChannel}
- * and both the currently logged in account and the target user are bots.
+ * If this is a {@link net.dv8tion.jda.api.entities.GuildMessageChannel GuildMessageChannel} and this account does not have
+ * {@link net.dv8tion.jda.api.Permission#VIEW_CHANNEL Permission.VIEW_CHANNEL} or {@link net.dv8tion.jda.api.Permission#MESSAGE_SEND Permission.MESSAGE_SEND}
*
- * @return {@link MessageAction MessageAction}
- * Providing the {@link net.dv8tion.jda.api.entities.Message Message} created from this upload.
+ * @return {@link MessageCreateAction}
*/
@Nonnull
@CheckReturnValue
- default MessageAction sendFile(@Nonnull File file, @Nonnull AttachmentOption... options)
+ default MessageCreateAction sendMessageEmbeds(@Nonnull MessageEmbed embed, @Nonnull MessageEmbed... other)
{
- Checks.notNull(file, "file");
- return sendFile(file, file.getName(), options);
+ Checks.notNull(embed, "MessageEmbeds");
+ Checks.noneNull(other, "MessageEmbeds");
+ List embeds = new ArrayList<>(1 + other.length);
+ embeds.add(embed);
+ Collections.addAll(embeds, other);
+ return new MessageCreateActionImpl(this).setEmbeds(embeds);
}
/**
- * Uploads a file to the Discord servers and sends it to this {@link net.dv8tion.jda.api.entities.MessageChannel MessageChannel}.
- * Sends the provided {@link net.dv8tion.jda.api.entities.Message Message} with the uploaded file.
- * If you want to send a Message with the uploaded file, you can add the file to the {@link net.dv8tion.jda.api.requests.restaction.MessageAction}
- * returned by {@link #sendMessage(Message)}.
- *
- * The {@code fileName} parameter is used to inform Discord about what the file should be called. This is 2 fold:
- *
- * The file name provided is the name that is found in {@link net.dv8tion.jda.api.entities.Message.Attachment#getFileName()}
- * after upload and it is the name that will show up in the client when the upload is displayed.
- * Note: The fileName does not show up on the Desktop client for images. It does on mobile however.
- * The extension of the provided fileName also determines how Discord will treat the file. Discord currently only
- * has special handling for image file types, but the fileName's extension must indicate that it is an image file.
- * This means it has to end in something like .png, .jpg, .jpeg, .gif, etc. As a note, you can also not provide
- * a full name for the file and instead ONLY provide the extension like "png" or "gif" and Discord will generate
- * a name for the upload and append the fileName as the extension.
- *
- *
- * Uploading images with Embeds
- * When uploading an image you can reference said image using the specified filename as URI {@code attachment://filename.ext}.
- *
- *
Example
- *
- * MessageChannel channel; // = reference of a MessageChannel
- * EmbedBuilder embed = new EmbedBuilder();
- * File file = new File("cat_01.gif");
- * embed.setImage("attachment://cat.gif") // we specify this in sendFile as "cat.gif"
- * .setDescription("This is a cute cat :3");
- * channel.sendFile(file, "cat.gif").setEmbeds(embed.build()).queue();
- *
+ * Send a message to this channel.
*
- * The following {@link net.dv8tion.jda.api.requests.ErrorResponse ErrorResponses} are possible:
+ *
Possible {@link net.dv8tion.jda.api.requests.ErrorResponse ErrorResponses} include:
*
- * {@link net.dv8tion.jda.api.requests.ErrorResponse#MISSING_ACCESS MISSING_ACCESS}
- * The send request was attempted after the account lost access to the {@link net.dv8tion.jda.api.entities.Guild Guild}
- * typically due to being kicked or removed.
- *
- * {@link net.dv8tion.jda.api.requests.ErrorResponse#MISSING_PERMISSIONS MISSING_PERMISSIONS}
- * The send request was attempted after the account lost {@link net.dv8tion.jda.api.Permission#MESSAGE_SEND Permission.MESSAGE_SEND} or
- * {@link net.dv8tion.jda.api.Permission#MESSAGE_ATTACH_FILES Permission.MESSAGE_ATTACH_FILES}
- * in the {@link net.dv8tion.jda.api.entities.GuildMessageChannel GuildMessageChannel}.
+ * {@link net.dv8tion.jda.api.requests.ErrorResponse#UNKNOWN_CHANNEL UNKNOWN_CHANNEL}
+ * if this channel was deleted
*
* {@link net.dv8tion.jda.api.requests.ErrorResponse#CANNOT_SEND_TO_USER CANNOT_SEND_TO_USER}
* If this is a {@link net.dv8tion.jda.api.entities.PrivateChannel PrivateChannel} and the currently logged in account
* does not share any Guilds with the recipient User
- *
- * {@link net.dv8tion.jda.api.requests.ErrorResponse#UNKNOWN_CHANNEL UNKNOWN_CHANNEL}
- * The send request was attempted after the channel was deleted.
*
*
- * @param file
- * The file to upload to the {@link net.dv8tion.jda.api.entities.MessageChannel MessageChannel}.
- * @param fileName
- * The name that should be sent to discord
- * @param options
- * Possible options to apply to this attachment, such as marking it as spoiler image
+ * Example: Attachment Images
+ *
{@code
+ * // Make a file upload instance which refers to a local file called "myFile.png"
+ * // The second parameter "image.png" is the filename we tell discord to use for the attachment
+ * FileUpload file = FileUpload.fromData(new File("myFile.png"), "image.png");
+ *
+ * // Build a message embed which refers to this attachment by the given name.
+ * // Note that this must be the same name as configured for the attachment, not your local filename.
+ * MessageEmbed embed = new EmbedBuilder()
+ * .setDescription("This is my cute cat :)")
+ * .setImage("attachment://image.png") // refer to the file by using the "attachment://" schema with the filename we gave it above
+ * .build();
+ *
+ * channel.sendMessageEmbeds(Collections.singleton(embed)) // send the embeds
+ * .addFiles(file) // add the file as attachment
+ * .queue();
+ * }
*
- * @throws java.lang.IllegalArgumentException
- *
- * Provided {@code file} is null.
- * Provided {@code file} does not exist.
- * Provided {@code file} is unreadable.
- * Provided {@code file} is greater than 8 MiB on a normal or 50 MiB on a nitro account.
- *
+ * @param embeds
+ * {@link MessageEmbed MessageEmbeds} to use (up to {@value Message#MAX_EMBED_COUNT})
+ *
+ * @throws UnsupportedOperationException
+ * If this is a {@link PrivateChannel} and the recipient is a bot
+ * @throws IllegalArgumentException
+ * If any of the embeds are null, more than {@value Message#MAX_EMBED_COUNT}, or longer than {@link MessageEmbed#EMBED_MAX_LENGTH_BOT}.
* @throws net.dv8tion.jda.api.exceptions.InsufficientPermissionException
- * If this is a {@link net.dv8tion.jda.api.entities.GuildMessageChannel GuildMessageChannel} and the logged in account does not have
- *
- * {@link net.dv8tion.jda.api.Permission#VIEW_CHANNEL Permission.VIEW_CHANNEL}
- * {@link net.dv8tion.jda.api.Permission#MESSAGE_SEND Permission.MESSAGE_SEND}
- * {@link net.dv8tion.jda.api.Permission#MESSAGE_ATTACH_FILES Permission.MESSAGE_ATTACH_FILES}
- *
- * @throws java.lang.UnsupportedOperationException
- * If this is a {@link net.dv8tion.jda.api.entities.PrivateChannel PrivateChannel}
- * and both the currently logged in account and the target user are bots.
+ * If this is a {@link net.dv8tion.jda.api.entities.GuildMessageChannel GuildMessageChannel} and this account does not have
+ * {@link net.dv8tion.jda.api.Permission#VIEW_CHANNEL Permission.VIEW_CHANNEL} or {@link net.dv8tion.jda.api.Permission#MESSAGE_SEND Permission.MESSAGE_SEND}
*
- * @return {@link MessageAction MessageAction}
- * Providing the {@link net.dv8tion.jda.api.entities.Message Message} created from this upload.
+ * @return {@link MessageCreateAction}
*/
@Nonnull
@CheckReturnValue
- default MessageAction sendFile(@Nonnull File file, @Nonnull String fileName, @Nonnull AttachmentOption... options)
+ default MessageCreateAction sendMessageEmbeds(@Nonnull Collection extends MessageEmbed> embeds)
{
- Checks.notNull(file, "file");
- Checks.check(file.exists() && file.canRead(),
- "Provided file doesn't exist or cannot be read!");
- Checks.notNull(fileName, "fileName");
-
- try
- {
- return sendFile(new FileInputStream(file), fileName, options);
- }
- catch (FileNotFoundException ex)
- {
- throw new IllegalArgumentException(ex);
- }
+ return new MessageCreateActionImpl(this).setEmbeds(embeds);
}
/**
- * Uploads a file to the Discord servers and sends it to this {@link net.dv8tion.jda.api.entities.MessageChannel MessageChannel}.
- * Sends the provided {@link net.dv8tion.jda.api.entities.Message Message} with the uploaded file.
- * If you want to send a Message with the uploaded file, you can add the file to the {@link net.dv8tion.jda.api.requests.restaction.MessageAction}
- * returned by {@link #sendMessage(Message)}.
- * This allows you to send an {@link java.io.InputStream InputStream} as substitute to a file.
+ * Send a message to this channel.
*
- * For information about the {@code fileName} parameter, Refer to the documentation for {@link #sendFile(java.io.File, String, AttachmentOption...)}.
- * For {@link net.dv8tion.jda.api.requests.ErrorResponse} information, refer to the documentation for {@link #sendFile(java.io.File, String, AttachmentOption...)}.
+ *
Resource Handling Note: Once the request is handed off to the requester, for example when you call {@link RestAction#queue()},
+ * the requester will automatically clean up all opened files by itself. You are only responsible to close them yourself if it is never handed off properly.
+ * For instance, if an exception occurs after using {@link FileUpload#fromData(File)}, before calling {@link RestAction#queue()}.
+ * You can safely use a try-with-resources to handle this, since {@link FileUpload#close()} becomes ineffective once the request is handed off.
*
- *
Uploading images with Embeds
- * When uploading an image you can reference said image using the specified filename as URI {@code attachment://filename.ext}.
+ *
Possible {@link net.dv8tion.jda.api.requests.ErrorResponse ErrorResponses} include:
+ *
+ * {@link net.dv8tion.jda.api.requests.ErrorResponse#UNKNOWN_CHANNEL UNKNOWN_CHANNEL}
+ * if this channel was deleted
*
- * Example
- *
- * MessageChannel channel; // = reference of a MessageChannel
- * EmbedBuilder embed = new EmbedBuilder();
- * InputStream file = new URL("https://http.cat/500").openStream();
- * embed.setImage("attachment://cat.png") // we specify this in sendFile as "cat.png"
- * .setDescription("This is a cute cat :3");
- * channel.sendFile(file, "cat.png").setEmbeds(embed.build()).queue();
- *
+ * {@link net.dv8tion.jda.api.requests.ErrorResponse#CANNOT_SEND_TO_USER CANNOT_SEND_TO_USER}
+ * If this is a {@link net.dv8tion.jda.api.entities.PrivateChannel PrivateChannel} and the currently logged in account
+ * does not share any Guilds with the recipient User
+ *
*
- * @param data
- * The InputStream data to upload to the {@link net.dv8tion.jda.api.entities.MessageChannel MessageChannel}.
- * @param fileName
- * The name that should be sent to discord
- * Refer to the documentation for {@link #sendFile(java.io.File, String, AttachmentOption...)} for information about this parameter.
- * @param options
- * Possible options to apply to this attachment, such as marking it as spoiler image
+ * Example: Attachment Images
+ *
{@code
+ * // Make a file upload instance which refers to a local file called "myFile.png"
+ * // The second parameter "image.png" is the filename we tell discord to use for the attachment
+ * FileUpload file = FileUpload.fromData(new File("myFile.png"), "image.png");
+ *
+ * // Build a message embed which refers to this attachment by the given name.
+ * // Note that this must be the same name as configured for the attachment, not your local filename.
+ * MessageEmbed embed = new EmbedBuilder()
+ * .setDescription("This is my cute cat :)")
+ * .setImage("attachment://image.png") // refer to the file by using the "attachment://" schema with the filename we gave it above
+ * .build();
+ *
+ * channel.sendFiles(Collections.singleton(file)) // send the file upload
+ * .addEmbeds(embed) // add the embed you want to reference the file with
+ * .queue();
+ * }
*
- * @throws java.lang.IllegalArgumentException
- * If the provided file or filename is {@code null} or {@code empty}.
+ * @param files
+ * The {@link FileUpload FileUploads} to attach to the message
+ *
+ * @throws UnsupportedOperationException
+ * If this is a {@link PrivateChannel} and the recipient is a bot
+ * @throws IllegalArgumentException
+ * If null is provided
* @throws net.dv8tion.jda.api.exceptions.InsufficientPermissionException
- * If this is a {@link net.dv8tion.jda.api.entities.GuildMessageChannel GuildMessageChannel} and the logged in account does not have
- *
- * {@link net.dv8tion.jda.api.Permission#VIEW_CHANNEL Permission.VIEW_CHANNEL}
- * {@link net.dv8tion.jda.api.Permission#MESSAGE_SEND Permission.MESSAGE_SEND}
- * {@link net.dv8tion.jda.api.Permission#MESSAGE_ATTACH_FILES Permission.MESSAGE_ATTACH_FILES}
- *
- * @throws java.lang.UnsupportedOperationException
- * If this is a {@link net.dv8tion.jda.api.entities.PrivateChannel PrivateChannel}
- * and both the currently logged in account and the target user are bots.
+ * If this is a {@link net.dv8tion.jda.api.entities.GuildMessageChannel GuildMessageChannel} and this account does not have
+ * {@link net.dv8tion.jda.api.Permission#VIEW_CHANNEL Permission.VIEW_CHANNEL} or {@link net.dv8tion.jda.api.Permission#MESSAGE_SEND Permission.MESSAGE_SEND}
+ *
+ * @return {@link MessageCreateAction}
*
- * @return {@link MessageAction MessageAction}
- * Provides the {@link net.dv8tion.jda.api.entities.Message Message} created from this upload.
+ * @see FileUpload#fromData(InputStream, String)
*/
@Nonnull
@CheckReturnValue
- default MessageAction sendFile(@Nonnull InputStream data, @Nonnull String fileName, @Nonnull AttachmentOption... options)
+ default MessageCreateAction sendFiles(@Nonnull Collection extends FileUpload> files)
{
- Checks.notNull(data, "data InputStream");
- Checks.notNull(fileName, "fileName");
- return new MessageActionImpl(getJDA(), null, this).addFile(data, fileName, options);
+ Checks.notEmpty(files, "File Collection");
+ Checks.noneNull(files, "Files");
+ return new MessageCreateActionImpl(this).addFiles(files);
}
/**
- * Uploads a file to the Discord servers and sends it to this {@link net.dv8tion.jda.api.entities.MessageChannel MessageChannel}.
- * Sends the provided {@link net.dv8tion.jda.api.entities.Message Message} with the uploaded file.
- * If you want to send a Message with the uploaded file, you can add the file to the {@link net.dv8tion.jda.api.requests.restaction.MessageAction}
- * returned by {@link #sendMessage(Message)}.
- * This allows you to send an {@code byte[]} as substitute to a file.
+ * Send a message to this channel.
*
- * For information about the {@code fileName} parameter, Refer to the documentation for {@link #sendFile(java.io.File, String, AttachmentOption...)}.
- * For {@link net.dv8tion.jda.api.requests.ErrorResponse} information, refer to the documentation for {@link #sendFile(java.io.File, String, AttachmentOption...)}.
+ *
Resource Handling Note: Once the request is handed off to the requester, for example when you call {@link RestAction#queue()},
+ * the requester will automatically clean up all opened files by itself. You are only responsible to close them yourself if it is never handed off properly.
+ * For instance, if an exception occurs after using {@link FileUpload#fromData(File)}, before calling {@link RestAction#queue()}.
+ * You can safely use a try-with-resources to handle this, since {@link FileUpload#close()} becomes ineffective once the request is handed off.
*
- *
Uploading images with Embeds
- * When uploading an image you can reference said image using the specified filename as URI {@code attachment://filename.ext}.
+ *
Possible {@link net.dv8tion.jda.api.requests.ErrorResponse ErrorResponses} include:
+ *
+ * {@link net.dv8tion.jda.api.requests.ErrorResponse#UNKNOWN_CHANNEL UNKNOWN_CHANNEL}
+ * if this channel was deleted
*
- * Example
- *
- * MessageChannel channel; // = reference of a MessageChannel
- * EmbedBuilder embed = new EmbedBuilder();
- * byte[] file = IOUtil.readFully(new URL("https://http.cat/500").openStream());
- * embed.setImage("attachment://cat.png") // we specify this in sendFile as "cat.png"
- * .setDescription("This is a cute cat :3");
- * channel.sendFile(file, "cat.png").setEmbeds(embed.build()).queue();
- *
+ * {@link net.dv8tion.jda.api.requests.ErrorResponse#CANNOT_SEND_TO_USER CANNOT_SEND_TO_USER}
+ * If this is a {@link net.dv8tion.jda.api.entities.PrivateChannel PrivateChannel} and the currently logged in account
+ * does not share any Guilds with the recipient User
+ *
*
- * @param data
- * The {@code byte[]} data to upload to the {@link net.dv8tion.jda.api.entities.MessageChannel MessageChannel}.
- * @param fileName
- * The name that should be sent to discord.
- * Refer to the documentation for {@link #sendFile(java.io.File, String, AttachmentOption...)} for information about this parameter.
- * @param options
- * Possible options to apply to this attachment, such as marking it as spoiler image
+ * Example: Attachment Images
+ *
{@code
+ * // Make a file upload instance which refers to a local file called "myFile.png"
+ * // The second parameter "image.png" is the filename we tell discord to use for the attachment
+ * FileUpload file = FileUpload.fromData(new File("myFile.png"), "image.png");
+ *
+ * // Build a message embed which refers to this attachment by the given name.
+ * // Note that this must be the same name as configured for the attachment, not your local filename.
+ * MessageEmbed embed = new EmbedBuilder()
+ * .setDescription("This is my cute cat :)")
+ * .setImage("attachment://image.png") // refer to the file by using the "attachment://" schema with the filename we gave it above
+ * .build();
+ *
+ * channel.sendFiles(file) // send the file upload
+ * .addEmbeds(embed) // add the embed you want to reference the file with
+ * .queue();
+ * }
*
- * @throws java.lang.IllegalArgumentException
- *
- * If the provided filename is {@code null} or {@code empty}
- * If the provided data is larger than 8 MiB on a normal or 50 MiB on a nitro account
- *
+ * @param files
+ * The {@link FileUpload FileUploads} to attach to the message
+ *
+ * @throws UnsupportedOperationException
+ * If this is a {@link PrivateChannel} and the recipient is a bot
+ * @throws IllegalArgumentException
+ * If null is provided
* @throws net.dv8tion.jda.api.exceptions.InsufficientPermissionException
- * If this is a {@link net.dv8tion.jda.api.entities.GuildMessageChannel GuildMessageChannel} and the logged in account does not have
- *
- * {@link net.dv8tion.jda.api.Permission#VIEW_CHANNEL Permission.VIEW_CHANNEL}
- * {@link net.dv8tion.jda.api.Permission#MESSAGE_SEND Permission.MESSAGE_SEND}
- * {@link net.dv8tion.jda.api.Permission#MESSAGE_ATTACH_FILES Permission.MESSAGE_ATTACH_FILES}
- *
- * @throws java.lang.UnsupportedOperationException
- * If this is a {@link net.dv8tion.jda.api.entities.PrivateChannel PrivateChannel}
- * and both the currently logged in account and the target user are bots.
+ * If this is a {@link net.dv8tion.jda.api.entities.GuildMessageChannel GuildMessageChannel} and this account does not have
+ * {@link net.dv8tion.jda.api.Permission#VIEW_CHANNEL Permission.VIEW_CHANNEL} or {@link net.dv8tion.jda.api.Permission#MESSAGE_SEND Permission.MESSAGE_SEND}
*
- * @return {@link MessageAction MessageAction}
- * Provides the {@link net.dv8tion.jda.api.entities.Message Message} created from this upload.
+ * @return {@link MessageCreateAction}
+ *
+ * @see FileUpload#fromData(InputStream, String)
*/
@Nonnull
@CheckReturnValue
- default MessageAction sendFile(@Nonnull byte[] data, @Nonnull String fileName, @Nonnull AttachmentOption... options)
+ default MessageCreateAction sendFiles(@Nonnull FileUpload... files)
{
- Checks.notNull(data, "data");
- Checks.notNull(fileName, "fileName");
-
- return sendFile(new ByteArrayInputStream(data), fileName, options);
+ Checks.notEmpty(files, "File Collection");
+ Checks.noneNull(files, "Files");
+ return sendFiles(Arrays.asList(files));
}
/**
@@ -2222,8 +2062,7 @@ default RestAction> retrievePinnedMessages()
}
/**
- * Attempts to edit a message by its id in this MessageChannel. The string provided as {@code newContent} must
- * have a length that is greater than 0 and less-than or equal to 2000. This is a Discord message length limitation.
+ * Attempts to edit a message by its id in this channel.
*
* The following {@link net.dv8tion.jda.api.requests.ErrorResponse ErrorResponses} are possible:
*
@@ -2253,31 +2092,26 @@ default RestAction> retrievePinnedMessages()
*
* If provided {@code messageId} is {@code null} or empty.
* If provided {@code newContent} is {@code null} or empty.
- * If provided {@code newContent} length is greater than {@code 2000} characters.
+ * If provided {@code newContent} length is greater than {@value Message#MAX_CONTENT_LENGTH} characters.
*
* @throws net.dv8tion.jda.api.exceptions.InsufficientPermissionException
* If this is a {@link net.dv8tion.jda.api.entities.GuildMessageChannel GuildMessageChannel} and this account does not have
* {@link net.dv8tion.jda.api.Permission#VIEW_CHANNEL Permission.VIEW_CHANNEL}
*
- * @return {@link MessageAction MessageAction}
- * The modified Message after it has been sent to Discord.
+ * @return {@link MessageEditAction}
*/
@Nonnull
@CheckReturnValue
- default MessageAction editMessageById(@Nonnull String messageId, @Nonnull CharSequence newContent)
+ default MessageEditAction editMessageById(@Nonnull String messageId, @Nonnull CharSequence newContent)
{
Checks.isSnowflake(messageId, "Message ID");
Checks.notEmpty(newContent, "Provided message content");
Checks.check(newContent.length() <= Message.MAX_CONTENT_LENGTH, "Provided newContent length must be %d or less characters.", Message.MAX_CONTENT_LENGTH);
- if (newContent instanceof StringBuilder)
- return new MessageActionImpl(getJDA(), messageId, this, (StringBuilder) newContent);
- else
- return new MessageActionImpl(getJDA(), messageId, this).append(newContent);
+ return new MessageEditActionImpl(this, messageId).setContent(newContent.toString());
}
/**
- * Attempts to edit a message by its id in this MessageChannel. The string provided as {@code newContent} must
- * have a length that is greater than 0 and less-than or equal to 2000. This is a Discord message length limitation.
+ * Attempts to edit a message by its id in this channel.
*
* The following {@link net.dv8tion.jda.api.requests.ErrorResponse ErrorResponses} are possible:
*
{@code
+ * // Make a file upload instance which refers to a local file called "myFile.png"
+ * // The second parameter "image.png" is the filename we tell discord to use for the attachment
+ * FileUpload file = FileUpload.fromData(new File("myFile.png"), "image.png");
+ *
+ * // Build a message embed which refers to this attachment by the given name.
+ * // Note that this must be the same name as configured for the attachment, not your local filename.
+ * MessageEmbed embed = new EmbedBuilder()
+ * .setDescription("This is my cute cat :)")
+ * .setImage("attachment://image.png") // refer to the file by using the "attachment://" schema with the filename we gave it above
+ * .build();
+ *
+ * webhook.sendMessageEmbeds(Collections.singleton(embed)) // send the embeds
+ * .addFiles(file) // add the file as attachment
+ * .queue();
+ * }
+ *
* @param embeds
- * {@link MessageEmbed MessageEmbeds} to use (up to {@value Message#MAX_EMBED_COUNT} in total)
+ * {@link MessageEmbed MessageEmbeds} to use (up to {@value Message#MAX_EMBED_COUNT})
*
* @throws IllegalArgumentException
* If any of the embeds are null, more than {@value Message#MAX_EMBED_COUNT}, or longer than {@link MessageEmbed#EMBED_MAX_LENGTH_BOT}.
*
- * @return {@link WebhookMessageAction}
+ * @return {@link net.dv8tion.jda.api.requests.restaction.WebhookMessageCreateAction}
*/
@Nonnull
@CheckReturnValue
- WebhookMessageAction sendMessageEmbeds(@Nonnull Collection extends MessageEmbed> embeds);
+ WebhookMessageCreateAction sendMessageEmbeds(@Nonnull Collection extends MessageEmbed> embeds);
/**
* Send a message to this webhook.
@@ -148,6 +173,24 @@ default WebhookMessageAction sendMessageFormat(@Nonnull String format, @Nonnu
* The webhook is no longer available, either it was deleted or in case of interactions it expired.
*
*
+ * Example: Attachment Images
+ *
{@code
+ * // Make a file upload instance which refers to a local file called "myFile.png"
+ * // The second parameter "image.png" is the filename we tell discord to use for the attachment
+ * FileUpload file = FileUpload.fromData(new File("myFile.png"), "image.png");
+ *
+ * // Build a message embed which refers to this attachment by the given name.
+ * // Note that this must be the same name as configured for the attachment, not your local filename.
+ * MessageEmbed embed = new EmbedBuilder()
+ * .setDescription("This is my cute cat :)")
+ * .setImage("attachment://image.png") // refer to the file by using the "attachment://" schema with the filename we gave it above
+ * .build();
+ *
+ * webhook.sendMessageEmbeds(embed) // send the embed
+ * .addFiles(file) // add the file as attachment
+ * .queue();
+ * }
+ *
* @param embed
* {@link MessageEmbed} to use
* @param embeds
@@ -156,11 +199,11 @@ default WebhookMessageAction sendMessageFormat(@Nonnull String format, @Nonnu
* @throws IllegalArgumentException
* If any of the embeds are null, more than {@value Message#MAX_EMBED_COUNT}, or longer than {@link MessageEmbed#EMBED_MAX_LENGTH_BOT}.
*
- * @return {@link WebhookMessageAction}
+ * @return {@link net.dv8tion.jda.api.requests.restaction.WebhookMessageCreateAction}
*/
@Nonnull
@CheckReturnValue
- default WebhookMessageAction sendMessageEmbeds(@Nonnull MessageEmbed embed, @Nonnull MessageEmbed... embeds)
+ default WebhookMessageCreateAction sendMessageEmbeds(@Nonnull MessageEmbed embed, @Nonnull MessageEmbed... embeds)
{
Checks.notNull(embed, "MessageEmbeds");
Checks.noneNull(embeds, "MessageEmbeds");
@@ -175,206 +218,88 @@ default WebhookMessageAction sendMessageEmbeds(@Nonnull MessageEmbed embed, @
*
* If this is an {@link net.dv8tion.jda.api.interactions.InteractionHook InteractionHook} this method will be delayed until the interaction is acknowledged.
*
- *
Uploading images with Embeds
- * When uploading an image you can reference said image using the specified filename as URI {@code attachment://filename.ext}.
- *
- *
Example
- *
- * WebhookClient hook; // = reference of a WebhookClient such as interaction.getHook()
- * EmbedBuilder embed = new EmbedBuilder();
- * InputStream file = new FileInputStream("image.png"); // the name in your file system can be different from the name used in discord
- * embed.setImage("attachment://cat.png") // we specify this in sendFile as "cat.png"
- * .setDescription("This is a cute cat :3");
- * hook.sendFile(file, "cat.png").addEmbeds(embed.build()).queue();
- *
- *
- * Possible {@link net.dv8tion.jda.api.requests.ErrorResponse ErrorResponses} include:
- *
- * {@link net.dv8tion.jda.api.requests.ErrorResponse#UNKNOWN_WEBHOOK UNKNOWN_WEBHOOK}
- * The webhook is no longer available, either it was deleted or in case of interactions it expired.
- * {@link net.dv8tion.jda.api.requests.ErrorResponse#REQUEST_ENTITY_TOO_LARGE REQUEST_ENTITY_TOO_LARGE}
- * The file exceeds the maximum upload size of {@link Message#MAX_FILE_SIZE}
- *
- *
- * @param data
- * The InputStream data to upload to the webhook.
- * @param name
- * The file name that should be sent to discord
- * Refer to the documentation for {@link #sendFile(java.io.File, String, AttachmentOption...)} for information about this parameter.
- * @param options
- * Possible options to apply to this attachment, such as marking it as spoiler image
- *
- * @throws java.lang.IllegalArgumentException
- * If the provided file or filename is {@code null} or {@code empty}.
- *
- * @return {@link WebhookMessageAction}
- */
- @Nonnull
- @CheckReturnValue
- WebhookMessageAction sendFile(@Nonnull InputStream data, @Nonnull String name, @Nonnull AttachmentOption... options);
-
- /**
- * Send a message to this webhook.
- *
- * If this is an {@link net.dv8tion.jda.api.interactions.InteractionHook InteractionHook} this method will be delayed until the interaction is acknowledged.
+ *
Resource Handling Note: Once the request is handed off to the requester, for example when you call {@link RestAction#queue()},
+ * the requester will automatically clean up all opened files by itself. You are only responsible to close them yourself if it is never handed off properly.
+ * For instance, if an exception occurs after using {@link FileUpload#fromData(File)}, before calling {@link RestAction#queue()}.
+ * You can safely use a try-with-resources to handle this, since {@link FileUpload#close()} becomes ineffective once the request is handed off.
*
- *
This is a shortcut to {@link #sendFile(java.io.File, String, AttachmentOption...)} by way of using {@link java.io.File#getName()}.
- *
sendFile(file, file.getName())
+ * Example: Attachment Images
+ *
{@code
+ * // Make a file upload instance which refers to a local file called "myFile.png"
+ * // The second parameter "image.png" is the filename we tell discord to use for the attachment
+ * FileUpload file = FileUpload.fromData(new File("myFile.png"), "image.png");
*
- * Uploading images with Embeds
- * When uploading an image you can reference said image using the specified filename as URI {@code attachment://filename.ext}.
+ * // Build a message embed which refers to this attachment by the given name.
+ * // Note that this must be the same name as configured for the attachment, not your local filename.
+ * MessageEmbed embed = new EmbedBuilder()
+ * .setDescription("This is my cute cat :)")
+ * .setImage("attachment://image.png") // refer to the file by using the "attachment://" schema with the filename we gave it above
+ * .build();
*
- *
Example
- *
- * WebhookClient hook; // = reference of a WebhookClient such as interaction.getHook()
- * EmbedBuilder embed = new EmbedBuilder();
- * File data = new File("image.png"); // the name in your file system can be different from the name used in discord
- * embed.setImage("attachment://cat.png") // we specify this in sendFile as "cat.png"
- * .setDescription("This is a cute cat :3");
- * hook.sendFile(file, "cat.png").addEmbeds(embed.build()).queue();
- *
+ * webhook.sendFiles(Collections.singleton(file)) // send the file upload
+ * .addEmbeds(embed) // add the embed you want to reference the file with
+ * .queue();
+ * }
*
- * Possible {@link net.dv8tion.jda.api.requests.ErrorResponse ErrorResponses} include:
- *
- * {@link net.dv8tion.jda.api.requests.ErrorResponse#UNKNOWN_WEBHOOK UNKNOWN_WEBHOOK}
- * The webhook is no longer available, either it was deleted or in case of interactions it expired.
- * {@link net.dv8tion.jda.api.requests.ErrorResponse#REQUEST_ENTITY_TOO_LARGE REQUEST_ENTITY_TOO_LARGE}
- * The file exceeds the maximum upload size of {@link Message#MAX_FILE_SIZE}
- *
+ * @param files
+ * The {@link FileUpload FileUploads} to attach to the message
*
- * @param file
- * The {@link File} data to upload to the webhook.
- * @param options
- * Possible options to apply to this attachment, such as marking it as spoiler image
+ * @throws IllegalArgumentException
+ * If null is provided
*
- * @throws java.lang.IllegalArgumentException
- * If the provided file is {@code null}.
+ * @return {@link WebhookMessageCreateAction}
*
- * @return {@link WebhookMessageAction}
+ * @see FileUpload#fromData(InputStream, String)
*/
@Nonnull
@CheckReturnValue
- default WebhookMessageAction sendFile(@Nonnull File file, @Nonnull AttachmentOption... options)
- {
- Checks.notNull(file, "File");
- return sendFile(file, file.getName(), options);
- }
+ WebhookMessageCreateAction sendFiles(@Nonnull Collection extends FileUpload> files);
/**
* Send a message to this webhook.
*
* If this is an {@link net.dv8tion.jda.api.interactions.InteractionHook InteractionHook} this method will be delayed until the interaction is acknowledged.
*
- *
The {@code name} parameter is used to inform Discord about what the file should be called. This is 2 fold:
- *
- * The file name provided is the name that is found in {@link net.dv8tion.jda.api.entities.Message.Attachment#getFileName()}
- * after upload and it is the name that will show up in the client when the upload is displayed.
- * Note: The fileName does not show up on the Desktop client for images. It does on mobile however.
- * The extension of the provided fileName also determines how Discord will treat the file. Discord currently only
- * has special handling for image file types, but the fileName's extension must indicate that it is an image file.
- * This means it has to end in something like .png, .jpg, .jpeg, .gif, etc. As a note, you can also not provide
- * a full name for the file and instead ONLY provide the extension like "png" or "gif" and Discord will generate
- * a name for the upload and append the fileName as the extension.
- *
- *
- * Uploading images with Embeds
- * When uploading an image you can reference said image using the specified filename as URI {@code attachment://filename.ext}.
- *
- *
Example
- *
- * WebhookClient hook; // = reference of a WebhookClient such as interaction.getHook()
- * EmbedBuilder embed = new EmbedBuilder();
- * byte[] data = IOUtils.readAllBytes(new FileInputStream("image.png")); // the name in your file system can be different from the name used in discord
- * embed.setImage("attachment://cat.png") // we specify this in sendFile as "cat.png"
- * .setDescription("This is a cute cat :3");
- * hook.sendFile(file, "cat.png").addEmbeds(embed.build()).queue();
- *
+ * Resource Handling Note: Once the request is handed off to the requester, for example when you call {@link RestAction#queue()},
+ * the requester will automatically clean up all opened files by itself. You are only responsible to close them yourself if it is never handed off properly.
+ * For instance, if an exception occurs after using {@link FileUpload#fromData(File)}, before calling {@link RestAction#queue()}.
+ * You can safely use a try-with-resources to handle this, since {@link FileUpload#close()} becomes ineffective once the request is handed off.
*
- *
Possible {@link net.dv8tion.jda.api.requests.ErrorResponse ErrorResponses} include:
- *
- * {@link net.dv8tion.jda.api.requests.ErrorResponse#UNKNOWN_WEBHOOK UNKNOWN_WEBHOOK}
- * The webhook is no longer available, either it was deleted or in case of interactions it expired.
- * {@link net.dv8tion.jda.api.requests.ErrorResponse#REQUEST_ENTITY_TOO_LARGE REQUEST_ENTITY_TOO_LARGE}
- * The file exceeds the maximum upload size of {@link Message#MAX_FILE_SIZE}
- *
+ * Example: Attachment Images
+ *
{@code
+ * // Make a file upload instance which refers to a local file called "myFile.png"
+ * // The second parameter "image.png" is the filename we tell discord to use for the attachment
+ * FileUpload file = FileUpload.fromData(new File("myFile.png"), "image.png");
*
- * @param file
- * The {@link File} data to upload to the webhook.
- * @param name
- * The file name that should be sent to discord
- * @param options
- * Possible options to apply to this attachment, such as marking it as spoiler image
+ * // Build a message embed which refers to this attachment by the given name.
+ * // Note that this must be the same name as configured for the attachment, not your local filename.
+ * MessageEmbed embed = new EmbedBuilder()
+ * .setDescription("This is my cute cat :)")
+ * .setImage("attachment://image.png") // refer to the file by using the "attachment://" schema with the filename we gave it above
+ * .build();
*
- * @throws java.lang.IllegalArgumentException
- * If the provided file or filename is {@code null} or {@code empty}.
+ * webhook.sendFiles(file) // send the file upload
+ * .addEmbeds(embed) // add the embed you want to reference the file with
+ * .queue();
+ * }
*
- * @return {@link WebhookMessageAction}
- */
- @Nonnull
- @CheckReturnValue
- default WebhookMessageAction sendFile(@Nonnull File file, @Nonnull String name, @Nonnull AttachmentOption... options)
- {
- Checks.notNull(file, "File");
- Checks.check(file.exists() && file.canRead(),
- "Provided file doesn't exist or cannot be read!");
- Checks.notNull(name, "Name");
-
- try
- {
- return sendFile(new FileInputStream(file), name, options);
- }
- catch (FileNotFoundException ex)
- {
- throw new IllegalArgumentException(ex);
- }
- }
-
- /**
- * Send a message to this webhook.
+ * @param files
+ * The {@link FileUpload FileUploads} to attach to the message
*
- * If this is an {@link net.dv8tion.jda.api.interactions.InteractionHook InteractionHook} this method will be delayed until the interaction is acknowledged.
- *
- *
Uploading images with Embeds
- * When uploading an image you can reference said image using the specified filename as URI {@code attachment://filename.ext}.
- *
- *
Example
- *
- * WebhookClient hook; // = reference of a WebhookClient such as interaction.getHook()
- * EmbedBuilder embed = new EmbedBuilder();
- * byte[] data = IOUtils.readAllBytes(new FileInputStream("image.png")); // the name in your file system can be different from the name used in discord
- * embed.setImage("attachment://cat.png") // we specify this in sendFile as "cat.png"
- * .setDescription("This is a cute cat :3");
- * hook.sendFile(file, "cat.png").addEmbeds(embed.build()).queue();
- *
- *
- * Possible {@link net.dv8tion.jda.api.requests.ErrorResponse ErrorResponses} include:
- *
- * {@link net.dv8tion.jda.api.requests.ErrorResponse#UNKNOWN_WEBHOOK UNKNOWN_WEBHOOK}
- * The webhook is no longer available, either it was deleted or in case of interactions it expired.
- * {@link net.dv8tion.jda.api.requests.ErrorResponse#REQUEST_ENTITY_TOO_LARGE REQUEST_ENTITY_TOO_LARGE}
- * The file exceeds the maximum upload size of {@link Message#MAX_FILE_SIZE}
- *
- *
- * @param data
- * The {@code byte[]} data to upload to the webhook.
- * @param name
- * The file name that should be sent to discord
- * Refer to the documentation for {@link #sendFile(java.io.File, String, AttachmentOption...)} for information about this parameter.
- * @param options
- * Possible options to apply to this attachment, such as marking it as spoiler image
+ * @throws IllegalArgumentException
+ * If null is provided
*
- * @throws java.lang.IllegalArgumentException
- * If the provided file or filename is {@code null} or {@code empty}.
+ * @return {@link WebhookMessageCreateAction}
*
- * @return {@link WebhookMessageAction}
+ * @see FileUpload#fromData(InputStream, String)
*/
@Nonnull
@CheckReturnValue
- default WebhookMessageAction sendFile(@Nonnull byte[] data, @Nonnull String name, @Nonnull AttachmentOption... options)
+ default WebhookMessageCreateAction sendFiles(@Nonnull FileUpload... files)
{
- Checks.notNull(data, "Data");
- Checks.notNull(name, "Name");
- return sendFile(new ByteArrayInputStream(data), name, options);
+ Checks.noneNull(files, "Files");
+ Checks.notEmpty(files, "Files");
+ return sendFiles(Arrays.asList(files));
}
/**
@@ -396,13 +321,13 @@ default WebhookMessageAction sendFile(@Nonnull byte[] data, @Nonnull String n
* The new message content to use
*
* @throws IllegalArgumentException
- * If the provided content is null, empty, or longer than {@link Message#MAX_CONTENT_LENGTH}
+ * If the provided content is null or longer than {@link Message#MAX_CONTENT_LENGTH} characters
*
- * @return {@link WebhookMessageUpdateAction}
+ * @return {@link WebhookMessageEditAction}
*/
@Nonnull
@CheckReturnValue
- WebhookMessageUpdateAction editMessageById(@Nonnull String messageId, @Nonnull String content);
+ WebhookMessageEditAction editMessageById(@Nonnull String messageId, @Nonnull String content);
/**
* Edit an existing message sent by this webhook.
@@ -423,13 +348,13 @@ default WebhookMessageAction sendFile(@Nonnull byte[] data, @Nonnull String n
* The new message content to use
*
* @throws IllegalArgumentException
- * If the provided content is null, empty, or longer than {@link Message#MAX_CONTENT_LENGTH}
+ * If the provided content is null or longer than {@link Message#MAX_CONTENT_LENGTH} characters
*
- * @return {@link WebhookMessageUpdateAction}
+ * @return {@link WebhookMessageEditAction}
*/
@Nonnull
@CheckReturnValue
- default WebhookMessageUpdateAction editMessageById(long messageId, @Nonnull String content)
+ default WebhookMessageEditAction editMessageById(long messageId, @Nonnull String content)
{
return editMessageById(Long.toUnsignedString(messageId), content);
}
@@ -450,16 +375,18 @@ default WebhookMessageUpdateAction editMessageById(long messageId, @Nonnull S
* @param messageId
* The message id. For interactions this supports {@code "@original"} to edit the source message of the interaction.
* @param message
- * The new message to replace the existing message with
+ * The {@link MessageEditData} containing the update information
*
* @throws IllegalArgumentException
* If the provided message is null
*
- * @return {@link WebhookMessageUpdateAction}
+ * @return {@link WebhookMessageEditAction}
+ *
+ * @see net.dv8tion.jda.api.utils.messages.MessageEditBuilder MessageEditBuilder
*/
@Nonnull
@CheckReturnValue
- WebhookMessageUpdateAction editMessageById(@Nonnull String messageId, @Nonnull Message message);
+ WebhookMessageEditAction editMessageById(@Nonnull String messageId, @Nonnull MessageEditData message);
/**
* Edit an existing message sent by this webhook.
@@ -477,16 +404,18 @@ default WebhookMessageUpdateAction editMessageById(long messageId, @Nonnull S
* @param messageId
* The message id. For interactions this supports {@code "@original"} to edit the source message of the interaction.
* @param message
- * The new message to replace the existing message with
+ * The {@link MessageEditData} containing the update information
*
* @throws IllegalArgumentException
* If the provided message is null
*
- * @return {@link WebhookMessageUpdateAction}
+ * @return {@link WebhookMessageEditAction}
+ *
+ * @see net.dv8tion.jda.api.utils.messages.MessageEditBuilder MessageEditBuilder
*/
@Nonnull
@CheckReturnValue
- default WebhookMessageUpdateAction editMessageById(long messageId, Message message)
+ default WebhookMessageEditAction editMessageById(long messageId, MessageEditData message)
{
return editMessageById(Long.toUnsignedString(messageId), message);
}
@@ -512,13 +441,13 @@ default WebhookMessageUpdateAction editMessageById(long messageId, Message me
* Format arguments for the content
*
* @throws IllegalArgumentException
- * If the formatted string is null, empty, or longer than {@link Message#MAX_CONTENT_LENGTH}
+ * If the formatted string is null or longer than {@link Message#MAX_CONTENT_LENGTH} characters
*
- * @return {@link WebhookMessageUpdateAction}
+ * @return {@link WebhookMessageEditAction}
*/
@Nonnull
@CheckReturnValue
- default WebhookMessageUpdateAction editMessageFormatById(@Nonnull String messageId, @Nonnull String format, @Nonnull Object... args)
+ default WebhookMessageEditAction editMessageFormatById(@Nonnull String messageId, @Nonnull String format, @Nonnull Object... args)
{
Checks.notNull(format, "Format String");
return editMessageById(messageId, String.format(format, args));
@@ -545,13 +474,13 @@ default WebhookMessageUpdateAction editMessageFormatById(@Nonnull String mess
* Format arguments for the content
*
* @throws IllegalArgumentException
- * If the formatted string is null, empty, or longer than {@link Message#MAX_CONTENT_LENGTH}
+ * If the formatted string is null or longer than {@link Message#MAX_CONTENT_LENGTH} characters
*
- * @return {@link WebhookMessageUpdateAction}
+ * @return {@link WebhookMessageEditAction}
*/
@Nonnull
@CheckReturnValue
- default WebhookMessageUpdateAction editMessageFormatById(long messageId, @Nonnull String format, @Nonnull Object... args)
+ default WebhookMessageEditAction editMessageFormatById(long messageId, @Nonnull String format, @Nonnull Object... args)
{
return editMessageFormatById(Long.toUnsignedString(messageId), format, args);
}
@@ -575,13 +504,13 @@ default WebhookMessageUpdateAction editMessageFormatById(long messageId, @Non
* {@link MessageEmbed MessageEmbeds} to use (up to {@value Message#MAX_EMBED_COUNT} in total)
*
* @throws IllegalArgumentException
- * If the provided embeds are null, or more than {@value Message#MAX_EMBED_COUNT}
+ * If null or more than {@value Message#MAX_EMBED_COUNT} embeds are provided
*
- * @return {@link WebhookMessageUpdateAction}
+ * @return {@link WebhookMessageEditAction}
*/
@Nonnull
@CheckReturnValue
- WebhookMessageUpdateAction editMessageEmbedsById(@Nonnull String messageId, @Nonnull Collection extends MessageEmbed> embeds);
+ WebhookMessageEditAction editMessageEmbedsById(@Nonnull String messageId, @Nonnull Collection extends MessageEmbed> embeds);
/**
* Edit an existing message sent by this webhook.
@@ -602,13 +531,13 @@ default WebhookMessageUpdateAction editMessageFormatById(long messageId, @Non
* {@link MessageEmbed MessageEmbeds} to use (up to {@value Message#MAX_EMBED_COUNT} in total)
*
* @throws IllegalArgumentException
- * If the provided embeds are null, or more than {@value Message#MAX_EMBED_COUNT}
+ * If null or more than {@value Message#MAX_EMBED_COUNT} embeds are provided
*
- * @return {@link WebhookMessageUpdateAction}
+ * @return {@link WebhookMessageEditAction}
*/
@Nonnull
@CheckReturnValue
- default WebhookMessageUpdateAction editMessageEmbedsById(long messageId, @Nonnull Collection extends MessageEmbed> embeds)
+ default WebhookMessageEditAction editMessageEmbedsById(long messageId, @Nonnull Collection extends MessageEmbed> embeds)
{
return editMessageEmbedsById(Long.toUnsignedString(messageId), embeds);
}
@@ -632,13 +561,13 @@ default WebhookMessageUpdateAction editMessageEmbedsById(long messageId, @Non
* The new {@link MessageEmbed MessageEmbeds} to use
*
* @throws IllegalArgumentException
- * If the provided embeds are null, or more than 10
+ * If null or more than {@value Message#MAX_EMBED_COUNT} embeds are provided
*
- * @return {@link WebhookMessageUpdateAction}
+ * @return {@link WebhookMessageEditAction}
*/
@Nonnull
@CheckReturnValue
- default WebhookMessageUpdateAction editMessageEmbedsById(@Nonnull String messageId, @Nonnull MessageEmbed... embeds)
+ default WebhookMessageEditAction editMessageEmbedsById(@Nonnull String messageId, @Nonnull MessageEmbed... embeds)
{
Checks.noneNull(embeds, "MessageEmbeds");
return editMessageEmbedsById(messageId, Arrays.asList(embeds));
@@ -663,13 +592,13 @@ default WebhookMessageUpdateAction editMessageEmbedsById(@Nonnull String mess
* The new {@link MessageEmbed MessageEmbeds} to use
*
* @throws IllegalArgumentException
- * If the provided embeds are null, or more than 10
+ * If null or more than {@value Message#MAX_EMBED_COUNT} embeds are provided
*
- * @return {@link WebhookMessageUpdateAction}
+ * @return {@link WebhookMessageEditAction}
*/
@Nonnull
@CheckReturnValue
- default WebhookMessageUpdateAction editMessageEmbedsById(long messageId, @Nonnull MessageEmbed... embeds)
+ default WebhookMessageEditAction editMessageEmbedsById(long messageId, @Nonnull MessageEmbed... embeds)
{
return editMessageEmbedsById(Long.toUnsignedString(messageId), embeds);
}
@@ -693,13 +622,17 @@ default WebhookMessageUpdateAction editMessageEmbedsById(long messageId, @Non
* The new component layouts for this message, such as {@link ActionRow ActionRows}
*
* @throws IllegalArgumentException
- * If the provided components are null, or more than 5 layouts are provided
+ *
+ * If {@code null} is provided
+ * If any of the components is not {@link LayoutComponent#isMessageCompatible() message compatible}
+ * If more than {@value Message#MAX_COMPONENT_COUNT} component layouts are provided
+ *
*
- * @return {@link WebhookMessageUpdateAction}
+ * @return {@link WebhookMessageEditAction}
*/
@Nonnull
@CheckReturnValue
- WebhookMessageUpdateAction editMessageComponentsById(@Nonnull String messageId, @Nonnull Collection extends LayoutComponent> components); // We use LayoutComponent for forward compatibility here
+ WebhookMessageEditAction editMessageComponentsById(@Nonnull String messageId, @Nonnull Collection extends LayoutComponent> components);
/**
* Edit an existing message sent by this webhook.
@@ -720,13 +653,17 @@ default WebhookMessageUpdateAction editMessageEmbedsById(long messageId, @Non
* The new component layouts for this message, such as {@link ActionRow ActionRows}
*
* @throws IllegalArgumentException
- * If the provided components are null, or more than 5 layouts are provided
+ *
+ * If {@code null} is provided
+ * If any of the components is not {@link LayoutComponent#isMessageCompatible() message compatible}
+ * If more than {@value Message#MAX_COMPONENT_COUNT} component layouts are provided
+ *
*
- * @return {@link WebhookMessageUpdateAction}
+ * @return {@link WebhookMessageEditAction}
*/
@Nonnull
@CheckReturnValue
- default WebhookMessageUpdateAction editMessageComponentsById(long messageId, @Nonnull Collection extends LayoutComponent> components)
+ default WebhookMessageEditAction editMessageComponentsById(long messageId, @Nonnull Collection extends LayoutComponent> components)
{
return editMessageComponentsById(Long.toUnsignedString(messageId), components);
}
@@ -750,13 +687,17 @@ default WebhookMessageUpdateAction editMessageComponentsById(long messageId,
* The new component layouts for this message, such as {@link ActionRow ActionRows}
*
* @throws IllegalArgumentException
- * If the provided components are null, or more than 5 layouts are provided
+ *
+ * If {@code null} is provided
+ * If any of the components is not {@link LayoutComponent#isMessageCompatible() message compatible}
+ * If more than {@value Message#MAX_COMPONENT_COUNT} component layouts are provided
+ *
*
- * @return {@link WebhookMessageUpdateAction}
+ * @return {@link WebhookMessageEditAction}
*/
@Nonnull
@CheckReturnValue
- default WebhookMessageUpdateAction editMessageComponentsById(@Nonnull String messageId, @Nonnull LayoutComponent... components)
+ default WebhookMessageEditAction editMessageComponentsById(@Nonnull String messageId, @Nonnull LayoutComponent... components)
{
Checks.noneNull(components, "LayoutComponents");
return editMessageComponentsById(messageId, Arrays.asList(components));
@@ -781,13 +722,17 @@ default WebhookMessageUpdateAction editMessageComponentsById(@Nonnull String
* The new component layouts for this message, such as {@link ActionRow ActionRows}
*
* @throws IllegalArgumentException
- * If the provided components are null, or more than 5 layouts are provided
+ *
+ * If {@code null} is provided
+ * If any of the components is not {@link LayoutComponent#isMessageCompatible() message compatible}
+ * If more than {@value Message#MAX_COMPONENT_COUNT} component layouts are provided
+ *
*
- * @return {@link WebhookMessageUpdateAction}
+ * @return {@link WebhookMessageEditAction}
*/
@Nonnull
@CheckReturnValue
- default WebhookMessageUpdateAction editMessageComponentsById(long messageId, @Nonnull LayoutComponent... components)
+ default WebhookMessageEditAction editMessageComponentsById(long messageId, @Nonnull LayoutComponent... components)
{
return editMessageComponentsById(Long.toUnsignedString(messageId), components);
}
@@ -795,407 +740,120 @@ default WebhookMessageUpdateAction editMessageComponentsById(long messageId,
/**
* Edit an existing message sent by this webhook.
- * The provided file will be appended to the message. You cannot delete or edit existing files on a message.
*
* If this is an {@link net.dv8tion.jda.api.interactions.InteractionHook InteractionHook} this method will be delayed until the interaction is acknowledged.
*
- *
Uploading images with Embeds
- * When uploading an image you can reference said image using the specified filename as URI {@code attachment://filename.ext}.
- *
- *
Example
- *
- * WebhookClient hook; // = reference of a WebhookClient such as interaction.getHook()
- * EmbedBuilder embed = new EmbedBuilder();
- * InputStream file = new FileInputStream("image.png"); // the name in your file system can be different from the name used in discord
- * embed.setImage("attachment://cat.png") // we specify this in sendFile as "cat.png"
- * .setDescription("This is a cute cat :3");
- * hook.editMessageById(messageId, file, "cat.png").setEmbeds(embed.build()).queue();
- *
- *
- * Possible {@link net.dv8tion.jda.api.requests.ErrorResponse ErrorResponses} include:
- *
- * {@link net.dv8tion.jda.api.requests.ErrorResponse#UNKNOWN_WEBHOOK UNKNOWN_WEBHOOK}
- * The webhook is no longer available, either it was deleted or in case of interactions it expired.
- * {@link net.dv8tion.jda.api.requests.ErrorResponse#UNKNOWN_MESSAGE UNKNOWN_MESSAGE}
- * The message for that id does not exist
- *
+ * Resource Handling Note: Once the request is handed off to the requester, for example when you call {@link RestAction#queue()},
+ * the requester will automatically clean up all opened files by itself. You are only responsible to close them yourself if it is never handed off properly.
+ * For instance, if an exception occurs after using {@link FileUpload#fromData(File)}, before calling {@link RestAction#queue()}.
+ * You can safely use a try-with-resources to handle this, since {@link FileUpload#close()} becomes ineffective once the request is handed off.
*
* @param messageId
* The message id. For interactions this supports {@code "@original"} to edit the source message of the interaction.
- * @param data
- * The InputStream data to upload to the webhook.
- * @param name
- * The file name that should be sent to discord
- * Refer to the documentation for {@link #sendFile(java.io.File, String, AttachmentOption...)} for information about this parameter.
- * @param options
- * Possible options to apply to this attachment, such as marking it as spoiler image
- *
- * @throws java.lang.IllegalArgumentException
- * If the provided message id, data, or filename is {@code null}.
- *
- * @return {@link WebhookMessageUpdateAction}
- */
- @Nonnull
- @CheckReturnValue
- WebhookMessageUpdateAction editMessageById(@Nonnull String messageId, @Nonnull InputStream data, @Nonnull String name, @Nonnull AttachmentOption... options);
-
- /**
- * Edit an existing message sent by this webhook.
- * The provided file will be appended to the message. You cannot delete or edit existing files on a message.
- *
- * If this is an {@link net.dv8tion.jda.api.interactions.InteractionHook InteractionHook} this method will be delayed until the interaction is acknowledged.
+ * @param attachments
+ * The new attachments of the message (Can be {@link FileUpload FileUploads} or {@link net.dv8tion.jda.api.utils.AttachmentUpdate AttachmentUpdates})
*
- *
This is a shortcut to {@link #editMessageById(java.lang.String, java.io.File, String, AttachmentOption...)} by way of using {@link java.io.File#getName()}.
- *
editMessageById(messageId, file, file.getName())
- *
- * Uploading images with Embeds
- * When uploading an image you can reference said image using the specified filename as URI {@code attachment://filename.ext}.
- *
- *
Example
- *
- * WebhookClient hook; // = reference of a WebhookClient such as interaction.getHook()
- * EmbedBuilder embed = new EmbedBuilder();
- * File file = new File("image.png"); // the name in your file system can be different from the name used in discord
- * embed.setImage("attachment://cat.png") // we specify this in sendFile as "cat.png"
- * .setDescription("This is a cute cat :3");
- * hook.editMessageById(messageId, file, "cat.png").setEmbeds(embed.build()).queue();
- *
- *
- * Possible {@link net.dv8tion.jda.api.requests.ErrorResponse ErrorResponses} include:
- *
- * {@link net.dv8tion.jda.api.requests.ErrorResponse#UNKNOWN_WEBHOOK UNKNOWN_WEBHOOK}
- * The webhook is no longer available, either it was deleted or in case of interactions it expired.
- * {@link net.dv8tion.jda.api.requests.ErrorResponse#UNKNOWN_MESSAGE UNKNOWN_MESSAGE}
- * The message for that id does not exist
- *
- *
- * @param messageId
- * The message id. For interactions this supports {@code "@original"} to edit the source message of the interaction.
- * @param file
- * The {@link File} data to upload to the webhook.
- * @param options
- * Possible options to apply to this attachment, such as marking it as spoiler image
+ * @throws IllegalArgumentException
+ * If null is provided
*
- * @throws java.lang.IllegalArgumentException
- * If the provided message id or file is {@code null}.
+ * @return {@link MessageEditCallbackAction} that can be used to further update the message
*
- * @return {@link WebhookMessageUpdateAction}
+ * @see AttachedFile#fromAttachment(Message.Attachment)
+ * @see FileUpload#fromData(InputStream, String)
*/
@Nonnull
@CheckReturnValue
- default WebhookMessageUpdateAction editMessageById(@Nonnull String messageId, @Nonnull File file, @Nonnull AttachmentOption... options)
- {
- Checks.notNull(file, "File");
- return editMessageById(messageId, file, file.getName(), options);
- }
+ WebhookMessageEditAction editMessageAttachmentsById(@Nonnull String messageId, @Nonnull Collection extends AttachedFile> attachments);
/**
* Edit an existing message sent by this webhook.
- * The provided file will be appended to the message. You cannot delete or edit existing files on a message.
*
* If this is an {@link net.dv8tion.jda.api.interactions.InteractionHook InteractionHook} this method will be delayed until the interaction is acknowledged.
*
- *
Uploading images with Embeds
- * When uploading an image you can reference said image using the specified filename as URI {@code attachment://filename.ext}.
- *
- *
Example
- *
- * WebhookClient hook; // = reference of a WebhookClient such as interaction.getHook()
- * EmbedBuilder embed = new EmbedBuilder();
- * File file = new File("image.png"); // the name in your file system can be different from the name used in discord
- * embed.setImage("attachment://cat.png") // we specify this in sendFile as "cat.png"
- * .setDescription("This is a cute cat :3");
- * hook.editMessageById(messageId, file, "cat.png").setEmbeds(embed.build()).queue();
- *
- *
- * Possible {@link net.dv8tion.jda.api.requests.ErrorResponse ErrorResponses} include:
- *
- * {@link net.dv8tion.jda.api.requests.ErrorResponse#UNKNOWN_WEBHOOK UNKNOWN_WEBHOOK}
- * The webhook is no longer available, either it was deleted or in case of interactions it expired.
- * {@link net.dv8tion.jda.api.requests.ErrorResponse#UNKNOWN_MESSAGE UNKNOWN_MESSAGE}
- * The message for that id does not exist
- *
+ * Resource Handling Note: Once the request is handed off to the requester, for example when you call {@link RestAction#queue()},
+ * the requester will automatically clean up all opened files by itself. You are only responsible to close them yourself if it is never handed off properly.
+ * For instance, if an exception occurs after using {@link FileUpload#fromData(File)}, before calling {@link RestAction#queue()}.
+ * You can safely use a try-with-resources to handle this, since {@link FileUpload#close()} becomes ineffective once the request is handed off.
*
* @param messageId
* The message id. For interactions this supports {@code "@original"} to edit the source message of the interaction.
- * @param file
- * The {@link File} data to upload to the webhook.
- * @param name
- * The file name that should be sent to discord
- * Refer to the documentation for {@link #sendFile(java.io.File, String, AttachmentOption...)} for information about this parameter.
- * @param options
- * Possible options to apply to this attachment, such as marking it as spoiler image
- *
- * @throws java.lang.IllegalArgumentException
- * If the provided file, message id, or filename is {@code null}.
- *
- * @return {@link WebhookMessageUpdateAction}
- */
- @Nonnull
- @CheckReturnValue
- default WebhookMessageUpdateAction editMessageById(@Nonnull String messageId, @Nonnull File file, @Nonnull String name, @Nonnull AttachmentOption... options)
- {
- Checks.notNull(file, "File");
- Checks.check(file.exists() && file.canRead(),
- "Provided file doesn't exist or cannot be read!");
- Checks.notNull(name, "Name");
-
- try
- {
- return editMessageById(messageId, new FileInputStream(file), name, options);
- }
- catch (FileNotFoundException ex)
- {
- throw new IllegalArgumentException(ex);
- }
- }
-
- /**
- * Edit an existing message sent by this webhook.
- * The provided file will be appended to the message. You cannot delete or edit existing files on a message.
- *
- * If this is an {@link net.dv8tion.jda.api.interactions.InteractionHook InteractionHook} this method will be delayed until the interaction is acknowledged.
+ * @param attachments
+ * The new attachments of the message (Can be {@link FileUpload FileUploads} or {@link net.dv8tion.jda.api.utils.AttachmentUpdate AttachmentUpdates})
*
- *
Uploading images with Embeds
- * When uploading an image you can reference said image using the specified filename as URI {@code attachment://filename.ext}.
+ * @throws IllegalArgumentException
+ * If null is provided
*
- *
Example
- *
- * WebhookClient hook; // = reference of a WebhookClient such as interaction.getHook()
- * EmbedBuilder embed = new EmbedBuilder();
- * InputStream file = new FileInputStream("image.png"); // the name in your file system can be different from the name used in discord
- * embed.setImage("attachment://cat.png") // we specify this in sendFile as "cat.png"
- * .setDescription("This is a cute cat :3");
- * hook.editMessageById(messageId, file, "cat.png").setEmbeds(embed.build()).queue();
- *
+ * @return {@link MessageEditCallbackAction} that can be used to further update the message
*
- * Possible {@link net.dv8tion.jda.api.requests.ErrorResponse ErrorResponses} include:
- *
- * {@link net.dv8tion.jda.api.requests.ErrorResponse#UNKNOWN_WEBHOOK UNKNOWN_WEBHOOK}
- * The webhook is no longer available, either it was deleted or in case of interactions it expired.
- * {@link net.dv8tion.jda.api.requests.ErrorResponse#UNKNOWN_MESSAGE UNKNOWN_MESSAGE}
- * The message for that id does not exist
- *
- *
- * @param messageId
- * The message id. For interactions this supports {@code "@original"} to edit the source message of the interaction.
- * @param data
- * The InputStream data to upload to the webhook.
- * @param name
- * The file name that should be sent to discord
- * Refer to the documentation for {@link #sendFile(java.io.File, String, AttachmentOption...)} for information about this parameter.
- * @param options
- * Possible options to apply to this attachment, such as marking it as spoiler image
- *
- * @throws java.lang.IllegalArgumentException
- * If the provided message id, data, or filename is {@code null}.
- *
- * @return {@link WebhookMessageUpdateAction}
+ * @see AttachedFile#fromAttachment(Message.Attachment)
+ * @see FileUpload#fromData(InputStream, String)
*/
@Nonnull
@CheckReturnValue
- default WebhookMessageUpdateAction editMessageById(@Nonnull String messageId, @Nonnull byte[] data, @Nonnull String name, @Nonnull AttachmentOption... options)
+ default WebhookMessageEditAction editMessageAttachmentsById(@Nonnull String messageId, @Nonnull AttachedFile... attachments)
{
- Checks.notNull(data, "Data");
- Checks.notNull(name, "Name");
-
- return editMessageById(messageId, new ByteArrayInputStream(data), name, options);
+ Checks.noneNull(attachments, "Attachments");
+ return editMessageAttachmentsById(messageId, Arrays.asList(attachments));
}
/**
* Edit an existing message sent by this webhook.
- * The provided file will be appended to the message. You cannot delete or edit existing files on a message.
*
* If this is an {@link net.dv8tion.jda.api.interactions.InteractionHook InteractionHook} this method will be delayed until the interaction is acknowledged.
*
- *
Uploading images with Embeds
- * When uploading an image you can reference said image using the specified filename as URI {@code attachment://filename.ext}.
- *
- *
Example
- *
- * WebhookClient hook; // = reference of a WebhookClient such as interaction.getHook()
- * EmbedBuilder embed = new EmbedBuilder();
- * InputStream file = new FileInputStream("image.png"); // the name in your file system can be different from the name used in discord
- * embed.setImage("attachment://cat.png") // we specify this in sendFile as "cat.png"
- * .setDescription("This is a cute cat :3");
- * hook.editMessageById(messageId, file, "cat.png").setEmbeds(embed.build()).queue();
- *
- *
- * Possible {@link net.dv8tion.jda.api.requests.ErrorResponse ErrorResponses} include:
- *
- * {@link net.dv8tion.jda.api.requests.ErrorResponse#UNKNOWN_WEBHOOK UNKNOWN_WEBHOOK}
- * The webhook is no longer available, either it was deleted or in case of interactions it expired.
- * {@link net.dv8tion.jda.api.requests.ErrorResponse#UNKNOWN_MESSAGE UNKNOWN_MESSAGE}
- * The message for that id does not exist
- *
+ * Resource Handling Note: Once the request is handed off to the requester, for example when you call {@link RestAction#queue()},
+ * the requester will automatically clean up all opened files by itself. You are only responsible to close them yourself if it is never handed off properly.
+ * For instance, if an exception occurs after using {@link FileUpload#fromData(File)}, before calling {@link RestAction#queue()}.
+ * You can safely use a try-with-resources to handle this, since {@link FileUpload#close()} becomes ineffective once the request is handed off.
*
* @param messageId
* The message id. For interactions this supports {@code "@original"} to edit the source message of the interaction.
- * @param data
- * The InputStream data to upload to the webhook.
- * @param name
- * The file name that should be sent to discord
- * Refer to the documentation for {@link #sendFile(java.io.File, String, AttachmentOption...)} for information about this parameter.
- * @param options
- * Possible options to apply to this attachment, such as marking it as spoiler image
- *
- * @throws java.lang.IllegalArgumentException
- * If the provided data or filename is {@code null}.
- *
- * @return {@link WebhookMessageUpdateAction}
- */
- @Nonnull
- @CheckReturnValue
- default WebhookMessageUpdateAction editMessageById(long messageId, @Nonnull InputStream data, @Nonnull String name, @Nonnull AttachmentOption... options)
- {
- return editMessageById(Long.toUnsignedString(messageId), data, name, options);
- }
-
- /**
- * Edit an existing message sent by this webhook.
- * The provided file will be appended to the message. You cannot delete or edit existing files on a message.
- *
- * If this is an {@link net.dv8tion.jda.api.interactions.InteractionHook InteractionHook} this method will be delayed until the interaction is acknowledged.
- *
- *
This is a shortcut to {@link #sendFile(java.io.File, String, AttachmentOption...)} by way of using {@link java.io.File#getName()}.
- *
sendFile(file, file.getName())
- *
- * Uploading images with Embeds
- * When uploading an image you can reference said image using the specified filename as URI {@code attachment://filename.ext}.
- *
- *
Example
- *
- * WebhookClient hook; // = reference of a WebhookClient such as interaction.getHook()
- * EmbedBuilder embed = new EmbedBuilder();
- * File file = new File("image.png"); // the name in your file system can be different from the name used in discord
- * embed.setImage("attachment://cat.png") // we specify this in sendFile as "cat.png"
- * .setDescription("This is a cute cat :3");
- * hook.editMessageById(messageId, file, "cat.png").setEmbeds(embed.build()).queue();
- *
- *
- * Possible {@link net.dv8tion.jda.api.requests.ErrorResponse ErrorResponses} include:
- *
- * {@link net.dv8tion.jda.api.requests.ErrorResponse#UNKNOWN_WEBHOOK UNKNOWN_WEBHOOK}
- * The webhook is no longer available, either it was deleted or in case of interactions it expired.
- * {@link net.dv8tion.jda.api.requests.ErrorResponse#UNKNOWN_MESSAGE UNKNOWN_MESSAGE}
- * The message for that id does not exist
- *
+ * @param attachments
+ * The new attachments of the message (Can be {@link FileUpload FileUploads} or {@link net.dv8tion.jda.api.utils.AttachmentUpdate AttachmentUpdates})
*
- * @param messageId
- * The message id. For interactions this supports {@code "@original"} to edit the source message of the interaction.
- * @param file
- * The {@link File} data to upload to the webhook.
- * @param options
- * Possible options to apply to this attachment, such as marking it as spoiler image
+ * @throws IllegalArgumentException
+ * If null is provided
*
- * @throws java.lang.IllegalArgumentException
- * If the provided file is {@code null}.
+ * @return {@link MessageEditCallbackAction} that can be used to further update the message
*
- * @return {@link WebhookMessageUpdateAction}
+ * @see AttachedFile#fromAttachment(Message.Attachment)
+ * @see FileUpload#fromData(InputStream, String)
*/
@Nonnull
@CheckReturnValue
- default WebhookMessageUpdateAction editMessageById(long messageId, @Nonnull File file, @Nonnull AttachmentOption... options)
+ default WebhookMessageEditAction editMessageAttachmentsById(long messageId, @Nonnull Collection extends AttachedFile> attachments)
{
- return editMessageById(Long.toUnsignedString(messageId), file, options);
+ return editMessageAttachmentsById(Long.toUnsignedString(messageId), attachments);
}
/**
* Edit an existing message sent by this webhook.
- * The provided file will be appended to the message. You cannot delete or edit existing files on a message.
*
* If this is an {@link net.dv8tion.jda.api.interactions.InteractionHook InteractionHook} this method will be delayed until the interaction is acknowledged.
*
- *
Uploading images with Embeds
- * When uploading an image you can reference said image using the specified filename as URI {@code attachment://filename.ext}.
- *
- *
Example
- *
- * WebhookClient hook; // = reference of a WebhookClient such as interaction.getHook()
- * EmbedBuilder embed = new EmbedBuilder();
- * File file = new File("image.png"); // the name in your file system can be different from the name used in discord
- * embed.setImage("attachment://cat.png") // we specify this in sendFile as "cat.png"
- * .setDescription("This is a cute cat :3");
- * hook.editMessageById(messageId, file, "cat.png").setEmbeds(embed.build()).queue();
- *
- *
- * Possible {@link net.dv8tion.jda.api.requests.ErrorResponse ErrorResponses} include:
- *
- * {@link net.dv8tion.jda.api.requests.ErrorResponse#UNKNOWN_WEBHOOK UNKNOWN_WEBHOOK}
- * The webhook is no longer available, either it was deleted or in case of interactions it expired.
- * {@link net.dv8tion.jda.api.requests.ErrorResponse#UNKNOWN_MESSAGE UNKNOWN_MESSAGE}
- * The message for that id does not exist
- *
+ * Resource Handling Note: Once the request is handed off to the requester, for example when you call {@link RestAction#queue()},
+ * the requester will automatically clean up all opened files by itself. You are only responsible to close them yourself if it is never handed off properly.
+ * For instance, if an exception occurs after using {@link FileUpload#fromData(File)}, before calling {@link RestAction#queue()}.
+ * You can safely use a try-with-resources to handle this, since {@link FileUpload#close()} becomes ineffective once the request is handed off.
*
* @param messageId
* The message id. For interactions this supports {@code "@original"} to edit the source message of the interaction.
- * @param file
- * The {@link File} data to upload to the webhook.
- * @param name
- * The file name that should be sent to discord
- * Refer to the documentation for {@link #sendFile(java.io.File, String, AttachmentOption...)} for information about this parameter.
- * @param options
- * Possible options to apply to this attachment, such as marking it as spoiler image
- *
- * @throws java.lang.IllegalArgumentException
- * If the provided file or filename is {@code null}.
- *
- * @return {@link WebhookMessageUpdateAction}
- */
- @Nonnull
- @CheckReturnValue
- default WebhookMessageUpdateAction editMessageById(long messageId, @Nonnull File file, @Nonnull String name, @Nonnull AttachmentOption... options)
- {
- return editMessageById(Long.toUnsignedString(messageId), file, name, options);
- }
-
- /**
- * Edit an existing message sent by this webhook.
- * The provided file will be appended to the message. You cannot delete or edit existing files on a message.
- *
- * If this is an {@link net.dv8tion.jda.api.interactions.InteractionHook InteractionHook} this method will be delayed until the interaction is acknowledged.
+ * @param attachments
+ * The new attachments of the message (Can be {@link FileUpload FileUploads} or {@link net.dv8tion.jda.api.utils.AttachmentUpdate AttachmentUpdates})
*
- *
Uploading images with Embeds
- * When uploading an image you can reference said image using the specified filename as URI {@code attachment://filename.ext}.
+ * @throws IllegalArgumentException
+ * If null is provided
*
- *
Example
- *
- * WebhookClient hook; // = reference of a WebhookClient such as interaction.getHook()
- * EmbedBuilder embed = new EmbedBuilder();
- * InputStream file = new FileInputStream("image.png"); // the name in your file system can be different from the name used in discord
- * embed.setImage("attachment://cat.png") // we specify this in sendFile as "cat.png"
- * .setDescription("This is a cute cat :3");
- * hook.editMessageById(messageId, file, "cat.png").setEmbeds(embed.build()).queue();
- *
+ * @return {@link MessageEditCallbackAction} that can be used to further update the message
*
- * Possible {@link net.dv8tion.jda.api.requests.ErrorResponse ErrorResponses} include:
- *
- * {@link net.dv8tion.jda.api.requests.ErrorResponse#UNKNOWN_WEBHOOK UNKNOWN_WEBHOOK}
- * The webhook is no longer available, either it was deleted or in case of interactions it expired.
- * {@link net.dv8tion.jda.api.requests.ErrorResponse#UNKNOWN_MESSAGE UNKNOWN_MESSAGE}
- * The message for that id does not exist
- *
- *
- * @param messageId
- * The message id. For interactions this supports {@code "@original"} to edit the source message of the interaction.
- * @param data
- * The InputStream data to upload to the webhook.
- * @param name
- * The file name that should be sent to discord
- * Refer to the documentation for {@link #sendFile(java.io.File, String, AttachmentOption...)} for information about this parameter.
- * @param options
- * Possible options to apply to this attachment, such as marking it as spoiler image
- *
- * @throws java.lang.IllegalArgumentException
- * If the provided data or filename is {@code null}.
- *
- * @return {@link WebhookMessageUpdateAction}
+ * @see AttachedFile#fromAttachment(Message.Attachment)
+ * @see FileUpload#fromData(InputStream, String)
*/
@Nonnull
@CheckReturnValue
- default WebhookMessageUpdateAction editMessageById(long messageId, @Nonnull byte[] data, @Nonnull String name, @Nonnull AttachmentOption... options)
+ default WebhookMessageEditAction editMessageAttachmentsById(long messageId, @Nonnull AttachedFile... attachments)
{
- return editMessageById(Long.toUnsignedString(messageId), data, name, options);
+ return editMessageAttachmentsById(Long.toUnsignedString(messageId), attachments);
}
diff --git a/src/main/java/net/dv8tion/jda/api/exceptions/InteractionFailureException.java b/src/main/java/net/dv8tion/jda/api/exceptions/InteractionFailureException.java
index bb51d3b8ed..2c4be4ed46 100644
--- a/src/main/java/net/dv8tion/jda/api/exceptions/InteractionFailureException.java
+++ b/src/main/java/net/dv8tion/jda/api/exceptions/InteractionFailureException.java
@@ -23,7 +23,7 @@
/**
* Exception caused by the failure of {@link ReplyCallbackAction ReplyAction}.
*
- * This is used to signal that a {@link net.dv8tion.jda.api.requests.restaction.WebhookMessageAction WebhookMessageAction}
+ *
This is used to signal that a {@link net.dv8tion.jda.api.requests.restaction.WebhookMessageCreateAction WebhookMessageCreateAction}
* was cancelled due to a cascading failure from the initial command acknowledgement.
*/
public class InteractionFailureException extends CancellationException
diff --git a/src/main/java/net/dv8tion/jda/api/interactions/InteractionHook.java b/src/main/java/net/dv8tion/jda/api/interactions/InteractionHook.java
index 68b7f7cecd..415ee8fac7 100644
--- a/src/main/java/net/dv8tion/jda/api/interactions/InteractionHook.java
+++ b/src/main/java/net/dv8tion/jda/api/interactions/InteractionHook.java
@@ -25,15 +25,15 @@
import net.dv8tion.jda.api.interactions.components.ActionRow;
import net.dv8tion.jda.api.interactions.components.LayoutComponent;
import net.dv8tion.jda.api.requests.RestAction;
-import net.dv8tion.jda.api.requests.restaction.WebhookMessageUpdateAction;
-import net.dv8tion.jda.api.utils.AttachmentOption;
+import net.dv8tion.jda.api.requests.restaction.WebhookMessageEditAction;
+import net.dv8tion.jda.api.utils.AttachedFile;
+import net.dv8tion.jda.api.utils.messages.MessageEditData;
import net.dv8tion.jda.internal.utils.Checks;
import javax.annotation.CheckReturnValue;
import javax.annotation.Nonnull;
-import java.io.File;
-import java.io.InputStream;
import java.time.temporal.ChronoUnit;
+import java.util.Arrays;
import java.util.Collection;
/**
@@ -157,11 +157,11 @@ default boolean isExpired()
* @throws IllegalArgumentException
* If the provided content is null, empty, or longer than {@link Message#MAX_CONTENT_LENGTH}
*
- * @return {@link WebhookMessageUpdateAction}
+ * @return {@link WebhookMessageEditAction}
*/
@Nonnull
@CheckReturnValue
- default WebhookMessageUpdateAction editOriginal(@Nonnull String content)
+ default WebhookMessageEditAction editOriginal(@Nonnull String content)
{
return editMessageById("@original", content);
}
@@ -187,11 +187,11 @@ default WebhookMessageUpdateAction editOriginal(@Nonnull String content
* @throws IllegalArgumentException
* If the provided components are null, or more than 5 layouts are provided
*
- * @return {@link WebhookMessageUpdateAction}
+ * @return {@link WebhookMessageEditAction}
*/
@Nonnull
@CheckReturnValue
- default WebhookMessageUpdateAction editOriginalComponents(@Nonnull Collection extends LayoutComponent> components)
+ default WebhookMessageEditAction editOriginalComponents(@Nonnull Collection extends LayoutComponent> components)
{
return editMessageComponentsById("@original", components);
}
@@ -217,11 +217,11 @@ default WebhookMessageUpdateAction editOriginalComponents(@Nonnull Coll
* @throws IllegalArgumentException
* If the provided components are null, or more than 5 layouts are provided
*
- * @return {@link WebhookMessageUpdateAction}
+ * @return {@link WebhookMessageEditAction}
*/
@Nonnull
@CheckReturnValue
- default WebhookMessageUpdateAction editOriginalComponents(@Nonnull LayoutComponent... components)
+ default WebhookMessageEditAction editOriginalComponents(@Nonnull LayoutComponent... components)
{
return editMessageComponentsById("@original", components);
}
@@ -247,11 +247,11 @@ default WebhookMessageUpdateAction editOriginalComponents(@Nonnull Layo
* @throws IllegalArgumentException
* If the provided embeds are null, or more than {@value Message#MAX_EMBED_COUNT}
*
- * @return {@link WebhookMessageUpdateAction}
+ * @return {@link WebhookMessageEditAction}
*/
@Nonnull
@CheckReturnValue
- default WebhookMessageUpdateAction editOriginalEmbeds(@Nonnull Collection extends MessageEmbed> embeds)
+ default WebhookMessageEditAction editOriginalEmbeds(@Nonnull Collection extends MessageEmbed> embeds)
{
return editMessageEmbedsById("@original", embeds);
}
@@ -277,11 +277,11 @@ default WebhookMessageUpdateAction editOriginalEmbeds(@Nonnull Collecti
* @throws IllegalArgumentException
* If the provided embeds are null, or more than 10
*
- * @return {@link WebhookMessageUpdateAction}
+ * @return {@link WebhookMessageEditAction}
*/
@Nonnull
@CheckReturnValue
- default WebhookMessageUpdateAction editOriginalEmbeds(@Nonnull MessageEmbed... embeds)
+ default WebhookMessageEditAction editOriginalEmbeds(@Nonnull MessageEmbed... embeds)
{
return editMessageEmbedsById("@original", embeds);
}
@@ -307,11 +307,11 @@ default WebhookMessageUpdateAction editOriginalEmbeds(@Nonnull MessageE
* @throws IllegalArgumentException
* If the provided message is null
*
- * @return {@link WebhookMessageUpdateAction}
+ * @return {@link WebhookMessageEditAction}
*/
@Nonnull
@CheckReturnValue
- default WebhookMessageUpdateAction editOriginal(@Nonnull Message message)
+ default WebhookMessageEditAction editOriginal(@Nonnull MessageEditData message)
{
return editMessageById("@original", message);
}
@@ -339,212 +339,32 @@ default WebhookMessageUpdateAction editOriginal(@Nonnull Message messag
* @throws IllegalArgumentException
* If the formatted string is null, empty, or longer than {@link Message#MAX_CONTENT_LENGTH}
*
- * @return {@link WebhookMessageUpdateAction}
+ * @return {@link WebhookMessageEditAction}
*/
@Nonnull
@CheckReturnValue
- default WebhookMessageUpdateAction editOriginalFormat(@Nonnull String format, @Nonnull Object... args)
+ default WebhookMessageEditAction editOriginalFormat(@Nonnull String format, @Nonnull Object... args)
{
Checks.notNull(format, "Format String");
return editOriginal(String.format(format, args));
}
- /**
- * Edit the source message sent by this interaction.
- * For {@link IMessageEditCallback#editComponents(Collection)} and {@link IMessageEditCallback#deferEdit()} this will be the message the components are attached to.
- * For {@link IReplyCallback#deferReply()} and {@link IReplyCallback#reply(String)} this will be the reply message instead.
- * The provided file will be appended to the message. You cannot delete or edit existing files on a message.
- *
- * This method will be delayed until the interaction is acknowledged.
- *
- *
Uploading images with Embeds
- * When uploading an image you can reference said image using the specified filename as URI {@code attachment://filename.ext}.
- *
- *
Example
- *
- * WebhookClient hook; // = reference of a WebhookClient such as interaction.getHook()
- * EmbedBuilder embed = new EmbedBuilder();
- * InputStream file = new FileInputStream("image.png"); // the name in your file system can be different from the name used in discord
- * embed.setImage("attachment://cat.png") // we specify this in sendFile as "cat.png"
- * .setDescription("This is a cute cat :3");
- * hook.editOriginal(file, "cat.png").setEmbeds(embed.build()).queue();
- *
- *
- * Possible {@link net.dv8tion.jda.api.requests.ErrorResponse ErrorResponses} include:
- *
- * {@link net.dv8tion.jda.api.requests.ErrorResponse#UNKNOWN_WEBHOOK UNKNOWN_WEBHOOK}
- * The webhook is no longer available, either it was deleted or in case of interactions it expired.
- * {@link net.dv8tion.jda.api.requests.ErrorResponse#UNKNOWN_MESSAGE UNKNOWN_MESSAGE}
- * The message for that id does not exist
- *
- *
- * @param data
- * The InputStream data to upload to the webhook.
- * @param name
- * The file name that should be sent to discord
- * Refer to the documentation for {@link #sendFile(java.io.File, String, AttachmentOption...)} for information about this parameter.
- * @param options
- * Possible options to apply to this attachment, such as marking it as spoiler image
- *
- * @throws java.lang.IllegalArgumentException
- * If the provided data, or filename is {@code null}.
- *
- * @return {@link WebhookMessageUpdateAction}
- */
- @Nonnull
- @CheckReturnValue
- default WebhookMessageUpdateAction editOriginal(@Nonnull InputStream data, @Nonnull String name, @Nonnull AttachmentOption... options)
- {
- return editMessageById("@original", data, name, options);
- }
-
- /**
- * Edit the source message sent by this interaction.
- * For {@link IMessageEditCallback#editComponents(Collection)} and {@link IMessageEditCallback#deferEdit()} this will be the message the components are attached to.
- * For {@link IReplyCallback#deferReply()} and {@link IReplyCallback#reply(String)} this will be the reply message instead.
- * The provided file will be appended to the message. You cannot delete or edit existing files on a message.
- *
- * This method will be delayed until the interaction is acknowledged.
- *
- *
This is a shortcut to {@link #editOriginal(java.io.File, String, AttachmentOption...)} by way of using {@link java.io.File#getName()}.
- *
editOriginal(file, file.getName())
- *
- * Uploading images with Embeds
- * When uploading an image you can reference said image using the specified filename as URI {@code attachment://filename.ext}.
- *
- *
Example
- *
- * WebhookClient hook; // = reference of a WebhookClient such as interaction.getHook()
- * EmbedBuilder embed = new EmbedBuilder();
- * File file = new File("image.png"); // the name in your file system can be different from the name used in discord
- * embed.setImage("attachment://cat.png") // we specify this in sendFile as "cat.png"
- * .setDescription("This is a cute cat :3");
- * hook.editOriginal(file, "cat.png").setEmbeds(embed.build()).queue();
- *
- *
- * Possible {@link net.dv8tion.jda.api.requests.ErrorResponse ErrorResponses} include:
- *
- * {@link net.dv8tion.jda.api.requests.ErrorResponse#UNKNOWN_WEBHOOK UNKNOWN_WEBHOOK}
- * The webhook is no longer available, either it was deleted or in case of interactions it expired.
- * {@link net.dv8tion.jda.api.requests.ErrorResponse#UNKNOWN_MESSAGE UNKNOWN_MESSAGE}
- * The message for that id does not exist
- *
- *
- * @param file
- * The {@link File} data to upload to the webhook.
- * @param options
- * Possible options to apply to this attachment, such as marking it as spoiler image
- *
- * @throws java.lang.IllegalArgumentException
- * If the provided file is {@code null}.
- *
- * @return {@link WebhookMessageUpdateAction}
- */
@Nonnull
@CheckReturnValue
- default WebhookMessageUpdateAction editOriginal(@Nonnull File file, @Nonnull AttachmentOption... options)
+ default WebhookMessageEditAction editOriginalAttachments(@Nonnull Collection extends AttachedFile> attachments)
{
- return editMessageById("@original", file, options);
+ return editMessageAttachmentsById("@original", attachments);
}
- /**
- * Edit the source message sent by this interaction.
- * For {@link IMessageEditCallback#editComponents(Collection)} and {@link IMessageEditCallback#deferEdit()} this will be the message the components are attached to.
- * For {@link IReplyCallback#deferReply()} and {@link IReplyCallback#reply(String)} this will be the reply message instead.
- * The provided file will be appended to the message. You cannot delete or edit existing files on a message.
- *
- * This method will be delayed until the interaction is acknowledged.
- *
- *
Uploading images with Embeds
- * When uploading an image you can reference said image using the specified filename as URI {@code attachment://filename.ext}.
- *
- *
Example
- *
- * WebhookClient hook; // = reference of a WebhookClient such as interaction.getHook()
- * EmbedBuilder embed = new EmbedBuilder();
- * File file = new File("image.png"); // the name in your file system can be different from the name used in discord
- * embed.setImage("attachment://cat.png") // we specify this in sendFile as "cat.png"
- * .setDescription("This is a cute cat :3");
- * hook.editOriginal(file, "cat.png").setEmbeds(embed.build()).queue();
- *
- *
- * Possible {@link net.dv8tion.jda.api.requests.ErrorResponse ErrorResponses} include:
- *
- * {@link net.dv8tion.jda.api.requests.ErrorResponse#UNKNOWN_WEBHOOK UNKNOWN_WEBHOOK}
- * The webhook is no longer available, either it was deleted or in case of interactions it expired.
- * {@link net.dv8tion.jda.api.requests.ErrorResponse#UNKNOWN_MESSAGE UNKNOWN_MESSAGE}
- * The message for that id does not exist
- *
- *
- * @param file
- * The {@link File} data to upload to the webhook.
- * @param name
- * The file name that should be sent to discord
- * Refer to the documentation for {@link #sendFile(java.io.File, String, AttachmentOption...)} for information about this parameter.
- * @param options
- * Possible options to apply to this attachment, such as marking it as spoiler image
- *
- * @throws java.lang.IllegalArgumentException
- * If the provided file or filename is {@code null}.
- *
- * @return {@link WebhookMessageUpdateAction}
- */
@Nonnull
@CheckReturnValue
- default WebhookMessageUpdateAction editOriginal(@Nonnull File file, @Nonnull String name, @Nonnull AttachmentOption... options)
+ default WebhookMessageEditAction editOriginalAttachments(@Nonnull AttachedFile... attachments)
{
- return editMessageById("@original", file, name, options);
+ Checks.noneNull(attachments, "Attachments");
+ return editOriginalAttachments(Arrays.asList(attachments));
}
- /**
- * Edit the source message sent by this interaction.
- * For {@link IMessageEditCallback#editComponents(Collection)} and {@link IMessageEditCallback#deferEdit()} this will be the message the components are attached to.
- * For {@link IReplyCallback#deferReply()} and {@link IReplyCallback#reply(String)} this will be the reply message instead.
- * The provided file will be appended to the message. You cannot delete or edit existing files on a message.
- *
- * This method will be delayed until the interaction is acknowledged.
- *
- *
Uploading images with Embeds
- * When uploading an image you can reference said image using the specified filename as URI {@code attachment://filename.ext}.
- *
- *
Example
- *
- * WebhookClient hook; // = reference of a WebhookClient such as interaction.getHook()
- * EmbedBuilder embed = new EmbedBuilder();
- * InputStream file = new FileInputStream("image.png"); // the name in your file system can be different from the name used in discord
- * embed.setImage("attachment://cat.png") // we specify this in sendFile as "cat.png"
- * .setDescription("This is a cute cat :3");
- * hook.editOriginal(file, "cat.png").setEmbeds(embed.build()).queue();
- *
- *
- * Possible {@link net.dv8tion.jda.api.requests.ErrorResponse ErrorResponses} include:
- *
- * {@link net.dv8tion.jda.api.requests.ErrorResponse#UNKNOWN_WEBHOOK UNKNOWN_WEBHOOK}
- * The webhook is no longer available, either it was deleted or in case of interactions it expired.
- * {@link net.dv8tion.jda.api.requests.ErrorResponse#UNKNOWN_MESSAGE UNKNOWN_MESSAGE}
- * The message for that id does not exist
- *
- *
- * @param data
- * The InputStream data to upload to the webhook.
- * @param name
- * The file name that should be sent to discord
- * Refer to the documentation for {@link #sendFile(java.io.File, String, AttachmentOption...)} for information about this parameter.
- * @param options
- * Possible options to apply to this attachment, such as marking it as spoiler image
- *
- * @throws java.lang.IllegalArgumentException
- * If the provided data or filename is {@code null}.
- *
- * @return {@link WebhookMessageUpdateAction}
- */
- @Nonnull
- @CheckReturnValue
- default WebhookMessageUpdateAction editOriginal(@Nonnull byte[] data, @Nonnull String name, @Nonnull AttachmentOption... options)
- {
- return editMessageById("@original", data, name, options);
- }
/**
* Delete the original reply.
diff --git a/src/main/java/net/dv8tion/jda/api/interactions/callbacks/IMessageEditCallback.java b/src/main/java/net/dv8tion/jda/api/interactions/callbacks/IMessageEditCallback.java
index 08e5a5d47c..79e82206bc 100644
--- a/src/main/java/net/dv8tion/jda/api/interactions/callbacks/IMessageEditCallback.java
+++ b/src/main/java/net/dv8tion/jda/api/interactions/callbacks/IMessageEditCallback.java
@@ -21,12 +21,18 @@
import net.dv8tion.jda.api.interactions.InteractionHook;
import net.dv8tion.jda.api.interactions.components.ActionRow;
import net.dv8tion.jda.api.interactions.components.LayoutComponent;
+import net.dv8tion.jda.api.requests.RestAction;
import net.dv8tion.jda.api.requests.restaction.interactions.MessageEditCallbackAction;
+import net.dv8tion.jda.api.utils.AttachedFile;
+import net.dv8tion.jda.api.utils.FileUpload;
+import net.dv8tion.jda.api.utils.messages.MessageEditData;
import net.dv8tion.jda.internal.requests.restaction.interactions.MessageEditCallbackActionImpl;
import net.dv8tion.jda.internal.utils.Checks;
import javax.annotation.CheckReturnValue;
import javax.annotation.Nonnull;
+import java.io.File;
+import java.io.InputStream;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
@@ -85,11 +91,11 @@ public interface IMessageEditCallback extends IDeferrableCallback
*/
@Nonnull
@CheckReturnValue
- default MessageEditCallbackAction editMessage(@Nonnull Message message)
+ default MessageEditCallbackAction editMessage(@Nonnull MessageEditData message)
{
Checks.notNull(message, "Message");
MessageEditCallbackActionImpl action = (MessageEditCallbackActionImpl) deferEdit();
- return action.applyMessage(message);
+ return action.applyData(message);
}
/**
@@ -105,7 +111,7 @@ default MessageEditCallbackAction editMessage(@Nonnull Message message)
* The new message content to use
*
* @throws IllegalArgumentException
- * If the provided content is null
+ * If the provided content is null or longer than {@value Message#MAX_CONTENT_LENGTH} characters
*
* @return {@link MessageEditCallbackAction} that can be used to further update the message
*/
@@ -133,6 +139,7 @@ default MessageEditCallbackAction editMessage(@Nonnull String content)
*
* If any of the provided LayoutComponents is null
* If any of the provided Components are not compatible with messages
+ * If more than {@value Message#MAX_COMPONENT_COUNT} component layouts are provided
*
*
* @return {@link MessageEditCallbackAction} that can be used to further update the message
@@ -147,7 +154,7 @@ default MessageEditCallbackAction editComponents(@Nonnull Collection extends L
if (components.stream().anyMatch(it -> !(it instanceof ActionRow)))
throw new UnsupportedOperationException("The provided component layout is not supported");
List actionRows = components.stream().map(ActionRow.class::cast).collect(Collectors.toList());
- return deferEdit().setActionRows(actionRows);
+ return deferEdit().setComponents(actionRows);
}
/**
@@ -166,6 +173,7 @@ default MessageEditCallbackAction editComponents(@Nonnull Collection extends L
*
* If any of the provided LayoutComponents are null
* If any of the provided Components are not compatible with messages
+ * If more than {@value Message#MAX_COMPONENT_COUNT} component layouts are provided
*
*
* @return {@link MessageEditCallbackAction} that can be used to further update the message
@@ -193,7 +201,7 @@ default MessageEditCallbackAction editComponents(@Nonnull LayoutComponent... com
* The new {@link MessageEmbed MessageEmbeds}
*
* @throws IllegalArgumentException
- * If any of the provided embeds is null
+ * If null or more than {@value Message#MAX_EMBED_COUNT} embeds are provided
*
* @return {@link MessageEditCallbackAction} that can be used to further update the message
*/
@@ -218,7 +226,7 @@ default MessageEditCallbackAction editMessageEmbeds(@Nonnull Collection extend
* The new message embeds to include in the message
*
* @throws IllegalArgumentException
- * If any of the provided embeds is null
+ * If null or more than {@value Message#MAX_EMBED_COUNT} embeds are provided
*
* @return {@link MessageEditCallbackAction} that can be used to further update the message
*/
@@ -256,4 +264,70 @@ default MessageEditCallbackAction editMessageFormat(@Nonnull String format, @Non
Checks.notNull(format, "Format String");
return editMessage(String.format(format, args));
}
+
+ /**
+ * Acknowledgement of this interaction with a message update.
+ * You can use {@link #getHook()} to edit the message further.
+ *
+ * You can only use deferEdit() or editMessage() once per interaction! Use {@link #getHook()} for any additional updates.
+ *
+ *
You only have 3 seconds to acknowledge an interaction!
+ * When the acknowledgement is sent after the interaction expired, you will receive {@link net.dv8tion.jda.api.requests.ErrorResponse#UNKNOWN_INTERACTION ErrorResponse.UNKNOWN_INTERACTION}.
+ *
+ *
Resource Handling Note: Once the request is handed off to the requester, for example when you call {@link RestAction#queue()},
+ * the requester will automatically clean up all opened files by itself. You are only responsible to close them yourself if it is never handed off properly.
+ * For instance, if an exception occurs after using {@link FileUpload#fromData(File)}, before calling {@link RestAction#queue()}.
+ * You can safely use a try-with-resources to handle this, since {@link FileUpload#close()} becomes ineffective once the request is handed off.
+ *
+ * @param attachments
+ * The new attachments of the message (Can be {@link FileUpload FileUploads} or {@link net.dv8tion.jda.api.utils.AttachmentUpdate AttachmentUpdates})
+ *
+ * @throws IllegalArgumentException
+ * If null is provided
+ *
+ * @return {@link MessageEditCallbackAction} that can be used to further update the message
+ *
+ * @see AttachedFile#fromAttachment(Message.Attachment)
+ * @see FileUpload#fromData(InputStream, String)
+ */
+ @Nonnull
+ @CheckReturnValue
+ default MessageEditCallbackAction editMessageAttachments(@Nonnull Collection extends AttachedFile> attachments)
+ {
+ Checks.noneNull(attachments, "Attachments");
+ return deferEdit().setAttachments(attachments);
+ }
+
+ /**
+ * Acknowledgement of this interaction with a message update.
+ * You can use {@link #getHook()} to edit the message further.
+ *
+ *
You can only use deferEdit() or editMessage() once per interaction! Use {@link #getHook()} for any additional updates.
+ *
+ *
You only have 3 seconds to acknowledge an interaction!
+ * When the acknowledgement is sent after the interaction expired, you will receive {@link net.dv8tion.jda.api.requests.ErrorResponse#UNKNOWN_INTERACTION ErrorResponse.UNKNOWN_INTERACTION}.
+ *
+ *
Resource Handling Note: Once the request is handed off to the requester, for example when you call {@link RestAction#queue()},
+ * the requester will automatically clean up all opened files by itself. You are only responsible to close them yourself if it is never handed off properly.
+ * For instance, if an exception occurs after using {@link FileUpload#fromData(File)}, before calling {@link RestAction#queue()}.
+ * You can safely use a try-with-resources to handle this, since {@link FileUpload#close()} becomes ineffective once the request is handed off.
+ *
+ * @param attachments
+ * The new attachments of the message (Can be {@link FileUpload FileUploads} or {@link net.dv8tion.jda.api.utils.AttachmentUpdate AttachmentUpdates})
+ *
+ * @throws IllegalArgumentException
+ * If null is provided
+ *
+ * @return {@link MessageEditCallbackAction} that can be used to further update the message
+ *
+ * @see AttachedFile#fromAttachment(Message.Attachment)
+ * @see FileUpload#fromData(InputStream, String)
+ */
+ @Nonnull
+ @CheckReturnValue
+ default MessageEditCallbackAction editMessageAttachments(@Nonnull AttachedFile... attachments)
+ {
+ Checks.noneNull(attachments, "Attachments");
+ return deferEdit().setAttachments(attachments);
+ }
}
diff --git a/src/main/java/net/dv8tion/jda/api/interactions/callbacks/IReplyCallback.java b/src/main/java/net/dv8tion/jda/api/interactions/callbacks/IReplyCallback.java
index 49c4e48d9e..ac9392cfed 100644
--- a/src/main/java/net/dv8tion/jda/api/interactions/callbacks/IReplyCallback.java
+++ b/src/main/java/net/dv8tion/jda/api/interactions/callbacks/IReplyCallback.java
@@ -19,8 +19,10 @@
import net.dv8tion.jda.api.entities.Message;
import net.dv8tion.jda.api.entities.MessageEmbed;
import net.dv8tion.jda.api.interactions.InteractionHook;
+import net.dv8tion.jda.api.requests.RestAction;
import net.dv8tion.jda.api.requests.restaction.interactions.ReplyCallbackAction;
-import net.dv8tion.jda.api.utils.AttachmentOption;
+import net.dv8tion.jda.api.utils.FileUpload;
+import net.dv8tion.jda.api.utils.messages.MessageCreateData;
import net.dv8tion.jda.internal.requests.restaction.interactions.ReplyCallbackActionImpl;
import net.dv8tion.jda.internal.utils.Checks;
@@ -109,20 +111,22 @@ default ReplyCallbackAction deferReply(boolean ephemeral)
*
If your handling can take longer than 3 seconds, due to various rate limits or other conditions, you should use {@link #deferReply()} instead.
*
* @param message
- * The message to send
+ * The {@link MessageCreateData} to send
*
* @throws IllegalArgumentException
* If null is provided
*
* @return {@link ReplyCallbackAction}
+ *
+ * @see net.dv8tion.jda.api.utils.messages.MessageCreateBuilder MessageCreateBuilder
*/
@Nonnull
@CheckReturnValue
- default ReplyCallbackAction reply(@Nonnull Message message)
+ default ReplyCallbackAction reply(@Nonnull MessageCreateData message)
{
Checks.notNull(message, "Message");
ReplyCallbackActionImpl action = (ReplyCallbackActionImpl) deferReply();
- return action.applyMessage(message);
+ return action.applyData(message);
}
/**
@@ -139,7 +143,7 @@ default ReplyCallbackAction reply(@Nonnull Message message)
* The message content to send
*
* @throws IllegalArgumentException
- * If null is provided or the content is empty or longer than {@link Message#MAX_CONTENT_LENGTH}
+ * If null is provided or the content is longer than {@link Message#MAX_CONTENT_LENGTH} characters
*
* @return {@link ReplyCallbackAction}
*/
@@ -281,7 +285,7 @@ default ReplyCallbackAction replyEmbeds(@Nonnull MessageEmbed embed, @Nonnull Me
* Format arguments for the content
*
* @throws IllegalArgumentException
- * If the format string is null or the resulting content is longer than {@link Message#MAX_CONTENT_LENGTH}
+ * If the format string is null or the resulting content is longer than {@link Message#MAX_CONTENT_LENGTH} characters
*
* @return {@link ReplyCallbackAction}
*/
@@ -303,66 +307,27 @@ default ReplyCallbackAction replyFormat(@Nonnull String format, @Nonnull Object.
* When the acknowledgement is sent after the interaction expired, you will receive {@link net.dv8tion.jda.api.requests.ErrorResponse#UNKNOWN_INTERACTION ErrorResponse.UNKNOWN_INTERACTION}.
*
If your handling can take longer than 3 seconds, due to various rate limits or other conditions, you should use {@link #deferReply()} instead.
*
- *
Possible {@link net.dv8tion.jda.api.requests.ErrorResponse ErrorResponses} include:
- *
- * {@link net.dv8tion.jda.api.requests.ErrorResponse#REQUEST_ENTITY_TOO_LARGE REQUEST_ENTITY_TOO_LARGE}
- * The file exceeds the maximum upload size of {@link Message#MAX_FILE_SIZE}
- *
+ * Resource Handling Note: Once the request is handed off to the requester, for example when you call {@link RestAction#queue()},
+ * the requester will automatically clean up all opened files by itself. You are only responsible to close them yourself if it is never handed off properly.
+ * For instance, if an exception occurs after using {@link FileUpload#fromData(File)}, before calling {@link RestAction#queue()}.
+ * You can safely use a try-with-resources to handle this, since {@link FileUpload#close()} becomes ineffective once the request is handed off.
*
- * @param data
- * The InputStream data to upload
- * @param name
- * The file name that should be sent to discord
- * Refer to the documentation for {@link #replyFile(java.io.File, String, AttachmentOption...)} for information about this parameter.
- * @param options
- * Possible options to apply to this attachment, such as marking it as spoiler image
+ * @param files
+ * The {@link FileUpload FileUploads} to attach to the message
*
- * @throws java.lang.IllegalArgumentException
- * If the provided file or filename is {@code null} or {@code empty}.
+ * @throws IllegalArgumentException
+ * If null is provided
*
* @return {@link ReplyCallbackAction}
- */
- @Nonnull
- @CheckReturnValue
- default ReplyCallbackAction replyFile(@Nonnull InputStream data, @Nonnull String name, @Nonnull AttachmentOption... options)
- {
- return deferReply().addFile(data, name, options);
- }
-
- /**
- * Reply to this interaction and acknowledge it.
- * This will send a reply message for this interaction.
- * You can use {@link ReplyCallbackAction#setEphemeral(boolean) setEphemeral(true)} to only let the target user see the message.
- * Replies are non-ephemeral by default.
- *
- *
You only have 3 seconds to acknowledge an interaction!
- * When the acknowledgement is sent after the interaction expired, you will receive {@link net.dv8tion.jda.api.requests.ErrorResponse#UNKNOWN_INTERACTION ErrorResponse.UNKNOWN_INTERACTION}.
- *
If your handling can take longer than 3 seconds, due to various rate limits or other conditions, you should use {@link #deferReply()} instead.
- *
- *
This is a shortcut to {@link #replyFile(java.io.File, String, AttachmentOption...)} by way of using {@link java.io.File#getName()}.
- *
sendFile(file, file.getName())
- *
- * Possible {@link net.dv8tion.jda.api.requests.ErrorResponse ErrorResponses} include:
- *
- * {@link net.dv8tion.jda.api.requests.ErrorResponse#REQUEST_ENTITY_TOO_LARGE REQUEST_ENTITY_TOO_LARGE}
- * The file exceeds the maximum upload size of {@link Message#MAX_FILE_SIZE}
- *
- *
- * @param file
- * The {@link File} data to upload
- * @param options
- * Possible options to apply to this attachment, such as marking it as spoiler image
- *
- * @throws java.lang.IllegalArgumentException
- * If the provided file is {@code null}.
*
- * @return {@link ReplyCallbackAction}
+ * @see FileUpload#fromData(InputStream, String)
*/
@Nonnull
@CheckReturnValue
- default ReplyCallbackAction replyFile(@Nonnull File file, @Nonnull AttachmentOption... options)
+ default ReplyCallbackAction replyFiles(@Nonnull Collection extends FileUpload> files)
{
- return deferReply().addFile(file, options);
+ Checks.notEmpty(files, "File Collection");
+ return deferReply().setFiles(files);
}
/**
@@ -375,76 +340,27 @@ default ReplyCallbackAction replyFile(@Nonnull File file, @Nonnull AttachmentOpt
* When the acknowledgement is sent after the interaction expired, you will receive {@link net.dv8tion.jda.api.requests.ErrorResponse#UNKNOWN_INTERACTION ErrorResponse.UNKNOWN_INTERACTION}.
* If your handling can take longer than 3 seconds, due to various rate limits or other conditions, you should use {@link #deferReply()} instead.
*
- *
The {@code name} parameter is used to inform Discord about what the file should be called. This is 2 fold:
- *
- * The file name provided is the name that is found in {@link net.dv8tion.jda.api.entities.Message.Attachment#getFileName()}
- * after upload and it is the name that will show up in the client when the upload is displayed.
- * Note: The fileName does not show up on the Desktop client for images. It does on mobile however.
- * The extension of the provided fileName also determines how Discord will treat the file. Discord currently only
- * has special handling for image file types, but the fileName's extension must indicate that it is an image file.
- * This means it has to end in something like .png, .jpg, .jpeg, .gif, etc. As a note, you can also not provide
- * a full name for the file and instead ONLY provide the extension like "png" or "gif" and Discord will generate
- * a name for the upload and append the fileName as the extension.
- *
- *
- * Possible {@link net.dv8tion.jda.api.requests.ErrorResponse ErrorResponses} include:
- *
- * {@link net.dv8tion.jda.api.requests.ErrorResponse#REQUEST_ENTITY_TOO_LARGE REQUEST_ENTITY_TOO_LARGE}
- * The file exceeds the maximum upload size of {@link Message#MAX_FILE_SIZE}
- *
+ * Resource Handling Note: Once the request is handed off to the requester, for example when you call {@link RestAction#queue()},
+ * the requester will automatically clean up all opened files by itself. You are only responsible to close them yourself if it is never handed off properly.
+ * For instance, if an exception occurs after using {@link FileUpload#fromData(File)}, before calling {@link RestAction#queue()}.
+ * You can safely use a try-with-resources to handle this, since {@link FileUpload#close()} becomes ineffective once the request is handed off.
*
- * @param file
- * The {@link File} data to upload
- * @param name
- * The file name that should be sent to discord
- * @param options
- * Possible options to apply to this attachment, such as marking it as spoiler image
+ * @param files
+ * The {@link FileUpload FileUploads} to attach to the message
*
- * @throws java.lang.IllegalArgumentException
- * If the provided file or filename is {@code null} or {@code empty}.
+ * @throws IllegalArgumentException
+ * If null is provided
*
* @return {@link ReplyCallbackAction}
- */
- @Nonnull
- @CheckReturnValue
- default ReplyCallbackAction replyFile(@Nonnull File file, @Nonnull String name, @Nonnull AttachmentOption... options)
- {
- return deferReply().addFile(file, name, options);
- }
-
- /**
- * Reply to this interaction and acknowledge it.
- * This will send a reply message for this interaction.
- * You can use {@link ReplyCallbackAction#setEphemeral(boolean) setEphemeral(true)} to only let the target user see the message.
- * Replies are non-ephemeral by default.
- *
- *
You only have 3 seconds to acknowledge an interaction!
- * When the acknowledgement is sent after the interaction expired, you will receive {@link net.dv8tion.jda.api.requests.ErrorResponse#UNKNOWN_INTERACTION ErrorResponse.UNKNOWN_INTERACTION}.
- *
If your handling can take longer than 3 seconds, due to various rate limits or other conditions, you should use {@link #deferReply()} instead.
*
- *
Possible {@link net.dv8tion.jda.api.requests.ErrorResponse ErrorResponses} include:
- *
- * {@link net.dv8tion.jda.api.requests.ErrorResponse#REQUEST_ENTITY_TOO_LARGE REQUEST_ENTITY_TOO_LARGE}
- * The file exceeds the maximum upload size of {@link Message#MAX_FILE_SIZE}
- *
- *
- * @param data
- * The {@code byte[]} data to upload
- * @param name
- * The file name that should be sent to discord
- * Refer to the documentation for {@link #replyFile(java.io.File, String, AttachmentOption...)} for information about this parameter.
- * @param options
- * Possible options to apply to this attachment, such as marking it as spoiler image
- *
- * @throws java.lang.IllegalArgumentException
- * If the provided file or filename is {@code null} or {@code empty}.
- *
- * @return {@link ReplyCallbackAction}
+ * @see FileUpload#fromData(InputStream, String)
*/
@Nonnull
@CheckReturnValue
- default ReplyCallbackAction replyFile(@Nonnull byte[] data, @Nonnull String name, @Nonnull AttachmentOption... options)
+ default ReplyCallbackAction replyFiles(@Nonnull FileUpload... files)
{
- return deferReply().addFile(data, name, options);
+ Checks.notEmpty(files, "File Collection");
+ Checks.noneNull(files, "FileUpload");
+ return deferReply().setFiles(files);
}
}
diff --git a/src/main/java/net/dv8tion/jda/api/interactions/components/buttons/Button.java b/src/main/java/net/dv8tion/jda/api/interactions/components/buttons/Button.java
index ff7f4cd349..f2b248e325 100644
--- a/src/main/java/net/dv8tion/jda/api/interactions/components/buttons/Button.java
+++ b/src/main/java/net/dv8tion/jda/api/interactions/components/buttons/Button.java
@@ -22,6 +22,7 @@
import net.dv8tion.jda.api.interactions.components.ActionComponent;
import net.dv8tion.jda.api.interactions.components.ActionRow;
import net.dv8tion.jda.api.interactions.components.ItemComponent;
+import net.dv8tion.jda.api.interactions.components.LayoutComponent;
import net.dv8tion.jda.api.requests.restaction.interactions.ReplyCallbackAction;
import net.dv8tion.jda.internal.interactions.component.ButtonImpl;
import net.dv8tion.jda.internal.utils.Checks;
@@ -70,7 +71,7 @@
*
*
* @see ReplyCallbackAction#addActionRow(ItemComponent...)
- * @see ReplyCallbackAction#addActionRows(ActionRow...)
+ * @see ReplyCallbackAction#addComponents(LayoutComponent...)
*/
public interface Button extends ActionComponent
{
diff --git a/src/main/java/net/dv8tion/jda/api/package-info.java b/src/main/java/net/dv8tion/jda/api/package-info.java
index 0a5f6a2915..abe966c3f1 100644
--- a/src/main/java/net/dv8tion/jda/api/package-info.java
+++ b/src/main/java/net/dv8tion/jda/api/package-info.java
@@ -22,18 +22,5 @@
*
* You can use {@link net.dv8tion.jda.api.JDABuilder JDABuilder} to create a {@link net.dv8tion.jda.api.JDA JDA} instance.
* Each JDA instance represents a connection to discord to receive events.
- *
- *
In addition this package included helpful builders for message sending
- * such as:
- *
- * {@link net.dv8tion.jda.api.MessageBuilder MessageBuilder}
- * Used to build a {@link net.dv8tion.jda.api.entities.Message Message} which can be used to
- * send a message to a {@link net.dv8tion.jda.api.entities.MessageChannel MessageChannel} together with
- * a {@link net.dv8tion.jda.api.entities.MessageEmbed MessageEmbed} and Text-To-Speech!
- *
- * {@link net.dv8tion.jda.api.EmbedBuilder EmbedBuilder}
- * Used to build a {@link net.dv8tion.jda.api.entities.MessageEmbed MessageEmbed}
- * which can then be used in the message sending process (see above)
- *
*/
package net.dv8tion.jda.api;
diff --git a/src/main/java/net/dv8tion/jda/api/requests/FluentRestAction.java b/src/main/java/net/dv8tion/jda/api/requests/FluentRestAction.java
new file mode 100644
index 0000000000..b517f05e03
--- /dev/null
+++ b/src/main/java/net/dv8tion/jda/api/requests/FluentRestAction.java
@@ -0,0 +1,60 @@
+/*
+ * 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.requests;
+
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+import java.util.concurrent.TimeUnit;
+import java.util.function.BooleanSupplier;
+
+/**
+ * Interface used to mixin the customization parameters for {@link RestAction RestActions}.
+ * This simply fixes the return types to be the concrete implementation instead of the base interface.
+ *
+ * @param
+ * The result type of the RestAction
+ * @param
+ * The concrete RestAction type used for chaining (fluent interface)
+ */
+@SuppressWarnings("unchecked")
+public interface FluentRestAction> extends RestAction
+{
+ @Nonnull
+ @Override
+ R setCheck(@Nullable BooleanSupplier checks);
+
+ @Nonnull
+ @Override
+ default R addCheck(@Nonnull BooleanSupplier checks)
+ {
+ return (R) RestAction.super.addCheck(checks);
+ }
+
+ @Nonnull
+ @Override
+ default R timeout(long timeout, @Nonnull TimeUnit unit)
+ {
+ return (R) RestAction.super.timeout(timeout, unit);
+ }
+
+ @Nonnull
+ @Override
+ default R deadline(long timestamp)
+ {
+ return (R) RestAction.super.deadline(timestamp);
+ }
+}
diff --git a/src/main/java/net/dv8tion/jda/api/requests/Request.java b/src/main/java/net/dv8tion/jda/api/requests/Request.java
index 0ed4b5f407..5e3b5a4239 100644
--- a/src/main/java/net/dv8tion/jda/api/requests/Request.java
+++ b/src/main/java/net/dv8tion/jda/api/requests/Request.java
@@ -26,6 +26,8 @@
import net.dv8tion.jda.internal.requests.CallbackContext;
import net.dv8tion.jda.internal.requests.RestActionImpl;
import net.dv8tion.jda.internal.requests.Route;
+import net.dv8tion.jda.internal.utils.IOUtil;
+import okhttp3.MultipartBody;
import okhttp3.RequestBody;
import org.apache.commons.collections4.map.CaseInsensitiveMap;
@@ -82,11 +84,31 @@ else if (RestActionImpl.isPassContext())
this.localReason = ThreadLocalReason.getCurrent();
}
+ private void cleanup()
+ {
+ // Try closing any open request bodies that were never read from
+ if (body instanceof MultipartBody)
+ {
+ MultipartBody multi = (MultipartBody) body;
+ multi.parts()
+ .stream()
+ .map(MultipartBody.Part::body)
+ .filter(AutoCloseable.class::isInstance)
+ .map(AutoCloseable.class::cast)
+ .forEach(IOUtil::silentClose);
+ }
+ else if (body instanceof AutoCloseable)
+ {
+ IOUtil.silentClose((AutoCloseable) body);
+ }
+ }
+
public void onSuccess(T successObj)
{
if (done)
return;
done = true;
+ cleanup();
api.getCallbackPool().execute(() ->
{
try (ThreadLocalReason.Closable __ = ThreadLocalReason.closable(localReason);
@@ -124,6 +146,7 @@ public void onFailure(Throwable failException)
if (done)
return;
done = true;
+ cleanup();
api.getCallbackPool().execute(() ->
{
try (ThreadLocalReason.Closable __ = ThreadLocalReason.closable(localReason);
diff --git a/src/main/java/net/dv8tion/jda/api/requests/RestAction.java b/src/main/java/net/dv8tion/jda/api/requests/RestAction.java
index bc3675606f..3a0feed5ee 100644
--- a/src/main/java/net/dv8tion/jda/api/requests/RestAction.java
+++ b/src/main/java/net/dv8tion/jda/api/requests/RestAction.java
@@ -530,7 +530,6 @@ default RestAction deadline(long timestamp)
* If the requester has been shutdown by {@link JDA#shutdown()} or {@link JDA#shutdownNow()}
*
* @see net.dv8tion.jda.api.entities.MessageChannel#sendMessage(java.lang.CharSequence) MessageChannel.sendMessage(CharSequence)
- * @see net.dv8tion.jda.api.requests.restaction.MessageAction MessageAction
* @see #queue(java.util.function.Consumer) queue(Consumer)
* @see #queue(java.util.function.Consumer, java.util.function.Consumer) queue(Consumer, Consumer)
*/
diff --git a/src/main/java/net/dv8tion/jda/api/requests/restaction/MessageAction.java b/src/main/java/net/dv8tion/jda/api/requests/restaction/MessageAction.java
deleted file mode 100644
index 2280b675fe..0000000000
--- a/src/main/java/net/dv8tion/jda/api/requests/restaction/MessageAction.java
+++ /dev/null
@@ -1,968 +0,0 @@
-/*
- * 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.requests.restaction;
-
-import net.dv8tion.jda.api.MessageBuilder;
-import net.dv8tion.jda.api.entities.Message;
-import net.dv8tion.jda.api.entities.MessageChannel;
-import net.dv8tion.jda.api.entities.MessageEmbed;
-import net.dv8tion.jda.api.entities.channel.unions.MessageChannelUnion;
-import net.dv8tion.jda.api.entities.sticker.GuildSticker;
-import net.dv8tion.jda.api.entities.sticker.Sticker;
-import net.dv8tion.jda.api.entities.sticker.StickerSnowflake;
-import net.dv8tion.jda.api.interactions.components.ActionComponent;
-import net.dv8tion.jda.api.interactions.components.ActionRow;
-import net.dv8tion.jda.api.interactions.components.ItemComponent;
-import net.dv8tion.jda.api.requests.RestAction;
-import net.dv8tion.jda.api.utils.AllowedMentions;
-import net.dv8tion.jda.api.utils.AttachmentOption;
-import net.dv8tion.jda.api.utils.MiscUtil;
-import net.dv8tion.jda.internal.requests.restaction.MessageActionImpl;
-import net.dv8tion.jda.internal.utils.Checks;
-
-import javax.annotation.CheckReturnValue;
-import javax.annotation.Nonnull;
-import javax.annotation.Nullable;
-import java.io.File;
-import java.io.InputStream;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.EnumSet;
-import java.util.concurrent.TimeUnit;
-import java.util.function.BiConsumer;
-import java.util.function.BooleanSupplier;
-import java.util.function.Consumer;
-import java.util.stream.Collectors;
-
-/**
- * Extension of a default {@link net.dv8tion.jda.api.requests.RestAction RestAction}
- * that allows setting message information before sending!
- *
- * This is available as return type of all sendMessage/sendFile methods in {@link net.dv8tion.jda.api.entities.MessageChannel MessageChannel}.
- *
- *
When updating a Message, unset fields will be ignored by default. To override existing fields with no value (remove content)
- * you can use {@link #override(boolean) override(true)}. Setting this to {@code true} will cause all fields to be considered
- * and will override the Message entirely causing unset values to be removed from that message.
- * This can be used to remove existing embeds from a message:
- * {@code message.editMessage("This message had an embed").override(true).queue()}
- *
- *
When this RestAction has been executed all provided files will be closed.
- * If you decide not to execute this action, you should call {@link #clearFiles()} to free resources.
- * Note that the garbage collector also frees opened file streams when it finalizes the stream object.
- *
- *
Example
- *
- * {@literal @Override}
- * public void onMessageReceived(MessageReceivedEvent event)
- * {
- * MessageChannel channel = event.getChannel();
- * channel.sendMessage("This has an embed with an image!")
- * .addFile(new File("dog.png"))
- * .setEmbeds(new EmbedBuilder()
- * .setImage("attachment://dog.png")
- * .build())
- * .queue(); // this actually sends the information to discord
- * }
- *
- *
- * @since 3.4.0
- *
- * @see Message#editMessage(Message)
- * @see Message#editMessage(CharSequence)
- * @see Message#editMessageEmbeds(MessageEmbed...)
- * @see Message#editMessageFormat(String, Object...)
- * @see net.dv8tion.jda.api.entities.MessageChannel#sendMessage(Message)
- * @see net.dv8tion.jda.api.entities.MessageChannel#sendMessage(CharSequence)
- * @see net.dv8tion.jda.api.entities.MessageChannel#sendMessageEmbeds(MessageEmbed, MessageEmbed...)
- * @see net.dv8tion.jda.api.entities.MessageChannel#sendMessageFormat(String, Object...)
- * @see net.dv8tion.jda.api.entities.MessageChannel#sendFile(File, AttachmentOption...)
- * @see net.dv8tion.jda.api.entities.MessageChannel#sendFile(File, String, AttachmentOption...)
- * @see net.dv8tion.jda.api.entities.MessageChannel#sendFile(InputStream, String, AttachmentOption...)
- * @see net.dv8tion.jda.api.entities.MessageChannel#sendFile(byte[], String, AttachmentOption...)
- */
-public interface MessageAction extends RestAction, Appendable, AllowedMentions
-{
- /**
- * Sets the {@link net.dv8tion.jda.api.entities.Message.MentionType MentionTypes} that should be parsed by default.
- * This just sets the default for all MessageActions and can be overridden on a per-action basis using {@link #allowedMentions(Collection)}.
- * If a message is sent with an empty Set of MentionTypes, then it will not ping any User, Role or {@code @everyone}/{@code @here},
- * while still showing up as mention tag.
- *
- * If {@code null} is provided to this method, then all Types will be pingable
- * (unless whitelisting via one of the {@code mention*} methods is used).
- *
- *
Example
- *
{@code
- * // Disable EVERYONE and HERE mentions by default (to avoid mass ping)
- * EnumSet deny = EnumSet.of(Message.MentionType.EVERYONE, Message.MentionType.HERE);
- * MessageAction.setDefaultMentions(EnumSet.complementOf(deny));
- * }
- *
- * @param allowedMentions
- * MentionTypes that are allowed to being parsed and pinged. {@code null} to disable and allow all mentions.
- */
- static void setDefaultMentions(@Nullable Collection allowedMentions)
- {
- AllowedMentions.setDefaultMentions(allowedMentions);
- }
-
- /**
- * Returns the default {@link net.dv8tion.jda.api.entities.Message.MentionType MentionTypes} previously set by
- * {@link #setDefaultMentions(Collection) MessageAction.setDefaultMentions(Collection)}.
- *
- * @return Default mentions set by MessageAction.setDefaultMentions(Collection)
- */
- @Nonnull
- static EnumSet getDefaultMentions()
- {
- return AllowedMentions.getDefaultMentions();
- }
-
- /**
- * Sets the default value for {@link #mentionRepliedUser(boolean)}
- *
- * Default: true
- *
- * @param mention
- * True, if replies should mention by default
- */
- static void setDefaultMentionRepliedUser(boolean mention)
- {
- AllowedMentions.setDefaultMentionRepliedUser(mention);
- }
-
- /**
- * Returns the default mention behavior for replies.
- * If this is {@code true} then all replies will mention the author of the target message by default.
- * You can specify this individually with {@link #mentionRepliedUser(boolean)} for each message.
- *
- *
Default: true
- *
- * @return True, if replies mention by default
- */
- static boolean isDefaultMentionRepliedUser()
- {
- return AllowedMentions.isDefaultMentionRepliedUser();
- }
-
- /**
- * Sets the default value for {@link #failOnInvalidReply(boolean)}
- *
- *
Default: false
- *
- * @param fail
- * True, to throw a exception if the referenced message does not exist
- */
- static void setDefaultFailOnInvalidReply(boolean fail)
- {
- MessageActionImpl.setDefaultFailOnInvalidReply(fail);
- }
-
- /**
- * Returns the default behavior for replies when the referenced message does not exist.
- * If this is {@code true} then all replies will throw an exception if the referenced message does not exist.
- * You can specify this individually with {@link #failOnInvalidReply(boolean)} for each message.
- *
- *
Default: false
- *
- * @return True, to throw a exception if the referenced message does not exist
- */
- static boolean isDefaultFailOnInvalidReply()
- {
- return MessageActionImpl.isDefaultFailOnInvalidReply();
- }
-
- @Nonnull
- @Override
- MessageAction setCheck(@Nullable BooleanSupplier checks);
-
- @Nonnull
- @Override
- MessageAction timeout(long timeout, @Nonnull TimeUnit unit);
-
- @Nonnull
- @Override
- MessageAction deadline(long timestamp);
-
- /**
- * The target {@link MessageChannel} for this message
- *
- * @return The target channel
- */
- @Nonnull
- MessageChannelUnion getChannel();
-
- /**
- * Whether this MessageAction has no values set.
- * Trying to execute with {@code isEmpty() == true} will result in an {@link java.lang.IllegalStateException IllegalStateException}!
- *
- *
This does not check for files!
- *
- * @return True, if no settings have been applied
- */
- boolean isEmpty();
-
- /**
- * Whether this MessageAction will be used to update an existing message.
- *
- * @return True, if this MessageAction targets an existing message
- */
- boolean isEdit();
-
- /**
- * Applies the sendable information of the provided {@link net.dv8tion.jda.api.entities.Message Message}
- * to this MessageAction settings.
- * This will override all existing settings if new settings are available.
- *
- *
This does not copy files!
- *
- * @param message
- * The nullable Message to apply settings from
- *
- * @throws java.lang.IllegalArgumentException
- * If the message contains a {@link net.dv8tion.jda.api.entities.MessageEmbed MessageEmbed}
- * that exceeds the sendable character limit,
- * see {@link net.dv8tion.jda.api.entities.MessageEmbed#isSendable() MessageEmbed.isSendable()}
- *
- * @return Updated MessageAction for chaining convenience
- */
- @Nonnull
- @CheckReturnValue
- MessageAction apply(@Nullable final Message message);
-
- /**
- * Make the message a reply to the referenced message.
- * You can only reply to messages from the same channel!
- * This will mention the author of the target message. You can disable this through {@link #mentionRepliedUser(boolean)}.
- * By default there won't be any error thrown if the referenced message does not exist.
- * This behavior can be changed with {@link #failOnInvalidReply(boolean)}.
- *
- *
This requires {@link net.dv8tion.jda.api.Permission#MESSAGE_HISTORY Permission.MESSAGE_HISTORY} in the channel!
- * You cannot reply to system messages such as {@link net.dv8tion.jda.api.entities.MessageType#CHANNEL_PINNED_ADD CHANNEL_PINNED_ADD} and similar.
- *
- * @param messageId
- * The target message
- *
- * @throws IllegalArgumentException
- * If the provided ID is null or not a valid snowflake
- * @throws UnsupportedOperationException
- * If the provided message is from a {@link MessageBuilder}
- *
- * @return Updated MessageAction for chaining convenience
- *
- * @since 4.2.1
- */
- @Nonnull
- @CheckReturnValue
- MessageAction referenceById(long messageId);
-
- /**
- * Make the message a reply to the referenced message.
- * You can only reply to messages from the same channel!
- * This will mention the author of the target message. You can disable this through {@link #mentionRepliedUser(boolean)}.
- * By default there won't be any error thrown if the referenced message does not exist.
- * This behavior can be changed with {@link #failOnInvalidReply(boolean)}.
- *
- *
This requires {@link net.dv8tion.jda.api.Permission#MESSAGE_HISTORY Permission.MESSAGE_HISTORY} in the channel!
- * You cannot reply to system messages such as {@link net.dv8tion.jda.api.entities.MessageType#CHANNEL_PINNED_ADD CHANNEL_PINNED_ADD} and similar.
- *
- * @param messageId
- * The target message
- *
- * @throws IllegalArgumentException
- * If the provided ID is null or not a valid snowflake
- * @throws UnsupportedOperationException
- * If the provided message is from a {@link MessageBuilder}
- *
- * @return Updated MessageAction for chaining convenience
- *
- * @since 4.2.1
- */
- @Nonnull
- @CheckReturnValue
- default MessageAction referenceById(@Nonnull String messageId)
- {
- return referenceById(MiscUtil.parseSnowflake(messageId));
- }
-
- /**
- * Make the message a reply to the referenced message.
- * You can only reply to messages from the same channel!
- * This will mention the author of the target message. You can disable this through {@link #mentionRepliedUser(boolean)}.
- * By default there won't be any error thrown if the referenced message does not exist.
- * This behavior can be changed with {@link #failOnInvalidReply(boolean)}.
- *
- *
This requires {@link net.dv8tion.jda.api.Permission#MESSAGE_HISTORY Permission.MESSAGE_HISTORY} in the channel!
- * You cannot reply to system messages such as {@link net.dv8tion.jda.api.entities.MessageType#CHANNEL_PINNED_ADD CHANNEL_PINNED_ADD} and similar.
- *
- * @param message
- * The target message
- *
- * @throws IllegalArgumentException
- * If the provided message is null
- * @throws UnsupportedOperationException
- * If the provided message is from a {@link MessageBuilder}
- *
- * @return Updated MessageAction for chaining convenience
- *
- * @since 4.2.1
- */
- @Nonnull
- @CheckReturnValue
- default MessageAction reference(@Nonnull Message message)
- {
- Checks.notNull(message, "Message");
- return referenceById(message.getIdLong());
- }
-
- /**
- * Whether to mention the user when replying to a message.
- * This only matters in combination with {@link #reference(Message)} and {@link #referenceById(long)}!
- *
- *
This is true by default but can be configured using {@link #setDefaultMentionRepliedUser(boolean)}!
- *
- * @param mention
- * True, to mention the author if the referenced message
- *
- * @return Updated MessageAction for chaining convenience
- *
- * @since 4.2.1
- */
- @Nonnull
- @CheckReturnValue
- MessageAction mentionRepliedUser(boolean mention);
-
- /**
- * Whether to throw a exception if the referenced message does not exist, when replying to a message.
- * This only matters in combination with {@link #reference(Message)} and {@link #referenceById(long)}!
- *
- *
This is false by default but can be configured using {@link #setDefaultFailOnInvalidReply(boolean)}!
- *
- * @param fail
- * True, to throw a exception if the referenced message does not exist
- *
- * @return Updated MessageAction for chaining convenience
- *
- * @since 4.2.1
- */
- @Nonnull
- @CheckReturnValue
- MessageAction failOnInvalidReply(boolean fail);
-
- /**
- * Enable/Disable Text-To-Speech for the resulting message.
- * This is only relevant to MessageActions that are not {@code isEdit() == true}!
- *
- * @param isTTS
- * True, if this should cause a Text-To-Speech effect when sent to the channel
- *
- * @return Updated MessageAction for chaining convenience
- */
- @Nonnull
- @CheckReturnValue
- MessageAction tts(final boolean isTTS);
-
- /**
- * Resets this MessageAction to empty state
- * {@link #isEmpty()} will result in {@code true} after this has been performed!
- *
- *
Convenience over using
- * {@code content(null).nonce(null).setEmbeds(emptyList()).tts(false).override(false).clearFiles()}
- *
- * @return Updated MessageAction for chaining convenience
- */
- @Nonnull
- @CheckReturnValue
- MessageAction reset();
-
- /**
- * Sets the validation nonce for the outgoing Message
- *
- *
For more information see {@link net.dv8tion.jda.api.MessageBuilder#setNonce(String) MessageBuilder.setNonce(String)}
- * and {@link net.dv8tion.jda.api.entities.Message#getNonce() Message.getNonce()}
- *
- * @param nonce
- * The nonce that shall be used
- *
- * @return Updated MessageAction for chaining convenience
- *
- * @see net.dv8tion.jda.api.entities.Message#getNonce()
- * @see net.dv8tion.jda.api.MessageBuilder#setNonce(String)
- * @see Cryptographic Nonce - Wikipedia
- */
- @Nonnull
- @CheckReturnValue
- MessageAction nonce(@Nullable final String nonce);
-
- /**
- * Overrides existing content with the provided input
- * The content of a Message may not exceed {@value Message#MAX_CONTENT_LENGTH}!
- *
- * @param content
- * Sets the specified content and overrides previous content
- * or {@code null} to reset content
- *
- * @throws java.lang.IllegalArgumentException
- * If the provided content exceeds the {@value Message#MAX_CONTENT_LENGTH} character limit
- *
- * @return Updated MessageAction for chaining convenience
- */
- @Nonnull
- @CheckReturnValue
- MessageAction content(@Nullable final String content);
-
- /**
- * Sets up to {@value Message#MAX_EMBED_COUNT} {@link net.dv8tion.jda.api.entities.MessageEmbed MessageEmbeds}
- * that should be used for this Message.
- * Refer to {@link net.dv8tion.jda.api.EmbedBuilder EmbedBuilder} for more information.
- *
- * @param embeds
- * The {@link net.dv8tion.jda.api.entities.MessageEmbed MessageEmbeds} that should
- * be attached to this message, {@code Collections.emptyList()} to use no embed.
- *
- * @throws java.lang.IllegalArgumentException
- * If any of the provided MessageEmbeds is not sendable according to
- * {@link net.dv8tion.jda.api.entities.MessageEmbed#isSendable() MessageEmbed.isSendable()}!
- * If the provided MessageEmbed is an unknown implementation this operation will fail as we are unable to deserialize it.
- *
- * @return Updated MessageAction for chaining convenience
- */
- @Nonnull
- @CheckReturnValue
- MessageAction setEmbeds(@Nonnull Collection extends MessageEmbed> embeds);
-
- /**
- * Sets up to {@value Message#MAX_EMBED_COUNT} {@link net.dv8tion.jda.api.entities.MessageEmbed MessageEmbeds}
- * that should be used for this Message.
- * Refer to {@link net.dv8tion.jda.api.EmbedBuilder EmbedBuilder} for more information.
- *
- * @param embeds
- * The {@link net.dv8tion.jda.api.entities.MessageEmbed MessageEmbeds} that should
- * be attached to this message, {@code Collections.emptyList()} to use no embed.
- *
- * @throws java.lang.IllegalArgumentException
- * If any of the provided MessageEmbeds is not sendable according to
- * {@link net.dv8tion.jda.api.entities.MessageEmbed#isSendable() MessageEmbed.isSendable()}!
- * If the provided MessageEmbed is an unknown implementation this operation will fail as we are unable to deserialize it.
- *
- * @return Updated MessageAction for chaining convenience
- */
- @Nonnull
- @CheckReturnValue
- default MessageAction setEmbeds(@Nonnull MessageEmbed... embeds)
- {
- Checks.noneNull(embeds, "MessageEmbeds");
- return setEmbeds(Arrays.asList(embeds));
- }
-
- /**
- * {@inheritDoc}
- * @throws java.lang.IllegalArgumentException
- * If the appended CharSequence is too big and will cause the content to
- * exceed the {@value net.dv8tion.jda.api.entities.Message#MAX_CONTENT_LENGTH} character limit
- *
- * @return Updated MessageAction for chaining convenience
- */
- @Nonnull
- @Override
- @CheckReturnValue
- default MessageAction append(@Nonnull final CharSequence csq)
- {
- return append(csq, 0, csq.length());
- }
-
- /**
- * {@inheritDoc}
- * @throws java.lang.IllegalArgumentException
- * If the appended CharSequence is too big and will cause the content to
- * exceed the {@value net.dv8tion.jda.api.entities.Message#MAX_CONTENT_LENGTH} character limit
- *
- * @return Updated MessageAction for chaining convenience
- */
- @Nonnull
- @Override
- @CheckReturnValue
- MessageAction append(@Nullable final CharSequence csq, final int start, final int end);
-
- /**
- * {@inheritDoc}
- * @throws java.lang.IllegalArgumentException
- * If the appended CharSequence is too big and will cause the content to
- * exceed the {@value net.dv8tion.jda.api.entities.Message#MAX_CONTENT_LENGTH} character limit
- *
- * @return Updated MessageAction for chaining convenience
- */
- @Nonnull
- @Override
- @CheckReturnValue
- MessageAction append(final char c);
-
- /**
- * Applies the result of {@link String#format(String, Object...) String.format(String, Object...)}
- * as content.
- *
- *
For more information of formatting review the {@link java.util.Formatter Formatter} documentation!
- *
- * @param format
- * The format String
- * @param args
- * The arguments that should be used for conversion
- *
- * @throws java.lang.IllegalArgumentException
- * If the appended formatting is too big and will cause the content to
- * exceed the {@value net.dv8tion.jda.api.entities.Message#MAX_CONTENT_LENGTH} character limit
- * @throws java.util.IllegalFormatException
- * If a format string contains an illegal syntax,
- * a format specifier that is incompatible with the given arguments,
- * insufficient arguments given the format string, or other illegal conditions.
- * For specification of all possible formatting errors,
- * see the Details
- * section of the formatter class specification.
- *
- * @return Updated MessageAction for chaining convenience
- */
- @Nonnull
- @CheckReturnValue
- default MessageAction appendFormat(@Nonnull final String format, final Object... args)
- {
- return append(String.format(format, args));
- }
-
- /**
- * Adds the provided {@link java.io.InputStream InputStream} as file data.
- * The stream will be closed upon execution!
- *
- *
To reset all files use {@link #clearFiles()}
- *
- * @param data
- * The InputStream that will be interpreted as file data
- * @param name
- * The file name that should be used to interpret the type of the given data
- * using the file-name extension. This name is similar to what will be visible
- * through {@link net.dv8tion.jda.api.entities.Message.Attachment#getFileName() Message.Attachment.getFileName()}
- * @param options
- * Possible options to apply to this attachment, such as marking it as spoiler image
- *
- * @throws java.lang.IllegalStateException
- * If the file limit of {@value Message#MAX_FILE_AMOUNT} has been reached prior to calling this method
- * @throws java.lang.IllegalArgumentException
- * If the provided data is {@code null} or the provided name is blank or {@code null}
- * @throws net.dv8tion.jda.api.exceptions.InsufficientPermissionException
- * If this is targeting a TextChannel and the currently logged in account does not have
- * {@link net.dv8tion.jda.api.Permission#MESSAGE_ATTACH_FILES Permission.MESSAGE_ATTACH_FILES}
- *
- * @return Updated MessageAction for chaining convenience
- */
- @Nonnull
- @CheckReturnValue
- MessageAction addFile(@Nonnull final InputStream data, @Nonnull final String name, @Nonnull AttachmentOption... options);
-
- /**
- * Adds the provided byte[] as file data.
- *
- *
To reset all files use {@link #clearFiles()}
- *
- * @param data
- * The byte[] that will be interpreted as file data
- * @param name
- * The file name that should be used to interpret the type of the given data
- * using the file-name extension. This name is similar to what will be visible
- * through {@link net.dv8tion.jda.api.entities.Message.Attachment#getFileName() Message.Attachment.getFileName()}
- * @param options
- * Possible options to apply to this attachment, such as marking it as spoiler image
- *
- * @throws java.lang.IllegalStateException
- * If the file limit of {@value Message#MAX_FILE_AMOUNT} has been reached prior to calling this method
- * @throws java.lang.IllegalArgumentException
- * If the provided data is {@code null} or the provided name is blank or {@code null}
- * or if the provided data exceeds the maximum file size of the currently logged in account
- * @throws net.dv8tion.jda.api.exceptions.InsufficientPermissionException
- * If this is targeting a TextChannel and the currently logged in account does not have
- * {@link net.dv8tion.jda.api.Permission#MESSAGE_ATTACH_FILES Permission.MESSAGE_ATTACH_FILES}
- *
- * @return Updated MessageAction for chaining convenience
- *
- * @see net.dv8tion.jda.api.entities.SelfUser#getAllowedFileSize() SelfUser.getAllowedFileSize()
- */
- @Nonnull
- @CheckReturnValue
- MessageAction addFile(@Nonnull final byte[] data, @Nonnull final String name, @Nonnull AttachmentOption... options);
-
- /**
- * Adds the provided {@link java.io.File File} as file data.
- * Shortcut for {@link #addFile(java.io.File, String, net.dv8tion.jda.api.utils.AttachmentOption...) addFile(file, file.getName())} with the same side-effects.
- *
- * @param file
- * The File that will be interpreted as file data
- * @param options
- * Possible options to apply to this attachment, such as marking it as spoiler image
- *
- * @throws java.lang.IllegalStateException
- * If the file limit of {@value Message#MAX_FILE_AMOUNT} has been reached prior to calling this method
- * @throws java.lang.IllegalArgumentException
- * If the provided file is {@code null} or if the provided File is bigger than the maximum file size of the currently logged in account
- * @throws net.dv8tion.jda.api.exceptions.InsufficientPermissionException
- * If this is targeting a TextChannel and the currently logged in account does not have
- * {@link net.dv8tion.jda.api.Permission#MESSAGE_ATTACH_FILES Permission.MESSAGE_ATTACH_FILES}
- *
- * @return Updated MessageAction for chaining convenience
- *
- * @see net.dv8tion.jda.api.entities.SelfUser#getAllowedFileSize() SelfUser.getAllowedFileSize()
- */
- @Nonnull
- @CheckReturnValue
- default MessageAction addFile(@Nonnull final File file, @Nonnull AttachmentOption... options)
- {
- Checks.notNull(file, "File");
- return addFile(file, file.getName(), options);
- }
-
- /**
- * Adds the provided {@link java.io.File File} as file data.
- *
- *
To reset all files use {@link #clearFiles()}
- * This method opens a {@link java.io.FileInputStream FileInputStream} which will be closed by executing this action or using {@link #clearFiles()}!
- *
- * @param file
- * The File that will be interpreted as file data
- * @param name
- * The file name that should be used to interpret the type of the given data
- * using the file-name extension. This name is similar to what will be visible
- * through {@link net.dv8tion.jda.api.entities.Message.Attachment#getFileName() Message.Attachment.getFileName()}
- * @param options
- * Possible options to apply to this attachment, such as marking it as spoiler image
- *
- * @throws java.lang.IllegalStateException
- * If the file limit of {@value Message#MAX_FILE_AMOUNT} has been reached prior to calling this method
- * @throws java.lang.IllegalArgumentException
- * If the provided file is {@code null} or the provided name is blank or {@code null}
- * or if the provided file is bigger than the maximum file size of the currently logged in account,
- * or if the provided file does not exist/ is not readable
- * @throws net.dv8tion.jda.api.exceptions.InsufficientPermissionException
- * If this is targeting a TextChannel and the currently logged in account does not have
- * {@link net.dv8tion.jda.api.Permission#MESSAGE_ATTACH_FILES Permission.MESSAGE_ATTACH_FILES}
- *
- * @return Updated MessageAction for chaining convenience
- *
- * @see net.dv8tion.jda.api.entities.SelfUser#getAllowedFileSize() SelfUser.getAllowedFileSize()
- */
- @Nonnull
- @CheckReturnValue
- MessageAction addFile(@Nonnull final File file, @Nonnull final String name, @Nonnull AttachmentOption... options);
-
- /**
- * Clears all previously added files
- * And closes {@code FileInputStreams} generated by {@link #addFile(File, String, net.dv8tion.jda.api.utils.AttachmentOption...)}.
- * To close all stream (including ones given by {@link #addFile(InputStream, String, net.dv8tion.jda.api.utils.AttachmentOption...)}) use {@link #clearFiles(Consumer)}.
- *
- * @return Updated MessageAction for chaining convenience
- *
- * @see #clearFiles(BiConsumer)
- */
- @Nonnull
- @CheckReturnValue
- MessageAction clearFiles();
-
- /**
- * Clears all previously added files
- *
- * @param finalizer
- * BiConsumer useful to close remaining resources,
- * the consumer will receive the name as a string parameter and the resource as {@code InputStream}.
- *
- * @return Updated MessageAction for chaining convenience
- *
- * @see java.io.Closeable
- */
- @Nonnull
- @CheckReturnValue
- MessageAction clearFiles(@Nonnull BiConsumer finalizer);
-
- /**
- * Clears all previously added files
- * The {@link #clearFiles(BiConsumer)} version provides the resource name for more selective operations.
- *
- * @param finalizer
- * Consumer useful to close remaining resources,
- * the consumer will receive only the resource in the form of an {@code InputStream}
- *
- * @return Updated MessageAction for chaining convenience
- *
- * @see java.io.Closeable
- */
- @Nonnull
- @CheckReturnValue
- MessageAction clearFiles(@Nonnull Consumer finalizer);
-
- /**
- * Removes all attachments that are currently attached to the existing message except for the ones provided.
- * For example {@code retainFilesById(Arrays.asList("123"))} would remove all attachments except for the one with the id 123.
- *
- * To remove all attachments from the message you can pass an empty list.
- *
- * @param ids
- * The ids for the attachments which should be retained on the message
- *
- * @throws IllegalArgumentException
- * If any of the ids is null or not a valid snowflake
- *
- * @return Updated MessageAction for chaining convenience
- */
- @Nonnull
- @CheckReturnValue
- MessageAction retainFilesById(@Nonnull Collection ids);
-
- /**
- * Removes all attachments that are currently attached to the existing message except for the ones provided.
- * For example {@code retainFilesById(Arrays.asList("123"))} would remove all attachments except for the one with the id 123.
- *
- * To remove all attachments from the message you can pass an empty list.
- *
- * @param ids
- * The ids for the attachments which should be retained on the message
- *
- * @throws IllegalArgumentException
- * If any of the ids is null or not a valid snowflake
- *
- * @return Updated MessageAction for chaining convenience
- */
- @Nonnull
- @CheckReturnValue
- default MessageAction retainFilesById(@Nonnull String... ids)
- {
- Checks.notNull(ids, "IDs");
- return retainFilesById(Arrays.asList(ids));
- }
-
- /**
- * Removes all attachments that are currently attached to the existing message except for the ones provided.
- * For example {@code retainFilesById(Arrays.asList("123"))} would remove all attachments except for the one with the id 123.
- *
- *
To remove all attachments from the message you can pass an empty list.
- *
- * @param ids
- * The ids for the attachments which should be retained on the message
- *
- * @throws IllegalArgumentException
- * If any of the ids is null or not a valid snowflake
- *
- * @return Updated MessageAction for chaining convenience
- */
- @Nonnull
- @CheckReturnValue
- default MessageAction retainFilesById(long... ids)
- {
- Checks.notNull(ids, "IDs");
- return retainFilesById(Arrays
- .stream(ids)
- .mapToObj(Long::toUnsignedString)
- .collect(Collectors.toList())
- );
- }
-
- /**
- * Removes all attachments that are currently attached to the existing message except for the ones provided.
- * For example {@code retainFiles(message.getAttachments().subList(1, message.getAttachments().size()))} would only remove the first attachment from the message.
- *
- *
To remove all attachments from the message you can pass an empty list.
- *
- * @param attachments
- * The attachments which should be retained on the message
- *
- * @throws IllegalArgumentException
- * If any of the ids is null or not a valid snowflake
- *
- * @return Updated MessageAction for chaining convenience
- */
- @Nonnull
- @CheckReturnValue
- default MessageAction retainFiles(@Nonnull Collection extends Message.Attachment> attachments)
- {
- Checks.noneNull(attachments, "Attachments");
- return retainFilesById(attachments
- .stream()
- .map(Message.Attachment::getId)
- .collect(Collectors.toList())
- );
- }
-
- /**
- * Set the action rows for the message.
- *
- * @param rows
- * The new action rows
- *
- * @throws IllegalArgumentException
- *
- * If null is provided, or more than 5 action rows are provided
- * If any custom {@link ActionComponent#getId() id} is duplicated
- * If any of the provided action rows are not compatible with messages
- *
- *
- * @return Updated MessageAction for chaining convenience
- *
- * @see ActionRow#isMessageCompatible()
- */
- @Nonnull
- @CheckReturnValue
- default MessageAction setActionRows(@Nonnull Collection extends ActionRow> rows)
- {
- Checks.noneNull(rows, "ActionRows");
- return setActionRows(rows.toArray(new ActionRow[0]));
- }
-
- /**
- * Set the action rows for the message.
- *
- * @param rows
- * The new action rows
- *
- * @throws IllegalArgumentException
- *
- * If null is provided, or more than 5 action rows are provided
- * If any custom {@link ActionComponent#getId() id} is duplicated
- * If any of the provided action rows are not compatible with messages
- *
- *
- * @return Updated MessageAction for chaining convenience
- *
- * @see ActionRow#isMessageCompatible()
- */
- @Nonnull
- @CheckReturnValue
- MessageAction setActionRows(@Nonnull ActionRow... rows);
-
- /**
- * Create one row of up to 5 message {@link ItemComponent components}.
- * This is identical to {@code setActionRows(ActionRow.of(components))}
- *
- * @param components
- * The components for this action row
- *
- * @throws IllegalArgumentException
- *
- * If null is provided, or more than 5 ItemComponents are provided
- * If any custom {@link ActionComponent#getId() id} is duplicated
- * If any of the provided ItemComponents are not compatible with messages
- *
- *
- * @return Updated MessageAction for chaining convenience
- *
- * @see ActionRow#of(Collection)
- * @see ItemComponent#isMessageCompatible()
- */
- @Nonnull
- @CheckReturnValue
- default MessageAction setActionRow(@Nonnull Collection extends ItemComponent> components)
- {
- return setActionRows(ActionRow.of(components));
- }
-
- /**
- * Create one row of up to 5 message {@link ItemComponent components}.
- * This is identical to {@code setActionRows(ActionRow.of(components))}
- *
- * @param components
- * The components for this action row
- *
- * @throws IllegalArgumentException
- *
- * If null is provided, or more than 5 ItemComponents are provided
- * If any custom {@link ActionComponent#getId() id} is duplicated
- * If any of the provided ItemComponents are not compatible with messages
- *
- *
- * @return Updated MessageAction for chaining convenience
- *
- * @see ActionRow#of(ItemComponent...)
- * @see ItemComponent#isMessageCompatible()
- */
- @Nonnull
- @CheckReturnValue
- default MessageAction setActionRow(@Nonnull ItemComponent... components)
- {
- return setActionRows(ActionRow.of(components));
- }
-
- /**
- * Set the stickers to send alongside this message.
- * This is not supported for message edits.
- *
- * @param stickers
- * The stickers to send, or null to not send any stickers
- *
- * @throws IllegalStateException
- * If this request is a message edit request
- * @throws IllegalArgumentException
- *
- * If any of the provided stickers is a {@link GuildSticker},
- * which is either {@link GuildSticker#isAvailable() unavailable} or from a different guild.
- * If the collection has more than {@value Message#MAX_STICKER_COUNT} stickers
- * If a collection with null entries is provided
- *
- *
- * @return Updated MessageAction for chaining convenience
- *
- * @see Sticker#fromId(long)
- */
- @Nonnull
- @CheckReturnValue
- MessageAction setStickers(@Nullable Collection extends StickerSnowflake> stickers);
-
- /**
- * Set the stickers to send alongside this message.
- * This is not supported for message edits.
- *
- * @param stickers
- * The stickers to send, or null to not send any stickers
- *
- * @throws IllegalStateException
- * If this request is a message edit request
- * @throws IllegalArgumentException
- *
- * If any of the provided stickers is a {@link GuildSticker},
- * which is either {@link GuildSticker#isAvailable() unavailable} or from a different guild.
- * If the collection has more than {@value Message#MAX_STICKER_COUNT} stickers
- * If a collection with null entries is provided
- *
- *
- * @return Updated MessageAction for chaining convenience
- *
- * @see Sticker#fromId(long)
- */
- @Nonnull
- @CheckReturnValue
- default MessageAction setStickers(@Nullable StickerSnowflake... stickers)
- {
- if (stickers != null)
- Checks.noneNull(stickers, "Sticker");
- return setStickers(stickers == null ? null : Arrays.asList(stickers));
- }
-
-
- /**
- * Whether all fields should be considered when editing a message
- *
- * @param bool
- * True, to override all fields even if they are not set
- *
- * @return Updated MessageAction for chaining convenience
- */
- @Nonnull
- @CheckReturnValue
- MessageAction override(final boolean bool);
-}
diff --git a/src/main/java/net/dv8tion/jda/api/requests/restaction/MessageCreateAction.java b/src/main/java/net/dv8tion/jda/api/requests/restaction/MessageCreateAction.java
new file mode 100644
index 0000000000..c87e3b4fd6
--- /dev/null
+++ b/src/main/java/net/dv8tion/jda/api/requests/restaction/MessageCreateAction.java
@@ -0,0 +1,216 @@
+/*
+ * 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.requests.restaction;
+
+import net.dv8tion.jda.api.entities.Message;
+import net.dv8tion.jda.api.entities.sticker.GuildSticker;
+import net.dv8tion.jda.api.entities.sticker.Sticker;
+import net.dv8tion.jda.api.entities.sticker.StickerSnowflake;
+import net.dv8tion.jda.api.requests.FluentRestAction;
+import net.dv8tion.jda.api.utils.messages.MessageCreateData;
+import net.dv8tion.jda.api.utils.messages.MessageCreateRequest;
+import net.dv8tion.jda.internal.requests.restaction.MessageCreateActionImpl;
+import net.dv8tion.jda.internal.utils.Checks;
+
+import javax.annotation.CheckReturnValue;
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+import java.util.Arrays;
+import java.util.Collection;
+
+/**
+ * Specialized {@link net.dv8tion.jda.api.requests.RestAction RestAction} used for sending messages to {@link net.dv8tion.jda.api.entities.MessageChannel MessageChannels}.
+ *
+ * @see net.dv8tion.jda.api.entities.MessageChannel#sendMessage(MessageCreateData) MessageChannel.sendMessage(...)
+ */
+public interface MessageCreateAction extends MessageCreateRequest, FluentRestAction
+{
+ /**
+ * Sets the default value for {@link #failOnInvalidReply(boolean)}
+ *
+ * Default: false
+ *
+ * @param fail
+ * True, to throw a exception if the referenced message does not exist
+ */
+ static void setDefaultFailOnInvalidReply(boolean fail)
+ {
+ MessageCreateActionImpl.setDefaultFailOnInvalidReply(fail);
+ }
+
+ /**
+ * Unique string/number used to identify messages using {@link Message#getNonce()} in events.
+ * This can be useful to handle round-trip messages.
+ *
+ *
Discord also uses the nonce to dedupe messages for users, but this is not currently supported for bots.
+ * However, for future proofing, it is highly recommended to use a unique nonce for each message.
+ *
+ * @param nonce
+ * The nonce string to use
+ *
+ * @throws IllegalArgumentException
+ * If the provided nonce is longer than {@value Message#MAX_NONCE_LENGTH} characters
+ *
+ * @return The same instance for chaining
+ *
+ * @see Cryptographic Nonce - Wikipedia
+ */
+ @Nonnull
+ MessageCreateAction setNonce(@Nullable String nonce);
+
+ /**
+ * Message reference used for a reply.
+ * The client will show this message as a reply to the target message.
+ *
+ *
You can only reply to messages from the same channel.
+ * By default, this will mention the author of the target message, this can be disabled using {@link #mentionRepliedUser(boolean)}.
+ *
+ *
This also requires {@link net.dv8tion.jda.api.Permission#MESSAGE_HISTORY Permission.MESSAGE_HISTORY} in the channel.
+ * If this permission is missing, you receive {@link net.dv8tion.jda.api.requests.ErrorResponse#REPLY_FAILED_MISSING_MESSAGE_HISTORY_PERM ErrorResponse.REPLY_FAILED_MISSING_MESSAGE_HISTORY_PERM}.
+ *
+ *
If the target message does not exist, this will result in {@link net.dv8tion.jda.api.requests.ErrorResponse#UNKNOWN_MESSAGE ErrorResponse.UNKNOWN_MESSAGE}.
+ * You can use {@link #failOnInvalidReply(boolean)} to allow unknown or deleted messages.
+ *
+ * @param messageId
+ * The target message id to reply to
+ *
+ * @throws IllegalArgumentException
+ * If the message id is not a valid snowflake
+ *
+ * @return The same instance for chaining
+ */
+ @Nonnull
+ MessageCreateAction setMessageReference(@Nullable String messageId);
+
+ /**
+ * Message reference used for a reply.
+ * The client will show this message as a reply to the target message.
+ *
+ *
You can only reply to messages from the same channel.
+ * By default, this will mention the author of the target message, this can be disabled using {@link #mentionRepliedUser(boolean)}.
+ *
+ *
This also requires {@link net.dv8tion.jda.api.Permission#MESSAGE_HISTORY Permission.MESSAGE_HISTORY} in the channel.
+ * If this permission is missing, you receive {@link net.dv8tion.jda.api.requests.ErrorResponse#REPLY_FAILED_MISSING_MESSAGE_HISTORY_PERM ErrorResponse.REPLY_FAILED_MISSING_MESSAGE_HISTORY_PERM}.
+ *
+ *
If the target message does not exist, this will result in {@link net.dv8tion.jda.api.requests.ErrorResponse#UNKNOWN_MESSAGE ErrorResponse.UNKNOWN_MESSAGE}.
+ * You can use {@link #failOnInvalidReply(boolean)} to allow unknown or deleted messages.
+ *
+ * @param messageId
+ * The target message id to reply to
+ *
+ * @return The same instance for chaining
+ */
+ @Nonnull
+ default MessageCreateAction setMessageReference(long messageId)
+ {
+ return setMessageReference(Long.toUnsignedString(messageId));
+ }
+
+ /**
+ * Message reference used for a reply.
+ * The client will show this message as a reply to the target message.
+ *
+ *
You can only reply to messages from the same channel.
+ * By default, this will mention the author of the target message, this can be disabled using {@link #mentionRepliedUser(boolean)}.
+ *
+ *
This also requires {@link net.dv8tion.jda.api.Permission#MESSAGE_HISTORY Permission.MESSAGE_HISTORY} in the channel.
+ * If this permission is missing, you receive {@link net.dv8tion.jda.api.requests.ErrorResponse#REPLY_FAILED_MISSING_MESSAGE_HISTORY_PERM ErrorResponse.REPLY_FAILED_MISSING_MESSAGE_HISTORY_PERM}.
+ *
+ *
If the target message does not exist, this will result in {@link net.dv8tion.jda.api.requests.ErrorResponse#UNKNOWN_MESSAGE ErrorResponse.UNKNOWN_MESSAGE}.
+ * You can use {@link #failOnInvalidReply(boolean)} to allow unknown or deleted messages.
+ *
+ * @param message
+ * The target message to reply to
+ *
+ * @return The same instance for chaining
+ */
+ @Nonnull
+ default MessageCreateAction setMessageReference(@Nullable Message message)
+ {
+ return setMessageReference(message == null ? null : message.getId());
+ }
+
+ /**
+ * Whether to throw a exception if the referenced message does not exist, when replying to a message.
+ * This only matters in combination with {@link #setMessageReference(Message)} and {@link #setMessageReference(long)}!
+ *
+ *
This is false by default but can be configured using {@link #setDefaultFailOnInvalidReply(boolean)}!
+ *
+ * @param fail
+ * True, to throw a exception if the referenced message does not exist
+ *
+ * @return Updated MessageCreateAction for chaining convenience
+ */
+ @Nonnull
+ @CheckReturnValue
+ MessageCreateAction failOnInvalidReply(boolean fail);
+
+ /**
+ * Set the stickers to send alongside this message.
+ * This is not supported for message edits.
+ *
+ * @param stickers
+ * The stickers to send, or null to not send any stickers
+ *
+ * @throws IllegalStateException
+ * If this request is a message edit request
+ * @throws IllegalArgumentException
+ *
+ * If any of the provided stickers is a {@link GuildSticker},
+ * which is either {@link GuildSticker#isAvailable() unavailable} or from a different guild.
+ * If the collection has more than {@value Message#MAX_STICKER_COUNT} stickers
+ * If a collection with null entries is provided
+ *
+ *
+ * @return Updated MessageCreateAction for chaining convenience
+ *
+ * @see Sticker#fromId(long)
+ */
+ @Nonnull
+ @CheckReturnValue
+ MessageCreateAction setStickers(@Nullable Collection extends StickerSnowflake> stickers);
+
+ /**
+ * Set the stickers to send alongside this message.
+ * This is not supported for message edits.
+ *
+ * @param stickers
+ * The stickers to send, or null to not send any stickers
+ *
+ * @throws IllegalStateException
+ * If this request is a message edit request
+ * @throws IllegalArgumentException
+ *
+ * If any of the provided stickers is a {@link GuildSticker},
+ * which is either {@link GuildSticker#isAvailable() unavailable} or from a different guild.
+ * If the collection has more than {@value Message#MAX_STICKER_COUNT} stickers
+ * If a collection with null entries is provided
+ *
+ *
+ * @return Updated MessageCreateAction for chaining convenience
+ *
+ * @see Sticker#fromId(long)
+ */
+ @Nonnull
+ @CheckReturnValue
+ default MessageCreateAction setStickers(@Nullable StickerSnowflake... stickers)
+ {
+ if (stickers != null)
+ Checks.noneNull(stickers, "Sticker");
+ return setStickers(stickers == null ? null : Arrays.asList(stickers));
+ }
+}
diff --git a/src/main/java/net/dv8tion/jda/api/requests/restaction/MessageEditAction.java b/src/main/java/net/dv8tion/jda/api/requests/restaction/MessageEditAction.java
new file mode 100644
index 0000000000..27d1f465da
--- /dev/null
+++ b/src/main/java/net/dv8tion/jda/api/requests/restaction/MessageEditAction.java
@@ -0,0 +1,31 @@
+/*
+ * 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.requests.restaction;
+
+import net.dv8tion.jda.api.entities.Message;
+import net.dv8tion.jda.api.requests.FluentRestAction;
+import net.dv8tion.jda.api.utils.messages.MessageEditData;
+import net.dv8tion.jda.api.utils.messages.MessageEditRequest;
+
+/**
+ * Specialized {@link net.dv8tion.jda.api.requests.RestAction RestAction} used for editing existing messages in {@link net.dv8tion.jda.api.entities.MessageChannel MessageChannels}.
+ *
+ * @see net.dv8tion.jda.api.entities.MessageChannel#editMessageById(long, MessageEditData) MessageChannel.editMessageById(...)
+ */
+public interface MessageEditAction extends MessageEditRequest, FluentRestAction
+{
+}
diff --git a/src/main/java/net/dv8tion/jda/api/requests/restaction/WebhookMessageAction.java b/src/main/java/net/dv8tion/jda/api/requests/restaction/WebhookMessageAction.java
deleted file mode 100644
index 6f783afe00..0000000000
--- a/src/main/java/net/dv8tion/jda/api/requests/restaction/WebhookMessageAction.java
+++ /dev/null
@@ -1,421 +0,0 @@
-/*
- * 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.requests.restaction;
-
-import net.dv8tion.jda.api.entities.Message;
-import net.dv8tion.jda.api.entities.MessageEmbed;
-import net.dv8tion.jda.api.interactions.components.ActionComponent;
-import net.dv8tion.jda.api.interactions.components.ActionRow;
-import net.dv8tion.jda.api.interactions.components.ItemComponent;
-import net.dv8tion.jda.api.interactions.components.buttons.Button;
-import net.dv8tion.jda.api.requests.RestAction;
-import net.dv8tion.jda.api.utils.AllowedMentions;
-import net.dv8tion.jda.api.utils.AttachmentOption;
-import net.dv8tion.jda.internal.utils.Checks;
-
-import javax.annotation.CheckReturnValue;
-import javax.annotation.Nonnull;
-import javax.annotation.Nullable;
-import java.io.*;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-
-/**
- * Extension of a default {@link net.dv8tion.jda.api.requests.RestAction RestAction}
- * that allows setting message information before sending!
- *
- * This is available as return type of all sendMessage/sendFile methods in {@link net.dv8tion.jda.api.entities.WebhookClient WebhookClient}.
- *
- *
When this RestAction has been executed all provided files will be closed.
- * Note that the garbage collector also frees opened file streams when it finalizes the stream object.
- *
- * @since 4.3.0
- *
- * @see net.dv8tion.jda.api.entities.WebhookClient#sendMessage(String)
- */
-// TODO: WebhookMessage type (no channel/guild attached)
-public interface WebhookMessageAction extends RestAction, AllowedMentions>
-{
-// /**
-// * Set the apparent username for the message author.
-// * This changes the username that is shown for the message author.
-// *
-// * This cannot be used with {@link net.dv8tion.jda.api.interactions.InteractionHook InteractionHooks}!
-// *
-// * @param name
-// * The username to use, or null to use the default
-// *
-// * @return The same message action, for chaining convenience
-// */
-// @Nonnull
-// @CheckReturnValue
-// WebhookMessageAction setUsername(@Nullable String name);
-//
-// /**
-// * Set the apparent avatar for the message author.
-// * This changes the avatar that is shown for the message author.
-// *
-// * This cannot be used with {@link net.dv8tion.jda.api.interactions.InteractionHook InteractionHooks}!
-// *
-// * @param iconUrl
-// * The URL to the avatar, or null to use default
-// *
-// * @return The same message action, for chaining convenience
-// */
-// @Nonnull
-// @CheckReturnValue
-// WebhookMessageAction setAvatarUrl(@Nullable String iconUrl);
-
- /**
- * Set whether this message should be visible to other users.
- * When a message is ephemeral, it will only be visible to the user that used the interaction.
- *
- * Ephemeral messages have some limitations and will be removed once the user restarts their client.
- * Limitations:
- *
- * Cannot be deleted by the bot
- * Cannot contain any files/attachments
- * Cannot be reacted to
- * Cannot be retrieved
- *
- *
- * This only works on {@link net.dv8tion.jda.api.interactions.InteractionHook InteractionHooks}!
- *
- * @param ephemeral
- * True, if this message should be invisible for other users
- *
- * @return The same message action, for chaining convenience
- */
- @Nonnull
- @CheckReturnValue
- WebhookMessageAction setEphemeral(boolean ephemeral);
-
- /**
- * Set the content for this message.
- *
- * @param content
- * The new message content
- *
- * @throws IllegalArgumentException
- * If the provided content is longer than {@link net.dv8tion.jda.api.entities.Message#MAX_CONTENT_LENGTH MAX_CONTENT_LENGTH} characters
- *
- * @return The same message action, for chaining convenience
- */
- @Nonnull
- @CheckReturnValue
- WebhookMessageAction setContent(@Nullable String content);
-
- /**
- * Enable/Disable Text-To-Speech for the resulting message.
- *
- * @param tts
- * True, if this should cause a Text-To-Speech effect when sent to the channel
- *
- * @return The same message action, for chaining convenience
- */
- @Nonnull
- @CheckReturnValue
- WebhookMessageAction setTTS(boolean tts);
-
- /**
- * Add {@link MessageEmbed MessageEmbeds} to this message
- *
- * @param embeds
- * The message embeds to add
- *
- * @throws IllegalArgumentException
- * If null is provided, or one of the embeds is too big
- *
- * @return The same message action, for chaining convenience
- */
- @Nonnull
- @CheckReturnValue
- WebhookMessageAction addEmbeds(@Nonnull Collection extends MessageEmbed> embeds); // Doesn't work on ephemeral messages!
-
- /**
- * Add {@link MessageEmbed MessageEmbeds} to this message
- *
- * @param embed
- * The first message embed to add
- * @param other
- * Additional message embeds to add
- *
- * @throws IllegalArgumentException
- * If null is provided, or one of the embeds is too big
- *
- * @return The same message action, for chaining convenience
- */
- @Nonnull
- @CheckReturnValue
- default WebhookMessageAction addEmbeds(@Nonnull MessageEmbed embed, @Nonnull MessageEmbed... other)
- {
- ArrayList embeds = new ArrayList<>();
- embeds.add(embed);
- Collections.addAll(embeds, other);
- return addEmbeds(embeds);
- }
-
- /**
- * Adds the provided {@link java.io.InputStream InputStream} as file data.
- * The stream will be closed upon execution!
- *
- * @param data
- * The InputStream that will be interpreted as file data
- * @param name
- * The file name that should be used to interpret the type of the given data
- * using the file-name extension. This name is similar to what will be visible
- * through {@link net.dv8tion.jda.api.entities.Message.Attachment#getFileName() Message.Attachment.getFileName()}
- * @param options
- * Possible options to apply to this attachment, such as marking it as spoiler image
- *
- * @throws java.lang.IllegalStateException
- * If the file limit of {@value Message#MAX_FILE_AMOUNT} has been reached prior to calling this method
- * @throws java.lang.IllegalArgumentException
- * If the provided data is {@code null} or the provided name is blank or {@code null}
- * @throws net.dv8tion.jda.api.exceptions.InsufficientPermissionException
- * If this is targeting a TextChannel and the currently logged in account does not have
- * {@link net.dv8tion.jda.api.Permission#MESSAGE_ATTACH_FILES Permission.MESSAGE_ATTACH_FILES}
- *
- * @return The same message action, for chaining convenience
- */
- @Nonnull
- @CheckReturnValue
- WebhookMessageAction addFile(@Nonnull InputStream data, @Nonnull String name, @Nonnull AttachmentOption... options);
-
- /**
- * Adds the provided byte[] as file data.
- *
- * @param data
- * The byte[] that will be interpreted as file data
- * @param name
- * The file name that should be used to interpret the type of the given data
- * using the file-name extension. This name is similar to what will be visible
- * through {@link net.dv8tion.jda.api.entities.Message.Attachment#getFileName() Message.Attachment.getFileName()}
- * @param options
- * Possible options to apply to this attachment, such as marking it as spoiler image
- *
- * @throws java.lang.IllegalStateException
- * If the file limit of {@value Message#MAX_FILE_AMOUNT} has been reached prior to calling this method
- * @throws java.lang.IllegalArgumentException
- * If the provided data is {@code null} or the provided name is blank or {@code null}
- * or if the provided data exceeds the maximum file size of the currently logged in account
- * @throws net.dv8tion.jda.api.exceptions.InsufficientPermissionException
- * If this is targeting a TextChannel and the currently logged in account does not have
- * {@link net.dv8tion.jda.api.Permission#MESSAGE_ATTACH_FILES Permission.MESSAGE_ATTACH_FILES}
- *
- * @return The same message action, for chaining convenience
- *
- * @see net.dv8tion.jda.api.entities.SelfUser#getAllowedFileSize() SelfUser.getAllowedFileSize()
- */
- @Nonnull
- @CheckReturnValue
- default WebhookMessageAction addFile(@Nonnull byte[] data, @Nonnull String name, @Nonnull AttachmentOption... options)
- {
- Checks.notNull(name, "Name");
- Checks.notNull(data, "Data");
- return addFile(new ByteArrayInputStream(data), name, options);
- }
-
- /**
- * Adds the provided {@link java.io.File File} as file data.
- *
- * This method opens a {@link java.io.FileInputStream FileInputStream} which will be closed by executing this action!
- *
- * @param file
- * The File that will be interpreted as file data
- * @param name
- * The file name that should be used to interpret the type of the given data
- * using the file-name extension. This name is similar to what will be visible
- * through {@link net.dv8tion.jda.api.entities.Message.Attachment#getFileName() Message.Attachment.getFileName()}
- * @param options
- * Possible options to apply to this attachment, such as marking it as spoiler image
- *
- * @throws java.lang.IllegalStateException
- * If the file limit of {@value Message#MAX_FILE_AMOUNT} has been reached prior to calling this method
- * @throws java.lang.IllegalArgumentException
- * If the provided file is {@code null} or the provided name is blank or {@code null}
- * or if the provided file is bigger than the maximum file size of the currently logged in account,
- * or if the provided file does not exist/ is not readable
- * @throws net.dv8tion.jda.api.exceptions.InsufficientPermissionException
- * If this is targeting a TextChannel and the currently logged in account does not have
- * {@link net.dv8tion.jda.api.Permission#MESSAGE_ATTACH_FILES Permission.MESSAGE_ATTACH_FILES}
- *
- * @return The same message action, for chaining convenience
- *
- * @see net.dv8tion.jda.api.entities.SelfUser#getAllowedFileSize() SelfUser.getAllowedFileSize()
- */
- @Nonnull
- @CheckReturnValue
- default WebhookMessageAction addFile(@Nonnull File file, @Nonnull String name, @Nonnull AttachmentOption... options)
- {
- Checks.notEmpty(name, "Name");
- Checks.notNull(file, "File");
- try
- {
- return addFile(new FileInputStream(file), name, options);
- }
- catch (FileNotFoundException e)
- {
- throw new IllegalArgumentException(e);
- }
- }
-
- /**
- * Adds the provided {@link java.io.File File} as file data.
- * Shortcut for {@link #addFile(java.io.File, String, net.dv8tion.jda.api.utils.AttachmentOption...) addFile(file, file.getName())} with the same side-effects.
- *
- * @param file
- * The File that will be interpreted as file data
- * @param options
- * Possible options to apply to this attachment, such as marking it as spoiler image
- *
- * @throws java.lang.IllegalStateException
- * If the file limit of {@value Message#MAX_FILE_AMOUNT} has been reached prior to calling this method
- * @throws java.lang.IllegalArgumentException
- * If the provided file is {@code null} or if the provided File is bigger than the maximum file size of the currently logged in account
- * @throws net.dv8tion.jda.api.exceptions.InsufficientPermissionException
- * If this is targeting a TextChannel and the currently logged in account does not have
- * {@link net.dv8tion.jda.api.Permission#MESSAGE_ATTACH_FILES Permission.MESSAGE_ATTACH_FILES}
- *
- * @return The same message action, for chaining convenience
- *
- * @see net.dv8tion.jda.api.entities.SelfUser#getAllowedFileSize() SelfUser.getAllowedFileSize()
- */
- @Nonnull
- @CheckReturnValue
- default WebhookMessageAction addFile(@Nonnull File file, @Nonnull AttachmentOption... options)
- {
- Checks.notNull(file, "File");
- return addFile(file, file.getName(), options);
- }
-
- /**
- * Add one {@link ActionRow ActionRow} for the message.
- *
- * @param components
- * The components for the action row, such as {@link Button Button}
- *
- * @throws IllegalArgumentException
- *
- * If null is provided, or more than 5 ItemComponents are provided
- * If any custom {@link ActionComponent#getId() id} is duplicated
- * If any of the provided ItemComponents are not compatible with messages
- *
- *
- * @return The same message action, for chaining convenience
- *
- * @see ItemComponent#isMessageCompatible()
- */
- @Nonnull
- @CheckReturnValue
- default WebhookMessageAction addActionRow(@Nonnull ItemComponent... components)
- {
- return addActionRows(ActionRow.of(components));
- }
-
- /**
- * Add one {@link ActionRow ActionRow} for the message.
- *
- * @param components
- * The components for the action row, such as {@link Button Button}
- *
- * @throws IllegalArgumentException
- *
- * If null is provided, or more than 5 ItemComponents are provided
- * If any custom {@link ActionComponent#getId() id} is duplicated
- * If any of the provided ItemComponents are not compatible with messages
- *
- *
- * @return The same message action, for chaining convenience
- *
- * @see ItemComponent#isMessageCompatible()
- */
- @Nonnull
- @CheckReturnValue
- default WebhookMessageAction addActionRow(@Nonnull Collection extends ItemComponent> components)
- {
- return addActionRows(ActionRow.of(components));
- }
-
- /**
- * Add {@link ActionRow ActionRows} for the message.
- *
- * @param rows
- * The action rows to add
- *
- * @throws IllegalArgumentException
- *
- * If null is provided, or more than 5 ActionRows are provided
- * If any custom {@link ActionComponent#getId() id} is duplicated
- * If any of the provided ActionRows are not compatible with messages
- *
- *
- * @return The same message action, for chaining convenience
- *
- * @see ActionRow#isMessageCompatible()
- */
- @Nonnull
- @CheckReturnValue
- default WebhookMessageAction addActionRows(@Nonnull Collection extends ActionRow> rows)
- {
- Checks.noneNull(rows, "ActionRows");
- return addActionRows(rows.toArray(new ActionRow[0]));
- }
-
- /**
- * Add {@link ActionRow ActionRows} for the message.
- *
- * @param rows
- * The action rows to add
- *
- * @throws IllegalArgumentException
- *
- * If null is provided, or more than 5 ActionRows are provided
- * If any custom {@link ActionComponent#getId() id} is duplicated
- * If any of the provided ActionRows are not compatible with messages
- *
- *
- * @return The same message action, for chaining convenience
- *
- * @see ActionRow#isMessageCompatible()
- */
- @Nonnull
- @CheckReturnValue
- WebhookMessageAction addActionRows(@Nonnull ActionRow... rows);
-
- /**
- * Applies the sendable information of the provided {@link net.dv8tion.jda.api.entities.Message Message}
- * to this message action settings.
- * This will override all existing settings if new settings are available.
- *
- * This does not copy files!
- *
- * @param message
- * The Message to apply settings from
- *
- * @throws java.lang.IllegalArgumentException
- * If the message contains a {@link net.dv8tion.jda.api.entities.MessageEmbed MessageEmbed}
- * that exceeds the sendable character limit,
- * see {@link net.dv8tion.jda.api.entities.MessageEmbed#isSendable() MessageEmbed.isSendable()}
- *
- * @return The same message action, for chaining convenience
- */
- @Nonnull
- @CheckReturnValue
- WebhookMessageAction applyMessage(@Nonnull Message message);
-}
diff --git a/src/main/java/net/dv8tion/jda/api/requests/restaction/WebhookMessageCreateAction.java b/src/main/java/net/dv8tion/jda/api/requests/restaction/WebhookMessageCreateAction.java
new file mode 100644
index 0000000000..c3644dd460
--- /dev/null
+++ b/src/main/java/net/dv8tion/jda/api/requests/restaction/WebhookMessageCreateAction.java
@@ -0,0 +1,94 @@
+/*
+ * 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.requests.restaction;
+
+import net.dv8tion.jda.api.requests.FluentRestAction;
+import net.dv8tion.jda.api.utils.messages.MessageCreateRequest;
+
+import javax.annotation.CheckReturnValue;
+import javax.annotation.Nonnull;
+
+/**
+ * Extension of a default {@link net.dv8tion.jda.api.requests.RestAction RestAction}
+ * that allows setting message information before sending!
+ *
+ * This is available as return type of all sendMessage/sendFile methods in {@link net.dv8tion.jda.api.entities.WebhookClient WebhookClient}.
+ *
+ *
When this RestAction has been executed all provided files will be closed.
+ * Note that the garbage collector also frees opened file streams when it finalizes the stream object.
+ *
+ * @since 4.3.0
+ *
+ * @see net.dv8tion.jda.api.entities.WebhookClient#sendMessage(String)
+ */
+// TODO: WebhookMessage type (no channel/guild attached)
+public interface WebhookMessageCreateAction extends MessageCreateRequest>, FluentRestAction>
+{
+// /**
+// * Set the apparent username for the message author.
+// * This changes the username that is shown for the message author.
+// *
+// * This cannot be used with {@link net.dv8tion.jda.api.interactions.InteractionHook InteractionHooks}!
+// *
+// * @param name
+// * The username to use, or null to use the default
+// *
+// * @return The same message action, for chaining convenience
+// */
+// @Nonnull
+// @CheckReturnValue
+// WebhookMessageAction setUsername(@Nullable String name);
+//
+// /**
+// * Set the apparent avatar for the message author.
+// * This changes the avatar that is shown for the message author.
+// *
+// * This cannot be used with {@link net.dv8tion.jda.api.interactions.InteractionHook InteractionHooks}!
+// *
+// * @param iconUrl
+// * The URL to the avatar, or null to use default
+// *
+// * @return The same message action, for chaining convenience
+// */
+// @Nonnull
+// @CheckReturnValue
+// WebhookMessageAction setAvatarUrl(@Nullable String iconUrl);
+
+ /**
+ * Set whether this message should be visible to other users.
+ * When a message is ephemeral, it will only be visible to the user that used the interaction.
+ *
+ * Ephemeral messages have some limitations and will be removed once the user restarts their client.
+ * Limitations:
+ *
+ * Cannot be deleted by the bot
+ * Cannot contain any files/attachments
+ * Cannot be reacted to
+ * Cannot be retrieved
+ *
+ *
+ * This only works on {@link net.dv8tion.jda.api.interactions.InteractionHook InteractionHooks}!
+ *
+ * @param ephemeral
+ * True, if this message should be invisible for other users
+ *
+ * @return The same message action, for chaining convenience
+ */
+ @Nonnull
+ @CheckReturnValue
+ WebhookMessageCreateAction setEphemeral(boolean ephemeral);
+}
diff --git a/src/main/java/net/dv8tion/jda/api/requests/restaction/WebhookMessageEditAction.java b/src/main/java/net/dv8tion/jda/api/requests/restaction/WebhookMessageEditAction.java
new file mode 100644
index 0000000000..1bfc10b675
--- /dev/null
+++ b/src/main/java/net/dv8tion/jda/api/requests/restaction/WebhookMessageEditAction.java
@@ -0,0 +1,35 @@
+/*
+ * 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.requests.restaction;
+
+import net.dv8tion.jda.api.requests.FluentRestAction;
+import net.dv8tion.jda.api.requests.RestAction;
+import net.dv8tion.jda.api.utils.messages.MessageEditRequest;
+
+/**
+ * Specialized {@link RestAction} used to update an existing message sent by a {@link net.dv8tion.jda.api.entities.Webhook Webhook} or {@link net.dv8tion.jda.api.interactions.InteractionHook InteractionHook}.
+ *
+ * @param
+ * The type of message that will be returned
+ *
+ * @see net.dv8tion.jda.api.interactions.InteractionHook#editOriginal(String)
+ * @see net.dv8tion.jda.api.entities.WebhookClient#editMessageById(long, String)
+ */
+// TODO: WebhookMessage type (no channel/guild attached)
+public interface WebhookMessageEditAction extends MessageEditRequest>, FluentRestAction>
+{
+}
diff --git a/src/main/java/net/dv8tion/jda/api/requests/restaction/WebhookMessageUpdateAction.java b/src/main/java/net/dv8tion/jda/api/requests/restaction/WebhookMessageUpdateAction.java
deleted file mode 100644
index 5e28a065e1..0000000000
--- a/src/main/java/net/dv8tion/jda/api/requests/restaction/WebhookMessageUpdateAction.java
+++ /dev/null
@@ -1,395 +0,0 @@
-/*
- * 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.requests.restaction;
-
-import net.dv8tion.jda.api.entities.Message;
-import net.dv8tion.jda.api.entities.MessageEmbed;
-import net.dv8tion.jda.api.interactions.components.ActionComponent;
-import net.dv8tion.jda.api.interactions.components.ActionRow;
-import net.dv8tion.jda.api.interactions.components.ItemComponent;
-import net.dv8tion.jda.api.interactions.components.buttons.Button;
-import net.dv8tion.jda.api.requests.RestAction;
-import net.dv8tion.jda.api.utils.AttachmentOption;
-import net.dv8tion.jda.internal.utils.Checks;
-
-import javax.annotation.CheckReturnValue;
-import javax.annotation.Nonnull;
-import javax.annotation.Nullable;
-import java.io.*;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.stream.Collectors;
-
-/**
- * Specialized {@link RestAction} used to update an existing message sent by a {@link net.dv8tion.jda.api.entities.Webhook Webhook} or {@link net.dv8tion.jda.api.interactions.InteractionHook InteractionHook}.
- *
- * @param
- * The type of message that will be returned
- *
- * @see net.dv8tion.jda.api.interactions.InteractionHook#editOriginal(String)
- * @see net.dv8tion.jda.api.entities.WebhookClient#editMessageById(long, String)
- */
-// TODO: WebhookMessage type (no channel/guild attached)
-public interface WebhookMessageUpdateAction extends RestAction
-{
- /**
- * Set the new content for this message.
- *
- * @param content
- * The new message content
- *
- * @throws IllegalArgumentException
- * If the provided content is longer than {@link net.dv8tion.jda.api.entities.Message#MAX_CONTENT_LENGTH MAX_CONTENT_LENGTH} characters
- *
- * @return The same update action, for chaining convenience
- */
- @Nonnull
- @CheckReturnValue
- WebhookMessageUpdateAction setContent(@Nullable String content);
-
- /**
- * Set the {@link MessageEmbed MessageEmbeds} for the message
- *
- * @param embeds
- * The message embeds
- *
- * @throws IllegalArgumentException
- * If null is provided, or one of the embeds is too big
- *
- * @return The same update action, for chaining convenience
- */
- @Nonnull
- @CheckReturnValue
- WebhookMessageUpdateAction setEmbeds(@Nonnull Collection extends MessageEmbed> embeds); // Doesn't work on ephemeral messages!
-
- /**
- * Set the {@link MessageEmbed MessageEmbeds} for the message
- *
- * @param embeds
- * The message embeds
- *
- * @throws IllegalArgumentException
- * If null is provided, or one of the embeds is too big
- *
- * @return The same update action, for chaining convenience
- */
- @Nonnull
- @CheckReturnValue
- default WebhookMessageUpdateAction setEmbeds(@Nonnull MessageEmbed... embeds)
- {
- Checks.noneNull(embeds, "MessageEmbeds");
- return setEmbeds(Arrays.asList(embeds));
- }
-
- /**
- * Set only one action row for convenience.
- *
- * @param components
- * The action row components, such as {@link Button Buttons}
- *
- * @throws IllegalArgumentException
- * If null is provided, an invalid number of components is provided,
- * or any custom {@link ActionComponent#getId() id} is duplicated
- *
- * @return The same update action, for chaining convenience
- */
- @Nonnull
- @CheckReturnValue
- default WebhookMessageUpdateAction setActionRow(@Nonnull ItemComponent... components)
- {
- return setActionRows(ActionRow.of(components));
- }
-
- /**
- * Set only one action row for convenience.
- *
- * @param components
- * The action row components, such as {@link Button Buttons}
- *
- * @throws IllegalArgumentException
- * If null is provided, an invalid number of components is provided,
- * or any custom {@link ActionComponent#getId() id} is duplicated
- *
- * @return The same update action, for chaining convenience
- */
- @Nonnull
- @CheckReturnValue
- default WebhookMessageUpdateAction setActionRow(@Nonnull Collection extends ItemComponent> components)
- {
- return setActionRows(ActionRow.of(components));
- }
-
- /**
- * Set the action rows for the message.
- *
- * @param rows
- * The new action rows
- *
- * @throws IllegalArgumentException
- * If null is provided, more than 5 action rows are provided,
- * or any custom {@link ActionComponent#getId() id} is duplicated
- *
- * @return The same update action, for chaining convenience
- */
- @Nonnull
- @CheckReturnValue
- default WebhookMessageUpdateAction setActionRows(@Nonnull Collection extends ActionRow> rows)
- {
- Checks.noneNull(rows, "ActionRows");
- return setActionRows(rows.toArray(new ActionRow[0]));
- }
-
- /**
- * Set the action rows for the message.
- *
- * @param rows
- * The new action rows
- *
- * @throws IllegalArgumentException
- * If null is provided, more than 5 action rows are provided,
- * or any custom {@link ActionComponent#getId() id} is duplicated
- *
- * @return The same update action, for chaining convenience
- */
- @Nonnull
- @CheckReturnValue
- WebhookMessageUpdateAction setActionRows(@Nonnull ActionRow... rows);
-
- /**
- * Applies the {@link Message} to overwrite the existing message.
- *
- * @param message
- * The message to use for updating
- *
- * @throws IllegalArgumentException
- * If null is provided
- *
- * @return The same update action, for chaining convenience
- */
- @Nonnull
- @CheckReturnValue
- WebhookMessageUpdateAction applyMessage(@Nonnull Message message);
-
- /**
- * Adds the provided {@link java.io.InputStream InputStream} as file data.
- * The stream will be closed upon execution!
- * The provided file will be appended to the message. You can use {@link #retainFiles(Collection)} to delete files from the message.
- *
- * @param data
- * The InputStream data to upload to the webhook.
- * @param name
- * The file name that should be sent to discord
- * Refer to the documentation for {@link #addFile(java.io.File, String, AttachmentOption...)} for information about this parameter.
- * @param options
- * Possible options to apply to this attachment, such as marking it as spoiler image
- *
- * @throws java.lang.IllegalArgumentException
- * If the provided data or filename is {@code null}.
- *
- * @return The same update action, for chaining convenience
- */
- @Nonnull
- @CheckReturnValue
- WebhookMessageUpdateAction addFile(@Nonnull InputStream data, @Nonnull String name, @Nonnull AttachmentOption... options);
-
- /**
- * Adds the provided {@code byte[]} as file data.
- * The stream will be closed upon execution!
- * The provided file will be appended to the message. You can use {@link #retainFiles(Collection)} to delete files from the message.
- *
- * @param data
- * The {@code byte[]} data to upload to the webhook.
- * @param name
- * The file name that should be sent to discord
- * Refer to the documentation for {@link #addFile(java.io.File, String, AttachmentOption...)} for information about this parameter.
- * @param options
- * Possible options to apply to this attachment, such as marking it as spoiler image
- *
- * @throws java.lang.IllegalArgumentException
- * If the provided data or filename is {@code null}.
- *
- * @return The same update action, for chaining convenience
- */
- @Nonnull
- @CheckReturnValue
- default WebhookMessageUpdateAction addFile(@Nonnull byte[] data, @Nonnull String name, @Nonnull AttachmentOption... options)
- {
- Checks.notNull(name, "Name");
- Checks.notNull(data, "Data");
- return addFile(new ByteArrayInputStream(data), name, options);
- }
-
- /**
- * Adds the provided {@link File}.
- * The stream will be closed upon execution!
- * The provided file will be appended to the message. You can use {@link #retainFiles(Collection)} to delete files from the message.
- *
- * The {@code name} parameter is used to inform Discord about what the file should be called. This is 2 fold:
- *
- * The file name provided is the name that is found in {@link net.dv8tion.jda.api.entities.Message.Attachment#getFileName()}
- * after upload and it is the name that will show up in the client when the upload is displayed.
- * Note: The fileName does not show up on the Desktop client for images. It does on mobile however.
- * The extension of the provided fileName also determines how Discord will treat the file. Discord currently only
- * has special handling for image file types, but the fileName's extension must indicate that it is an image file.
- * This means it has to end in something like .png, .jpg, .jpeg, .gif, etc. As a note, you can also not provide
- * a full name for the file and instead ONLY provide the extension like "png" or "gif" and Discord will generate
- * a name for the upload and append the fileName as the extension.
- *
- *
- * @param file
- * The {@link File} data to upload to the webhook.
- * @param name
- * The file name that should be sent to discord
- * @param options
- * Possible options to apply to this attachment, such as marking it as spoiler image
- *
- * @throws java.lang.IllegalArgumentException
- * If the provided file or filename is {@code null}.
- *
- * @return The same update action, for chaining convenience
- */
- @Nonnull
- @CheckReturnValue
- default WebhookMessageUpdateAction addFile(@Nonnull File file, @Nonnull String name, @Nonnull AttachmentOption... options)
- {
- Checks.notEmpty(name, "Name");
- Checks.notNull(file, "File");
- try
- {
- return addFile(new FileInputStream(file), name, options);
- }
- catch (FileNotFoundException e)
- {
- throw new IllegalArgumentException(e);
- }
- }
-
- /**
- * Adds the provided {@link File}.
- * The stream will be closed upon execution!
- * The provided file will be appended to the message. You can use {@link #retainFiles(Collection)} to delete files from the message.
- *
- * @param file
- * The {@link File} data to upload to the webhook.
- * @param options
- * Possible options to apply to this attachment, such as marking it as spoiler image
- *
- * @throws java.lang.IllegalArgumentException
- * If the provided file is {@code null}.
- *
- * @return The same update action, for chaining convenience
- */
- @Nonnull
- @CheckReturnValue
- default WebhookMessageUpdateAction addFile(@Nonnull File file, @Nonnull AttachmentOption... options)
- {
- Checks.notNull(file, "File");
- return addFile(file, file.getName(), options);
- }
-
- /**
- * Removes all attachments that are currently attached to the existing message except for the ones provided.
- * For example {@code retainFilesById(Arrays.asList("123"))} would remove all attachments except for the one with the id 123.
- *
- * To remove all attachments from the message you can pass an empty list.
- *
- * @param ids
- * The ids for the attachments which should be retained on the message
- *
- * @throws IllegalArgumentException
- * If any of the ids is null or not a valid snowflake
- *
- * @return The same update action, for chaining convenience
- */
- @Nonnull
- @CheckReturnValue
- WebhookMessageUpdateAction retainFilesById(@Nonnull Collection ids);
-
- /**
- * Removes all attachments that are currently attached to the existing message except for the ones provided.
- * For example {@code retainFilesById(Arrays.asList("123"))} would remove all attachments except for the one with the id 123.
- *
- * To remove all attachments from the message you can pass an empty list.
- *
- * @param ids
- * The ids for the attachments which should be retained on the message
- *
- * @throws IllegalArgumentException
- * If any of the ids is null or not a valid snowflake
- *
- * @return The same update action, for chaining convenience
- */
- @Nonnull
- @CheckReturnValue
- default WebhookMessageUpdateAction retainFilesById(@Nonnull String... ids)
- {
- Checks.notNull(ids, "IDs");
- return retainFilesById(Arrays.asList(ids));
- }
-
- /**
- * Removes all attachments that are currently attached to the existing message except for the ones provided.
- * For example {@code retainFilesById(Arrays.asList("123"))} would remove all attachments except for the one with the id 123.
- *
- * To remove all attachments from the message you can pass an empty list.
- *
- * @param ids
- * The ids for the attachments which should be retained on the message
- *
- * @throws IllegalArgumentException
- * If any of the ids is null or not a valid snowflake
- *
- * @return The same update action, for chaining convenience
- */
- @Nonnull
- @CheckReturnValue
- default WebhookMessageUpdateAction retainFilesById(long... ids)
- {
- Checks.notNull(ids, "IDs");
- return retainFilesById(Arrays
- .stream(ids)
- .mapToObj(Long::toUnsignedString)
- .collect(Collectors.toList())
- );
- }
-
- /**
- * Removes all attachments that are currently attached to the existing message except for the ones provided.
- * For example {@code retainFiles(message.getAttachments().subList(1, message.getAttachments().size()))} would only remove the first attachment from the message.
- *
- * To remove all attachments from the message you can pass an empty list.
- *
- * @param attachments
- * The attachments which should be retained on the message
- *
- * @throws IllegalArgumentException
- * If any of the ids is null or not a valid snowflake
- *
- * @return The same update action, for chaining convenience
- */
- @Nonnull
- @CheckReturnValue
- default WebhookMessageUpdateAction retainFiles(@Nonnull Collection extends Message.Attachment> attachments)
- {
- Checks.noneNull(attachments, "Attachments");
- return retainFilesById(attachments
- .stream()
- .map(Message.Attachment::getId)
- .collect(Collectors.toList())
- );
- }
-}
diff --git a/src/main/java/net/dv8tion/jda/api/requests/restaction/interactions/AutoCompleteCallbackAction.java b/src/main/java/net/dv8tion/jda/api/requests/restaction/interactions/AutoCompleteCallbackAction.java
index 397214b69b..8c4a5ea94c 100644
--- a/src/main/java/net/dv8tion/jda/api/requests/restaction/interactions/AutoCompleteCallbackAction.java
+++ b/src/main/java/net/dv8tion/jda/api/requests/restaction/interactions/AutoCompleteCallbackAction.java
@@ -21,6 +21,7 @@
import net.dv8tion.jda.api.interactions.commands.CommandAutoCompleteInteraction;
import net.dv8tion.jda.api.interactions.commands.OptionType;
import net.dv8tion.jda.api.interactions.commands.build.OptionData;
+import net.dv8tion.jda.api.requests.FluentRestAction;
import net.dv8tion.jda.internal.utils.Checks;
import javax.annotation.CheckReturnValue;
@@ -36,7 +37,7 @@
* @see IAutoCompleteCallback
* @see CommandAutoCompleteInteraction
*/
-public interface AutoCompleteCallbackAction extends InteractionCallbackAction
+public interface AutoCompleteCallbackAction extends InteractionCallbackAction, FluentRestAction
{
/**
* The {@link OptionType} of the choices you can suggest.
diff --git a/src/main/java/net/dv8tion/jda/api/requests/restaction/interactions/MessageEditCallbackAction.java b/src/main/java/net/dv8tion/jda/api/requests/restaction/interactions/MessageEditCallbackAction.java
index b40a60e9b0..6bcadd2bde 100644
--- a/src/main/java/net/dv8tion/jda/api/requests/restaction/interactions/MessageEditCallbackAction.java
+++ b/src/main/java/net/dv8tion/jda/api/requests/restaction/interactions/MessageEditCallbackAction.java
@@ -16,418 +16,18 @@
package net.dv8tion.jda.api.requests.restaction.interactions;
-import net.dv8tion.jda.api.entities.Message;
-import net.dv8tion.jda.api.entities.MessageEmbed;
import net.dv8tion.jda.api.interactions.InteractionHook;
-import net.dv8tion.jda.api.interactions.components.ActionComponent;
-import net.dv8tion.jda.api.interactions.components.ActionRow;
-import net.dv8tion.jda.api.interactions.components.ItemComponent;
-import net.dv8tion.jda.api.interactions.components.buttons.Button;
-import net.dv8tion.jda.api.utils.AttachmentOption;
-import net.dv8tion.jda.internal.utils.Checks;
+import net.dv8tion.jda.api.requests.FluentRestAction;
+import net.dv8tion.jda.api.utils.messages.MessageEditRequest;
-import javax.annotation.CheckReturnValue;
import javax.annotation.Nonnull;
-import javax.annotation.Nullable;
-import java.io.*;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.concurrent.TimeUnit;
-import java.util.function.BooleanSupplier;
-import java.util.stream.Collectors;
/**
* A {@link InteractionCallbackAction} which can be used to edit the message for an interaction.
*/
-public interface MessageEditCallbackAction extends InteractionCallbackAction
+public interface MessageEditCallbackAction extends InteractionCallbackAction, MessageEditRequest, FluentRestAction
{
- @Nonnull
- @Override
- MessageEditCallbackAction setCheck(@Nullable BooleanSupplier checks);
-
- @Nonnull
- @Override
- MessageEditCallbackAction timeout(long timeout, @Nonnull TimeUnit unit);
-
- @Nonnull
- @Override
- MessageEditCallbackAction deadline(long timestamp);
-
@Nonnull
@Override
MessageEditCallbackAction closeResources();
-
- /**
- * Set the new content for this message.
- *
- * @param content
- * The new message content
- *
- * @throws IllegalArgumentException
- * If the provided content is longer than {@link net.dv8tion.jda.api.entities.Message#MAX_CONTENT_LENGTH MAX_CONTENT_LENGTH} characters
- *
- * @return The same update action, for chaining convenience
- */
- @Nonnull
- MessageEditCallbackAction setContent(@Nullable final String content);
-
- /**
- * Set the {@link MessageEmbed MessageEmbeds} for the message
- *
- * @param embeds
- * The message embeds
- *
- * @throws IllegalArgumentException
- * If null is provided, or one of the embeds is too big, or more than {@value Message#MAX_EMBED_COUNT} embeds are provided
- *
- * @return The same update action, for chaining convenience
- */
- @Nonnull
- @CheckReturnValue
- default MessageEditCallbackAction setEmbeds(@Nonnull MessageEmbed... embeds)
- {
- Checks.noneNull(embeds, "MessageEmbed");
- return setEmbeds(Arrays.asList(embeds));
- }
-
- /**
- * Set the {@link MessageEmbed MessageEmbeds} for the message
- *
- * @param embeds
- * The message embeds
- *
- * @throws IllegalArgumentException
- * If null is provided, one of the embeds is too big, or more than {@value Message#MAX_EMBED_COUNT} embeds are provided
- *
- * @return The same update action, for chaining convenience
- */
- @Nonnull
- @CheckReturnValue
- MessageEditCallbackAction setEmbeds(@Nonnull Collection extends MessageEmbed> embeds);
-
- /**
- * Set the action rows for the message.
- *
- * @param rows
- * The new action rows
- *
- * @throws IllegalArgumentException
- *
- * If null is provided, or more than 5 ActionRows are provided
- * If any custom {@link ActionComponent#getId() id} is duplicated
- * If any of the provided ActionRows are not compatible with messages
- *
- *
- * @return The same update action, for chaining convenience
- *
- * @see ActionRow#isMessageCompatible()
- */
- @Nonnull
- @CheckReturnValue
- default MessageEditCallbackAction setActionRows(@Nonnull Collection extends ActionRow> rows)
- {
- Checks.noneNull(rows, "ActionRows");
- return setActionRows(rows.toArray(new ActionRow[0]));
- }
-
- /**
- * Set the action rows for the message.
- *
- * @param rows
- * The new action rows
- *
- * @throws IllegalArgumentException
- *
- * If null is provided, or more than 5 ActionRows are provided
- * If any custom {@link ActionComponent#getId() id} is duplicated
- * If any of the provided ActionRows are not compatible with messages
- *
- *
- * @return The same update action, for chaining convenience
- *
- * @see ActionRow#isMessageCompatible()
- */
- @Nonnull
- @CheckReturnValue
- MessageEditCallbackAction setActionRows(@Nonnull ActionRow... rows);
-
- /**
- * Set only one action row for convenience.
- *
- * @param components
- * The action row components, such as {@link Button Buttons}
- *
- * @throws IllegalArgumentException
- *
- * If null is provided, or more than 5 ItemComponents are provided
- * If any custom {@link ActionComponent#getId() id} is duplicated
- * If any of the provided ItemComponents are not compatible with messages
- *
- *
- * @return The same update action, for chaining convenience
- *
- * @see ActionRow#of(ItemComponent...)
- * @see ItemComponent#isMessageCompatible()
- */
- @Nonnull
- @CheckReturnValue
- default MessageEditCallbackAction setActionRow(@Nonnull ItemComponent... components)
- {
- return setActionRows(ActionRow.of(components));
- }
-
- /**
- * Set only one action row for convenience.
- *
- * @param components
- * The action row components, such as {@link Button Buttons}
- *
- * @throws IllegalArgumentException
- *
- * If null is provided, or more than 5 ItemComponents are provided
- * If any custom {@link ActionComponent#getId() id} is duplicated
- * If any of the provided ItemComponents are not compatible with messages
- *
- *
- * @return The same update action, for chaining convenience
- *
- * @see ActionRow#of(Collection)
- * @see ItemComponent#isMessageCompatible()
- */
- @Nonnull
- @CheckReturnValue
- default MessageEditCallbackAction setActionRow(@Nonnull Collection extends ItemComponent> components)
- {
- return setActionRows(ActionRow.of(components));
- }
-
- /**
- * Adds the provided {@link File}.
- * The stream will be closed upon execution!
- * The provided file will be appended to the message.
- *
- * @param file
- * The {@link File} data to upload in response to the interaction.
- * @param options
- * Possible options to apply to this attachment, such as marking it as spoiler image
- *
- * @throws java.lang.IllegalArgumentException
- * If the provided file is {@code null}.
- *
- * @return The same update action, for chaining convenience
- */
- @Nonnull
- @CheckReturnValue
- default MessageEditCallbackAction addFile(@Nonnull File file, @Nonnull AttachmentOption... options)
- {
- Checks.notNull(file, "File");
- return addFile(file, file.getName(), options);
- }
-
- /**
- * Adds the provided {@link File}.
- * The stream will be closed upon execution!
- * The provided file will be appended to the message.
- *
- * The {@code name} parameter is used to inform Discord about what the file should be called. This is 2 fold:
- *
- * The file name provided is the name that is found in {@link net.dv8tion.jda.api.entities.Message.Attachment#getFileName()}
- * after upload and it is the name that will show up in the client when the upload is displayed.
- * Note: The fileName does not show up on the Desktop client for images. It does on mobile however.
- * The extension of the provided fileName also determines how Discord will treat the file. Discord currently only
- * has special handling for image file types, but the fileName's extension must indicate that it is an image file.
- * This means it has to end in something like .png, .jpg, .jpeg, .gif, etc. As a note, you can also not provide
- * a full name for the file and instead ONLY provide the extension like "png" or "gif" and Discord will generate
- * a name for the upload and append the fileName as the extension.
- *
- *
- * @param file
- * The {@link File} data to upload in response to the interaction.
- * @param name
- * The file name that should be sent to discord
- * @param options
- * Possible options to apply to this attachment, such as marking it as spoiler image
- *
- * @throws java.lang.IllegalArgumentException
- * If the provided file or filename is {@code null}.
- *
- * @return The same update action, for chaining convenience
- */
- @Nonnull
- @CheckReturnValue
- default MessageEditCallbackAction addFile(@Nonnull File file, @Nonnull String name, @Nonnull AttachmentOption... options)
- {
- try
- {
- Checks.notNull(file, "File");
- Checks.check(file.exists() && file.canRead(), "Provided file either does not exist or cannot be read from!");
- return addFile(new FileInputStream(file), name, options);
- }
- catch (FileNotFoundException e)
- {
- throw new IllegalArgumentException(e);
- }
- }
-
- /**
- * Adds the provided {@code byte[]} as file data.
- * The stream will be closed upon execution!
- * The provided file will be appended to the message.
- *
- * @param data
- * The {@code byte[]} data to upload in response to the interaction.
- * @param name
- * The file name that should be sent to discord
- * Refer to the documentation for {@link #addFile(java.io.File, String, AttachmentOption...)} for information about this parameter.
- * @param options
- * Possible options to apply to this attachment, such as marking it as spoiler image
- *
- * @throws java.lang.IllegalArgumentException
- * If the provided data or filename is {@code null}.
- *
- * @return The same update action, for chaining convenience
- */
- @Nonnull
- @CheckReturnValue
- default MessageEditCallbackAction addFile(@Nonnull byte[] data, @Nonnull String name, @Nonnull AttachmentOption... options)
- {
- Checks.notNull(data, "Data");
- return addFile(new ByteArrayInputStream(data), name, options);
- }
-
- /**
- * Adds the provided {@link java.io.InputStream InputStream} as file data.
- * The stream will be closed upon execution!
- * The provided file will be appended to the message.
- *
- * @param data
- * The InputStream data to upload in response to the interaction.
- * @param name
- * The file name that should be sent to discord
- * Refer to the documentation for {@link #addFile(java.io.File, String, AttachmentOption...)} for information about this parameter.
- * @param options
- * Possible options to apply to this attachment, such as marking it as spoiler image
- *
- * @throws java.lang.IllegalArgumentException
- * If the provided data or filename is {@code null}.
- *
- * @return The same update action, for chaining convenience
- */
- @Nonnull
- @CheckReturnValue
- MessageEditCallbackAction addFile(@Nonnull InputStream data, @Nonnull String name, @Nonnull AttachmentOption... options);
-
- /**
- * Removes all attachments that are currently attached to the existing message except for the ones provided.
- * For example {@code retainFilesById(Arrays.asList("123"))} would remove all attachments except for the one with the id 123.
- *
- * To remove all attachments from the message you can pass an empty list.
- *
- * @param ids
- * The ids for the attachments which should be retained on the message
- *
- * @throws IllegalArgumentException
- * If any of the ids is null or not a valid snowflake
- *
- * @return The same update action, for chaining convenience
- */
- @Nonnull
- @CheckReturnValue
- MessageEditCallbackAction retainFilesById(@Nonnull Collection ids);
-
- /**
- * Removes all attachments that are currently attached to the existing message except for the ones provided.
- * For example {@code retainFilesById(Arrays.asList("123"))} would remove all attachments except for the one with the id 123.
- *
- * To remove all attachments from the message you can pass an empty list.
- *
- * @param ids
- * The ids for the attachments which should be retained on the message
- *
- * @throws IllegalArgumentException
- * If any of the ids is null or not a valid snowflake
- *
- * @return The same update action, for chaining convenience
- */
- @Nonnull
- @CheckReturnValue
- default MessageEditCallbackAction retainFilesById(@Nonnull String... ids)
- {
- Checks.notNull(ids, "IDs");
- return retainFilesById(Arrays.asList(ids));
- }
-
- /**
- * Removes all attachments that are currently attached to the existing message except for the ones provided.
- * For example {@code retainFilesById(Arrays.asList("123"))} would remove all attachments except for the one with the id 123.
- *
- *
To remove all attachments from the message you can pass an empty list.
- *
- * @param ids
- * The ids for the attachments which should be retained on the message
- *
- * @throws IllegalArgumentException
- * If any of the ids is null or not a valid snowflake
- *
- * @return The same update action, for chaining convenience
- */
- @Nonnull
- @CheckReturnValue
- default MessageEditCallbackAction retainFilesById(long... ids)
- {
- Checks.notNull(ids, "IDs");
- return retainFilesById(Arrays
- .stream(ids)
- .mapToObj(Long::toUnsignedString)
- .collect(Collectors.toList())
- );
- }
-
- /**
- * Removes all attachments that are currently attached to the existing message except for the ones provided.
- * For example {@code retainFiles(message.getAttachments().subList(1, message.getAttachments().size()))} would only remove the first attachment from the message.
- *
- *
To remove all attachments from the message you can pass an empty list.
- *
- * @param attachments
- * The attachments which should be retained on the message
- *
- * @throws IllegalArgumentException
- * If any of the ids is null or not a valid snowflake
- *
- * @return The same update action, for chaining convenience
- */
- @Nonnull
- @CheckReturnValue
- default MessageEditCallbackAction retainFiles(@Nonnull Collection extends Message.Attachment> attachments)
- {
- Checks.noneNull(attachments, "Attachments");
- return retainFilesById(attachments
- .stream()
- .map(Message.Attachment::getId)
- .collect(Collectors.toList())
- );
- }
-
- /**
- * Removes all attachments that are currently attached to the existing message except for the ones provided.
- * For example {@code retainFiles(message.getAttachments().subList(1, message.getAttachments().size()))} would only remove the first attachment from the message.
- *
- *
To remove all attachments from the message you can pass an empty list.
- *
- * @param attachments
- * The attachments which should be retained on the message
- *
- * @throws IllegalArgumentException
- * If any of the ids is null or not a valid snowflake
- *
- * @return The same update action, for chaining convenience
- */
- @Nonnull
- @CheckReturnValue
- default MessageEditCallbackAction retainFiles(@Nonnull Message.Attachment... attachments)
- {
- Checks.noneNull(attachments, "Attachments");
- return retainFiles(Arrays.asList(attachments));
- }
}
diff --git a/src/main/java/net/dv8tion/jda/api/requests/restaction/interactions/ModalCallbackAction.java b/src/main/java/net/dv8tion/jda/api/requests/restaction/interactions/ModalCallbackAction.java
index 9697a414c8..47fcb03abb 100644
--- a/src/main/java/net/dv8tion/jda/api/requests/restaction/interactions/ModalCallbackAction.java
+++ b/src/main/java/net/dv8tion/jda/api/requests/restaction/interactions/ModalCallbackAction.java
@@ -16,13 +16,14 @@
package net.dv8tion.jda.api.requests.restaction.interactions;
+import net.dv8tion.jda.api.requests.FluentRestAction;
+
/**
* An {@link InteractionCallbackAction} that can be used to send Modals.
*
* @see net.dv8tion.jda.api.interactions.callbacks.IModalCallback
* @see net.dv8tion.jda.api.events.interaction.ModalInteractionEvent
*/
-public interface ModalCallbackAction extends InteractionCallbackAction
+public interface ModalCallbackAction extends InteractionCallbackAction, FluentRestAction
{
-
}
diff --git a/src/main/java/net/dv8tion/jda/api/requests/restaction/interactions/ReplyCallbackAction.java b/src/main/java/net/dv8tion/jda/api/requests/restaction/interactions/ReplyCallbackAction.java
index 2e7f6e8a36..f7deddc5fd 100644
--- a/src/main/java/net/dv8tion/jda/api/requests/restaction/interactions/ReplyCallbackAction.java
+++ b/src/main/java/net/dv8tion/jda/api/requests/restaction/interactions/ReplyCallbackAction.java
@@ -16,201 +16,23 @@
package net.dv8tion.jda.api.requests.restaction.interactions;
-import net.dv8tion.jda.api.entities.MessageEmbed;
import net.dv8tion.jda.api.interactions.InteractionHook;
-import net.dv8tion.jda.api.interactions.components.ActionComponent;
-import net.dv8tion.jda.api.interactions.components.ActionRow;
-import net.dv8tion.jda.api.interactions.components.ItemComponent;
-import net.dv8tion.jda.api.utils.AllowedMentions;
-import net.dv8tion.jda.api.utils.AttachmentOption;
-import net.dv8tion.jda.internal.utils.Checks;
+import net.dv8tion.jda.api.requests.FluentRestAction;
+import net.dv8tion.jda.api.utils.messages.MessageCreateRequest;
import javax.annotation.CheckReturnValue;
import javax.annotation.Nonnull;
-import javax.annotation.Nullable;
-import java.io.*;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.concurrent.TimeUnit;
-import java.util.function.BooleanSupplier;
/**
* A {@link InteractionCallbackAction} which can be used to send a message reply for an interaction.
* You can use {@link #setEphemeral(boolean)} to hide this message from other users.
*/
-public interface ReplyCallbackAction extends InteractionCallbackAction, AllowedMentions
+public interface ReplyCallbackAction extends InteractionCallbackAction, MessageCreateRequest, FluentRestAction
{
- @Nonnull
- @Override
- ReplyCallbackAction setCheck(@Nullable BooleanSupplier checks);
-
- @Nonnull
- @Override
- ReplyCallbackAction timeout(long timeout, @Nonnull TimeUnit unit);
-
- @Nonnull
- @Override
- ReplyCallbackAction deadline(long timestamp);
-
@Nonnull
@Override
ReplyCallbackAction closeResources();
- /**
- * Add {@link MessageEmbed MessageEmbeds} for the message
- *
- * @param embeds
- * The message embeds to add
- *
- * @throws IllegalArgumentException
- * If null is provided, or one of the embeds is too big
- *
- * @return The same reply action, for chaining convenience
- */
- @Nonnull
- @CheckReturnValue
- default ReplyCallbackAction addEmbeds(@Nonnull MessageEmbed... embeds)
- {
- Checks.noneNull(embeds, "MessageEmbed");
- return addEmbeds(Arrays.asList(embeds));
- }
-
- /**
- * Add {@link MessageEmbed MessageEmbeds} for the message
- *
- * @param embeds
- * The message embeds to add
- *
- * @throws IllegalArgumentException
- * If null is provided, or one of the embeds is too big
- *
- * @return The same reply action, for chaining convenience
- */
- @Nonnull
- @CheckReturnValue
- ReplyCallbackAction addEmbeds(@Nonnull Collection extends MessageEmbed> embeds);
-
- /**
- * Add a single {@link ActionRow} to the message.
- *
- * @param components
- * The components for this action row
- *
- * @throws IllegalArgumentException
- *
- * If null is provided, or more than 5 ItemComponents are provided
- * If any custom {@link ActionComponent#getId() id} is duplicated
- * If any of the provided ItemComponents are not compatible with messages
- *
- *
- * @return The same reply action, for chaining convenience
- *
- * @see ActionRow#of(ItemComponent...)
- * @see ItemComponent#isMessageCompatible()
- */
- @Nonnull
- @CheckReturnValue
- default ReplyCallbackAction addActionRow(@Nonnull ItemComponent... components)
- {
- return addActionRows(ActionRow.of(components));
- }
-
- /**
- * Add a single {@link ActionRow} to the message.
- *
- * @param components
- * The components for this action row
- *
- * @throws IllegalArgumentException
- *
- * If null is provided, or more than 5 ItemComponents are provided
- * If any custom {@link ActionComponent#getId() id} is duplicated
- * If any of the provided ItemComponents are not compatible with messages
- *
- *
- * @return The same reply action, for chaining convenience
- *
- * @see ActionRow#of(Collection)
- * @see ItemComponent#isMessageCompatible()
- */
- @Nonnull
- @CheckReturnValue
- default ReplyCallbackAction addActionRow(@Nonnull Collection extends ItemComponent> components)
- {
- return addActionRows(ActionRow.of(components));
- }
-
- /**
- * Add {@link ActionRow ActionRows} to the message.
- *
- * @param rows
- * The action rows to add
- *
- * @throws IllegalArgumentException
- *
- * If null is provided, or more than 5 action rows are provided
- * If any custom {@link ActionComponent#getId() id} is duplicated
- * If any of the provided action rows are not compatible with messages
- *
- *
- * @return The same reply action, for chaining convenience
- *
- * @see ActionRow#isMessageCompatible()
- */
- @Nonnull
- @CheckReturnValue
- default ReplyCallbackAction addActionRows(@Nonnull Collection extends ActionRow> rows)
- {
- Checks.noneNull(rows, "ActionRows");
- return addActionRows(rows.toArray(new ActionRow[0]));
- }
-
- /**
- * Add {@link ActionRow ActionRows} to the message.
- *
- * @param rows
- * The action rows to add
- *
- * @throws IllegalArgumentException
- *
- * If null is provided, or more than 5 action rows are provided
- * If any custom {@link ActionComponent#getId() id} is duplicated
- * If any of the provided action rows are not compatible with messages
- *
- *
- * @return The same reply action, for chaining convenience
- *
- * @see ActionRow#isMessageCompatible()
- */
- @Nonnull
- @CheckReturnValue
- ReplyCallbackAction addActionRows(@Nonnull ActionRow... rows);
-
- /**
- * Set the content for this message.
- *
- * @param content
- * The new message content or null to unset
- *
- * @throws IllegalArgumentException
- * If the provided content is longer than {@link net.dv8tion.jda.api.entities.Message#MAX_CONTENT_LENGTH MAX_CONTENT_LENGTH} characters
- *
- * @return The same reply action, for chaining convenience
- */
- @Nonnull
- ReplyCallbackAction setContent(@Nullable final String content);
-
- /**
- * Enable/Disable Text-To-Speech for the resulting message.
- *
- * @param isTTS
- * True, if this should cause a Text-To-Speech effect when sent to the channel
- *
- * @return The same reply action, for chaining convenience
- */
- @Nonnull
- ReplyCallbackAction setTTS(final boolean isTTS);
-
/**
* Set whether this message should be visible to other users.
* When a message is ephemeral, it will only be visible to the user that used the interaction.
@@ -232,121 +54,4 @@ default ReplyCallbackAction addActionRows(@Nonnull Collection extends ActionRo
@Nonnull
@CheckReturnValue
ReplyCallbackAction setEphemeral(boolean ephemeral);
-
-
- /**
- * Adds the provided {@link File}.
- * The stream will be closed upon execution!
- * The provided file will be appended to the message.
- *
- * @param file
- * The {@link File} data to upload in response to the interaction.
- * @param options
- * Possible options to apply to this attachment, such as marking it as spoiler image
- *
- * @throws java.lang.IllegalArgumentException
- * If the provided file is {@code null}.
- *
- * @return The same reply action, for chaining convenience
- */
- @Nonnull
- @CheckReturnValue
- default ReplyCallbackAction addFile(@Nonnull File file, @Nonnull AttachmentOption... options)
- {
- Checks.notNull(file, "File");
- return addFile(file, file.getName(), options);
- }
-
- /**
- * Adds the provided {@link File}.
- * The stream will be closed upon execution!
- * The provided file will be appended to the message.
- *
- * The {@code name} parameter is used to inform Discord about what the file should be called. This is 2 fold:
- *
- * The file name provided is the name that is found in {@link net.dv8tion.jda.api.entities.Message.Attachment#getFileName()}
- * after upload and it is the name that will show up in the client when the upload is displayed.
- * Note: The fileName does not show up on the Desktop client for images. It does on mobile however.
- * The extension of the provided fileName also determines how Discord will treat the file. Discord currently only
- * has special handling for image file types, but the fileName's extension must indicate that it is an image file.
- * This means it has to end in something like .png, .jpg, .jpeg, .gif, etc. As a note, you can also not provide
- * a full name for the file and instead ONLY provide the extension like "png" or "gif" and Discord will generate
- * a name for the upload and append the fileName as the extension.
- *
- *
- * @param file
- * The {@link File} data to upload in response to the interaction.
- * @param name
- * The file name that should be sent to discord
- * @param options
- * Possible options to apply to this attachment, such as marking it as spoiler image
- *
- * @throws java.lang.IllegalArgumentException
- * If the provided file or filename is {@code null}.
- *
- * @return The same reply action, for chaining convenience
- */
- @Nonnull
- @CheckReturnValue
- default ReplyCallbackAction addFile(@Nonnull File file, @Nonnull String name, @Nonnull AttachmentOption... options)
- {
- try
- {
- Checks.notNull(file, "File");
- Checks.check(file.exists() && file.canRead(), "Provided file either does not exist or cannot be read from!");
- return addFile(new FileInputStream(file), name, options);
- }
- catch (FileNotFoundException e)
- {
- throw new IllegalArgumentException(e);
- }
- }
-
- /**
- * Adds the provided {@code byte[]} as file data.
- * The stream will be closed upon execution!
- * The provided file will be appended to the message.
- *
- * @param data
- * The {@code byte[]} data to upload in response to the interaction.
- * @param name
- * The file name that should be sent to discord
- * Refer to the documentation for {@link #addFile(java.io.File, String, AttachmentOption...)} for information about this parameter.
- * @param options
- * Possible options to apply to this attachment, such as marking it as spoiler image
- *
- * @throws java.lang.IllegalArgumentException
- * If the provided data or filename is {@code null}.
- *
- * @return The same reply action, for chaining convenience
- */
- @Nonnull
- @CheckReturnValue
- default ReplyCallbackAction addFile(@Nonnull byte[] data, @Nonnull String name, @Nonnull AttachmentOption... options)
- {
- Checks.notNull(data, "Data");
- return addFile(new ByteArrayInputStream(data), name, options);
- }
-
- /**
- * Adds the provided {@link java.io.InputStream InputStream} as file data.
- * The stream will be closed upon execution!
- * The provided file will be appended to the message.
- *
- * @param data
- * The InputStream data to upload in response to the interaction.
- * @param name
- * The file name that should be sent to discord
- * Refer to the documentation for {@link #addFile(java.io.File, String, AttachmentOption...)} for information about this parameter.
- * @param options
- * Possible options to apply to this attachment, such as marking it as spoiler image
- *
- * @throws java.lang.IllegalArgumentException
- * If the provided data or filename is {@code null}.
- *
- * @return The same reply action, for chaining convenience
- */
- @Nonnull
- @CheckReturnValue
- ReplyCallbackAction addFile(@Nonnull InputStream data, @Nonnull String name, @Nonnull AttachmentOption... options);
}
diff --git a/src/main/java/net/dv8tion/jda/api/utils/AllowedMentions.java b/src/main/java/net/dv8tion/jda/api/utils/AllowedMentions.java
deleted file mode 100644
index 760fb8bbc0..0000000000
--- a/src/main/java/net/dv8tion/jda/api/utils/AllowedMentions.java
+++ /dev/null
@@ -1,298 +0,0 @@
-/*
- * 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.utils;
-
-import net.dv8tion.jda.api.entities.IMentionable;
-import net.dv8tion.jda.api.entities.Message;
-import net.dv8tion.jda.internal.utils.AllowedMentionsImpl;
-import net.dv8tion.jda.internal.utils.Checks;
-
-import javax.annotation.CheckReturnValue;
-import javax.annotation.Nonnull;
-import javax.annotation.Nullable;
-import java.util.Collection;
-import java.util.EnumSet;
-
-/**
- * Represents the operations used to whitelist/blacklist mentions.
- *
- * @param
- * The entity that implements this interface, used for fluid interface returns
- */
-public interface AllowedMentions
-{
- /**
- * Sets the {@link net.dv8tion.jda.api.entities.Message.MentionType MentionTypes} that should be parsed by default.
- * This just sets the default for all RestActions and can be overridden on a per-action basis using {@link #allowedMentions(Collection)}.
- * If a message is sent with an empty Set of MentionTypes, then it will not ping any User, Role or {@code @everyone}/{@code @here},
- * while still showing up as mention tag.
- *
- * If {@code null} is provided to this method, then all Types will be pingable
- * (unless whitelisting via one of the {@code mention*} methods is used).
- *
- *
Example
- *
{@code
- * // Disable EVERYONE and HERE mentions by default (to avoid mass ping)
- * EnumSet deny = EnumSet.of(Message.MentionType.EVERYONE, Message.MentionType.HERE);
- * AllowedMentions.setDefaultMentions(EnumSet.complementOf(deny));
- * }
- *
- * @param allowedMentions
- * MentionTypes that are allowed to being parsed and pinged. {@code null} to disable and allow all mentions.
- */
- static void setDefaultMentions(@Nullable Collection allowedMentions)
- {
- AllowedMentionsImpl.setDefaultMentions(allowedMentions);
- }
-
- /**
- * Returns the default {@link net.dv8tion.jda.api.entities.Message.MentionType MentionTypes} previously set by
- * {@link #setDefaultMentions(Collection) AllowedMentions.setDefaultMentions(Collection)}.
- *
- * @return Default mentions set by AllowedMentions.setDefaultMentions(Collection)
- */
- @Nonnull
- static EnumSet getDefaultMentions()
- {
- return AllowedMentionsImpl.getDefaultMentions();
- }
-
- /**
- * Sets the default value for {@link #mentionRepliedUser(boolean)}
- *
- * Default: true
- *
- * @param mention
- * True, if replies should mention by default
- */
- static void setDefaultMentionRepliedUser(boolean mention)
- {
- AllowedMentionsImpl.setDefaultMentionRepliedUser(mention);
- }
-
- /**
- * Returns the default mention behavior for replies.
- * If this is {@code true} then all replies will mention the author of the target message by default.
- * You can specify this individually with {@link #mentionRepliedUser(boolean)} for each message.
- *
- *
Default: true
- *
- * @return True, if replies mention by default
- */
- static boolean isDefaultMentionRepliedUser()
- {
- return AllowedMentionsImpl.isDefaultMentionRepliedUser();
- }
-
- /**
- * Whether to mention the used, when replying to a message.
- * This only matters in combination with {@link net.dv8tion.jda.api.requests.restaction.MessageAction#reference(Message)} and {@link net.dv8tion.jda.api.requests.restaction.MessageAction#referenceById(long)}!
- *
- *
This is true by default but can be configured using {@link #setDefaultMentionRepliedUser(boolean)}!
- *
- * @param mention
- * True, to mention the author if the referenced message
- *
- * @return Updated Action for chaining convenience
- */
- @Nonnull
- @CheckReturnValue
- R mentionRepliedUser(boolean mention);
-
- /**
- * Sets the {@link net.dv8tion.jda.api.entities.Message.MentionType MentionTypes} that should be parsed.
- * If a message is sent with an empty Set of MentionTypes, then it will not ping any User, Role or {@code @everyone}/{@code @here},
- * while still showing up as mention tag.
- *
- * If {@code null} is provided to this method, then all Types will be pingable
- * (unless whitelisting via one of the {@code mention*} methods is used).
- *
- * Note: A default for this can be set using {@link #setDefaultMentions(Collection) AllowedMentions.setDefaultMentions(Collection)}.
- *
- * @param allowedMentions
- * MentionTypes that are allowed to being parsed and pinged. {@code null} to disable and allow all mentions.
- *
- * @return Updated Action for chaining convenience
- */
- @Nonnull
- @CheckReturnValue
- R allowedMentions(@Nullable Collection allowedMentions);
-
- /**
- * Used to provide a whitelist for {@link net.dv8tion.jda.api.entities.User Users}, {@link net.dv8tion.jda.api.entities.Member Members}
- * and {@link net.dv8tion.jda.api.entities.Role Roles} that should be pinged,
- * even when they would not be pinged otherwise according to the Set of allowed mention types.
- * On other types of {@link net.dv8tion.jda.api.entities.IMentionable IMentionable}, this does nothing.
- *
- * Note: When a User/Member is whitelisted this way, then parsing of User mentions is automatically disabled (same applies to Roles).
- * Also note that whitelisting users or roles implicitly disables parsing of other mentions, if not otherwise set via
- * {@link #setDefaultMentions(Collection)} or {@link #allowedMentions(Collection)}.
- *
- * @param mentions
- * Users, Members and Roles that should be explicitly whitelisted to be pingable.
- *
- * @throws IllegalArgumentException
- * If null is provided
- *
- * @return Updated Action for chaining convenience
- *
- * @see #allowedMentions(Collection)
- * @see #setDefaultMentions(Collection)
- */
- @Nonnull
- @CheckReturnValue
- R mention(@Nonnull IMentionable... mentions);
-
- /**
- * Used to provide a whitelist for {@link net.dv8tion.jda.api.entities.User Users}, {@link net.dv8tion.jda.api.entities.Member Members}
- * and {@link net.dv8tion.jda.api.entities.Role Roles} that should be pinged,
- * even when they would not be pinged otherwise according to the Set of allowed mention types.
- * On other types of {@link net.dv8tion.jda.api.entities.IMentionable IMentionable}, this does nothing.
- *
- *
Note: When a User/Member is whitelisted this way, then parsing of User mentions is automatically disabled (same applies to Roles).
- * Also note that whitelisting users or roles implicitly disables parsing of other mentions, if not otherwise set via
- * {@link #setDefaultMentions(Collection)} or {@link #allowedMentions(Collection)}.
- *
- * @param mentions
- * Users, Members and Roles that should be explicitly whitelisted to be pingable.
- *
- * @throws IllegalArgumentException
- * If null is provided
- *
- * @return Updated Action for chaining convenience
- *
- * @see #allowedMentions(Collection)
- * @see #setDefaultMentions(Collection)
- */
- @Nonnull
- @CheckReturnValue
- default R mention(@Nonnull Collection extends IMentionable> mentions)
- {
- Checks.noneNull(mentions, "Mention");
- return mention(mentions.toArray(new IMentionable[0]));
- }
-
- /**
- * Used to provide a whitelist of {@link net.dv8tion.jda.api.entities.User Users} that should be pinged,
- * even when they would not be pinged otherwise according to the Set of allowed mention types.
- *
- *
Note: When a User is whitelisted this way, then parsing of User mentions is automatically disabled.
- * Also note that whitelisting users or roles implicitly disables parsing of other mentions, if not otherwise set via
- * {@link #setDefaultMentions(Collection)} or {@link #allowedMentions(Collection)}.
- *
- * @param userIds
- * Ids of Users that should be explicitly whitelisted to be pingable.
- *
- * @throws IllegalArgumentException
- * If null is provided
- *
- * @return Updated Action for chaining convenience
- *
- * @see #allowedMentions(Collection)
- * @see #setDefaultMentions(Collection)
- */
- @Nonnull
- @CheckReturnValue
- R mentionUsers(@Nonnull String... userIds);
-
- /**
- * Used to provide a whitelist of {@link net.dv8tion.jda.api.entities.User Users} that should be pinged,
- * even when they would not be pinged otherwise according to the Set of allowed mention types.
- *
- *
Note: When a User is whitelisted this way, then parsing of User mentions is automatically disabled.
- * Also note that whitelisting users or roles implicitly disables parsing of other mentions, if not otherwise set via
- * {@link #setDefaultMentions(Collection)} or {@link #allowedMentions(Collection)}.
- *
- * @param userIds
- * Ids of Users that should be explicitly whitelisted to be pingable.
- *
- * @throws IllegalArgumentException
- * If null is provided
- *
- * @return Updated Action for chaining convenience
- *
- * @see #allowedMentions(Collection)
- * @see #setDefaultMentions(Collection)
- */
- @Nonnull
- @CheckReturnValue
- default R mentionUsers(@Nonnull long... userIds)
- {
- Checks.notNull(userIds, "UserId array");
- String[] stringIds = new String[userIds.length];
- for (int i = 0; i < userIds.length; i++)
- {
- stringIds[i] = Long.toUnsignedString(userIds[i]);
- }
- return mentionUsers(stringIds);
- }
-
- /**
- * Used to provide a whitelist of {@link net.dv8tion.jda.api.entities.Role Roles} that should be pinged,
- * even when they would not be pinged otherwise according to the Set of allowed mention types.
- *
- *
Note: When a Role is whitelisted this way, then parsing of Role mentions is automatically disabled.
- * Also note that whitelisting users or roles implicitly disables parsing of other mentions, if not otherwise set via
- * {@link #setDefaultMentions(Collection)} or {@link #allowedMentions(Collection)}.
- *
- * @param roleIds
- * Ids of Roles that should be explicitly whitelisted to be pingable.
- *
- * @throws IllegalArgumentException
- * If null is provided
- *
- * @return Updated Action for chaining convenience
- *
- * @see #allowedMentions(Collection)
- * @see #setDefaultMentions(Collection)
- */
- @Nonnull
- @CheckReturnValue
- R mentionRoles(@Nonnull String... roleIds);
-
- /**
- * Used to provide a whitelist of {@link net.dv8tion.jda.api.entities.Role Roles} that should be pinged,
- * even when they would not be pinged otherwise according to the Set of allowed mention types.
- *
- *
Note: When a Role is whitelisted this way, then parsing of Role mentions is automatically disabled.
- * Also note that whitelisting users or roles implicitly disables parsing of other mentions, if not otherwise set via
- * {@link #setDefaultMentions(Collection)} or {@link #allowedMentions(Collection)}.
- *
- * @param roleIds
- * Ids of Roles that should be explicitly whitelisted to be pingable.
- *
- * @throws IllegalArgumentException
- * If null is provided
- *
- * @return Updated Action for chaining convenience
- *
- * @see #allowedMentions(Collection)
- * @see #setDefaultMentions(Collection)
- */
- @Nonnull
- @CheckReturnValue
- default R mentionRoles(@Nonnull long... roleIds)
- {
- Checks.notNull(roleIds, "RoleId array");
- String[] stringIds = new String[roleIds.length];
- for (int i = 0; i < roleIds.length; i++)
- {
- stringIds[i] = Long.toUnsignedString(roleIds[i]);
- }
- return mentionRoles(stringIds);
- }
-}
diff --git a/src/main/java/net/dv8tion/jda/api/utils/AttachedFile.java b/src/main/java/net/dv8tion/jda/api/utils/AttachedFile.java
index 945412b278..3ff26d0f8f 100644
--- a/src/main/java/net/dv8tion/jda/api/utils/AttachedFile.java
+++ b/src/main/java/net/dv8tion/jda/api/utils/AttachedFile.java
@@ -17,9 +17,10 @@
package net.dv8tion.jda.api.utils;
import net.dv8tion.jda.api.entities.Message;
-import net.dv8tion.jda.api.utils.data.DataArray;
import net.dv8tion.jda.api.utils.data.DataObject;
+import net.dv8tion.jda.internal.requests.Requester;
import okhttp3.MultipartBody;
+import okhttp3.RequestBody;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
@@ -34,6 +35,11 @@
*/
public interface AttachedFile extends Closeable
{
+ /**
+ * The maximum length a {@link FileUpload#setDescription(String) description} can be ({@value}).
+ */
+ int MAX_DESCRIPTION_LENGTH = 1024;
+
/**
* Create a new {@link FileUpload} for an input stream.
* This is used to upload data to discord for various purposes.
@@ -260,12 +266,28 @@ static AttachmentUpdate fromAttachment(@Nonnull Message.Attachment attachment)
/**
* Build a complete request using the provided files and payload data.
- * If the provided {@code payloadJson} is null, the multipart request will not set {@code attachments}.
+ *
+ * @param files
+ * The files to upload/edit
+ *
+ * @throws IllegalArgumentException
+ * If the file list is null
+ *
+ * @return {@link MultipartBody.Builder}
+ */
+ @Nonnull
+ static MultipartBody.Builder createMultipartBody(@Nonnull List extends AttachedFile> files)
+ {
+ return createMultipartBody(files, (RequestBody) null);
+ }
+
+ /**
+ * Build a complete request using the provided files and payload data.
*
* @param files
* The files to upload/edit
* @param payloadJson
- * The payload data to send, excluding {@code attachments} field
+ * The payload data to send, null to not add a payload_json part
*
* @throws IllegalArgumentException
* If the file list is null
@@ -274,20 +296,44 @@ static AttachmentUpdate fromAttachment(@Nonnull Message.Attachment attachment)
*/
@Nonnull
static MultipartBody.Builder createMultipartBody(@Nonnull List extends AttachedFile> files, @Nullable DataObject payloadJson)
+ {
+ RequestBody body = payloadJson != null ? RequestBody.create(payloadJson.toJson(), Requester.MEDIA_TYPE_JSON) : null;
+ return createMultipartBody(files, body);
+ }
+
+ /**
+ * Build a complete request using the provided files and payload data.
+ *
+ * @param files
+ * The files to upload/edit
+ * @param payloadJson
+ * The payload data to send, null to not add a payload_json part
+ *
+ * @throws IllegalArgumentException
+ * If the file list is null
+ *
+ * @return {@link MultipartBody.Builder}
+ */
+ @Nonnull
+ static MultipartBody.Builder createMultipartBody(@Nonnull List extends AttachedFile> files, @Nullable RequestBody payloadJson)
{
MultipartBody.Builder builder = new MultipartBody.Builder().setType(MultipartBody.FORM);
- DataArray descriptors = DataArray.empty();
for (int i = 0; i < files.size(); i++)
{
AttachedFile file = files.get(i);
file.addPart(builder, i);
- descriptors.add(file.toAttachmentData(i));
}
- if (payloadJson == null)
- return builder;
- payloadJson.put("attachments", descriptors);
- builder.addFormDataPart("payload_json", payloadJson.toString());
+ if (payloadJson != null)
+ builder.addFormDataPart("payload_json", null, payloadJson);
return builder;
}
+
+ /**
+ * Forces the underlying resource to be closed, even if the file is already handled by a request.
+ *
+ * @throws IOException
+ * If an IOException is thrown while closing the resource
+ */
+ void forceClose() throws IOException;
}
diff --git a/src/main/java/net/dv8tion/jda/api/utils/AttachmentOption.java b/src/main/java/net/dv8tion/jda/api/utils/AttachmentOption.java
deleted file mode 100644
index b80ef378b2..0000000000
--- a/src/main/java/net/dv8tion/jda/api/utils/AttachmentOption.java
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * 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.utils;
-
-/**
- * Options that can be applied to attachments in {@link net.dv8tion.jda.api.requests.restaction.MessageAction}.
- */
-public enum AttachmentOption
-{
- /** Marks an image attachment as a spoiler by prefixing the name with {@code SPOILER_} */
- SPOILER
-}
diff --git a/src/main/java/net/dv8tion/jda/api/utils/AttachmentUpdate.java b/src/main/java/net/dv8tion/jda/api/utils/AttachmentUpdate.java
index eb95edfa65..b405fcc4da 100644
--- a/src/main/java/net/dv8tion/jda/api/utils/AttachmentUpdate.java
+++ b/src/main/java/net/dv8tion/jda/api/utils/AttachmentUpdate.java
@@ -122,6 +122,9 @@ public DataObject toAttachmentData(int index)
@Override
public void close() {}
+ @Override
+ public void forceClose() {}
+
@Override
public String toString()
{
diff --git a/src/main/java/net/dv8tion/jda/api/utils/FileUpload.java b/src/main/java/net/dv8tion/jda/api/utils/FileUpload.java
index 9b434a5317..d87963f7af 100644
--- a/src/main/java/net/dv8tion/jda/api/utils/FileUpload.java
+++ b/src/main/java/net/dv8tion/jda/api/utils/FileUpload.java
@@ -26,6 +26,7 @@
import okhttp3.RequestBody;
import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
import java.io.*;
import java.nio.file.Files;
import java.nio.file.OpenOption;
@@ -41,8 +42,9 @@
public class FileUpload implements Closeable, AttachedFile
{
private final InputStream resource;
- private final String name;
+ private String name;
private BufferedRequestBody body;
+ private String description;
protected FileUpload(InputStream resource, String name)
{
@@ -234,6 +236,59 @@ public static FileUpload fromData(@Nonnull Path path, @Nonnull OpenOption... opt
return fromData(path, fileName.toString(), options);
}
+ /**
+ * Changes the name of this file, to be prefixed as {@code SPOILER_}.
+ * This will cause the file to be rendered as a spoiler attachment in the client.
+ *
+ * @return The updated FileUpload instance
+ */
+ @Nonnull
+ public FileUpload asSpoiler()
+ {
+ if (name.startsWith("SPOILER_"))
+ return this;
+ return setName("SPOILER_" + name);
+ }
+
+ /**
+ * Changes the name of this file.
+ *
+ * @param name
+ * The new filename
+ *
+ * @throws IllegalArgumentException
+ * If the name is null, blank, or empty
+ *
+ * @return The updated FileUpload instance
+ */
+ @Nonnull
+ public FileUpload setName(@Nonnull String name)
+ {
+ Checks.notBlank(name, "Name");
+ this.name = name;
+ return this;
+ }
+
+ /**
+ * Set the file description used as ALT text for screenreaders.
+ *
+ * @param description
+ * The alt text describing this file attachment (up to {@value MAX_DESCRIPTION_LENGTH} characters)
+ *
+ * @throws IllegalArgumentException
+ * If the description is longer than {@value MAX_DESCRIPTION_LENGTH} characters
+ *
+ * @return The same FileUpload instance with the new description
+ */
+ @Nonnull
+ public FileUpload setDescription(@Nullable String description)
+ {
+ if (description != null)
+ Checks.notLonger(description = description.trim(), MAX_DESCRIPTION_LENGTH, "Description");
+ this.description = description;
+ return this;
+ }
+
/**
* The filename for the file.
*
@@ -292,11 +347,19 @@ public DataObject toAttachmentData(int index)
{
return DataObject.empty()
.put("id", index)
+ .put("description", description == null ? "" : description)
.put("filename", name);
}
@Override
- public void close() throws IOException
+ public synchronized void close() throws IOException
+ {
+ if (body == null)
+ forceClose();
+ }
+
+ @Override
+ public void forceClose() throws IOException
{
if (resource != null)
resource.close();
diff --git a/src/main/java/net/dv8tion/jda/api/utils/SplitUtil.java b/src/main/java/net/dv8tion/jda/api/utils/SplitUtil.java
new file mode 100644
index 0000000000..19b4f37922
--- /dev/null
+++ b/src/main/java/net/dv8tion/jda/api/utils/SplitUtil.java
@@ -0,0 +1,268 @@
+/*
+ * 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.utils;
+
+import net.dv8tion.jda.internal.utils.Checks;
+
+import javax.annotation.Nonnull;
+import java.util.Collections;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.function.Predicate;
+
+/**
+ * Utility to strategically split strings.
+ *
+ *
Example
+ *
+ *
{@code
+ * // Given some arbitrary input string
+ * String input = "Hello World";
+ *
+ * // Try to best-effort split based on the strategy,
+ * // in this case by spaces even if the partial string is not close to the limit
+ *
+ * // ["Hello", "World"]
+ * SplitUtil.split(input, 8, true, Strategy.SPACE);
+ *
+ * // Cases where the string can fit within the limit, will result in no splitting
+ *
+ * // ["Hello World"]
+ * SplitUtil.split(input, 50, true, Strategy.SPACE);
+ * }
+ *
+ * In a more applied use-case, you can also define a smaller limit so it can fit into codeblocks of a message:
+ *
+ *
{@code
+ * public List getRoleNames(Guild guild)
+ * {
+ * // Create a newline separated list of role names from the guild
+ * String roleNames = guild.getRoleCache().applyStream(stream ->
+ * stream.map(Role::getName)
+ * .collect(Collectors.joining("\n"))
+ * );
+ *
+ * // Split the role names into a list of strings each small enough to fit into a message codeblock
+ * // A message can be 2000 characters long, do the math (2000 - 7 = 1993 characters) but to be safe go a little lower
+ * List blocks = SplitUtil.split(roleNames, 1990, true, Strategy.NEWLINE, Strategy.ANYWHERE);
+ *
+ * // Then wrap each of these blocks into a codeblock for sending
+ * return blocks.stream()
+ * .map(block -> "```\n" + block + "```")
+ * .collect(Collectors.toList());
+ * }
+ * }
+ *
+ * @see #split(String, int, Strategy...)
+ * @see #split(String, int, boolean, Strategy...)
+ */
+public class SplitUtil
+{
+ /**
+ * Apply a list of {@link Strategy Strategies} to split the provided string into chunks of a maximum {@code limit} characters.
+ * The substring chunks will not be trimmed of whitespace, you can use {@link #split(String, int, boolean, Strategy...)} to trim them.
+ *
+ * If no strategies are provided, ie. {@code split(string, limit, true)}, then it only uses the limit to split with {@link Strategy#ANYWHERE}.
+ *
+ *
Strategies are applied in order, each trying to split with different criteria.
+ * When a strategy fails, the next in the list is tried until all strategies are exhausted.
+ * If not a single strategy can split the string, an {@link IllegalStateException} is thrown.
+ *
+ * @param input
+ * The input string to split up
+ * @param limit
+ * The maximum string length for each chunk
+ * @param strategies
+ * The split strategies
+ *
+ * @throws IllegalStateException
+ * If none of the strategies successfully split the string.
+ * You can use {@link Strategy#ANYWHERE} to always split at the limit and avoid this exception.
+ *
+ * @return {@link List} of each substring which is at most {@code limit} characters long
+ *
+ * @see Strategy#ANYWHERE
+ * @see Strategy#NEWLINE
+ * @see Strategy#WHITESPACE
+ */
+ @Nonnull
+ public static List split(@Nonnull String input, int limit, @Nonnull Strategy... strategies)
+ {
+ return split(input, limit, false, strategies);
+ }
+
+ /**
+ * Apply a list of {@link Strategy Strategies} to split the provided string into chunks of a maximum {@code limit} characters.
+ *
+ * If no strategies are provided, ie. {@code split(string, limit, true)}, then it only uses the limit to split with {@link Strategy#ANYWHERE}.
+ *
+ *
Strategies are applied in order, each trying to split with different criteria.
+ * When a strategy fails, the next in the list is tried until all strategies are exhausted.
+ * If not a single strategy can split the string, an {@link IllegalStateException} is thrown.
+ *
+ * @param input
+ * The input string to split up
+ * @param limit
+ * The maximum string length for each chunk
+ * @param trim
+ * Whether to trim the chunks after splitting (See {@link String#trim()})
+ * @param strategies
+ * The split strategies
+ *
+ * @throws IllegalStateException
+ * If none of the strategies successfully split the string.
+ * You can use {@link Strategy#ANYWHERE} to always split at the limit and avoid this exception.
+ *
+ * @return {@link List} of each substring which is at most {@code limit} characters long
+ *
+ * @see Strategy#ANYWHERE
+ * @see Strategy#NEWLINE
+ * @see Strategy#WHITESPACE
+ */
+ @Nonnull
+ public static List split(@Nonnull String input, int limit, boolean trim, @Nonnull Strategy... strategies)
+ {
+ Checks.notNull(input, "Input string");
+ if (input.isEmpty() || input.length() <= limit)
+ return Collections.singletonList(input);
+ if (strategies.length == 0)
+ strategies = new Strategy[] { Strategy.ANYWHERE };
+ int offset = 0;
+ List chunks = new LinkedList<>();
+
+ while (offset < input.length())
+ {
+ String chunk = null;
+
+ if (input.length() - offset <= limit)
+ {
+ chunk = input.substring(offset);
+ offset = input.length();
+ }
+ else
+ {
+ for (Strategy strategy : strategies)
+ {
+ int newOffset = strategy.apply(input, offset, limit);
+ if (newOffset > offset)
+ {
+ newOffset = Math.min(newOffset, input.length());
+ chunk = input.substring(offset, newOffset);
+ offset = newOffset;
+ break;
+ }
+ }
+ }
+
+ if (chunk == null)
+ throw new IllegalStateException("None of the strategies successfully split the string. Try adding Strategy.ANYWHERE to the end of your strategy list.");
+ if (trim)
+ chunk = chunk.trim();
+ if (chunk.isEmpty())
+ continue;
+ chunks.add(chunk);
+ }
+
+ return chunks;
+ }
+
+ /**
+ * Function which applies a programmable strategy used to determine a splitting point.
+ *
+ * @see #ANYWHERE
+ * @see #NEWLINE
+ * @see #WHITESPACE
+ */
+ public interface Strategy
+ {
+ /**
+ * Implements a splitting strategy.
+ *
+ * The goal of a strategy is to implement a greedy algorithm to find the optimal point to split the string.
+ * Ideally, this should be close to the {@code limit}.
+ *
+ *
This should not return an offset larger than {@code limit}.
+ * Any offset lower than the input offset, is interpreted as unsuccessful.
+ *
+ * @param string
+ * The input string
+ * @param offset
+ * The current offset where to start your substring
+ * @param limit
+ * The maximum length your substring should be
+ *
+ * @return The exclusive end index of your chunk, negative to indicate failure. (should be in range of {@code offset < x <= limit}).
+ */
+ int apply(@Nonnull String string, int offset, int limit);
+
+ /**
+ * Strategy which splits at any character to satisfy the limit.
+ * This is the default strategy if none is provided, and should ideally only be the final one in your list.
+ */
+ Strategy ANYWHERE = (string, offset, limit) -> offset + limit;
+ /**
+ * Splits on newline characters. Specifically on {@code '\n'}.
+ */
+ Strategy NEWLINE = onChar('\n');
+ /**
+ * Splits on every character which is considered {@link Character#isWhitespace(char) whitespace}.
+ */
+ Strategy WHITESPACE = onChar(Character::isWhitespace);
+
+ /**
+ * Strategy to split on the provided character.
+ *
+ *
An example use-case would be to define places via {@code '\0'} and then splitting exactly on those.
+ *
+ * @param c
+ * The splitting character
+ *
+ * @return The strategy to split on that character
+ */
+ @Nonnull
+ static Strategy onChar(char c)
+ {
+ return (string, offset, limit) -> string.lastIndexOf(c, offset + limit);
+ }
+
+ /**
+ * Strategy to split on the provided character tests.
+ *
+ * @param predicate
+ * The splitting character test
+ *
+ * @throws IllegalArgumentException
+ * If the predicate is null
+ *
+ * @return The strategy to split on characters that pass the test
+ */
+ @Nonnull
+ static Strategy onChar(@Nonnull Predicate predicate)
+ {
+ Checks.notNull(predicate, "Predicate");
+ return (string, offset, limit) ->
+ {
+ for (int i = offset + limit; i > offset; i--)
+ {
+ if (predicate.test(string.charAt(i)))
+ return i;
+ }
+ return -1;
+ };
+ }
+ }
+}
diff --git a/src/main/java/net/dv8tion/jda/api/utils/messages/AbstractMessageBuilder.java b/src/main/java/net/dv8tion/jda/api/utils/messages/AbstractMessageBuilder.java
new file mode 100644
index 0000000000..c7e0a93bfa
--- /dev/null
+++ b/src/main/java/net/dv8tion/jda/api/utils/messages/AbstractMessageBuilder.java
@@ -0,0 +1,271 @@
+/*
+ * 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.utils.messages;
+
+import net.dv8tion.jda.api.entities.IMentionable;
+import net.dv8tion.jda.api.entities.Message;
+import net.dv8tion.jda.api.entities.MessageEmbed;
+import net.dv8tion.jda.api.interactions.components.LayoutComponent;
+import net.dv8tion.jda.api.utils.AttachedFile;
+import net.dv8tion.jda.internal.utils.Checks;
+
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+import java.util.*;
+
+/**
+ * Abstract builder implementation of {@link MessageRequest}.
+ *
+ * This builder cannot be instantiated directly. You should use {@link MessageCreateBuilder} or {@link MessageEditBuilder} instead.
+ *
+ * @param
+ * The result type used for {@link #build()}
+ * @param
+ * The return type used for method chaining
+ *
+ * @see MessageCreateBuilder
+ * @see MessageEditBuilder
+ */
+@SuppressWarnings("unchecked")
+public abstract class AbstractMessageBuilder> implements MessageRequest
+{
+ protected final List embeds = new ArrayList<>(Message.MAX_EMBED_COUNT);
+ protected final List components = new ArrayList<>(Message.MAX_COMPONENT_COUNT);
+ protected final StringBuilder content = new StringBuilder(Message.MAX_CONTENT_LENGTH);
+ protected AllowedMentionsData mentions = new AllowedMentionsData();
+ protected int messageFlags;
+
+ protected AbstractMessageBuilder() {}
+
+ @Nonnull
+ @Override
+ public R setContent(@Nullable String content)
+ {
+ if (content != null)
+ {
+ content = content.trim();
+ Checks.notLonger(content, Message.MAX_CONTENT_LENGTH, "Content");
+ this.content.setLength(0);
+ this.content.append(content);
+ }
+ else
+ {
+ this.content.setLength(0);
+ }
+ return (R) this;
+ }
+
+ @Nonnull
+ @Override
+ public String getContent()
+ {
+ return content.toString();
+ }
+
+ @Nonnull
+ @Override
+ public R mentionRepliedUser(boolean mention)
+ {
+ mentions.mentionRepliedUser(mention);
+ return (R) this;
+ }
+
+ @Nonnull
+ @Override
+ public R setAllowedMentions(@Nullable Collection allowedMentions)
+ {
+ mentions.setAllowedMentions(allowedMentions);
+ return (R) this;
+ }
+
+ @Nonnull
+ @Override
+ public R mention(@Nonnull Collection extends IMentionable> mentions)
+ {
+ this.mentions.mention(mentions);
+ return (R) this;
+ }
+
+ @Nonnull
+ @Override
+ public R mentionUsers(@Nonnull Collection userIds)
+ {
+ this.mentions.mentionUsers(userIds);
+ return (R) this;
+ }
+
+ @Nonnull
+ @Override
+ public R mentionRoles(@Nonnull Collection roleIds)
+ {
+ this.mentions.mentionRoles(roleIds);
+ return (R) this;
+ }
+
+ @Nonnull
+ @Override
+ public Set getMentionedUsers()
+ {
+ return mentions.getMentionedUsers();
+ }
+
+ @Nonnull
+ @Override
+ public Set getMentionedRoles()
+ {
+ return mentions.getMentionedRoles();
+ }
+
+ @Nonnull
+ @Override
+ public EnumSet