Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for modals #2024

Merged
merged 110 commits into from
Apr 20, 2022
Merged
Show file tree
Hide file tree
Changes from 67 commits
Commits
Show all changes
110 commits
Select commit Hold shift + click to select a range
6345986
Register TEXT_INPUT ComponentType
Xirado Feb 9, 2022
6576f7d
Add MODAL_SUBMIT InteractionType
Xirado Feb 9, 2022
afc20a2
Add TextInput component
Xirado Feb 9, 2022
6b8f1a8
Add ModalInteraction
Xirado Feb 9, 2022
cead90e
Add TextInputStyle enum
Xirado Feb 9, 2022
d165cd2
Make TextInput extend ActionComponent instead of ItemComponent
Xirado Feb 9, 2022
e5917a4
Make ActionRow accept TextInputs
Xirado Feb 9, 2022
072492c
Make CommandInteraction and ComponentInteraction extend IReplyAction
Xirado Feb 9, 2022
5c7de65
Add IModalCallback
Xirado Feb 9, 2022
b158a8e
Add InteractionCallbackAction MODAL type
Xirado Feb 9, 2022
c24679f
Add Modal and TextInput classes
Xirado Feb 9, 2022
be75bd0
Add ModalSubmitInteractionEvent
Xirado Feb 9, 2022
571b53c
Code cleanup
Xirado Feb 9, 2022
57426f5
Add checks
Xirado Feb 9, 2022
da6dbb2
Add copyright
Xirado Feb 9, 2022
00e6a85
Add some docs
Xirado Feb 9, 2022
baf0d90
Add missing docs
Xirado Feb 9, 2022
77f447e
Move methods to ModalInteraction interface
Xirado Feb 9, 2022
1e85194
Apply suggestions from code review
Xirado Feb 9, 2022
f979d2d
Fix stuff
Xirado Feb 9, 2022
a1b3d40
Rename getInputField to getTextInputField
Xirado Feb 9, 2022
070e8f1
Fix misaligned case
Xirado Feb 9, 2022
56464f1
Add missing break
Xirado Feb 9, 2022
18be567
fix getTextInputField()
Xirado Feb 9, 2022
0c87843
Add constants
Xirado Feb 9, 2022
374a912
Rename addComponents parameter name
Xirado Feb 9, 2022
70a3249
Rename component setters/getters
Xirado Feb 9, 2022
1c8b31f
Add TextInput#Builder#setRequiredRange
Xirado Feb 9, 2022
27c78dd
Use javax annotations and fix some docs
Xirado Feb 9, 2022
15323d0
Fix docs
Xirado Feb 9, 2022
3feeada
Made Checks use constant
Xirado Feb 9, 2022
d8555b3
Remove unnecessary constant and reword Check error messages
Xirado Feb 9, 2022
14af57a
Apply suggestions from code review
Xirado Feb 10, 2022
2c64de0
Fix some annotations and compile error
Xirado Feb 10, 2022
bb36859
Apply suggestions from code review
Xirado Feb 10, 2022
637b027
Use TextInputMapping for received ModalSubmitInteractionEvents
Xirado Feb 10, 2022
bf4e748
Use TextInputMapping for received ModalSubmitInteractionEvents
Xirado Feb 10, 2022
6b74d19
Add back DataObject constructor
Xirado Feb 10, 2022
3105e54
Remove redundant import and documented TextInputMapping
Xirado Feb 10, 2022
04eb516
Renamed TextInputMapping to ModalMapping
Xirado Feb 10, 2022
0b468fb
Improve docs
Xirado Feb 10, 2022
80d0290
Improve docs
Xirado Feb 11, 2022
5a1e4b9
Add line
Xirado Feb 11, 2022
40947da
Apply suggestions from code review
Xirado Feb 11, 2022
1cdb9aa
Update src/main/java/net/dv8tion/jda/api/interactions/callbacks/IModa…
Xirado Feb 11, 2022
79d18b2
Add ModalCallbackAction
Xirado Feb 12, 2022
f4dfec4
Docs
Xirado Feb 12, 2022
bbb65a1
Missed copyright header
Xirado Feb 13, 2022
54c8aa7
No jetbrains i don't want your annotations
Xirado Feb 13, 2022
6da03f5
Remove jetbrains NotNull annotation
Xirado Feb 13, 2022
b53af11
Add more missing copyright headers
Xirado Feb 13, 2022
a67fc9e
Apply suggestions from code review
Xirado Feb 15, 2022
70b3ea1
Add Component.Type#isModalCompatible and Component.Type#isMessageComp…
Xirado Feb 15, 2022
0ee8573
Add ItemComponent#isModalCompatible and ItemComponent#isMessageCompat…
Xirado Feb 15, 2022
69370cf
Improve docs in Modal
Xirado Feb 15, 2022
53cd9f9
Improve docs in ModalInteraction
Xirado Feb 15, 2022
84cea82
Fix infinite recursion in ModalInteractionImpl
Xirado Feb 15, 2022
a8b792c
Better toString() in ModalMapping
Xirado Feb 15, 2022
70b7679
Add LayoutComponent#isMessageCompatible and LayoutComponent#isModalCo…
Xirado Feb 15, 2022
eefea74
Add docs and checks for actionrow compatibility to MessageAction, Mes…
Xirado Feb 15, 2022
c483eb4
Add ModalInteraction#getValue fallback overloads
Xirado Feb 15, 2022
919086e
Remove redundant imports
Xirado Feb 15, 2022
8fbee19
Add IModalCallback to Interaction docs
Xirado Feb 15, 2022
c1e12a7
Apply suggestions from code review
Xirado Feb 16, 2022
01939c6
Apply suggestions from code review
Xirado Feb 16, 2022
29f72b2
Add TextInput.Builder setters for id, label and style
Xirado Feb 16, 2022
15bf756
Merge branch 'feature/modals' of https://github.com/Xirado/JDA into f…
Xirado Feb 16, 2022
d66d7bc
Use setters inside TextInput.Builder constructor
Xirado Feb 16, 2022
35ac75d
Fix unnecessary line break in jdocs
Xirado Feb 16, 2022
688b83d
Remove ModalInteraction value fallback overloads
Xirado Feb 17, 2022
f4162a1
Fix typo in CommandAutoCompleteInteractionEvent
Xirado Feb 20, 2022
ef20a40
Apply suggestions from @Sanduhr32
Xirado Feb 20, 2022
a2be8dc
Apply suggestions from code review
Xirado Feb 21, 2022
996cc4f
Fix javadocs error
Xirado Feb 21, 2022
179c8fd
Merge branch 'master' into feature/modals
Xirado Feb 21, 2022
13c17fc
Add missing throws in javadocs
Xirado Feb 21, 2022
e1aec45
Fix docs in ModalMapping
Xirado Feb 21, 2022
ced2a2b
Merge branch 'master' into feature/modals
Xirado Feb 23, 2022
f94109b
Add some checks to TextInput and Modal
Xirado Feb 23, 2022
36eea2a
Merge branch 'master' into feature/modals
Xirado Feb 27, 2022
f0e621f
Apply suggestions from code review
Xirado Mar 24, 2022
7679f5c
Apply suggestion from code review
Xirado Mar 24, 2022
29e6c9f
Apply suggestions from code review
Xirado Mar 25, 2022
78a7414
Apply suggestions from code review
Xirado Mar 25, 2022
149479e
Added explanation to TextInput#getPlaceHolder docs
Xirado Mar 25, 2022
6adee1e
Merge branch 'feature/modals' of https://github.com/Xirado/JDA into f…
Xirado Mar 25, 2022
11e0b83
Wording
Xirado Apr 5, 2022
efab61c
Apply suggestions from code review
Xirado Apr 13, 2022
4aa9262
Fix docs and min/maxLength
Xirado Apr 13, 2022
3679b49
Revert change to min/maxLength
Xirado Apr 13, 2022
0964890
Docs
Xirado Apr 13, 2022
b2e08c0
Add checks to TextInput.Builder#setValue
Xirado Apr 13, 2022
71638f1
InteractionHook begone
Xirado Apr 14, 2022
484b432
Add Checks.checkComponents()
Xirado Apr 14, 2022
015e707
Fix TextInput.Builder#setRequired(boolean)
Xirado Apr 14, 2022
1f64595
Add handling for interaction hook
MinnDevelopment Apr 15, 2022
821a37c
Fix code example in Modal.java
Xirado Apr 15, 2022
781bcff
Improve docs and use correct Check for Modal.Builder#addActionRows
Xirado Apr 15, 2022
b37020f
Improve docs and fix checks for TextInput.Builder#setPlaceholder
Xirado Apr 15, 2022
7e0ffc5
Merge branch 'master' into feature/modals
Xirado Apr 18, 2022
eb57895
Removed duplicate code
DV8FromTheWorld Apr 19, 2022
1bc7646
Handle context wrapping in InteractionHook
MinnDevelopment Apr 19, 2022
6ac32e8
Merge branch 'feature/modals' of github.com:xirado/JDA into feature/m…
MinnDevelopment Apr 19, 2022
7eb4d11
Apply suggestions from code review
Xirado Apr 19, 2022
cc03f95
Apply suggestions
Xirado Apr 19, 2022
80ca752
Fix compile error
Xirado Apr 19, 2022
14bf76a
Made TextInput required by default
Xirado Apr 19, 2022
a0de537
Forgot TextInputImpl constructor
Xirado Apr 19, 2022
7632a1b
Add Checks.checkComponents Component array overload
Xirado Apr 20, 2022
3431a3a
Update src/main/java/net/dv8tion/jda/api/interactions/components/text…
MinnDevelopment Apr 20, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
/*
* 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.events.interaction;

import net.dv8tion.jda.api.JDA;
import net.dv8tion.jda.api.interactions.InteractionHook;
import net.dv8tion.jda.api.interactions.ModalInteraction;
import net.dv8tion.jda.api.interactions.modals.ModalMapping;
import net.dv8tion.jda.api.requests.restaction.interactions.MessageEditCallbackAction;
import net.dv8tion.jda.api.requests.restaction.interactions.ReplyCallbackAction;

import javax.annotation.Nonnull;
import java.util.List;

/**
* Indicates that a {@link net.dv8tion.jda.api.interactions.components.text.Modal Modal} was submitted.
*
* <h2>Requirements</h2>
* To receive these events, you must unset the <b>Interactions Endpoint URL</b> in your application dashboard.
* You can simply remove the URL for this endpoint in your settings at the <a href="https://discord.com/developers/applications" target="_blank">Discord Developers Portal</a>.
*
* @see net.dv8tion.jda.api.interactions.ModalInteraction
*/
public class ModalInteractionEvent extends GenericInteractionCreateEvent implements ModalInteraction
{
private final ModalInteraction interaction;

public ModalInteractionEvent(@Nonnull JDA api, long responseNumber, @Nonnull ModalInteraction interaction)
{
super(api, responseNumber, interaction);
this.interaction = interaction;
}

@Nonnull
@Override
public ModalInteraction getInteraction()
{
return interaction;
}

@Nonnull
@Override
public String getModalId()
{
return interaction.getModalId();
}

@Nonnull
@Override
public List<ModalMapping> getValues()
{
return interaction.getValues();
}

@Nonnull
@Override
public ReplyCallbackAction deferReply()
{
return interaction.deferReply();
}

@Nonnull
@Override
public InteractionHook getHook()
{
return interaction.getHook();
}

@Nonnull
@Override
public MessageEditCallbackAction deferEdit()
{
return interaction.deferEdit();
}
}
2 changes: 2 additions & 0 deletions src/main/java/net/dv8tion/jda/api/hooks/ListenerAdapter.java
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@
import net.dv8tion.jda.api.events.http.HttpRequestEvent;
import net.dv8tion.jda.api.events.interaction.GenericAutoCompleteInteractionEvent;
import net.dv8tion.jda.api.events.interaction.GenericInteractionCreateEvent;
import net.dv8tion.jda.api.events.interaction.ModalInteractionEvent;
import net.dv8tion.jda.api.events.interaction.command.*;
import net.dv8tion.jda.api.events.interaction.component.ButtonInteractionEvent;
import net.dv8tion.jda.api.events.interaction.component.GenericComponentInteractionCreateEvent;
Expand Down Expand Up @@ -128,6 +129,7 @@ public void onMessageContextInteraction(@Nonnull MessageContextInteractionEvent
public void onButtonInteraction(@Nonnull ButtonInteractionEvent event) {}
public void onSelectMenuInteraction(@Nonnull SelectMenuInteractionEvent event) {}
public void onCommandAutoCompleteInteraction(@Nonnull CommandAutoCompleteInteractionEvent event) {}
public void onModalInteraction(@Nonnull ModalInteractionEvent event) {}

//User Events
public void onUserUpdateName(@Nonnull UserUpdateNameEvent event) {}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,15 +23,16 @@
import net.dv8tion.jda.api.interactions.callbacks.IMessageEditCallback;
import net.dv8tion.jda.api.interactions.callbacks.IReplyCallback;
import net.dv8tion.jda.api.interactions.commands.Command;
import net.dv8tion.jda.api.interactions.components.text.Modal;

import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.util.Locale;

/**
* Abstract representation for any kind of Discord interaction.
* <br>This includes things such as {@link net.dv8tion.jda.api.interactions.commands.SlashCommandInteraction Slash-Commands}
* or {@link net.dv8tion.jda.api.interactions.components.buttons.ButtonInteraction Buttons}.
* <br>This includes things such as {@link net.dv8tion.jda.api.interactions.commands.SlashCommandInteraction Slash-Commands},
* {@link net.dv8tion.jda.api.interactions.components.buttons.ButtonInteraction Buttons} or {@link ModalInteraction Modals}.
*
* <p>To properly handle an interaction you must acknowledge it.
* Each interaction has different callbacks which acknowledge the interaction. These are added by the individual {@code I...Callback} interfaces:
Expand All @@ -42,6 +43,8 @@
* <br>Which supports direct message edits and deferred message edits (or no-operation) via {@link IMessageEditCallback#editMessage(String)} and {@link IMessageEditCallback#deferEdit()}</li>
* <li>{@link IAutoCompleteCallback}
* <br>Which supports choice suggestions for auto-complete interactions via {@link IAutoCompleteCallback#replyChoices(Command.Choice...)}</li>
* <li>{@link net.dv8tion.jda.api.interactions.callbacks.IModalCallback}
* <br>Which supports replying using a {@link net.dv8tion.jda.api.interactions.components.text.Modal Modal} via {@link net.dv8tion.jda.api.interactions.callbacks.IModalCallback#replyModal(Modal)}</li>
* </ul>
*
* <p>Once the interaction is acknowledged, you can not reply with these methods again. If the interaction is a {@link IDeferrableCallback deferrable},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ public enum InteractionType
COMMAND(2),
COMPONENT(3),
COMMAND_AUTOCOMPLETE(4),
MODAL_SUBMIT(5),
;

private final int key;
Expand Down Expand Up @@ -59,6 +60,8 @@ public static InteractionType fromKey(int key)
return COMPONENT;
case 4:
return COMMAND_AUTOCOMPLETE;
case 5:
return MODAL_SUBMIT;
default:
return UNKNOWN;
}
Expand Down
219 changes: 219 additions & 0 deletions src/main/java/net/dv8tion/jda/api/interactions/ModalInteraction.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,219 @@
/*
* 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.interactions;

import net.dv8tion.jda.api.interactions.callbacks.IMessageEditCallback;
import net.dv8tion.jda.api.interactions.callbacks.IReplyCallback;
import net.dv8tion.jda.api.interactions.modals.ModalMapping;
import net.dv8tion.jda.internal.utils.Checks;

import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.util.List;
import java.util.function.Function;
import java.util.function.Supplier;

/**
* Interaction on a {@link net.dv8tion.jda.api.interactions.components.text.Modal Modal}
*
* If the modal of this interaction was a reply to a {@link net.dv8tion.jda.api.interactions.components.ComponentInteraction ComponentInteraction}, you can also use {@link #deferEdit()} to edit the message instead of replying.
Xirado marked this conversation as resolved.
Show resolved Hide resolved
*
* @see net.dv8tion.jda.api.events.interaction.ModalInteractionEvent
*/
public interface ModalInteraction extends IReplyCallback, IMessageEditCallback
Xirado marked this conversation as resolved.
Show resolved Hide resolved
{
/**
* Returns the custom id of the Modal in question
*
* @return Custom id
*
* @see net.dv8tion.jda.api.interactions.components.text.Modal.Builder#setId(String)
*/
@Nonnull
String getModalId();
Xirado marked this conversation as resolved.
Show resolved Hide resolved

/**
* Returns a List of {@link ModalMapping ModalMappings} the modal in question contains
*
* @return List of {@link ModalMapping ModalMappings}
*
* @see #getValue(String)
*/
@Nonnull
List<ModalMapping> getValues();

/**
* Convenience method to get a {@link ModalMapping ModalMapping} by its id from the List of {@link ModalMapping ModalMappings}
*
* <p>Returns null if no component with that id has been found
*
* <p>You can use the second and third parameter overloads to handle optional arguments gracefully.
* See {@link #getValue(String, Function)} and {@link #getValue(String, Object, Function)}
*
* @param id
* The custom id
*
* @throws IllegalArgumentException
* If the provided id is null
*
* @return ModalMapping with this id, or null if not found
*
* @see #getValues()
* @see #getValue(String, Function)
* @see #getValue(String, Object, Function)
* @see #getValue(String, Supplier, Function)
*/
@Nullable
default ModalMapping getValue(@Nonnull String id)
Xirado marked this conversation as resolved.
Show resolved Hide resolved
{
Checks.notNull(id, "ID");
return getValues().stream()
.filter(mapping -> mapping.getId().equals(id))
.findFirst().orElse(null);
}

/**
* Finds the first value with the specified id.
* <br>A resolver is used to get the value if it is provided.
* If no value is provided for the given id, this will simply return null instead.
* You can use {@link #getValue(String, Object, Function)} to provide a fallback for missing values.
*
* <p><b>Example</b>
* <br>>ou can understand this as a shortcut for these lines of code:
* <pre>{@code
* ModalMapping mapping = event.getValue("email");
* String email = mapping == null ? null : mapping.getAsString();
* }</pre>
* Which can be written with this resolver as:
* <pre>{@code
* String email = event.getValue("email", ModalMapping::getAsString);
* }</pre>
*
* @param id
* The value id
* @param resolver
* The mapping resolver function to use if there is a mapping available,
* the provided mapping will never be null!
* @param <T>
* The type of the resolved value
*
* @throws IllegalArgumentException
* If the id or resolver is null
*
* @return The resolved value with the provided id, or null if that value is not provided.
*
* @see #getValue(String, Object, Function)
* @see #getValue(String, Supplier, Function)
*/
default <T> T getValue(@Nonnull String id,
@Nonnull Function<? super ModalMapping, ? extends T> resolver)
{
return getValue(id, null, resolver);
}

/**
* Finds the first value with the specified id.
* <br>A resolver is used to get the value if it is provided.
* If no value is provided for the given id, this will simply return your provided fallback instead.
* You can use {@link #getValue(String, Function)} to fall back to {@code null}.
*
* <p><b>Example</b>
* <br>You can understand this as a shortcut for these lines of code:
* <pre>{@code
* ModalMapping mapping = event.getValue("email");
* String email = mapping == null ? "No email provided" : mapping.getAsString();
* }</pre>
* Which can be written with this resolver as:
* <pre>{@code
* String email = event.getValue("email", "No email provided", ModalMapping::getAsString);
* }</pre>
*
* @param id
* The value id
* @param fallback
* The fallback to use if the value is not provided, meaning {@link #getValue(String)} returns null
* @param resolver
* The mapping resolver function to use if there is a mapping available,
* the provided mapping will never be null!
* @param <T>
* The type of the resolved value
*
* @throws IllegalArgumentException
* If the id or resolver is null
*
* @return The resolved option with the provided id, or {@code fallback} if that option is not provided
*
* @see #getValue(String, Function)
* @see #getValue(String, Supplier, Function)
*/
default <T> T getValue(@Nonnull String id,
@Nullable T fallback,
@Nonnull Function<? super ModalMapping, ? extends T> resolver)
{
Checks.notNull(resolver, "Resolver");
ModalMapping mapping = getValue(id);
if (mapping != null)
return resolver.apply(mapping);
return fallback;
}

/**
* Finds the first value with the specified id.
* <br>A resolver is used to get the value if it is provided.
* If no value is provided for the given id, this will simply return your provided fallback instead.
* You can use {@link #getValue(String, Function)} to fall back to {@code null}.
*
* <p><b>Example</b>
* <br>You can understand this as a shortcut for these lines of code:
* <pre>{@code
* ModalMapping mapping = event.getValue("email");
* String email = mapping == null ? context.getMissingEmailString() : mapping.getAsString();
* }</pre>
* Which can be written with this resolver as:
* <pre>{@code
* String email = event.getValue("email", context::getMissingEmailString , ModalMapping::getAsString);
* }</pre>
*
* @param id
* The option id
* @param fallback
* The fallback supplier to use if the value is not provided, meaning {@link #getValue(String)} returns null
* @param resolver
* The mapping resolver function to use if there is a mapping available,
* the provided mapping will never be null!
* @param <T>
* The type of the resolved value
*
* @throws IllegalArgumentException
* If the id or resolver is null
*
* @return The resolved option with the provided id, or {@code fallback} if that option is not provided
*
* @see #getValue(String, Function)
* @see #getValue(String, Object, Function)
*/
default <T> T getValue(@Nonnull String id,
@Nullable Supplier<? extends T> fallback,
@Nonnull Function<? super ModalMapping, ? extends T> resolver)
{
Checks.notNull(resolver, "Resolver");
ModalMapping mapping = getValue(id);
if (mapping != null)
return resolver.apply(mapping);
return fallback == null ? null : fallback.get();
}
}
Loading