diff --git a/src/main/java/net/dv8tion/jda/api/JDA.java b/src/main/java/net/dv8tion/jda/api/JDA.java index 7f50e3b45c..6557c74fde 100644 --- a/src/main/java/net/dv8tion/jda/api/JDA.java +++ b/src/main/java/net/dv8tion/jda/api/JDA.java @@ -32,6 +32,7 @@ import net.dv8tion.jda.api.interactions.commands.Command; import net.dv8tion.jda.api.interactions.commands.build.CommandData; import net.dv8tion.jda.api.interactions.commands.build.Commands; +import net.dv8tion.jda.api.interactions.commands.build.EntryPointCommandData; import net.dv8tion.jda.api.managers.AudioManager; import net.dv8tion.jda.api.managers.DirectAudioController; import net.dv8tion.jda.api.managers.Presence; @@ -775,6 +776,7 @@ default CommandCreateAction upsertCommand(@Nonnull String name, @Nonnull String /** * Configures the complete list of global commands. *
This will replace the existing command list for this bot. You should only use this once on startup! + *
If your bot has activities enabled, you must {@link GlobalCommandListUpdateAction#setEntryPointCommand(EntryPointCommandData) set your entry point command}. * *

This operation is idempotent. * Commands will persist between restarts of your bot, you only have to create a command once. @@ -799,13 +801,13 @@ default CommandCreateAction upsertCommand(@Nonnull String name, @Nonnull String * jda.updateCommands().queue(); * } * - * @return {@link CommandListUpdateAction} + * @return {@link GlobalCommandListUpdateAction} * * @see Guild#updateCommands() */ @Nonnull @CheckReturnValue - CommandListUpdateAction updateCommands(); + GlobalCommandListUpdateAction updateCommands(); /** * Edit an existing global command by id. diff --git a/src/main/java/net/dv8tion/jda/api/entities/ApplicationInfo.java b/src/main/java/net/dv8tion/jda/api/entities/ApplicationInfo.java index d7391675f0..3716611698 100644 --- a/src/main/java/net/dv8tion/jda/api/entities/ApplicationInfo.java +++ b/src/main/java/net/dv8tion/jda/api/entities/ApplicationInfo.java @@ -425,7 +425,7 @@ enum Flag GATEWAY_GUILD_MEMBERS_LIMITED(1 << 15), /** Indicates unusual growth of an app that prevents verification */ VERIFICATION_PENDING_GUILD_LIMIT(1 << 16), - /** Indicates if an app is embedded within the Discord client (currently unavailable publicly) */ + /** Indicates if an app is embedded within the Discord client, or is an app with an Activity */ EMBEDDED(1 << 17), /** Bot can use {@link net.dv8tion.jda.api.requests.GatewayIntent#MESSAGE_CONTENT GatewayIntent.MESSAGE_CONTENT} in 100 or more guilds */ GATEWAY_MESSAGE_CONTENT(1 << 18), diff --git a/src/main/java/net/dv8tion/jda/api/events/interaction/ModalInteractionEvent.java b/src/main/java/net/dv8tion/jda/api/events/interaction/ModalInteractionEvent.java index 36224ec2cf..e8825be6af 100644 --- a/src/main/java/net/dv8tion/jda/api/events/interaction/ModalInteractionEvent.java +++ b/src/main/java/net/dv8tion/jda/api/events/interaction/ModalInteractionEvent.java @@ -23,6 +23,7 @@ import net.dv8tion.jda.api.interactions.modals.Modal; import net.dv8tion.jda.api.interactions.modals.ModalInteraction; import net.dv8tion.jda.api.interactions.modals.ModalMapping; +import net.dv8tion.jda.api.requests.restaction.interactions.LaunchActivityCallbackAction; import net.dv8tion.jda.api.requests.restaction.interactions.MessageEditCallbackAction; import net.dv8tion.jda.api.requests.restaction.interactions.ReplyCallbackAction; @@ -101,6 +102,14 @@ public MessageEditCallbackAction deferEdit() return interaction.deferEdit(); } + @Nonnull + @Override + @CheckReturnValue + public LaunchActivityCallbackAction replyWithLaunchedActivity() + { + return interaction.replyWithLaunchedActivity(); + } + @Nonnull @Override public MessageChannelUnion getChannel() diff --git a/src/main/java/net/dv8tion/jda/api/events/interaction/command/GenericCommandInteractionEvent.java b/src/main/java/net/dv8tion/jda/api/events/interaction/command/GenericCommandInteractionEvent.java index 7a0c4ef531..4c2ab2ae1b 100644 --- a/src/main/java/net/dv8tion/jda/api/events/interaction/command/GenericCommandInteractionEvent.java +++ b/src/main/java/net/dv8tion/jda/api/events/interaction/command/GenericCommandInteractionEvent.java @@ -23,6 +23,7 @@ import net.dv8tion.jda.api.interactions.commands.CommandInteraction; import net.dv8tion.jda.api.interactions.commands.OptionMapping; import net.dv8tion.jda.api.interactions.modals.Modal; +import net.dv8tion.jda.api.requests.restaction.interactions.LaunchActivityCallbackAction; import net.dv8tion.jda.api.requests.restaction.interactions.ModalCallbackAction; import net.dv8tion.jda.api.requests.restaction.interactions.PremiumRequiredCallbackAction; import net.dv8tion.jda.api.requests.restaction.interactions.ReplyCallbackAction; @@ -131,4 +132,12 @@ public PremiumRequiredCallbackAction replyWithPremiumRequired() { return getInteraction().replyWithPremiumRequired(); } + + @Nonnull + @Override + @CheckReturnValue + public LaunchActivityCallbackAction replyWithLaunchedActivity() + { + return getInteraction().replyWithLaunchedActivity(); + } } diff --git a/src/main/java/net/dv8tion/jda/api/events/interaction/command/PrimaryEntryPointInteractionEvent.java b/src/main/java/net/dv8tion/jda/api/events/interaction/command/PrimaryEntryPointInteractionEvent.java new file mode 100644 index 0000000000..d9a930e999 --- /dev/null +++ b/src/main/java/net/dv8tion/jda/api/events/interaction/command/PrimaryEntryPointInteractionEvent.java @@ -0,0 +1,65 @@ +/* + * 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.command; + +import net.dv8tion.jda.api.JDA; +import net.dv8tion.jda.api.entities.channel.middleman.MessageChannel; +import net.dv8tion.jda.api.entities.channel.unions.MessageChannelUnion; +import net.dv8tion.jda.api.interactions.commands.PrimaryEntryPointInteraction; +import net.dv8tion.jda.api.interactions.commands.build.EntryPointCommandData; +import net.dv8tion.jda.api.requests.restaction.GlobalCommandListUpdateAction; + +import javax.annotation.Nonnull; + +/** + * Indicates that an activity entry point was used in a {@link MessageChannel}. + + *
This interaction requires activities to be enabled, + * and an {@link GlobalCommandListUpdateAction#setEntryPointCommand(EntryPointCommandData) entry point} + * with its {@link EntryPointCommandData#setHandler(EntryPointCommandData.Handler) handler} + * set to {@link EntryPointCommandData.Handler#APP_HANDLER APP_HANDLER} to be configured. + * + *

Requirements
+ * To receive these events, you must unset the Interactions Endpoint URL in your application dashboard. + * You can simply remove the URL for this endpoint in your settings at the Discord Developers Portal. + * + * @see PrimaryEntryPointInteraction + */ +public class PrimaryEntryPointInteractionEvent extends GenericCommandInteractionEvent implements PrimaryEntryPointInteraction +{ + private final PrimaryEntryPointInteraction interaction; + + public PrimaryEntryPointInteractionEvent(@Nonnull JDA api, long responseNumber, @Nonnull PrimaryEntryPointInteraction interaction) + { + super(api, responseNumber, interaction); + this.interaction = interaction; + } + + @Nonnull + @Override + public PrimaryEntryPointInteraction getInteraction() + { + return interaction; + } + + @Nonnull + @Override + public MessageChannelUnion getChannel() + { + return interaction.getChannel(); + } +} diff --git a/src/main/java/net/dv8tion/jda/api/events/interaction/component/GenericComponentInteractionCreateEvent.java b/src/main/java/net/dv8tion/jda/api/events/interaction/component/GenericComponentInteractionCreateEvent.java index a470852bea..763910f11d 100644 --- a/src/main/java/net/dv8tion/jda/api/events/interaction/component/GenericComponentInteractionCreateEvent.java +++ b/src/main/java/net/dv8tion/jda/api/events/interaction/component/GenericComponentInteractionCreateEvent.java @@ -25,10 +25,7 @@ import net.dv8tion.jda.api.interactions.components.Component; import net.dv8tion.jda.api.interactions.components.ComponentInteraction; import net.dv8tion.jda.api.interactions.modals.Modal; -import net.dv8tion.jda.api.requests.restaction.interactions.MessageEditCallbackAction; -import net.dv8tion.jda.api.requests.restaction.interactions.ModalCallbackAction; -import net.dv8tion.jda.api.requests.restaction.interactions.PremiumRequiredCallbackAction; -import net.dv8tion.jda.api.requests.restaction.interactions.ReplyCallbackAction; +import net.dv8tion.jda.api.requests.restaction.interactions.*; import javax.annotation.CheckReturnValue; import javax.annotation.Nonnull; @@ -138,4 +135,12 @@ public PremiumRequiredCallbackAction replyWithPremiumRequired() { return interaction.replyWithPremiumRequired(); } + + @Nonnull + @Override + @CheckReturnValue + public LaunchActivityCallbackAction replyWithLaunchedActivity() + { + return interaction.replyWithLaunchedActivity(); + } } diff --git a/src/main/java/net/dv8tion/jda/api/hooks/ListenerAdapter.java b/src/main/java/net/dv8tion/jda/api/hooks/ListenerAdapter.java index 81e5ae6a49..a5722bbf8a 100644 --- a/src/main/java/net/dv8tion/jda/api/hooks/ListenerAdapter.java +++ b/src/main/java/net/dv8tion/jda/api/hooks/ListenerAdapter.java @@ -149,6 +149,7 @@ public void onException(@Nonnull ExceptionEvent event) {} public void onSlashCommandInteraction(@Nonnull SlashCommandInteractionEvent event) {} public void onUserContextInteraction(@Nonnull UserContextInteractionEvent event) {} public void onMessageContextInteraction(@Nonnull MessageContextInteractionEvent event) {} + public void onPrimaryEntryPointInteraction(@Nonnull PrimaryEntryPointInteractionEvent event) {} public void onButtonInteraction(@Nonnull ButtonInteractionEvent event) {} public void onCommandAutoCompleteInteraction(@Nonnull CommandAutoCompleteInteractionEvent event) {} public void onModalInteraction(@Nonnull ModalInteractionEvent event) {} diff --git a/src/main/java/net/dv8tion/jda/api/interactions/Interaction.java b/src/main/java/net/dv8tion/jda/api/interactions/Interaction.java index 9f2e154d5e..bae15d8fe4 100644 --- a/src/main/java/net/dv8tion/jda/api/interactions/Interaction.java +++ b/src/main/java/net/dv8tion/jda/api/interactions/Interaction.java @@ -48,6 +48,8 @@ *
Which supports choice suggestions for auto-complete interactions via {@link IAutoCompleteCallback#replyChoices(Command.Choice...)} *

  • {@link IModalCallback} *
    Which supports replying using a {@link Modal} via {@link IModalCallback#replyModal(Modal)}
  • + *
  • {@link ILaunchActivityReplyCallback} + *
    Which will launch the app's activity
  • * * *

    Once the interaction is acknowledged, you can not reply with these methods again. If the interaction is a {@link IDeferrableCallback deferrable}, diff --git a/src/main/java/net/dv8tion/jda/api/interactions/callbacks/ILaunchActivityReplyCallback.java b/src/main/java/net/dv8tion/jda/api/interactions/callbacks/ILaunchActivityReplyCallback.java new file mode 100644 index 0000000000..92263241ce --- /dev/null +++ b/src/main/java/net/dv8tion/jda/api/interactions/callbacks/ILaunchActivityReplyCallback.java @@ -0,0 +1,41 @@ +/* + * 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.callbacks; + +import net.dv8tion.jda.api.requests.restaction.interactions.LaunchActivityCallbackAction; + +import javax.annotation.CheckReturnValue; +import javax.annotation.Nonnull; + +/** + * Callback which launches this app's activity. + * + *

    Replying with {@link #replyWithLaunchedActivity()} will automatically acknowledge this interaction. + * + *

    Note:This interaction requires activities to be enabled. + */ +public interface ILaunchActivityReplyCallback extends IDeferrableCallback +{ + /** + * Launches this app's activity and acknowledges this interaction. + * + * @return {@link LaunchActivityCallbackAction} + */ + @Nonnull + @CheckReturnValue + LaunchActivityCallbackAction replyWithLaunchedActivity(); +} diff --git a/src/main/java/net/dv8tion/jda/api/interactions/commands/Command.java b/src/main/java/net/dv8tion/jda/api/interactions/commands/Command.java index 2b1c1c3798..57f82e7200 100644 --- a/src/main/java/net/dv8tion/jda/api/interactions/commands/Command.java +++ b/src/main/java/net/dv8tion/jda/api/interactions/commands/Command.java @@ -22,6 +22,7 @@ import net.dv8tion.jda.api.entities.channel.ChannelType; import net.dv8tion.jda.api.interactions.DiscordLocale; import net.dv8tion.jda.api.interactions.commands.build.CommandData; +import net.dv8tion.jda.api.interactions.commands.build.EntryPointCommandData; import net.dv8tion.jda.api.interactions.commands.localization.LocalizationMap; import net.dv8tion.jda.api.interactions.commands.privileges.IntegrationPrivilege; import net.dv8tion.jda.api.requests.RestAction; @@ -146,6 +147,14 @@ public interface Command extends ISnowflake, ICommandReference @Nonnull LocalizationMap getDescriptionLocalizations(); + /** + * The handler, if this is an {@link EntryPointCommandData entry point command}. + * + * @return The entry point handler + */ + @Nullable + EntryPointCommandData.Handler getHandler(); + /** * The {@link Option Options} of this command. * @@ -249,7 +258,8 @@ enum Type UNKNOWN(-1), SLASH(1), USER(2), - MESSAGE(3); + MESSAGE(3), + PRIMARY_ENTRY_POINT(4); private final int id; diff --git a/src/main/java/net/dv8tion/jda/api/interactions/commands/CommandInteraction.java b/src/main/java/net/dv8tion/jda/api/interactions/commands/CommandInteraction.java index d0a87b1ed5..1940f0a5d4 100644 --- a/src/main/java/net/dv8tion/jda/api/interactions/commands/CommandInteraction.java +++ b/src/main/java/net/dv8tion/jda/api/interactions/commands/CommandInteraction.java @@ -16,6 +16,7 @@ package net.dv8tion.jda.api.interactions.commands; +import net.dv8tion.jda.api.interactions.callbacks.ILaunchActivityReplyCallback; import net.dv8tion.jda.api.interactions.callbacks.IModalCallback; import net.dv8tion.jda.api.interactions.callbacks.IPremiumRequiredReplyCallback; import net.dv8tion.jda.api.interactions.callbacks.IReplyCallback; @@ -29,6 +30,6 @@ * @see ContextInteraction * @see SlashCommandInteraction */ -public interface CommandInteraction extends IReplyCallback, CommandInteractionPayload, IModalCallback, IPremiumRequiredReplyCallback +public interface CommandInteraction extends IReplyCallback, CommandInteractionPayload, IModalCallback, IPremiumRequiredReplyCallback, ILaunchActivityReplyCallback { } diff --git a/src/main/java/net/dv8tion/jda/api/interactions/commands/PrimaryEntryPointInteraction.java b/src/main/java/net/dv8tion/jda/api/interactions/commands/PrimaryEntryPointInteraction.java new file mode 100644 index 0000000000..d528ff1abf --- /dev/null +++ b/src/main/java/net/dv8tion/jda/api/interactions/commands/PrimaryEntryPointInteraction.java @@ -0,0 +1,51 @@ +/* + * 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.api.entities.channel.unions.GuildMessageChannelUnion; +import net.dv8tion.jda.api.entities.channel.unions.MessageChannelUnion; +import net.dv8tion.jda.api.interactions.commands.build.EntryPointCommandData; +import net.dv8tion.jda.api.requests.restaction.GlobalCommandListUpdateAction; + +import javax.annotation.Nonnull; + +/** + * Interaction to launch your app's activity. + * + *

    Note: This interaction requires activities to be enabled, + * and an {@link GlobalCommandListUpdateAction#setEntryPointCommand(EntryPointCommandData) entry point} + * with its {@link EntryPointCommandData#setHandler(EntryPointCommandData.Handler) handler} + * set to {@link EntryPointCommandData.Handler#APP_HANDLER APP_HANDLER} to be configured. + */ +public interface PrimaryEntryPointInteraction extends CommandInteraction +{ + /** + * The respective {@link MessageChannelUnion} for this interaction. + * + * @return The {@link MessageChannelUnion} + */ + @Nonnull + @Override + MessageChannelUnion getChannel(); + + @Nonnull + @Override + default GuildMessageChannelUnion getGuildChannel() + { + return (GuildMessageChannelUnion) CommandInteraction.super.getGuildChannel(); + } +} diff --git a/src/main/java/net/dv8tion/jda/api/interactions/commands/build/CommandData.java b/src/main/java/net/dv8tion/jda/api/interactions/commands/build/CommandData.java index e1122a060b..99330e5746 100644 --- a/src/main/java/net/dv8tion/jda/api/interactions/commands/build/CommandData.java +++ b/src/main/java/net/dv8tion/jda/api/interactions/commands/build/CommandData.java @@ -19,8 +19,11 @@ import net.dv8tion.jda.api.interactions.DiscordLocale; import net.dv8tion.jda.api.interactions.commands.Command; import net.dv8tion.jda.api.interactions.commands.DefaultMemberPermissions; +import net.dv8tion.jda.api.interactions.commands.build.attributes.IAgeRestrictedCommandData; +import net.dv8tion.jda.api.interactions.commands.build.attributes.INamedCommandData; +import net.dv8tion.jda.api.interactions.commands.build.attributes.IRestrictedCommandData; +import net.dv8tion.jda.api.interactions.commands.build.attributes.IScopedCommandData; import net.dv8tion.jda.api.interactions.commands.localization.LocalizationFunction; -import net.dv8tion.jda.api.interactions.commands.localization.LocalizationMap; import net.dv8tion.jda.api.utils.data.DataObject; import net.dv8tion.jda.api.utils.data.SerializableData; import net.dv8tion.jda.internal.interactions.CommandDataImpl; @@ -37,189 +40,43 @@ * * @see Commands */ -public interface CommandData extends SerializableData +public interface CommandData + extends INamedCommandData, IScopedCommandData, IRestrictedCommandData, IAgeRestrictedCommandData, + SerializableData { - /** - * The maximum length the name of a command can be. ({@value}) - */ - int MAX_NAME_LENGTH = 32; - - /** - * The maximum length the description of a command can be. ({@value}) - */ - int MAX_DESCRIPTION_LENGTH = 100; - /** * The maximum amount of options/subcommands/groups that can be added to a command or subcommand. ({@value}) */ int MAX_OPTIONS = 25; - /** - * Sets the {@link LocalizationFunction} for this command - *
    This enables you to have the entirety of this command to be localized. - * - * @param localizationFunction - * The localization function - * - * @throws IllegalArgumentException - * If the localization function is null - * - * @return The builder instance, for chaining - */ @Nonnull + @Override CommandData setLocalizationFunction(@Nonnull LocalizationFunction localizationFunction); - /** - * Configure the command name. - * - * @param name - * The name, 1-{@value #MAX_NAME_LENGTH} characters (lowercase and alphanumeric for {@link Command.Type#SLASH}) - * - * @throws IllegalArgumentException - * If the name is not between 1-{@value #MAX_NAME_LENGTH} characters long, or not lowercase and alphanumeric for slash commands - * - * @return The builder instance, for chaining - */ @Nonnull + @Override CommandData setName(@Nonnull String name); - /** - * Sets a {@link DiscordLocale language-specific} localization of this command's name. - * - * @param locale - * The locale to associate the translated name with - * - * @param name - * The translated name to put - * - * @throws IllegalArgumentException - *

    - * - * @return This builder instance, for chaining - */ @Nonnull + @Override CommandData setNameLocalization(@Nonnull DiscordLocale locale, @Nonnull String name); - /** - * Sets multiple {@link DiscordLocale language-specific} localizations of this command's name. - * - * @param map - * The map from which to transfer the translated names - * - * @throws IllegalArgumentException - * - * - * @return This builder instance, for chaining - */ @Nonnull + @Override CommandData setNameLocalizations(@Nonnull Map map); - /** - * Sets the {@link net.dv8tion.jda.api.Permission Permissions} that a user must have in a specific channel to be able to use this command. - *
    By default, everyone can use this command ({@link DefaultMemberPermissions#ENABLED}). Additionally, a command can be disabled for everyone but admins via {@link DefaultMemberPermissions#DISABLED}. - *

    These configurations can be overwritten by moderators in each guild. See {@link Command#retrievePrivileges(net.dv8tion.jda.api.entities.Guild)} to get moderator defined overrides. - * - * @param permission - * {@link DefaultMemberPermissions} representing the default permissions of this command. - * - * @return The builder instance, for chaining - * - * @see DefaultMemberPermissions#ENABLED - * @see DefaultMemberPermissions#DISABLED - */ @Nonnull + @Override CommandData setDefaultPermissions(@Nonnull DefaultMemberPermissions permission); - /** - * Sets whether this command is only usable in a guild (Default: false). - *
    This only has an effect if this command is registered globally. - * - * @param guildOnly - * Whether to restrict this command to guilds - * - * @return The builder instance, for chaining - */ @Nonnull + @Override CommandData setGuildOnly(boolean guildOnly); - /** - * Sets whether this command should only be usable in NSFW (age-restricted) channels. - *
    Default: false - * - *

    Note: Age-restricted commands will not show up in direct messages by default unless the user enables them in their settings. - * - * @param nsfw - * True, to make this command nsfw - * - * @return The builder instance, for chaining - * - * @see Age-Restricted Commands FAQ - */ @Nonnull + @Override CommandData setNSFW(boolean nsfw); - /** - * The current command name - * - * @return The command name - */ - @Nonnull - String getName(); - - /** - * The localizations of this command's name for {@link DiscordLocale various languages}. - * - * @return The {@link LocalizationMap} containing the mapping from {@link DiscordLocale} to the localized name - */ - @Nonnull - LocalizationMap getNameLocalizations(); - - /** - * The {@link Command.Type} - * - * @return The {@link Command.Type} - */ - @Nonnull - Command.Type getType(); - - /** - * Gets the {@link DefaultMemberPermissions} of this command. - *
    If no permissions have been set, this returns {@link DefaultMemberPermissions#ENABLED}. - * - * @return DefaultMemberPermissions of this command. - * - * @see DefaultMemberPermissions#ENABLED - * @see DefaultMemberPermissions#DISABLED - */ - @Nonnull - DefaultMemberPermissions getDefaultPermissions(); - - /** - * Whether the command can only be used inside a guild. - *
    Always true for guild commands. - * - * @return True, if this command is restricted to guilds. - */ - boolean isGuildOnly(); - - /** - * Whether this command should only be usable in NSFW (age-restricted) channels - * - * @return True, if this command is restricted to NSFW channels - * - * @see Age-Restricted Commands FAQ - */ - boolean isNSFW(); - /** * Converts the provided {@link Command} into a CommandData instance. * diff --git a/src/main/java/net/dv8tion/jda/api/interactions/commands/build/Commands.java b/src/main/java/net/dv8tion/jda/api/interactions/commands/build/Commands.java index 96796b4477..4cd6de3d87 100644 --- a/src/main/java/net/dv8tion/jda/api/interactions/commands/build/Commands.java +++ b/src/main/java/net/dv8tion/jda/api/interactions/commands/build/Commands.java @@ -20,6 +20,7 @@ import net.dv8tion.jda.api.utils.data.DataArray; import net.dv8tion.jda.api.utils.data.DataObject; import net.dv8tion.jda.internal.interactions.CommandDataImpl; +import net.dv8tion.jda.internal.interactions.EntryPointCommandDataImpl; import net.dv8tion.jda.internal.utils.Checks; import javax.annotation.Nonnull; @@ -129,11 +130,37 @@ public static CommandData context(@Nonnull Command.Type type, @Nonnull String na return new CommandDataImpl(type, name); } + /** + * Create an activity entry point command builder. + * + *

    Only one entry point can be created per app. + * + * @param name + * The entry point name, 1-32 lowercase alphanumeric characters + * @param description + * The entry point description, 1-100 characters + * + * @throws IllegalArgumentException + * If any of the following requirements are not met + *

    + * + * @return {@link EntryPointCommandData} builder for the app's activity entry point command + */ + @Nonnull + public static EntryPointCommandData entryPoint(@Nonnull String name, @Nonnull String description) + { + return new EntryPointCommandDataImpl(name, description); + } /** * Parses the provided serialization back into an CommandData instance. *
    This is the reverse function for {@link CommandData#toData()}. * + *

    Note: This does not take into account {@link #entryPoint(String, String) entry point commands}. + * * @param array * Array of serialized {@link DataObject} representing the commands * @@ -146,6 +173,7 @@ public static CommandData context(@Nonnull Command.Type type, @Nonnull String na * * @see CommandData#fromData(DataObject) * @see SlashCommandData#fromData(DataObject) + * @see EntryPointCommandData#fromData(DataObject) */ @Nonnull public static List fromList(@Nonnull DataArray array) @@ -160,6 +188,8 @@ public static List fromList(@Nonnull DataArray array) * Parses the provided serialization back into an CommandData instance. *
    This is the reverse function for {@link CommandData#toData()}. * + *

    Note: This does not take into account {@link #entryPoint(String, String) entry point commands}. + * * @param collection * Collection of serialized {@link DataObject} representing the commands * @@ -172,6 +202,7 @@ public static List fromList(@Nonnull DataArray array) * * @see CommandData#fromData(DataObject) * @see SlashCommandData#fromData(DataObject) + * @see EntryPointCommandData#fromData(DataObject) */ @Nonnull public static List fromList(@Nonnull Collection collection) diff --git a/src/main/java/net/dv8tion/jda/api/interactions/commands/build/EntryPointCommandData.java b/src/main/java/net/dv8tion/jda/api/interactions/commands/build/EntryPointCommandData.java new file mode 100644 index 0000000000..58fccbf97e --- /dev/null +++ b/src/main/java/net/dv8tion/jda/api/interactions/commands/build/EntryPointCommandData.java @@ -0,0 +1,217 @@ +/* + * 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.build; + +import net.dv8tion.jda.api.interactions.DiscordLocale; +import net.dv8tion.jda.api.interactions.commands.Command; +import net.dv8tion.jda.api.interactions.commands.DefaultMemberPermissions; +import net.dv8tion.jda.api.interactions.commands.build.attributes.*; +import net.dv8tion.jda.api.interactions.commands.localization.LocalizationFunction; +import net.dv8tion.jda.api.requests.restaction.GlobalCommandListUpdateAction; +import net.dv8tion.jda.api.utils.data.DataObject; +import net.dv8tion.jda.api.utils.data.SerializableData; +import net.dv8tion.jda.internal.interactions.EntryPointCommandDataImpl; +import net.dv8tion.jda.internal.utils.Checks; +import net.dv8tion.jda.internal.utils.localization.LocalizationUtils; + +import javax.annotation.Nonnull; +import java.util.Map; + +/** + * Builder for Entry Point Commands. + *
    Use {@link Commands#entryPoint(String, String)} to create instances of this interface. + * + *

    This command can only be added via {@link GlobalCommandListUpdateAction#setEntryPointCommand(EntryPointCommandData)}. + * + * @see Commands#entryPoint(String, String) + */ +public interface EntryPointCommandData + extends IDescribedCommandData, INamedCommandData, IScopedCommandData, IRestrictedCommandData, + IAgeRestrictedCommandData, SerializableData +{ + @Nonnull + @Override + EntryPointCommandData setLocalizationFunction(@Nonnull LocalizationFunction localizationFunction); + + @Nonnull + @Override + EntryPointCommandData setName(@Nonnull String name); + + @Nonnull + @Override + EntryPointCommandData setNameLocalization(@Nonnull DiscordLocale locale, @Nonnull String name); + + @Nonnull + @Override + EntryPointCommandData setNameLocalizations(@Nonnull Map map); + + @Nonnull + @Override + EntryPointCommandData setDescription(@Nonnull String description); + + @Nonnull + @Override + EntryPointCommandData setDescriptionLocalization(@Nonnull DiscordLocale locale, @Nonnull String description); + + @Nonnull + @Override + EntryPointCommandData setDescriptionLocalizations(@Nonnull Map map); + + @Nonnull + @Override + EntryPointCommandData setDefaultPermissions(@Nonnull DefaultMemberPermissions permission); + + @Nonnull + @Override + EntryPointCommandData setGuildOnly(boolean guildOnly); + + @Nonnull + @Override + EntryPointCommandData setNSFW(boolean nsfw); + + /** + * Sets the handler of this entry point command. + * This defines the behavior when this command is used. + * + * @param handler + * The handler type for this command + * + * @return This builder instance, for chaining + */ + @Nonnull + EntryPointCommandData setHandler(@Nonnull Handler handler); + + /** + * Converts the provided {@link Command} into a {@link EntryPointCommandData} instance. + * + * @param command + * The command to convert + * + * @throws IllegalArgumentException + * If null is provided or the command has illegal configuration + * + * @return An instance of {@link EntryPointCommandData} + */ + @Nonnull + @SuppressWarnings("DataFlowIssue") // Handler cannot be null if command type is correct + static EntryPointCommandData fromCommand(@Nonnull Command command) + { + Checks.notNull(command, "Command"); + if (command.getType() != Command.Type.PRIMARY_ENTRY_POINT) + throw new IllegalArgumentException("Cannot convert command of type " + command.getType() + " to EntryPointCommandData!"); + + EntryPointCommandDataImpl data = new EntryPointCommandDataImpl(command.getName(), command.getDescription()); + data.setGuildOnly(command.isGuildOnly()); + data.setNSFW(command.isNSFW()); + data.setDefaultPermissions(command.getDefaultPermissions()); + //Command localizations are unmodifiable, make a copy + data.setNameLocalizations(command.getNameLocalizations().toMap()); + data.setDescriptionLocalizations(command.getDescriptionLocalizations().toMap()); + data.setHandler(command.getHandler()); + return data; + } + + /** + * Parses the provided serialization back into a {@link EntryPointCommandData} instance. + *
    This is the reverse function for {@link EntryPointCommandData#toData()}. + * + * @param object + * The serialized {@link DataObject} representing the command + * + * @throws net.dv8tion.jda.api.exceptions.ParsingException + * If the serialized object is missing required fields + * @throws IllegalArgumentException + * If any of the values are failing the respective checks such as length + * + * @return The parsed {@link EntryPointCommandData} instance, which can be further configured through setters + */ + @Nonnull + static EntryPointCommandData fromData(@Nonnull DataObject object) + { + Checks.notNull(object, "DataObject"); + + Command.Type commandType = Command.Type.fromId(object.getInt("type", 1)); + Checks.check(commandType == Command.Type.PRIMARY_ENTRY_POINT, "Cannot convert command of type " + commandType + " to EntryPointCommandData!"); + + String name = object.getString("name"); + String description = object.getString("description"); + EntryPointCommandDataImpl command = new EntryPointCommandDataImpl(name, description); + command.setGuildOnly(!object.getBoolean("dm_permission", true)); + command.setNSFW(object.getBoolean("nsfw")); + + command.setDefaultPermissions( + object.isNull("default_member_permissions") + ? DefaultMemberPermissions.ENABLED + : DefaultMemberPermissions.enabledFor(object.getLong("default_member_permissions")) + ); + + command.setNameLocalizations(LocalizationUtils.mapFromProperty(object, "name_localizations")); + command.setDescriptionLocalizations(LocalizationUtils.mapFromProperty(object, "description_localizations")); + + command.setHandler(Handler.fromValue(object.getLong("handler"))); + + return command; + } + + /** + * Defines the behavior of an Entry Point Command. + */ + enum Handler + { + UNKNOWN(-1), + /** + * Lets this app handle the activity start via an interaction. + */ + APP_HANDLER(1), + /** + * Lets Discord handle the activity start, + * and sends a follow-up message without coordinating with this app. + */ + DISCORD_LAUNCH_ACTIVITY(2); + + private final int value; + + Handler(int value) + { + this.value = value; + } + + public int getValue() + { + return value; + } + + /** + * Converts the value to the corresponding handler. + * + * @param value + * The value of the handler + * + * @return {@link Handler} + */ + @Nonnull + public static Handler fromValue(long value) + { + for (Handler handler : values()) + { + if (handler.value == value) + return handler; + } + return UNKNOWN; + } + } +} diff --git a/src/main/java/net/dv8tion/jda/api/interactions/commands/build/SlashCommandData.java b/src/main/java/net/dv8tion/jda/api/interactions/commands/build/SlashCommandData.java index fde42cb574..0e0914bed8 100644 --- a/src/main/java/net/dv8tion/jda/api/interactions/commands/build/SlashCommandData.java +++ b/src/main/java/net/dv8tion/jda/api/interactions/commands/build/SlashCommandData.java @@ -21,8 +21,8 @@ import net.dv8tion.jda.api.interactions.commands.Command; import net.dv8tion.jda.api.interactions.commands.DefaultMemberPermissions; import net.dv8tion.jda.api.interactions.commands.OptionType; +import net.dv8tion.jda.api.interactions.commands.build.attributes.IDescribedCommandData; import net.dv8tion.jda.api.interactions.commands.localization.LocalizationFunction; -import net.dv8tion.jda.api.interactions.commands.localization.LocalizationMap; import net.dv8tion.jda.api.utils.data.DataArray; import net.dv8tion.jda.api.utils.data.DataObject; import net.dv8tion.jda.internal.interactions.CommandDataImpl; @@ -39,7 +39,7 @@ /** * Extension of {@link CommandData} which allows setting slash-command specific settings such as options and subcommands. */ -public interface SlashCommandData extends CommandData +public interface SlashCommandData extends CommandData, IDescribedCommandData { @Nonnull @Override @@ -69,76 +69,18 @@ public interface SlashCommandData extends CommandData @Override SlashCommandData setNSFW(boolean nsfw); - /** - * Configure the description - * - * @param description - * The description, 1-{@value #MAX_DESCRIPTION_LENGTH} characters - * - * @throws IllegalArgumentException - * If the name is null or not between 1-{@value #MAX_DESCRIPTION_LENGTH} characters - * - * @return The builder, for chaining - */ @Nonnull + @Override SlashCommandData setDescription(@Nonnull String description); - /** - * Sets a {@link DiscordLocale language-specific} localizations of this command's description. - * - * @param locale - * The locale to associate the translated description with - * - * @param description - * The translated description to put - * - * @throws IllegalArgumentException - *

    - * - * @return This builder instance, for chaining - */ @Nonnull + @Override SlashCommandData setDescriptionLocalization(@Nonnull DiscordLocale locale, @Nonnull String description); - /** - * Sets multiple {@link DiscordLocale language-specific} localizations of this command's description. - * - * @param map - * The map from which to transfer the translated descriptions - * - * @throws IllegalArgumentException - * - * - * @return This builder instance, for chaining - */ @Nonnull + @Override SlashCommandData setDescriptionLocalizations(@Nonnull Map map); - /** - * The configured description - * - * @return The description - */ - @Nonnull - String getDescription(); - - /** - * The localizations of this command's description for {@link DiscordLocale various languages}. - * - * @return The {@link LocalizationMap} containing the mapping from {@link DiscordLocale} to the localized description - */ - @Nonnull - LocalizationMap getDescriptionLocalizations(); - /** * Removes all options that evaluate to {@code true} under the provided {@code condition}. *
    This will not affect options within subcommands. diff --git a/src/main/java/net/dv8tion/jda/api/interactions/commands/build/attributes/IAgeRestrictedCommandData.java b/src/main/java/net/dv8tion/jda/api/interactions/commands/build/attributes/IAgeRestrictedCommandData.java new file mode 100644 index 0000000000..bdec558acf --- /dev/null +++ b/src/main/java/net/dv8tion/jda/api/interactions/commands/build/attributes/IAgeRestrictedCommandData.java @@ -0,0 +1,54 @@ +/* + * 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.build.attributes; + +import javax.annotation.Nonnull; + +/** + * Builder for age restricted Application Commands. + * + * @see net.dv8tion.jda.api.interactions.commands.build.CommandData + * @see net.dv8tion.jda.api.interactions.commands.build.SlashCommandData + * @see net.dv8tion.jda.api.interactions.commands.build.EntryPointCommandData + */ +public interface IAgeRestrictedCommandData extends INamedCommandData +{ + /** + * Sets whether this command should only be usable in NSFW (age-restricted) channels. + *
    Default: false + * + *

    Note: Age-restricted commands will not show up in direct messages by default unless the user enables them in their settings. + * + * @param nsfw + * True, to make this command nsfw + * + * @return The builder instance, for chaining + * + * @see Age-Restricted Commands FAQ + */ + @Nonnull + IAgeRestrictedCommandData setNSFW(boolean nsfw); + + /** + * Whether this command should only be usable in NSFW (age-restricted) channels + * + * @return True, if this command is restricted to NSFW channels + * + * @see Age-Restricted Commands FAQ + */ + boolean isNSFW(); +} diff --git a/src/main/java/net/dv8tion/jda/api/interactions/commands/build/attributes/IDescribedCommandData.java b/src/main/java/net/dv8tion/jda/api/interactions/commands/build/attributes/IDescribedCommandData.java new file mode 100644 index 0000000000..5ad821ad9a --- /dev/null +++ b/src/main/java/net/dv8tion/jda/api/interactions/commands/build/attributes/IDescribedCommandData.java @@ -0,0 +1,124 @@ +/* + * 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.build.attributes; + +import net.dv8tion.jda.api.interactions.DiscordLocale; +import net.dv8tion.jda.api.interactions.commands.localization.LocalizationFunction; +import net.dv8tion.jda.api.interactions.commands.localization.LocalizationMap; + +import javax.annotation.Nonnull; +import java.util.Map; + +/** + * Builder for describable Application Commands. + * + * @see net.dv8tion.jda.api.interactions.commands.build.SlashCommandData + * @see net.dv8tion.jda.api.interactions.commands.build.EntryPointCommandData + */ +public interface IDescribedCommandData extends INamedCommandData +{ + /** + * The maximum length the description of a command can be. ({@value}) + */ + int MAX_DESCRIPTION_LENGTH = 100; + + @Nonnull + @Override + IDescribedCommandData setLocalizationFunction(@Nonnull LocalizationFunction localizationFunction); + + @Nonnull + @Override + IDescribedCommandData setName(@Nonnull String name); + + @Nonnull + @Override + IDescribedCommandData setNameLocalization(@Nonnull DiscordLocale locale, @Nonnull String name); + + @Nonnull + @Override + IDescribedCommandData setNameLocalizations(@Nonnull Map map); + + /** + * Configure the description + * + * @param description + * The description, 1-{@value #MAX_DESCRIPTION_LENGTH} characters + * + * @throws IllegalArgumentException + * If the name is null or not between 1-{@value #MAX_DESCRIPTION_LENGTH} characters + * + * @return The builder, for chaining + */ + @Nonnull + IDescribedCommandData setDescription(@Nonnull String description); + + /** + * Sets a {@link DiscordLocale language-specific} localizations of this command's description. + * + * @param locale + * The locale to associate the translated description with + * + * @param description + * The translated description to put + * + * @throws IllegalArgumentException + *

    + * + * @return This builder instance, for chaining + */ + @Nonnull + IDescribedCommandData setDescriptionLocalization(@Nonnull DiscordLocale locale, @Nonnull String description); + + /** + * Sets multiple {@link DiscordLocale language-specific} localizations of this command's description. + * + * @param map + * The map from which to transfer the translated descriptions + * + * @throws IllegalArgumentException + * + * + * @return This builder instance, for chaining + */ + @Nonnull + IDescribedCommandData setDescriptionLocalizations(@Nonnull Map map); + + /** + * The configured description + * + * @return The description + */ + @Nonnull + String getDescription(); + + /** + * The localizations of this command's description for {@link DiscordLocale various languages}. + * + * @return The {@link LocalizationMap} containing the mapping from {@link DiscordLocale} to the localized description + */ + @Nonnull + LocalizationMap getDescriptionLocalizations(); +} diff --git a/src/main/java/net/dv8tion/jda/api/interactions/commands/build/attributes/INamedCommandData.java b/src/main/java/net/dv8tion/jda/api/interactions/commands/build/attributes/INamedCommandData.java new file mode 100644 index 0000000000..facc9b128f --- /dev/null +++ b/src/main/java/net/dv8tion/jda/api/interactions/commands/build/attributes/INamedCommandData.java @@ -0,0 +1,133 @@ +/* + * 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.build.attributes; + +import net.dv8tion.jda.api.interactions.DiscordLocale; +import net.dv8tion.jda.api.interactions.commands.Command; +import net.dv8tion.jda.api.interactions.commands.localization.LocalizationFunction; +import net.dv8tion.jda.api.interactions.commands.localization.LocalizationMap; + +import javax.annotation.Nonnull; +import java.util.Map; + +/** + * Builder for named Application Commands. + * + * @see net.dv8tion.jda.api.interactions.commands.build.CommandData + * @see net.dv8tion.jda.api.interactions.commands.build.SlashCommandData + * @see net.dv8tion.jda.api.interactions.commands.build.EntryPointCommandData + */ +public interface INamedCommandData +{ + /** + * The maximum length the name of a command can be. ({@value}) + */ + int MAX_NAME_LENGTH = 32; + + /** + * The {@link Command.Type} + * + * @return The {@link Command.Type} + */ + @Nonnull + Command.Type getType(); + + /** + * Sets the {@link LocalizationFunction} for this command + *
    This enables you to have the entirety of this command to be localized. + * + * @param localizationFunction + * The localization function + * + * @throws IllegalArgumentException + * If the localization function is null + * + * @return The builder instance, for chaining + */ + @Nonnull + INamedCommandData setLocalizationFunction(@Nonnull LocalizationFunction localizationFunction); + + /** + * Configure the command name. + * + * @param name + * The name, 1-{@value #MAX_NAME_LENGTH} characters (lowercase and alphanumeric for {@link Command.Type#SLASH}) + * + * @throws IllegalArgumentException + * If the name is not between 1-{@value #MAX_NAME_LENGTH} characters long, or not lowercase and alphanumeric for slash commands + * + * @return The builder instance, for chaining + */ + @Nonnull + INamedCommandData setName(@Nonnull String name); + + /** + * Sets a {@link DiscordLocale language-specific} localization of this command's name. + * + * @param locale + * The locale to associate the translated name with + * + * @param name + * The translated name to put + * + * @throws IllegalArgumentException + *
      + *
    • If the locale is null
    • + *
    • If the name is null
    • + *
    • If the locale is {@link DiscordLocale#UNKNOWN}
    • + *
    • If the name does not pass the corresponding {@link #setName(String) name check}
    • + *
    + * + * @return This builder instance, for chaining + */ + @Nonnull + INamedCommandData setNameLocalization(@Nonnull DiscordLocale locale, @Nonnull String name); + + /** + * Sets multiple {@link DiscordLocale language-specific} localizations of this command's name. + * + * @param map + * The map from which to transfer the translated names + * + * @throws IllegalArgumentException + *
      + *
    • If the map is null
    • + *
    • If the map contains an {@link DiscordLocale#UNKNOWN} key
    • + *
    • If the map contains a name which does not pass the corresponding {@link #setName(String) name check}
    • + *
    + * + * @return This builder instance, for chaining + */ + @Nonnull + INamedCommandData setNameLocalizations(@Nonnull Map map); + + /** + * The current command name + * + * @return The command name + */ + @Nonnull + String getName(); + + /** + * The localizations of this command's name for {@link DiscordLocale various languages}. + * + * @return The {@link LocalizationMap} containing the mapping from {@link DiscordLocale} to the localized name + */ + @Nonnull + LocalizationMap getNameLocalizations(); +} diff --git a/src/main/java/net/dv8tion/jda/api/interactions/commands/build/attributes/IRestrictedCommandData.java b/src/main/java/net/dv8tion/jda/api/interactions/commands/build/attributes/IRestrictedCommandData.java new file mode 100644 index 0000000000..06829228c0 --- /dev/null +++ b/src/main/java/net/dv8tion/jda/api/interactions/commands/build/attributes/IRestrictedCommandData.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.interactions.commands.build.attributes; + +import net.dv8tion.jda.api.interactions.commands.Command; +import net.dv8tion.jda.api.interactions.commands.DefaultMemberPermissions; + +import javax.annotation.Nonnull; + +/** + * Builder for permission restricted Application Commands. + * + * @see net.dv8tion.jda.api.interactions.commands.build.CommandData + * @see net.dv8tion.jda.api.interactions.commands.build.SlashCommandData + * @see net.dv8tion.jda.api.interactions.commands.build.EntryPointCommandData + */ +public interface IRestrictedCommandData extends INamedCommandData +{ + /** + * Sets the {@link net.dv8tion.jda.api.Permission Permissions} that a user must have in a specific channel to be able to use this command. + *
    By default, everyone can use this command ({@link DefaultMemberPermissions#ENABLED}). Additionally, a command can be disabled for everyone but admins via {@link DefaultMemberPermissions#DISABLED}. + *

    These configurations can be overwritten by moderators in each guild. See {@link Command#retrievePrivileges(net.dv8tion.jda.api.entities.Guild)} to get moderator defined overrides. + * + * @param permission + * {@link DefaultMemberPermissions} representing the default permissions of this command. + * + * @return The builder instance, for chaining + * + * @see DefaultMemberPermissions#ENABLED + * @see DefaultMemberPermissions#DISABLED + */ + @Nonnull + IRestrictedCommandData setDefaultPermissions(@Nonnull DefaultMemberPermissions permission); + + /** + * Gets the {@link DefaultMemberPermissions} of this command. + *
    If no permissions have been set, this returns {@link DefaultMemberPermissions#ENABLED}. + * + * @return DefaultMemberPermissions of this command. + * + * @see DefaultMemberPermissions#ENABLED + * @see DefaultMemberPermissions#DISABLED + */ + @Nonnull + DefaultMemberPermissions getDefaultPermissions(); +} diff --git a/src/main/java/net/dv8tion/jda/api/interactions/commands/build/attributes/IScopedCommandData.java b/src/main/java/net/dv8tion/jda/api/interactions/commands/build/attributes/IScopedCommandData.java new file mode 100644 index 0000000000..2018d53c86 --- /dev/null +++ b/src/main/java/net/dv8tion/jda/api/interactions/commands/build/attributes/IScopedCommandData.java @@ -0,0 +1,49 @@ +/* + * 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.build.attributes; + +import javax.annotation.Nonnull; + +/** + * Builder for scoped Application Commands. + * + * @see net.dv8tion.jda.api.interactions.commands.build.CommandData + * @see net.dv8tion.jda.api.interactions.commands.build.SlashCommandData + * @see net.dv8tion.jda.api.interactions.commands.build.EntryPointCommandData + */ +public interface IScopedCommandData extends INamedCommandData +{ + /** + * Sets whether this command is only usable in a guild (Default: false). + *
    This only has an effect if this command is registered globally. + * + * @param guildOnly + * Whether to restrict this command to guilds + * + * @return The builder instance, for chaining + */ + @Nonnull + IScopedCommandData setGuildOnly(boolean guildOnly); + + /** + * Whether the command can only be used inside a guild. + *
    Always true for guild commands. + * + * @return True, if this command is restricted to guilds. + */ + boolean isGuildOnly(); +} 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 2b2290c213..0f3c477cce 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 @@ -19,10 +19,7 @@ import net.dv8tion.jda.api.entities.Message; import net.dv8tion.jda.api.entities.channel.unions.GuildMessageChannelUnion; import net.dv8tion.jda.api.entities.channel.unions.MessageChannelUnion; -import net.dv8tion.jda.api.interactions.callbacks.IMessageEditCallback; -import net.dv8tion.jda.api.interactions.callbacks.IModalCallback; -import net.dv8tion.jda.api.interactions.callbacks.IPremiumRequiredReplyCallback; -import net.dv8tion.jda.api.interactions.callbacks.IReplyCallback; +import net.dv8tion.jda.api.interactions.callbacks.*; import javax.annotation.Nonnull; @@ -32,7 +29,7 @@ *

    Instead of {@link #deferReply()} and {@link #reply(String)} you can use {@link #deferEdit()} and {@link #editMessage(String)} with these interactions! * You can only acknowledge an interaction once! */ -public interface ComponentInteraction extends IReplyCallback, IMessageEditCallback, IModalCallback, IPremiumRequiredReplyCallback +public interface ComponentInteraction extends IReplyCallback, IMessageEditCallback, IModalCallback, IPremiumRequiredReplyCallback, ILaunchActivityReplyCallback { /** * The custom component ID provided to the component when it was originally created. diff --git a/src/main/java/net/dv8tion/jda/api/interactions/modals/ModalInteraction.java b/src/main/java/net/dv8tion/jda/api/interactions/modals/ModalInteraction.java index f602cdc82f..9f28f8734f 100644 --- a/src/main/java/net/dv8tion/jda/api/interactions/modals/ModalInteraction.java +++ b/src/main/java/net/dv8tion/jda/api/interactions/modals/ModalInteraction.java @@ -19,6 +19,7 @@ import net.dv8tion.jda.api.entities.Message; import net.dv8tion.jda.api.entities.channel.unions.GuildMessageChannelUnion; import net.dv8tion.jda.api.entities.channel.unions.MessageChannelUnion; +import net.dv8tion.jda.api.interactions.callbacks.ILaunchActivityReplyCallback; import net.dv8tion.jda.api.interactions.callbacks.IMessageEditCallback; import net.dv8tion.jda.api.interactions.callbacks.IReplyCallback; import net.dv8tion.jda.internal.utils.Checks; @@ -36,7 +37,7 @@ * * @see net.dv8tion.jda.api.events.interaction.ModalInteractionEvent */ -public interface ModalInteraction extends IReplyCallback, IMessageEditCallback +public interface ModalInteraction extends IReplyCallback, IMessageEditCallback, ILaunchActivityReplyCallback { /** * Returns the custom id of the Modal in question diff --git a/src/main/java/net/dv8tion/jda/api/requests/restaction/GlobalCommandListUpdateAction.java b/src/main/java/net/dv8tion/jda/api/requests/restaction/GlobalCommandListUpdateAction.java new file mode 100644 index 0000000000..450a184862 --- /dev/null +++ b/src/main/java/net/dv8tion/jda/api/requests/restaction/GlobalCommandListUpdateAction.java @@ -0,0 +1,82 @@ +/* + * 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.interactions.commands.build.CommandData; +import net.dv8tion.jda.api.interactions.commands.build.EntryPointCommandData; +import net.dv8tion.jda.api.requests.RestAction; + +import javax.annotation.CheckReturnValue; +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import java.util.Collection; +import java.util.concurrent.TimeUnit; +import java.util.function.BooleanSupplier; + +/** + * Specialized {@link RestAction} used to replace existing commands globally. + *
    Any commands that currently exist and are not listed through {@link #addCommands(CommandData...)} will be DELETED! + *
    If your bot has activities enabled, you must {@link #setEntryPointCommand(EntryPointCommandData) set your entry point command}. + * + *

    This operation is idempotent. Commands will persist between restarts of your bot, you only have to create a command once. + */ +public interface GlobalCommandListUpdateAction extends CommandListUpdateAction +{ + @Nonnull + @Override + @CheckReturnValue + GlobalCommandListUpdateAction timeout(long timeout, @Nonnull TimeUnit unit); + + @Nonnull + @Override + @CheckReturnValue + GlobalCommandListUpdateAction deadline(long timestamp); + + @Nonnull + @Override + @CheckReturnValue + GlobalCommandListUpdateAction setCheck(@Nullable BooleanSupplier checks); + + @Nonnull + @Override + @CheckReturnValue + GlobalCommandListUpdateAction addCheck(@Nonnull BooleanSupplier checks); + + @Nonnull + @Override + @CheckReturnValue + GlobalCommandListUpdateAction addCommands(@Nonnull Collection commands); + + @Nonnull + @Override + @CheckReturnValue + GlobalCommandListUpdateAction addCommands(@Nonnull CommandData... commands); + + /** + * Sets your app's activity primary entry point. + *
    This must be set if your application has activities enabled. + *
    Using this with activities disabled will not make the entry point appear. + * + * @param entryPoint + * The entry point data + * + * @return This instance, for chaining + */ + @Nonnull + @CheckReturnValue + GlobalCommandListUpdateAction setEntryPointCommand(@Nonnull EntryPointCommandData entryPoint); +} diff --git a/src/main/java/net/dv8tion/jda/api/requests/restaction/interactions/InteractionCallbackAction.java b/src/main/java/net/dv8tion/jda/api/requests/restaction/interactions/InteractionCallbackAction.java index 10c3363a8c..a7d85d3623 100644 --- a/src/main/java/net/dv8tion/jda/api/requests/restaction/interactions/InteractionCallbackAction.java +++ b/src/main/java/net/dv8tion/jda/api/requests/restaction/interactions/InteractionCallbackAction.java @@ -65,6 +65,8 @@ enum ResponseType */ @Deprecated PREMIUM_REQUIRED(10), + /** Launch the app's activity */ + LAUNCH_ACTIVITY(12), ; private final int raw; diff --git a/src/main/java/net/dv8tion/jda/api/requests/restaction/interactions/LaunchActivityCallbackAction.java b/src/main/java/net/dv8tion/jda/api/requests/restaction/interactions/LaunchActivityCallbackAction.java new file mode 100644 index 0000000000..d234bcb0f5 --- /dev/null +++ b/src/main/java/net/dv8tion/jda/api/requests/restaction/interactions/LaunchActivityCallbackAction.java @@ -0,0 +1,29 @@ +/* + * 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.interactions; + +import net.dv8tion.jda.api.requests.FluentRestAction; + +/** + * An {@link InteractionCallbackAction} that can be used to launch an activity. + * + * @see net.dv8tion.jda.api.interactions.callbacks.ILaunchActivityReplyCallback + */ +public interface LaunchActivityCallbackAction extends InteractionCallbackAction, FluentRestAction +{ + +} diff --git a/src/main/java/net/dv8tion/jda/internal/JDAImpl.java b/src/main/java/net/dv8tion/jda/internal/JDAImpl.java index 9c1be36130..87f18e6cb8 100644 --- a/src/main/java/net/dv8tion/jda/internal/JDAImpl.java +++ b/src/main/java/net/dv8tion/jda/internal/JDAImpl.java @@ -1109,10 +1109,10 @@ public CommandCreateAction upsertCommand(@Nonnull CommandData command) @Nonnull @Override - public CommandListUpdateAction updateCommands() + public GlobalCommandListUpdateAction updateCommands() { Route.CompiledRoute route = Route.Interactions.UPDATE_COMMANDS.compile(getSelfUser().getApplicationId()); - return new CommandListUpdateActionImpl(this, null, route); + return new GlobalCommandListUpdateActionImpl(this, route); } @Nonnull diff --git a/src/main/java/net/dv8tion/jda/internal/handle/InteractionCreateHandler.java b/src/main/java/net/dv8tion/jda/internal/handle/InteractionCreateHandler.java index 719080c70b..5b1506ff61 100644 --- a/src/main/java/net/dv8tion/jda/internal/handle/InteractionCreateHandler.java +++ b/src/main/java/net/dv8tion/jda/internal/handle/InteractionCreateHandler.java @@ -20,10 +20,7 @@ import net.dv8tion.jda.api.entities.channel.ChannelType; import net.dv8tion.jda.api.events.interaction.GenericInteractionCreateEvent; import net.dv8tion.jda.api.events.interaction.ModalInteractionEvent; -import net.dv8tion.jda.api.events.interaction.command.CommandAutoCompleteInteractionEvent; -import net.dv8tion.jda.api.events.interaction.command.MessageContextInteractionEvent; -import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent; -import net.dv8tion.jda.api.events.interaction.command.UserContextInteractionEvent; +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.EntitySelectInteractionEvent; import net.dv8tion.jda.api.events.interaction.component.StringSelectInteractionEvent; @@ -33,10 +30,7 @@ import net.dv8tion.jda.api.utils.data.DataObject; import net.dv8tion.jda.internal.JDAImpl; import net.dv8tion.jda.internal.interactions.InteractionImpl; -import net.dv8tion.jda.internal.interactions.command.CommandAutoCompleteInteractionImpl; -import net.dv8tion.jda.internal.interactions.command.MessageContextInteractionImpl; -import net.dv8tion.jda.internal.interactions.command.SlashCommandInteractionImpl; -import net.dv8tion.jda.internal.interactions.command.UserContextInteractionImpl; +import net.dv8tion.jda.internal.interactions.command.*; import net.dv8tion.jda.internal.interactions.component.ButtonInteractionImpl; import net.dv8tion.jda.internal.interactions.component.EntitySelectInteractionImpl; import net.dv8tion.jda.internal.interactions.component.StringSelectInteractionImpl; @@ -123,6 +117,11 @@ private void handleCommand(DataObject content) new UserContextInteractionEvent(api, responseNumber, new UserContextInteractionImpl(api, content))); break; + case PRIMARY_ENTRY_POINT: + api.handleEvent( + new PrimaryEntryPointInteractionEvent(api, responseNumber, + new PrimaryEntryPointInteractionImpl(api, content))); + break; } } diff --git a/src/main/java/net/dv8tion/jda/internal/interactions/CommandDataImpl.java b/src/main/java/net/dv8tion/jda/internal/interactions/CommandDataImpl.java index 88bc202595..b882f6bd34 100644 --- a/src/main/java/net/dv8tion/jda/internal/interactions/CommandDataImpl.java +++ b/src/main/java/net/dv8tion/jda/internal/interactions/CommandDataImpl.java @@ -27,6 +27,7 @@ import net.dv8tion.jda.api.utils.data.DataObject; import net.dv8tion.jda.api.utils.data.SerializableData; import net.dv8tion.jda.internal.interactions.command.localization.LocalizationMapper; +import net.dv8tion.jda.internal.interactions.mixin.attributes.IDescribedCommandDataMixin; import net.dv8tion.jda.internal.utils.Checks; import net.dv8tion.jda.internal.utils.Helpers; @@ -35,7 +36,7 @@ import java.util.function.Predicate; import java.util.stream.Stream; -public class CommandDataImpl implements SlashCommandData +public class CommandDataImpl implements SlashCommandData, IDescribedCommandDataMixin { protected final List options = new ArrayList<>(MAX_OPTIONS); @@ -74,22 +75,6 @@ protected void checkType(Command.Type required, String action) throw new IllegalStateException("Cannot " + action + " for commands of type " + type); } - public void checkName(@Nonnull String name) - { - Checks.inRange(name, 1, MAX_NAME_LENGTH, "Name"); - if (type == Command.Type.SLASH) - { - Checks.matches(name, Checks.ALPHANUMERIC_WITH_DASH, "Name"); - Checks.isLowercase(name, "Name"); - } - } - - public void checkDescription(@Nonnull String description) - { - checkType(Command.Type.SLASH, "set description"); - Checks.inRange(description, 1, MAX_DESCRIPTION_LENGTH, "Description"); - } - @Nonnull @Override public DataObject toData() diff --git a/src/main/java/net/dv8tion/jda/internal/interactions/EntryPointCommandDataImpl.java b/src/main/java/net/dv8tion/jda/internal/interactions/EntryPointCommandDataImpl.java new file mode 100644 index 0000000000..031d2cea5a --- /dev/null +++ b/src/main/java/net/dv8tion/jda/internal/interactions/EntryPointCommandDataImpl.java @@ -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.internal.interactions; + +import net.dv8tion.jda.api.interactions.DiscordLocale; +import net.dv8tion.jda.api.interactions.commands.Command; +import net.dv8tion.jda.api.interactions.commands.DefaultMemberPermissions; +import net.dv8tion.jda.api.interactions.commands.build.EntryPointCommandData; +import net.dv8tion.jda.api.interactions.commands.localization.LocalizationFunction; +import net.dv8tion.jda.api.interactions.commands.localization.LocalizationMap; +import net.dv8tion.jda.api.utils.data.DataArray; +import net.dv8tion.jda.api.utils.data.DataObject; +import net.dv8tion.jda.internal.interactions.command.localization.LocalizationMapper; +import net.dv8tion.jda.internal.interactions.mixin.attributes.IDescribedCommandDataMixin; +import net.dv8tion.jda.internal.utils.Checks; + +import javax.annotation.Nonnull; +import java.util.Map; + +public class EntryPointCommandDataImpl implements EntryPointCommandData, IDescribedCommandDataMixin +{ + protected String name, description = ""; + private LocalizationMapper localizationMapper; + private final LocalizationMap nameLocalizations = new LocalizationMap(this::checkName); + private final LocalizationMap descriptionLocalizations = new LocalizationMap(this::checkDescription); + + private boolean guildOnly = false; + private boolean nsfw = false; + private DefaultMemberPermissions defaultMemberPermissions = DefaultMemberPermissions.ENABLED; + private Handler handler; + + public EntryPointCommandDataImpl(@Nonnull String name, @Nonnull String description) + { + setName(name); + setDescription(description); + } + + @Nonnull + @Override + public DataObject toData() + { + if (localizationMapper != null) localizationMapper.localizeCommand(this, DataArray.empty()); + + return DataObject.empty() + .put("type", getType().getId()) + .put("handler", handler.getValue()) + .put("name", name) + .put("description", description) + .put("description_localizations", descriptionLocalizations) + .put("nsfw", nsfw) + .put("dm_permission", !guildOnly) + .put("default_member_permissions", defaultMemberPermissions == DefaultMemberPermissions.ENABLED + ? null + : Long.toUnsignedString(defaultMemberPermissions.getPermissionsRaw())) + .put("name_localizations", nameLocalizations); + } + + @Nonnull + @Override + public Command.Type getType() + { + return Command.Type.PRIMARY_ENTRY_POINT; + } + + @Nonnull + @Override + public DefaultMemberPermissions getDefaultPermissions() + { + return defaultMemberPermissions; + } + + @Override + public boolean isGuildOnly() + { + return guildOnly; + } + + @Override + public boolean isNSFW() + { + return nsfw; + } + + @Nonnull + @Override + public EntryPointCommandDataImpl setDefaultPermissions(@Nonnull DefaultMemberPermissions permissions) + { + Checks.notNull(permissions, "Permissions"); + this.defaultMemberPermissions = permissions; + return this; + } + + @Nonnull + @Override + public EntryPointCommandDataImpl setGuildOnly(boolean guildOnly) + { + this.guildOnly = guildOnly; + return this; + } + + @Nonnull + @Override + public EntryPointCommandDataImpl setNSFW(boolean nsfw) + { + this.nsfw = nsfw; + return this; + } + + @Nonnull + @Override + public EntryPointCommandDataImpl setLocalizationFunction(@Nonnull LocalizationFunction localizationFunction) { + Checks.notNull(localizationFunction, "Localization function"); + + this.localizationMapper = LocalizationMapper.fromFunction(localizationFunction); + return this; + } + + @Nonnull + @Override + public EntryPointCommandDataImpl setName(@Nonnull String name) + { + checkName(name); + this.name = name; + return this; + } + + @Nonnull + @Override + public EntryPointCommandDataImpl setNameLocalization(@Nonnull DiscordLocale locale, @Nonnull String name) + { + //Checks are done in LocalizationMap + nameLocalizations.setTranslation(locale, name); + return this; + } + + @Nonnull + @Override + public EntryPointCommandDataImpl setNameLocalizations(@Nonnull Map map) + { + nameLocalizations.setTranslations(map); + return this; + } + + @Nonnull + @Override + public EntryPointCommandDataImpl setDescription(@Nonnull String description) + { + checkDescription(description); + this.description = description; + return this; + } + + @Nonnull + @Override + public EntryPointCommandDataImpl setDescriptionLocalization(@Nonnull DiscordLocale locale, @Nonnull String description) + { + //Checks are done in LocalizationMap + descriptionLocalizations.setTranslation(locale, description); + return this; + } + + @Nonnull + @Override + public EntryPointCommandDataImpl setDescriptionLocalizations(@Nonnull Map map) + { + descriptionLocalizations.setTranslations(map); + return this; + } + + @Nonnull + @Override + public EntryPointCommandData setHandler(@Nonnull Handler handler) + { + this.handler = handler; + return this; + } + + @Nonnull + @Override + public String getName() + { + return name; + } + + @Nonnull + @Override + public LocalizationMap getNameLocalizations() + { + return nameLocalizations; + } + + @Nonnull + @Override + public String getDescription() + { + return description; + } + + @Nonnull + @Override + public LocalizationMap getDescriptionLocalizations() + { + return descriptionLocalizations; + } +} diff --git a/src/main/java/net/dv8tion/jda/internal/interactions/command/CommandImpl.java b/src/main/java/net/dv8tion/jda/internal/interactions/command/CommandImpl.java index 1300583913..8170ec610a 100644 --- a/src/main/java/net/dv8tion/jda/internal/interactions/command/CommandImpl.java +++ b/src/main/java/net/dv8tion/jda/internal/interactions/command/CommandImpl.java @@ -21,6 +21,7 @@ import net.dv8tion.jda.api.interactions.commands.Command; import net.dv8tion.jda.api.interactions.commands.DefaultMemberPermissions; import net.dv8tion.jda.api.interactions.commands.OptionType; +import net.dv8tion.jda.api.interactions.commands.build.EntryPointCommandData; import net.dv8tion.jda.api.interactions.commands.localization.LocalizationMap; import net.dv8tion.jda.api.interactions.commands.privileges.IntegrationPrivilege; import net.dv8tion.jda.api.requests.RestAction; @@ -36,6 +37,7 @@ import net.dv8tion.jda.internal.utils.localization.LocalizationUtils; import javax.annotation.Nonnull; +import javax.annotation.Nullable; import java.util.Collections; import java.util.EnumSet; import java.util.List; @@ -55,6 +57,7 @@ public class CommandImpl implements Command private final String name, description; private final LocalizationMap nameLocalizations; private final LocalizationMap descriptionLocalizations; + private final EntryPointCommandData.Handler handler; private final List options; private final List groups; private final List subcommands; @@ -71,6 +74,9 @@ public CommandImpl(JDAImpl api, Guild guild, DataObject json) this.nameLocalizations = LocalizationUtils.unmodifiableFromProperty(json, "name_localizations"); this.description = json.getString("description", ""); this.descriptionLocalizations = LocalizationUtils.unmodifiableFromProperty(json, "description_localizations"); + this.handler = json.hasKey("handler") + ? EntryPointCommandData.Handler.fromValue(json.getLong("handler")) + : null; this.type = Command.Type.fromId(json.getInt("type", 1)); this.id = json.getUnsignedLong("id"); this.guildId = guild != null ? guild.getIdLong() : 0L; @@ -178,6 +184,13 @@ public LocalizationMap getDescriptionLocalizations() return descriptionLocalizations; } + @Nullable + @Override + public EntryPointCommandData.Handler getHandler() + { + return handler; + } + @Nonnull @Override public List getOptions() diff --git a/src/main/java/net/dv8tion/jda/internal/interactions/command/CommandInteractionImpl.java b/src/main/java/net/dv8tion/jda/internal/interactions/command/CommandInteractionImpl.java index 9d437bac2c..4bea3ae8cb 100644 --- a/src/main/java/net/dv8tion/jda/internal/interactions/command/CommandInteractionImpl.java +++ b/src/main/java/net/dv8tion/jda/internal/interactions/command/CommandInteractionImpl.java @@ -19,12 +19,14 @@ import net.dv8tion.jda.api.interactions.commands.CommandInteraction; import net.dv8tion.jda.api.interactions.commands.CommandInteractionPayload; import net.dv8tion.jda.api.interactions.modals.Modal; +import net.dv8tion.jda.api.requests.restaction.interactions.LaunchActivityCallbackAction; import net.dv8tion.jda.api.requests.restaction.interactions.ModalCallbackAction; import net.dv8tion.jda.api.requests.restaction.interactions.PremiumRequiredCallbackAction; import net.dv8tion.jda.api.requests.restaction.interactions.ReplyCallbackAction; import net.dv8tion.jda.api.utils.data.DataObject; import net.dv8tion.jda.internal.JDAImpl; import net.dv8tion.jda.internal.interactions.DeferrableInteractionImpl; +import net.dv8tion.jda.internal.requests.restaction.interactions.LaunchActivityCallbackActionImpl; import net.dv8tion.jda.internal.requests.restaction.interactions.ModalCallbackActionImpl; import net.dv8tion.jda.internal.requests.restaction.interactions.PremiumRequiredCallbackActionImpl; import net.dv8tion.jda.internal.requests.restaction.interactions.ReplyCallbackActionImpl; @@ -69,4 +71,11 @@ public PremiumRequiredCallbackAction replyWithPremiumRequired() { return new PremiumRequiredCallbackActionImpl(this); } + + @Nonnull + @Override + public LaunchActivityCallbackAction replyWithLaunchedActivity() + { + return new LaunchActivityCallbackActionImpl(this); + } } diff --git a/src/main/java/net/dv8tion/jda/internal/interactions/command/PrimaryEntryPointInteractionImpl.java b/src/main/java/net/dv8tion/jda/internal/interactions/command/PrimaryEntryPointInteractionImpl.java new file mode 100644 index 0000000000..bb9fab374a --- /dev/null +++ b/src/main/java/net/dv8tion/jda/internal/interactions/command/PrimaryEntryPointInteractionImpl.java @@ -0,0 +1,40 @@ +/* + * 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.internal.interactions.command; + +import net.dv8tion.jda.api.entities.channel.unions.MessageChannelUnion; +import net.dv8tion.jda.api.interactions.commands.PrimaryEntryPointInteraction; +import net.dv8tion.jda.api.utils.data.DataObject; +import net.dv8tion.jda.internal.JDAImpl; + +import javax.annotation.Nonnull; + +public class PrimaryEntryPointInteractionImpl extends CommandInteractionImpl implements PrimaryEntryPointInteraction +{ + public PrimaryEntryPointInteractionImpl(JDAImpl jda, DataObject data) + { + super(jda, data); + } + + @Nonnull + @Override + @SuppressWarnings("ConstantConditions") + public MessageChannelUnion getChannel() + { + return (MessageChannelUnion) super.getChannel(); + } +} diff --git a/src/main/java/net/dv8tion/jda/internal/interactions/command/localization/LocalizationMapper.java b/src/main/java/net/dv8tion/jda/internal/interactions/command/localization/LocalizationMapper.java index d7ab4b9638..ba0b3fda65 100644 --- a/src/main/java/net/dv8tion/jda/internal/interactions/command/localization/LocalizationMapper.java +++ b/src/main/java/net/dv8tion/jda/internal/interactions/command/localization/LocalizationMapper.java @@ -17,10 +17,9 @@ package net.dv8tion.jda.internal.interactions.command.localization; import net.dv8tion.jda.api.interactions.DiscordLocale; -import net.dv8tion.jda.api.interactions.commands.Command; import net.dv8tion.jda.api.interactions.commands.OptionType; -import net.dv8tion.jda.api.interactions.commands.build.CommandData; -import net.dv8tion.jda.api.interactions.commands.build.SlashCommandData; +import net.dv8tion.jda.api.interactions.commands.build.attributes.IDescribedCommandData; +import net.dv8tion.jda.api.interactions.commands.build.attributes.INamedCommandData; import net.dv8tion.jda.api.interactions.commands.localization.LocalizationFunction; import net.dv8tion.jda.api.interactions.commands.localization.LocalizationMap; import net.dv8tion.jda.api.utils.data.DataArray; @@ -69,16 +68,16 @@ public static LocalizationMapper fromFunction(@Nonnull LocalizationFunction loca return new LocalizationMapper(localizationFunction); } - public void localizeCommand(CommandData commandData, DataArray optionArray) + public void localizeCommand(INamedCommandData commandData, DataArray optionArray) { final TranslationContext ctx = new TranslationContext(); ctx.withKey(commandData.getName(), () -> { ctx.trySetTranslation(commandData.getNameLocalizations(), "name"); - if (commandData.getType() == Command.Type.SLASH) + if (commandData instanceof IDescribedCommandData) { - final SlashCommandData slashCommandData = (SlashCommandData) commandData; - ctx.trySetTranslation(slashCommandData.getDescriptionLocalizations(), "description"); + final IDescribedCommandData describedCommandData = (IDescribedCommandData) commandData; + ctx.trySetTranslation(describedCommandData.getDescriptionLocalizations(), "description"); localizeOptionArray(optionArray, ctx); } }); diff --git a/src/main/java/net/dv8tion/jda/internal/interactions/component/ComponentInteractionImpl.java b/src/main/java/net/dv8tion/jda/internal/interactions/component/ComponentInteractionImpl.java index e7ec45268b..1f7504374e 100644 --- a/src/main/java/net/dv8tion/jda/internal/interactions/component/ComponentInteractionImpl.java +++ b/src/main/java/net/dv8tion/jda/internal/interactions/component/ComponentInteractionImpl.java @@ -22,6 +22,7 @@ import net.dv8tion.jda.api.entities.channel.unions.MessageChannelUnion; import net.dv8tion.jda.api.interactions.components.ComponentInteraction; import net.dv8tion.jda.api.interactions.modals.Modal; +import net.dv8tion.jda.api.requests.restaction.interactions.LaunchActivityCallbackAction; import net.dv8tion.jda.api.requests.restaction.interactions.ModalCallbackAction; import net.dv8tion.jda.api.requests.restaction.interactions.PremiumRequiredCallbackAction; import net.dv8tion.jda.api.requests.restaction.interactions.ReplyCallbackAction; @@ -29,10 +30,7 @@ import net.dv8tion.jda.internal.JDAImpl; import net.dv8tion.jda.internal.entities.ReceivedMessage; import net.dv8tion.jda.internal.interactions.DeferrableInteractionImpl; -import net.dv8tion.jda.internal.requests.restaction.interactions.MessageEditCallbackActionImpl; -import net.dv8tion.jda.internal.requests.restaction.interactions.ModalCallbackActionImpl; -import net.dv8tion.jda.internal.requests.restaction.interactions.PremiumRequiredCallbackActionImpl; -import net.dv8tion.jda.internal.requests.restaction.interactions.ReplyCallbackActionImpl; +import net.dv8tion.jda.internal.requests.restaction.interactions.*; import net.dv8tion.jda.internal.utils.Checks; import javax.annotation.Nonnull; @@ -124,4 +122,11 @@ public PremiumRequiredCallbackAction replyWithPremiumRequired() { return new PremiumRequiredCallbackActionImpl(this); } + + @Nonnull + @Override + public LaunchActivityCallbackAction replyWithLaunchedActivity() + { + return new LaunchActivityCallbackActionImpl(this); + } } diff --git a/src/main/java/net/dv8tion/jda/internal/interactions/mixin/attributes/IDescribedCommandDataMixin.java b/src/main/java/net/dv8tion/jda/internal/interactions/mixin/attributes/IDescribedCommandDataMixin.java new file mode 100644 index 0000000000..0bdbfa9f66 --- /dev/null +++ b/src/main/java/net/dv8tion/jda/internal/interactions/mixin/attributes/IDescribedCommandDataMixin.java @@ -0,0 +1,33 @@ +/* + * 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.internal.interactions.mixin.attributes; + +import net.dv8tion.jda.api.interactions.commands.Command; +import net.dv8tion.jda.api.interactions.commands.build.attributes.IDescribedCommandData; +import net.dv8tion.jda.internal.utils.Checks; + +import javax.annotation.Nonnull; + +public interface IDescribedCommandDataMixin extends INamedCommandDataMixin, IDescribedCommandData +{ + default void checkDescription(@Nonnull String description) + { + if (getType() != Command.Type.SLASH && getType() != Command.Type.PRIMARY_ENTRY_POINT) + throw new IllegalStateException("Cannot set description for commands of type " + getType()); + Checks.inRange(description, 1, MAX_DESCRIPTION_LENGTH, "Description"); + } +} diff --git a/src/main/java/net/dv8tion/jda/internal/interactions/mixin/attributes/INamedCommandDataMixin.java b/src/main/java/net/dv8tion/jda/internal/interactions/mixin/attributes/INamedCommandDataMixin.java new file mode 100644 index 0000000000..be0f96f5b3 --- /dev/null +++ b/src/main/java/net/dv8tion/jda/internal/interactions/mixin/attributes/INamedCommandDataMixin.java @@ -0,0 +1,36 @@ +/* + * 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.internal.interactions.mixin.attributes; + +import net.dv8tion.jda.api.interactions.commands.Command; +import net.dv8tion.jda.api.interactions.commands.build.attributes.INamedCommandData; +import net.dv8tion.jda.internal.utils.Checks; + +import javax.annotation.Nonnull; + +public interface INamedCommandDataMixin extends INamedCommandData +{ + default void checkName(@Nonnull String name) + { + Checks.inRange(name, 1, MAX_NAME_LENGTH, "Name"); + if (getType() == Command.Type.SLASH) + { + Checks.matches(name, Checks.ALPHANUMERIC_WITH_DASH, "Name"); + Checks.isLowercase(name, "Name"); + } + } +} diff --git a/src/main/java/net/dv8tion/jda/internal/interactions/modal/ModalInteractionImpl.java b/src/main/java/net/dv8tion/jda/internal/interactions/modal/ModalInteractionImpl.java index 064afdf7ed..bf41830b68 100644 --- a/src/main/java/net/dv8tion/jda/internal/interactions/modal/ModalInteractionImpl.java +++ b/src/main/java/net/dv8tion/jda/internal/interactions/modal/ModalInteractionImpl.java @@ -20,12 +20,14 @@ import net.dv8tion.jda.api.entities.channel.unions.MessageChannelUnion; import net.dv8tion.jda.api.interactions.modals.ModalInteraction; import net.dv8tion.jda.api.interactions.modals.ModalMapping; +import net.dv8tion.jda.api.requests.restaction.interactions.LaunchActivityCallbackAction; import net.dv8tion.jda.api.requests.restaction.interactions.MessageEditCallbackAction; import net.dv8tion.jda.api.requests.restaction.interactions.ReplyCallbackAction; import net.dv8tion.jda.api.utils.data.DataArray; import net.dv8tion.jda.api.utils.data.DataObject; import net.dv8tion.jda.internal.JDAImpl; import net.dv8tion.jda.internal.interactions.DeferrableInteractionImpl; +import net.dv8tion.jda.internal.requests.restaction.interactions.LaunchActivityCallbackActionImpl; import net.dv8tion.jda.internal.requests.restaction.interactions.MessageEditCallbackActionImpl; import net.dv8tion.jda.internal.requests.restaction.interactions.ReplyCallbackActionImpl; @@ -91,6 +93,13 @@ public MessageEditCallbackAction deferEdit() return new MessageEditCallbackActionImpl(hook); } + @Nonnull + @Override + public LaunchActivityCallbackAction replyWithLaunchedActivity() + { + return new LaunchActivityCallbackActionImpl(this); + } + @Nonnull @Override @SuppressWarnings("ConstantConditions") diff --git a/src/main/java/net/dv8tion/jda/internal/requests/restaction/GlobalCommandListUpdateActionImpl.java b/src/main/java/net/dv8tion/jda/internal/requests/restaction/GlobalCommandListUpdateActionImpl.java new file mode 100644 index 0000000000..5770e45401 --- /dev/null +++ b/src/main/java/net/dv8tion/jda/internal/requests/restaction/GlobalCommandListUpdateActionImpl.java @@ -0,0 +1,147 @@ +/* + * 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.internal.requests.restaction; + +import net.dv8tion.jda.api.JDA; +import net.dv8tion.jda.api.interactions.commands.build.CommandData; +import net.dv8tion.jda.api.interactions.commands.build.Commands; +import net.dv8tion.jda.api.interactions.commands.build.EntryPointCommandData; +import net.dv8tion.jda.api.requests.Route; +import net.dv8tion.jda.api.requests.restaction.GlobalCommandListUpdateAction; +import net.dv8tion.jda.api.utils.data.DataArray; +import net.dv8tion.jda.internal.utils.Checks; +import okhttp3.RequestBody; + +import javax.annotation.Nonnull; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.concurrent.TimeUnit; +import java.util.function.BooleanSupplier; +import java.util.stream.Stream; + +public class GlobalCommandListUpdateActionImpl extends CommandListUpdateActionImpl implements GlobalCommandListUpdateAction +{ + private final List commands = new ArrayList<>(); + private int slash, user, message; + private EntryPointCommandData entryPoint; + + public GlobalCommandListUpdateActionImpl(JDA api, Route.CompiledRoute route) + { + super(api, null, route); + } + + @Nonnull + @Override + public GlobalCommandListUpdateAction timeout(long timeout, @Nonnull TimeUnit unit) + { + return (GlobalCommandListUpdateAction) super.timeout(timeout, unit); + } + + @Nonnull + @Override + public GlobalCommandListUpdateAction addCheck(@Nonnull BooleanSupplier checks) + { + return (GlobalCommandListUpdateAction) super.addCheck(checks); + } + + @Nonnull + @Override + public GlobalCommandListUpdateAction setCheck(BooleanSupplier checks) + { + return (GlobalCommandListUpdateAction) super.setCheck(checks); + } + + @Nonnull + @Override + public GlobalCommandListUpdateAction deadline(long timestamp) + { + return (GlobalCommandListUpdateAction) super.deadline(timestamp); + } + + @Nonnull + @Override + public GlobalCommandListUpdateAction addCommands(@Nonnull Collection commands) + { + Checks.noneNull(commands, "Command"); + int newSlash = 0, newUser = 0, newMessage = 0; + for (CommandData command : commands) + { + switch (command.getType()) + { + case SLASH: + newSlash++; + break; + case MESSAGE: + newMessage++; + break; + case USER: + newUser++; + break; + } + } + + Checks.check(slash + newSlash <= Commands.MAX_SLASH_COMMANDS, + "Cannot have more than %d slash commands! Try using subcommands instead.", Commands.MAX_SLASH_COMMANDS); + Checks.check(user + newUser <= Commands.MAX_USER_COMMANDS, + "Cannot have more than %d user context commands!", Commands.MAX_USER_COMMANDS); + Checks.check(message + newMessage <= Commands.MAX_MESSAGE_COMMANDS, + "Cannot have more than %d message context commands!", Commands.MAX_MESSAGE_COMMANDS); + + Checks.checkUnique( + Stream.concat(commands.stream(), this.commands.stream()).map(c -> c.getType() + " " + c.getName()), + "Cannot have multiple commands of the same type with identical names. " + + "Name: \"%s\" with type %s appeared %d times!", + (count, value) -> { + String[] tuple = value.split(" ", 2); + return new Object[] { tuple[1], tuple[0], count }; + } + ); + + slash += newSlash; + user += newUser; + message += newMessage; + + this.commands.addAll(commands); + return this; + } + + @Nonnull + @Override + public GlobalCommandListUpdateAction addCommands(@Nonnull CommandData... commands) + { + return (GlobalCommandListUpdateAction) super.addCommands(commands); + } + + @Nonnull + @Override + public GlobalCommandListUpdateAction setEntryPointCommand(@Nonnull EntryPointCommandData entryPoint) + { + this.entryPoint = entryPoint; + return this; + } + + @Override + protected RequestBody finalizeData() + { + DataArray json = DataArray.empty(); + json.addAll(commands); + if (entryPoint != null) + json.add(entryPoint); + return getRequestBody(json); + } +} diff --git a/src/main/java/net/dv8tion/jda/internal/requests/restaction/interactions/LaunchActivityCallbackActionImpl.java b/src/main/java/net/dv8tion/jda/internal/requests/restaction/interactions/LaunchActivityCallbackActionImpl.java new file mode 100644 index 0000000000..549f888e77 --- /dev/null +++ b/src/main/java/net/dv8tion/jda/internal/requests/restaction/interactions/LaunchActivityCallbackActionImpl.java @@ -0,0 +1,57 @@ +/* + * 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.internal.requests.restaction.interactions; + +import net.dv8tion.jda.api.interactions.callbacks.ILaunchActivityReplyCallback; +import net.dv8tion.jda.api.requests.restaction.interactions.LaunchActivityCallbackAction; +import net.dv8tion.jda.api.utils.data.DataObject; +import net.dv8tion.jda.internal.interactions.InteractionImpl; +import okhttp3.RequestBody; + +import javax.annotation.Nonnull; +import java.util.function.BooleanSupplier; + +public class LaunchActivityCallbackActionImpl extends InteractionCallbackImpl implements LaunchActivityCallbackAction +{ + + public LaunchActivityCallbackActionImpl(ILaunchActivityReplyCallback interaction) + { + super((InteractionImpl) interaction); + } + + @Override + protected RequestBody finalizeData() + { + return getRequestBody(DataObject.empty() + .put("type", ResponseType.LAUNCH_ACTIVITY.getRaw()) + .put("data", DataObject.empty())); + } + + @Nonnull + @Override + public LaunchActivityCallbackAction setCheck(BooleanSupplier checks) + { + return (LaunchActivityCallbackAction) super.setCheck(checks); + } + + @Nonnull + @Override + public LaunchActivityCallbackAction deadline(long timestamp) + { + return (LaunchActivityCallbackAction) super.deadline(timestamp); + } +}