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 4415188bae..9a5cd204b0 100644 --- a/src/main/java/net/dv8tion/jda/api/entities/Message.java +++ b/src/main/java/net/dv8tion/jda/api/entities/Message.java @@ -1615,8 +1615,11 @@ default MessageAction reply(@Nonnull byte[] data, @Nonnull String name, @Nonnull * does not have {@link net.dv8tion.jda.api.Permission#MESSAGE_MANAGE Permission.MESSAGE_MANAGE} in * the channel. * @throws java.lang.IllegalStateException - * If this Message was not sent by the currently logged in account and it was not sent in a - * {@link net.dv8tion.jda.api.entities.TextChannel TextChannel}. + * * * @return {@link net.dv8tion.jda.api.requests.restaction.AuditableRestAction AuditableRestAction} * @@ -1680,6 +1683,8 @@ default MessageAction reply(@Nonnull byte[] data, @Nonnull String name, @Nonnull *
  • Missing {@link net.dv8tion.jda.api.Permission#MESSAGE_MANAGE Permission.MESSAGE_MANAGE}. *
    Required to actually pin the Message.
  • * + * @throws IllegalStateException + * If this Message is ephemeral * * @return {@link net.dv8tion.jda.api.requests.RestAction RestAction} - Type: {@link java.lang.Void} */ @@ -1719,6 +1724,8 @@ default MessageAction reply(@Nonnull byte[] data, @Nonnull String name, @Nonnull *
  • Missing {@link net.dv8tion.jda.api.Permission#MESSAGE_MANAGE Permission.MESSAGE_MANAGE}. *
    Required to actually pin the Message.
  • * + * @throws IllegalStateException + * If this Message is ephemeral * * @return {@link net.dv8tion.jda.api.requests.RestAction RestAction} - Type: {@link java.lang.Void} */ @@ -1781,6 +1788,8 @@ default MessageAction reply(@Nonnull byte[] data, @Nonnull String name, @Nonnull *
  • If the provided {@link net.dv8tion.jda.api.entities.Emote Emote} cannot be used in the current channel. * See {@link Emote#canInteract(User, MessageChannel)} or {@link Emote#canInteract(Member)} for more information.
  • * + * @throws IllegalStateException + * If this message is ephemeral * * @return {@link net.dv8tion.jda.api.requests.RestAction RestAction} - Type: {@link java.lang.Void} */ @@ -1850,6 +1859,8 @@ default MessageAction reply(@Nonnull byte[] data, @Nonnull String name, @Nonnull * * @throws java.lang.IllegalArgumentException * If the provided unicode emoji is null or empty. + * @throws IllegalStateException + * If this Message is ephemeral * * @return {@link net.dv8tion.jda.api.requests.RestAction RestAction} - Type: {@link java.lang.Void} */ @@ -1888,8 +1899,11 @@ default MessageAction reply(@Nonnull byte[] data, @Nonnull String name, @Nonnull * and the currently logged in account does not have {@link net.dv8tion.jda.api.Permission#MESSAGE_MANAGE Permission.MESSAGE_MANAGE} * in the channel. * @throws java.lang.IllegalStateException - * If this message was not sent in a - * {@link net.dv8tion.jda.api.entities.Guild Guild}. + * + * * * @return {@link net.dv8tion.jda.api.requests.RestAction RestAction} - Type: {@link java.lang.Void} */ @@ -1937,8 +1951,11 @@ default MessageAction reply(@Nonnull byte[] data, @Nonnull String name, @Nonnull * @throws IllegalArgumentException * If provided with null * @throws java.lang.IllegalStateException - * If this message was not sent in a - * {@link net.dv8tion.jda.api.entities.Guild Guild}. + * + * * * @return {@link RestAction} * @@ -1976,8 +1993,10 @@ default MessageAction reply(@Nonnull byte[] data, @Nonnull String name, @Nonnull * @throws IllegalArgumentException * If provided with null * @throws java.lang.IllegalStateException - * If this message was not sent in a - * {@link net.dv8tion.jda.api.entities.Guild Guild}. + * * * @return {@link RestAction} * @@ -2027,6 +2046,8 @@ default MessageAction reply(@Nonnull byte[] data, @Nonnull String name, @Nonnull *
  • If the provided {@link net.dv8tion.jda.api.entities.Emote Emote} cannot be used in the current channel. * See {@link Emote#canInteract(User, MessageChannel)} or {@link Emote#canInteract(Member)} for more information.
  • * + * @throws IllegalStateException + * If this is an ephemeral message * * @return {@link net.dv8tion.jda.api.requests.RestAction RestAction} - Type: {@link java.lang.Void} * @@ -2086,9 +2107,13 @@ default MessageAction reply(@Nonnull byte[] data, @Nonnull String name, @Nonnull *
  • If the provided user is null
  • * * @throws java.lang.IllegalStateException - * If this message was not sent in a + * + * * * @return {@link net.dv8tion.jda.api.requests.RestAction RestAction} - Type: {@link java.lang.Void} * @@ -2146,6 +2171,8 @@ default MessageAction reply(@Nonnull byte[] data, @Nonnull String name, @Nonnull * and the logged in account does not have {@link net.dv8tion.jda.api.Permission#MESSAGE_HISTORY Permission.MESSAGE_HISTORY} * @throws java.lang.IllegalArgumentException * If the provided unicode emoji is null or empty. + * @throws IllegalStateException + * If this is an ephemeral message * * @return {@link net.dv8tion.jda.api.requests.RestAction RestAction} - Type: {@link java.lang.Void} * @@ -2206,9 +2233,14 @@ default MessageAction reply(@Nonnull byte[] data, @Nonnull String name, @Nonnull * @throws java.lang.IllegalArgumentException * If the provided unicode emoji is null or empty or if the provided user is null. * @throws java.lang.IllegalStateException - * If this message was not sent in a - * {@link net.dv8tion.jda.api.entities.Guild Guild} - * and the given user is not the {@link net.dv8tion.jda.api.entities.SelfUser SelfUser}. + * If this message: + * + * * * @return {@link net.dv8tion.jda.api.requests.RestAction RestAction} - Type: {@link java.lang.Void} * @@ -2250,7 +2282,8 @@ default MessageAction reply(@Nonnull byte[] data, @Nonnull String name, @Nonnull * logged in account does not have {@link net.dv8tion.jda.api.Permission#MESSAGE_HISTORY Permission.MESSAGE_HISTORY} in the channel. * @throws java.lang.IllegalArgumentException * If the provided {@link net.dv8tion.jda.api.entities.Emote Emote} is null. - * + * @throws IllegalStateException + * If this Message is ephemeral * @return The {@link net.dv8tion.jda.api.requests.restaction.pagination.ReactionPaginationAction ReactionPaginationAction} of the emote's users. * * @since 4.1.0 @@ -2293,7 +2326,8 @@ default MessageAction reply(@Nonnull byte[] data, @Nonnull String name, @Nonnull * logged in account does not have {@link net.dv8tion.jda.api.Permission#MESSAGE_HISTORY Permission.MESSAGE_HISTORY} in the channel. * @throws java.lang.IllegalArgumentException * If the provided unicode emoji is null or empty. - * + * @throws IllegalStateException + * If this Message is ephemeral * @return The {@link net.dv8tion.jda.api.requests.restaction.pagination.ReactionPaginationAction ReactionPaginationAction} of the emoji's users. * * @since 4.1.0 @@ -2403,6 +2437,8 @@ default MessageAction reply(@Nonnull byte[] data, @Nonnull String name, @Nonnull * @throws net.dv8tion.jda.api.exceptions.PermissionException * If the MessageChannel this message was sent in was a {@link net.dv8tion.jda.api.entities.PrivateChannel PrivateChannel} * and the message was not sent by the currently logged in account. + * @throws IllegalStateException + * If this Message is ephemeral * @return {@link net.dv8tion.jda.api.requests.restaction.AuditableRestAction AuditableRestAction} - Type: {@link java.lang.Void} * @see #isSuppressedEmbeds() */ @@ -2438,7 +2474,10 @@ default MessageAction reply(@Nonnull byte[] data, @Nonnull String name, @Nonnull * @throws java.lang.UnsupportedOperationException * If this is a system message * @throws IllegalStateException - * If the channel is not a text or news channel. See {@link TextChannel#isNews()}. + * * @throws net.dv8tion.jda.api.exceptions.InsufficientPermissionException * If the currently logged in account does not have * {@link net.dv8tion.jda.api.Permission#VIEW_CHANNEL Permission.VIEW_CHANNEL} in this channel @@ -2476,6 +2515,27 @@ default MessageAction reply(@Nonnull byte[] data, @Nonnull String name, @Nonnull @Nonnull EnumSet getFlags(); + /** + * Returns the raw message flags of this message + * + * @throws java.lang.UnsupportedOperationException + * If this is a system message + * @return The raw message flags + * @see #getFlags() + */ + long getFlagsRaw(); + + /** + * Whether this message is ephemeral. + *
    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 system message + * @return Whether the message is ephemeral + */ + boolean isEphemeral(); + /** * This specifies the {@link net.dv8tion.jda.api.entities.MessageType MessageType} of this Message. * @@ -2583,7 +2643,16 @@ enum MessageFlag /** * Indicates, that this Message came from the urgent message system */ - URGENT(4); + URGENT(4), + /** + * Indicates, that this Message is ephemeral, the Message is only visible to the bot and the interacting user + * @see Message#isEphemeral + */ + EPHEMERAL(6), + /** + * Indicates, that this Message is an interaction response and the bot is "thinking" + */ + LOADING(7); private final int value; diff --git a/src/main/java/net/dv8tion/jda/api/events/interaction/GenericComponentInteractionCreateEvent.java b/src/main/java/net/dv8tion/jda/api/events/interaction/GenericComponentInteractionCreateEvent.java index db2e5d8d38..0e6f66a449 100644 --- a/src/main/java/net/dv8tion/jda/api/events/interaction/GenericComponentInteractionCreateEvent.java +++ b/src/main/java/net/dv8tion/jda/api/events/interaction/GenericComponentInteractionCreateEvent.java @@ -72,7 +72,7 @@ public Component getComponent() return interaction.getComponent(); } - @Nullable + @Nonnull @Override public Message getMessage() { diff --git a/src/main/java/net/dv8tion/jda/api/interactions/components/ButtonInteraction.java b/src/main/java/net/dv8tion/jda/api/interactions/components/ButtonInteraction.java index 4e626fcfc4..30914ee9c0 100644 --- a/src/main/java/net/dv8tion/jda/api/interactions/components/ButtonInteraction.java +++ b/src/main/java/net/dv8tion/jda/api/interactions/components/ButtonInteraction.java @@ -53,7 +53,6 @@ default Button getComponent() /** * Update the button with a new button instance. - *
    This only works for non-ephemeral messages where {@link #getMessage()} is available! * *

    If this interaction is already acknowledged this will use {@link #getHook()} * and otherwise {@link #editComponents(Collection)} directly to acknowledge the interaction. @@ -71,8 +70,6 @@ default Button getComponent() default RestAction editButton(@Nullable Button newButton) { Message message = getMessage(); - if (message == null) - throw new IllegalStateException("Cannot update button for ephemeral messages! Discord does not provide enough information to perform the update."); List components = new ArrayList<>(message.getActionRows()); ComponentLayout.updateComponent(components, getComponentId(), newButton); diff --git a/src/main/java/net/dv8tion/jda/api/interactions/components/ComponentInteraction.java b/src/main/java/net/dv8tion/jda/api/interactions/components/ComponentInteraction.java index d1ed44b33c..97271642f5 100644 --- a/src/main/java/net/dv8tion/jda/api/interactions/components/ComponentInteraction.java +++ b/src/main/java/net/dv8tion/jda/api/interactions/components/ComponentInteraction.java @@ -62,11 +62,10 @@ public interface ComponentInteraction extends Interaction /** * The {@link Message} instance. - *
    This is null on interactions for ephemeral messages. * - * @return The {@link Message}, or null if this message is ephemeral + * @return The {@link Message} */ - @Nullable + @Nonnull Message getMessage(); /** diff --git a/src/main/java/net/dv8tion/jda/api/interactions/components/selections/SelectionMenuInteraction.java b/src/main/java/net/dv8tion/jda/api/interactions/components/selections/SelectionMenuInteraction.java index 04535a8940..ab0005e9e5 100644 --- a/src/main/java/net/dv8tion/jda/api/interactions/components/selections/SelectionMenuInteraction.java +++ b/src/main/java/net/dv8tion/jda/api/interactions/components/selections/SelectionMenuInteraction.java @@ -85,7 +85,6 @@ default List getSelectedOptions() /** * Update the selection menu with a new selection menu instance. - *
    This only works for non-ephemeral messages where {@link #getMessage()} is available! * *

    If this interaction is already acknowledged this will use {@link #getHook()} * and otherwise {@link #editComponents(Collection)} directly to acknowledge the interaction. @@ -106,8 +105,6 @@ default List getSelectedOptions() default RestAction editSelectionMenu(@Nullable SelectionMenu newMenu) { Message message = getMessage(); - if (message == null) - throw new IllegalStateException("Cannot update selection menu for ephemeral messages! Discord does not provide enough information to perform the update."); List components = new ArrayList<>(message.getActionRows()); ComponentLayout.updateComponent(components, getComponentId(), newMenu); diff --git a/src/main/java/net/dv8tion/jda/internal/entities/AbstractMessage.java b/src/main/java/net/dv8tion/jda/internal/entities/AbstractMessage.java index 24bab16dab..6b2d840386 100644 --- a/src/main/java/net/dv8tion/jda/internal/entities/AbstractMessage.java +++ b/src/main/java/net/dv8tion/jda/internal/entities/AbstractMessage.java @@ -597,6 +597,20 @@ public EnumSet getFlags() return null; } + @Override + public long getFlagsRaw() + { + unsupported(); + return 0; + } + + @Override + public boolean isEphemeral() + { + unsupported(); + return false; + } + @Nonnull @Override public MessageType getType() diff --git a/src/main/java/net/dv8tion/jda/internal/entities/ReceivedMessage.java b/src/main/java/net/dv8tion/jda/internal/entities/ReceivedMessage.java index 59df0220e1..5ddc3819bf 100644 --- a/src/main/java/net/dv8tion/jda/internal/entities/ReceivedMessage.java +++ b/src/main/java/net/dv8tion/jda/internal/entities/ReceivedMessage.java @@ -148,6 +148,9 @@ public boolean isPinned() @Override public RestAction pin() { + if (isEphemeral()) + throw new IllegalStateException("Cannot pin ephemeral messages."); + return channel.pinMessageById(getId()); } @@ -155,6 +158,9 @@ public RestAction pin() @Override public RestAction unpin() { + if (isEphemeral()) + throw new IllegalStateException("Cannot unpin ephemeral messages."); + return channel.unpinMessageById(getId()); } @@ -162,6 +168,9 @@ public RestAction unpin() @Override public RestAction addReaction(@Nonnull Emote emote) { + if (isEphemeral()) + throw new IllegalStateException("Cannot add reactions to ephemeral messages."); + Checks.notNull(emote, "Emote"); boolean missingReaction = reactions.stream() @@ -181,6 +190,9 @@ public RestAction addReaction(@Nonnull Emote emote) @Override public RestAction addReaction(@Nonnull String unicode) { + if (isEphemeral()) + throw new IllegalStateException("Cannot add reactions to ephemeral messages."); + return channel.addReactionById(getId(), unicode); } @@ -188,6 +200,8 @@ public RestAction addReaction(@Nonnull String unicode) @Override public RestAction clearReactions() { + if (isEphemeral()) + throw new IllegalStateException("Cannot clear reactions from ephemeral messages."); if (!isFromGuild()) throw new IllegalStateException("Cannot clear reactions from a message in a Group or PrivateChannel."); return getTextChannel().clearReactionsById(getId()); @@ -197,6 +211,8 @@ public RestAction clearReactions() @Override public RestAction clearReactions(@Nonnull String unicode) { + if (isEphemeral()) + throw new IllegalStateException("Cannot clear reactions from ephemeral messages."); if (!isFromGuild()) throw new IllegalStateException("Cannot clear reactions from a message in a Group or PrivateChannel."); return getTextChannel().clearReactionsById(getId(), unicode); @@ -206,6 +222,8 @@ public RestAction clearReactions(@Nonnull String unicode) @Override public RestAction clearReactions(@Nonnull Emote emote) { + if (isEphemeral()) + throw new IllegalStateException("Cannot clear reactions from ephemeral messages."); if (!isFromGuild()) throw new IllegalStateException("Cannot clear reactions from a message in a Group or PrivateChannel."); return getTextChannel().clearReactionsById(getId(), emote); @@ -215,6 +233,9 @@ public RestAction clearReactions(@Nonnull Emote emote) @Override public RestAction removeReaction(@Nonnull Emote emote) { + if (isEphemeral()) + throw new IllegalStateException("Cannot remove reactions from ephemeral messages."); + return channel.removeReactionById(getId(), emote); } @@ -223,6 +244,8 @@ public RestAction removeReaction(@Nonnull Emote emote) public RestAction removeReaction(@Nonnull Emote emote, @Nonnull User user) { Checks.notNull(user, "User"); // to prevent NPEs + if (isEphemeral()) + throw new IllegalStateException("Cannot remove reactions from ephemeral messages."); // check if the passed user is the SelfUser, then the ChannelType doesn't matter and // we can safely remove that if (user.equals(getJDA().getSelfUser())) @@ -237,6 +260,9 @@ public RestAction removeReaction(@Nonnull Emote emote, @Nonnull User user) @Override public RestAction removeReaction(@Nonnull String unicode) { + if (isEphemeral()) + throw new IllegalStateException("Cannot remove reactions from ephemeral messages."); + return channel.removeReactionById(getId(), unicode); } @@ -248,6 +274,8 @@ public RestAction removeReaction(@Nonnull String unicode, @Nonnull User us if (user.equals(getJDA().getSelfUser())) return channel.removeReactionById(getIdLong(), unicode); + if (isEphemeral()) + throw new IllegalStateException("Cannot remove reactions from ephemeral messages."); if (!isFromGuild()) throw new IllegalStateException("Cannot remove reactions of others from a message in a Group or PrivateChannel."); return getTextChannel().removeReactionById(getId(), unicode, user); @@ -257,6 +285,9 @@ public RestAction removeReaction(@Nonnull String unicode, @Nonnull User us @Override public ReactionPaginationAction retrieveReactionUsers(@Nonnull Emote emote) { + if (isEphemeral()) + throw new IllegalStateException("Cannot retrieve reactions on ephemeral messages."); + return channel.retrieveReactionUsersById(id, emote); } @@ -264,6 +295,9 @@ public ReactionPaginationAction retrieveReactionUsers(@Nonnull Emote emote) @Override public ReactionPaginationAction retrieveReactionUsers(@Nonnull String unicode) { + if (isEphemeral()) + throw new IllegalStateException("Cannot retrieve reactions on ephemeral messages."); + return channel.retrieveReactionUsersById(id, unicode); } @@ -856,6 +890,9 @@ private void checkUser() @Override public AuditableRestAction delete() { + if (isEphemeral()) + throw new IllegalStateException("Cannot delete ephemeral messages."); + if (!getJDA().getSelfUser().equals(getAuthor())) { if (isFromType(ChannelType.PRIVATE)) @@ -873,6 +910,9 @@ else if (!getGuild().getSelfMember() @Override public AuditableRestAction suppressEmbeds(boolean suppressed) { + if (isEphemeral()) + throw new IllegalStateException("Cannot suppress embeds on ephemeral messages."); + if (!getJDA().getSelfUser().equals(getAuthor())) { if (isFromType(ChannelType.PRIVATE)) @@ -895,6 +935,9 @@ else if (!getGuild().getSelfMember().hasPermission(getTextChannel(), Permission. @Override public RestAction crosspost() { + if (isEphemeral()) + throw new IllegalStateException("Cannot crosspost ephemeral messages."); + if (getFlags().contains(MessageFlag.CROSSPOSTED)) return new CompletedRestAction<>(getJDA(), this); TextChannel textChannel = getTextChannel(); @@ -918,6 +961,18 @@ public EnumSet getFlags() return MessageFlag.fromBitField(flags); } + @Override + public long getFlagsRaw() + { + return flags; + } + + @Override + public boolean isEphemeral() + { + return (this.flags & MessageFlag.EPHEMERAL.getValue()) != 0; + } + @Override public boolean equals(Object o) { diff --git a/src/main/java/net/dv8tion/jda/internal/interactions/ComponentInteractionImpl.java b/src/main/java/net/dv8tion/jda/internal/interactions/ComponentInteractionImpl.java index ab902c240e..456b5511a3 100644 --- a/src/main/java/net/dv8tion/jda/internal/interactions/ComponentInteractionImpl.java +++ b/src/main/java/net/dv8tion/jda/internal/interactions/ComponentInteractionImpl.java @@ -24,7 +24,6 @@ import net.dv8tion.jda.internal.requests.restaction.interactions.UpdateInteractionActionImpl; import javax.annotation.Nonnull; -import javax.annotation.Nullable; public abstract class ComponentInteractionImpl extends InteractionImpl implements ComponentInteraction { @@ -58,7 +57,7 @@ public String getComponentId() return customId; } - @Nullable + @Nonnull @Override public Message getMessage() {