net.dv8tion.jda.api.interactions.commands.CommandInteractionPayload Maven / Gradle / Ivy
Show all versions of JDA Show documentation
/*
* 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.commands;
import net.dv8tion.jda.annotations.UnknownNullability;
import net.dv8tion.jda.api.JDA;
import net.dv8tion.jda.api.entities.Guild;
import net.dv8tion.jda.api.entities.Member;
import net.dv8tion.jda.api.entities.Role;
import net.dv8tion.jda.api.entities.User;
import net.dv8tion.jda.api.interactions.Interaction;
import net.dv8tion.jda.api.interactions.commands.build.CommandData;
import net.dv8tion.jda.internal.utils.Checks;
import org.jetbrains.annotations.Contract;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.util.List;
import java.util.function.Function;
import java.util.function.Supplier;
import java.util.stream.Collectors;
/**
* Interactions which provide command data.
*
This is an abstraction for {@link CommandAutoCompleteInteraction} and {@link CommandInteraction}.
*/
public interface CommandInteractionPayload extends Interaction
{
/**
* The {@link Command.Type Type} of command this interaction is for.
*
* @return The command type
*/
@Nonnull
Command.Type getCommandType();
/**
* The command name.
*
This can be useful for abstractions.
*
* Note that commands can have these following structures:
*
* - {@code /name subcommandGroup subcommandName}
* - {@code /name subcommandName}
* - {@code /name}
*
*
* You can use {@link #getFullCommandName()} to simplify your checks.
*
* @return The command name
*/
@Nonnull
String getName();
/**
* The subcommand name.
*
This can be useful for abstractions.
*
* Note that commands can have these following structures:
*
* - {@code /name subcommandGroup subcommandName}
* - {@code /name subcommandName}
* - {@code /name}
*
*
* You can use {@link #getFullCommandName()} to simplify your checks.
*
* @return The subcommand name, or null if this is not a subcommand
*/
@Nullable
String getSubcommandName();
/**
* The subcommand group name.
*
This can be useful for abstractions.
*
* Note that commands can have these following structures:
*
* - {@code /name subcommandGroup subcommandName}
* - {@code /name subcommandName}
* - {@code /name}
*
*
* You can use {@link #getFullCommandName()} to simplify your checks.
*
* @return The subcommand group name, or null if this is not a subcommand group
*/
@Nullable
String getSubcommandGroup();
/**
* Combination of {@link #getName()}, {@link #getSubcommandGroup()}, and {@link #getSubcommandName()}.
*
This will format the command into a path such as {@code mod mute} where {@code mod} would be the {@link #getName()} and {@code mute} the {@link #getSubcommandName()}.
*
* Examples:
*
* - {@code /mod ban -> "mod ban"}
* - {@code /admin config owner -> "admin config owner"}
* - {@code /ban -> "ban"}
*
*
* @return The command path
*/
@Nonnull
default String getFullCommandName()
{
StringBuilder builder = new StringBuilder(getName());
if (getSubcommandGroup() != null)
builder.append(' ').append(getSubcommandGroup());
if (getSubcommandName() != null)
builder.append(' ').append(getSubcommandName());
return builder.toString();
}
/**
* Gets the display string for this command.
*
This is similar to the string you see when clicking the interaction name in the client.
* For non-slash command types, this simply returns {@link #getName()} instead.
*
* Example return for an echo command: {@code /say echo phrase: Say this}
*
* @return The display string for this command
*/
@Nonnull
default String getCommandString()
{
//Get text like the text that appears when you hover over the interaction in discord
if (getCommandType() != Command.Type.SLASH)
return getName();
StringBuilder builder = new StringBuilder();
builder.append("/").append(getName());
if (getSubcommandGroup() != null)
builder.append(" ").append(getSubcommandGroup());
if (getSubcommandName() != null)
builder.append(" ").append(getSubcommandName());
for (OptionMapping o : getOptions())
{
builder.append(" ").append(o.getName()).append(": ");
// Discord doesn't send the resolved entities on autocomplete interactions
if (this instanceof CommandAutoCompleteInteraction)
{
switch (o.getType())
{
case CHANNEL:
case USER:
case ROLE:
case MENTIONABLE:
builder.append(o.getAsLong());
continue;
}
}
switch (o.getType())
{
case CHANNEL:
builder.append("#").append(o.getAsChannel().getName());
break;
case USER:
builder.append("@").append(o.getAsUser().getName());
break;
case ROLE:
builder.append("@").append(o.getAsRole().getName());
break;
case MENTIONABLE: //client only allows user or role mentionable as of Aug 4, 2021
if (o.getAsMentionable() instanceof Role)
builder.append("@").append(o.getAsRole().getName());
else if (o.getAsMentionable() instanceof Member)
builder.append("@").append(o.getAsUser().getName());
else if (o.getAsMentionable() instanceof User)
builder.append("@").append(o.getAsUser().getName());
else
builder.append("@").append(o.getAsMentionable().getIdLong());
break;
default:
builder.append(o.getAsString());
break;
}
}
return builder.toString();
}
/**
* The command id.
*
This is the id generated when a command is created via {@link Guild#updateCommands()} or similar.
*
*
It is usually preferred to discriminate commands by the {@link #getName() command names} instead.
*
* @return The command id
*/
long getCommandIdLong();
/**
* The command id
*
This is the id generated when a command is created via {@link Guild#updateCommands()} or similar.
*
*
It is usually preferred to discriminate commands by the {@link #getName() command names} instead.
*
* @return The command id
*/
@Nonnull
default String getCommandId()
{
return Long.toUnsignedString(getCommandIdLong());
}
/**
* Whether the used command is a guild command.
*
*
Guild commands can be created with {@link Guild#upsertCommand(CommandData)}.
*
* @return True, if the used command is a guild command
*/
boolean isGuildCommand();
/**
* Whether the used command is a global command.
*
*
Global commands can be created with {@link JDA#upsertCommand(CommandData)}.
*
* @return True, if the used command is a global command
*/
default boolean isGlobalCommand()
{
return !isGuildCommand();
}
/**
* The options provided by the user when this command was executed.
*
Each option has a name and value.
*
*
For {@link CommandAutoCompleteInteraction}, this might be incomplete and unvalidated.
* Auto-complete interactions happen on incomplete command inputs and are not validated.
*
* @return The options passed for this command
*
* @see #getOption(String)
*/
@Nonnull
List getOptions();
/**
* Gets all options for the specified name.
*
* For {@link CommandAutoCompleteInteraction}, this might be incomplete and unvalidated.
* Auto-complete interactions happen on incomplete command inputs and are not validated.
*
* @param name
* The option name
*
* @throws IllegalArgumentException
* If the provided name is null
*
* @return The list of options
*
* @see #getOption(String)
* @see #getOptions()
*/
@Nonnull
default List getOptionsByName(@Nonnull String name)
{
Checks.notNull(name, "Name");
return getOptions().stream()
.filter(opt -> opt.getName().equals(name))
.collect(Collectors.toList());
}
/**
* Gets all options for the specified type.
*
* For {@link CommandAutoCompleteInteraction}, this might be incomplete and unvalidated.
* Auto-complete interactions happen on incomplete command inputs and are not validated.
*
* @param type
* The option type
*
* @throws IllegalArgumentException
* If the provided type is null
*
* @return The list of options
*
* @see #getOptions()
*/
@Nonnull
default List getOptionsByType(@Nonnull OptionType type)
{
Checks.notNull(type, "Type");
return getOptions().stream()
.filter(it -> it.getType() == type)
.collect(Collectors.toList());
}
/**
* Finds the first option with the specified name.
*
* For {@link CommandAutoCompleteInteraction}, this might be incomplete and unvalidated.
* Auto-complete interactions happen on incomplete command inputs and are not validated.
*
*
You can use the second and third parameter overloads to handle optional arguments gracefully.
* See {@link #getOption(String, Function)} and {@link #getOption(String, Object, Function)}.
*
* @param name
* The option name
*
* @throws IllegalArgumentException
* If the name is null
*
* @return The option with the provided name, or null if that option is not provided
*
* @see #getOption(String, Function)
* @see #getOption(String, Object, Function)
* @see #getOption(String, Supplier, Function)
*/
@Nullable
default OptionMapping getOption(@Nonnull String name)
{
List options = getOptionsByName(name);
return options.isEmpty() ? null : options.get(0);
}
/**
* Finds the first option with the specified name.
*
A resolver is used to get the value if the option is provided.
* If no option is provided for the given name, this will simply return null instead.
* You can use {@link #getOption(String, Object, Function)} to provide a fallback for missing options.
*
* For {@link CommandAutoCompleteInteraction}, this might be incomplete and unvalidated.
* Auto-complete interactions happen on incomplete command inputs and are not validated.
*
*
Example
*
You can understand this as a shortcut for these lines of code:
*
{@code
* OptionMapping opt = event.getOption("reason");
* String reason = opt == null ? null : opt.getAsString();
* }
* Which can be written with this resolver as:
* {@code
* String reason = event.getOption("reason", OptionMapping::getAsString);
* }
*
* @param name
* The option name
* @param resolver
* The mapping resolver function to use if there is a mapping available,
* the provided mapping will never be null!
* @param
* The type of the resolved option value
*
* @throws IllegalArgumentException
* If the name or resolver is null
*
* @return The resolved option with the provided name, or null if that option is not provided
*
* @see #getOption(String, Object, Function)
* @see #getOption(String, Supplier, Function)
*/
@Nullable
default T getOption(@Nonnull String name, @Nonnull Function super OptionMapping, ? extends T> resolver)
{
return getOption(name, null, resolver);
}
/**
* Finds the first option with the specified name.
*
A resolver is used to get the value if the option is provided.
* If no option is provided for the given name, this will simply return your provided fallback instead.
* You can use {@link #getOption(String, Function)} to fall back to {@code null}.
*
* For {@link CommandAutoCompleteInteraction}, this might be incomplete and unvalidated.
* Auto-complete interactions happen on incomplete command inputs and are not validated.
*
*
Example
*
You can understand this as a shortcut for these lines of code:
*
{@code
* OptionMapping opt = event.getOption("reason");
* String reason = opt == null ? "ban by mod" : opt.getAsString();
* }
* Which can be written with this resolver as:
* {@code
* String reason = event.getOption("reason", "ban by mod", OptionMapping::getAsString);
* }
*
* @param name
* The option name
* @param fallback
* The fallback to use if the option is not provided, meaning {@link #getOption(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
* The type of the resolved option value
*
* @throws IllegalArgumentException
* If the name or resolver is null
*
* @return The resolved option with the provided name, or {@code fallback} if that option is not provided
*
* @see #getOption(String, Function)
* @see #getOption(String, Supplier, Function)
*/
@Contract("_,null,_->null")
default T getOption(@Nonnull String name,
@Nullable T fallback,
@Nonnull Function super OptionMapping, ? extends T> resolver)
{
Checks.notNull(resolver, "Resolver");
OptionMapping mapping = getOption(name);
if (mapping != null)
return resolver.apply(mapping);
return fallback;
}
/**
* Finds the first option with the specified name.
*
A resolver is used to get the value if the option is provided.
* If no option is provided for the given name, this will simply return your provided fallback instead.
* You can use {@link #getOption(String, Function)} to fall back to {@code null}.
*
* For {@link CommandAutoCompleteInteraction}, this might be incomplete and unvalidated.
* Auto-complete interactions happen on incomplete command inputs and are not validated.
*
*
Example
*
You can understand this as a shortcut for these lines of code:
*
{@code
* OptionMapping opt = event.getOption("reason");
* String reason = opt == null ? context.getFallbackReason() : opt.getAsString();
* }
* Which can be written with this resolver as:
* {@code
* String reason = event.getOption("reason", context::getFallbackReason , OptionMapping::getAsString);
* }
*
* @param name
* The option name
* @param fallback
* The fallback supplier to use if the option is not provided, meaning {@link #getOption(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
* The type of the resolved option value
*
* @throws IllegalArgumentException
* If the name or resolver is null
*
* @return The resolved option with the provided name, or {@code fallback} if that option is not provided
*
* @see #getOption(String, Function)
* @see #getOption(String, Object, Function)
*/
@UnknownNullability
default T getOption(@Nonnull String name,
@Nullable Supplier extends T> fallback,
@Nonnull Function super OptionMapping, ? extends T> resolver)
{
Checks.notNull(resolver, "Resolver");
OptionMapping mapping = getOption(name);
if (mapping != null)
return resolver.apply(mapping);
return fallback == null ? null : fallback.get();
}
}