diff --git a/src/main/java/com/github/kaktushose/jda/commands/JDACommands.java b/src/main/java/com/github/kaktushose/jda/commands/JDACommands.java
index 2e1346a1d..cbeb02375 100644
--- a/src/main/java/com/github/kaktushose/jda/commands/JDACommands.java
+++ b/src/main/java/com/github/kaktushose/jda/commands/JDACommands.java
@@ -1,13 +1,20 @@
package com.github.kaktushose.jda.commands;
+import com.github.kaktushose.jda.commands.annotations.interactions.CommandScope;
import com.github.kaktushose.jda.commands.annotations.interactions.EntitySelectMenu;
import com.github.kaktushose.jda.commands.annotations.interactions.StringSelectMenu;
+import com.github.kaktushose.jda.commands.definitions.description.reflective.ReflectiveClassFinder;
+import com.github.kaktushose.jda.commands.definitions.description.reflective.ReflectiveDescriptor;
+import com.github.kaktushose.jda.commands.definitions.interactions.CustomId;
+import com.github.kaktushose.jda.commands.definitions.interactions.InteractionRegistry;
+import com.github.kaktushose.jda.commands.definitions.interactions.component.ButtonDefinition;
+import com.github.kaktushose.jda.commands.definitions.interactions.component.menu.SelectMenuDefinition;
import com.github.kaktushose.jda.commands.dependency.DefaultDependencyInjector;
import com.github.kaktushose.jda.commands.dependency.DependencyInjector;
-import com.github.kaktushose.jda.commands.dispatching.ExpirationStrategy;
-import com.github.kaktushose.jda.commands.dispatching.internal.JDAEventListener;
-import com.github.kaktushose.jda.commands.dispatching.internal.Runtime;
+import com.github.kaktushose.jda.commands.dispatching.ImplementationRegistry;
+import com.github.kaktushose.jda.commands.dispatching.JDAEventListener;
import com.github.kaktushose.jda.commands.dispatching.adapter.TypeAdapterRegistry;
+import com.github.kaktushose.jda.commands.dispatching.expiration.ExpirationStrategy;
import com.github.kaktushose.jda.commands.dispatching.handling.DispatchingContext;
import com.github.kaktushose.jda.commands.dispatching.middleware.MiddlewareRegistry;
import com.github.kaktushose.jda.commands.dispatching.middleware.Priority;
@@ -17,10 +24,6 @@
import com.github.kaktushose.jda.commands.dispatching.validation.ValidatorRegistry;
import com.github.kaktushose.jda.commands.internal.JDAContext;
import com.github.kaktushose.jda.commands.internal.register.SlashCommandUpdater;
-import com.github.kaktushose.jda.commands.reflect.ImplementationRegistry;
-import com.github.kaktushose.jda.commands.reflect.InteractionRegistry;
-import com.github.kaktushose.jda.commands.reflect.interactions.components.ButtonDefinition;
-import com.github.kaktushose.jda.commands.reflect.interactions.components.menus.GenericSelectMenuDefinition;
import net.dv8tion.jda.api.JDA;
import net.dv8tion.jda.api.interactions.commands.localization.LocalizationFunction;
import net.dv8tion.jda.api.interactions.commands.localization.ResourceBundleLocalizationFunction;
@@ -53,7 +56,7 @@ private static JDACommands startInternal(Object jda, Class> clazz, Localizatio
var adapterRegistry = new TypeAdapterRegistry();
var validatorRegistry = new ValidatorRegistry();
var implementationRegistry = new ImplementationRegistry(dependencyInjector, middlewareRegistry, adapterRegistry, validatorRegistry);
- var interactionRegistry = new InteractionRegistry(validatorRegistry, dependencyInjector, function);
+ var interactionRegistry = new InteractionRegistry(dependencyInjector, validatorRegistry, function, new ReflectiveDescriptor());
middlewareRegistry.register(Priority.PERMISSIONS, new PermissionsMiddleware(implementationRegistry));
middlewareRegistry.register(Priority.NORMAL, new ConstraintMiddleware(implementationRegistry), new CooldownMiddleware(implementationRegistry));
@@ -62,7 +65,7 @@ private static JDACommands startInternal(Object jda, Class> clazz, Localizatio
implementationRegistry.index(clazz, packages);
- interactionRegistry.index(clazz, packages);
+ interactionRegistry.index(ReflectiveClassFinder.find(clazz, packages));
var updater = new SlashCommandUpdater(jdaContext, implementationRegistry.getGuildScopeProvider(), interactionRegistry);
updater.updateAllCommands();
@@ -171,14 +174,14 @@ public void shutdown() {
/**
* Updates all slash commands that are registered with
- * {@link com.github.kaktushose.jda.commands.annotations.interactions.SlashCommand.CommandScope#GUILD
+ * {@link CommandScope#GUILD
* CommandScope#Guild}
*/
public void updateGuildCommands() {
updater.updateGuildCommands();
}
- /// Gets a [`Button`][com.github.kaktushose.jda.commands.annotations.interactions.Button] based on the method name
+ /// Gets a [`Button`][com.github.kaktushose.jda.commands.annotations.interactions.Button] based on the definition id
/// and transforms it into a JDA [Button].
///
/// The button will be [`Runtime`]({@docRoot}/index.html#runtime-concept-heading) independent. This may be useful if you want to send a message without
@@ -188,38 +191,22 @@ public void updateGuildCommands() {
/// @return the JDA [Button]
@NotNull
public Button getButton(@NotNull String button) {
- if (!button.matches("[a-zA-Z]+\\.[a-zA-Z]+")) {
- throw new IllegalArgumentException("Unknown Button");
- }
-
- String sanitizedId = button.replaceAll("\\.", "");
- ButtonDefinition buttonDefinition = interactionRegistry.getButtons().stream()
- .filter(it -> it.getDefinitionId().equals(sanitizedId))
- .findFirst().orElseThrow(() -> new IllegalArgumentException("Unknown Button"));
-
- return buttonDefinition.toButton().withId(buttonDefinition.independentCustomId());
+ var id = String.valueOf(button.replaceAll("\\.", "").hashCode());
+ var definition = interactionRegistry.find(ButtonDefinition.class, false, it -> it.definitionId().equals(id));
+ return definition.toJDAEntity(CustomId.independent(definition.definitionId()));
}
- /// Gets a [StringSelectMenu] or [EntitySelectMenu] based on the method name and transforms it into a JDA [SelectMenu].
+ /// Gets a [StringSelectMenu] or [EntitySelectMenu] based on the definition id and transforms it into a JDA [SelectMenu].
///
/// The select menu will be [`Runtime`]({@docRoot}/index.html#runtime-concept-heading) independent. This may be useful if you want to send a component
/// without using the framework.
///
- /// @param the type of [SelectMenu]
/// @param menu the name of the select menu
/// @return the JDA [SelectMenu]
- @SuppressWarnings("unchecked")
@NotNull
- public S getSelectMenu(@NotNull String menu) {
- if (!menu.matches("[a-zA-Z]+\\.[a-zA-Z]+")) {
- throw new IllegalArgumentException("Unknown Select Menu");
- }
-
- String sanitizedId = menu.replaceAll("\\.", "");
- GenericSelectMenuDefinition> selectMenuDefinition = interactionRegistry.getSelectMenus().stream()
- .filter(it -> it.getDefinitionId().equals(sanitizedId))
- .findFirst().orElseThrow(() -> new IllegalArgumentException("Unknown Select Menu"));
-
- return (S) selectMenuDefinition.toSelectMenu(selectMenuDefinition.independentCustomId(), true);
+ public SelectMenu getSelectMenu(@NotNull String menu) {
+ var id = String.valueOf(menu.replaceAll("\\.", "").hashCode());
+ var definition = interactionRegistry.find(SelectMenuDefinition.class, false, it -> it.definitionId().equals(id));
+ return (SelectMenu) definition.toJDAEntity(CustomId.independent(definition.definitionId()));
}
}
diff --git a/src/main/java/com/github/kaktushose/jda/commands/annotations/Implementation.java b/src/main/java/com/github/kaktushose/jda/commands/annotations/Implementation.java
index 99aedd334..6df27a324 100644
--- a/src/main/java/com/github/kaktushose/jda/commands/annotations/Implementation.java
+++ b/src/main/java/com/github/kaktushose/jda/commands/annotations/Implementation.java
@@ -1,46 +1,40 @@
package com.github.kaktushose.jda.commands.annotations;
import com.github.kaktushose.jda.commands.annotations.constraints.Constraint;
+import com.github.kaktushose.jda.commands.dispatching.ImplementationRegistry;
+import com.github.kaktushose.jda.commands.dispatching.adapter.TypeAdapter;
+import com.github.kaktushose.jda.commands.dispatching.middleware.Middleware;
import com.github.kaktushose.jda.commands.dispatching.middleware.Priority;
+import com.github.kaktushose.jda.commands.dispatching.validation.Validator;
import com.github.kaktushose.jda.commands.embeds.error.ErrorMessageFactory;
+import com.github.kaktushose.jda.commands.permissions.PermissionsProvider;
+import com.github.kaktushose.jda.commands.scope.GuildScopeProvider;
import java.lang.annotation.*;
-/**
- * Indicates that the annotated class is a custom implementation that should replace the default implementation.
- *
- * @see com.github.kaktushose.jda.commands.reflect.ImplementationRegistry ImplementationRegistry
- * @see com.github.kaktushose.jda.commands.dispatching.middleware.Middleware Middleware
- * @see com.github.kaktushose.jda.commands.dispatching.validation.Validator Validator
- * @see com.github.kaktushose.jda.commands.dispatching.adapter.TypeAdapter TypeAdapter
- * @see com.github.kaktushose.jda.commands.permissions.PermissionsProvider PermissionsProvider
- * @see com.github.kaktushose.jda.commands.scope.GuildScopeProvider GuildScopeProvider
- * @see ErrorMessageFactory ErrorMessageFactory
- * @since 2.0.0
- */
+/// Indicates that the annotated class is a custom implementation that should replace the default implementation.
+///
+/// @see ImplementationRegistry
+/// @see Middleware
+/// @see Validator
+/// @see TypeAdapter
+/// @see PermissionsProvider
+/// @see GuildScopeProvider
+/// @see ErrorMessageFactory
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface Implementation {
- /**
- * Gets the {@link Priority} to register the
- * {@link com.github.kaktushose.jda.commands.dispatching.middleware.Middleware Middleware} with. If this
- * implementation is not a subtype
- * of {@link com.github.kaktushose.jda.commands.dispatching.middleware.Middleware Middleware}, this field can be
- * ignored.
- *
- * @return the {@link Priority}
- */
+ /// Gets the [Priority] to register the [Middleware] with. If this implementation is not a subtype of [Middleware],
+ /// this field can be ignored.
+ ///
+ /// @return the [Priority]
Priority priority() default Priority.NORMAL;
- /**
- * Gets the annotation the {@link com.github.kaktushose.jda.commands.dispatching.validation.Validator Validator}
- * should be mapped to. If this class is not a subtype of
- * {@link com.github.kaktushose.jda.commands.dispatching.validation.Validator Validator}, this field can be ignored.
- *
- * @return the annotation the {@link com.github.kaktushose.jda.commands.dispatching.validation.Validator Validator}
- * should be mapped to
- */
+ /// Gets the annotation the [Validator] should be mapped to. If this class is not a subtype of [Validator],
+ /// this field can be ignored.
+ ///
+ /// @return the annotation the [Validator] should be mapped to
Class extends Annotation> annotation() default Constraint.class;
}
diff --git a/src/main/java/com/github/kaktushose/jda/commands/annotations/Inject.java b/src/main/java/com/github/kaktushose/jda/commands/annotations/Inject.java
index 55ccbc257..81371c243 100644
--- a/src/main/java/com/github/kaktushose/jda/commands/annotations/Inject.java
+++ b/src/main/java/com/github/kaktushose/jda/commands/annotations/Inject.java
@@ -5,14 +5,11 @@
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
-/**
- * Fields annotated with Inject will be assigned a value that is provided by a {@link Produces} method.
- * If no Producer for the field type is available then the field will be assigned {@code null}. Please note, that each
- * field type can only have one producer.
- *
- * @see Produces
- * @since 1.0.0
- */
+/// Fields annotated with Inject will be assigned a value that is provided by a [Produces] method.
+/// If no Producer for the field type is available then the field will be assigned `null`. Please note, that each
+/// field type can only have one producer.
+///
+/// @see Produces
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Inject {
diff --git a/src/main/java/com/github/kaktushose/jda/commands/annotations/Produces.java b/src/main/java/com/github/kaktushose/jda/commands/annotations/Produces.java
index 63383d2fc..63aa6c485 100644
--- a/src/main/java/com/github/kaktushose/jda/commands/annotations/Produces.java
+++ b/src/main/java/com/github/kaktushose/jda/commands/annotations/Produces.java
@@ -1,42 +1,37 @@
package com.github.kaktushose.jda.commands.annotations;
+import com.github.kaktushose.jda.commands.annotations.interactions.Interaction;
+import com.github.kaktushose.jda.commands.dependency.DependencyInjector;
+
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
-/**
- * Methods annotated with Produces will be used to get the instance of a dependency.
- *
- * The instances provided by producer methods are used to inject values to the fields inside a
- * {@link com.github.kaktushose.jda.commands.annotations.interactions.Interaction Interaction}
- * that are annotated with {@link Inject}. The access modifier of a producer method must be
- * public.
- *
- *
Classes containing producer methods will be found automatically on startup. They can also be registered via
- * {@link com.github.kaktushose.jda.commands.dependency.DependencyInjector#registerProvider(Object)
- * DependencyInjector.registerProvider(Object)}
- *
- *
Please note that this is only a very basic implementation of dependency injection and can only be used inside
- * interaction controller classes or custom {@link Implementation implementations}. Furthermore, each type can only
- * have one producer. In other words you cannot register different instances of the same dependency.
- *
- * @see Inject
- * @see com.github.kaktushose.jda.commands.dependency.DependencyInjector DependencyInjector
- * @since 1.0.0
- */
+/// Methods annotated with Produces will be used to get the instance of a dependency.
+///
+/// The instances provided by producer methods are used to inject values to the fields inside a [Interaction]
+/// that are annotated with [Inject]. The access modifier of a producer method must be
+/// public.
+///
+/// Classes containing producer methods will be found automatically on startup. They can also be registered via
+/// [DependencyInjector#registerProvider(Object)]
+///
+/// Please note that this is only a very basic implementation of dependency injection and can only be used inside
+/// interaction controller classes or custom [Implementation]s. Furthermore, each type can only
+/// have one producer. In other words you cannot register different instances of the same dependency.
+///
+/// @see Inject
+/// @see com.github.kaktushose.jda.commands.dependency.DependencyInjector DependencyInjector
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Produces {
- /**
- * Whether jda-commands should ignore this method at indexing during startup. Useful if you wish to register your
- * dependency providers manually by calling
- * {@link com.github.kaktushose.jda.commands.dependency.DependencyInjector#registerProvider(Object)
- * DependencyInjector#registerProvider(Object)}
- *
- * @return Whether jda-commands should ignore this method, default {@code true}
- */
+ /// Whether jda-commands should ignore this method at indexing during startup. Useful if you wish to register your
+ /// dependency providers manually by calling
+ /// [DependencyInjector#registerProvider(Object)]
+ ///
+ /// @return Whether jda-commands should ignore this method, default `true`
boolean skipIndexing() default false;
}
diff --git a/src/main/java/com/github/kaktushose/jda/commands/annotations/constraints/Constraint.java b/src/main/java/com/github/kaktushose/jda/commands/annotations/constraints/Constraint.java
index 3ed0aef29..e27e1eb5f 100644
--- a/src/main/java/com/github/kaktushose/jda/commands/annotations/constraints/Constraint.java
+++ b/src/main/java/com/github/kaktushose/jda/commands/annotations/constraints/Constraint.java
@@ -5,21 +5,16 @@
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
-/**
- * Indicates that an annotation type can be used for parameter validation. When implementing custom validators, the
- * annotation type must be annotated with this annotation.
- *
- * @see com.github.kaktushose.jda.commands.dispatching.validation.ValidatorRegistry ValidatorRegistry
- * @since 2.0.0
- */
+/// Indicates that an annotation type can be used for parameter validation. When implementing custom validators, the
+/// annotation type must be annotated with this annotation.
+///
+/// @see com.github.kaktushose.jda.commands.dispatching.validation.ValidatorRegistry ValidatorRegistry
@Target(ElementType.ANNOTATION_TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface Constraint {
- /**
- * Returns an array of all types this annotation can be used for.
- *
- * @return an array of all types this annotation can be used for
- */
+ /// Returns an array of all types this annotation can be used for.
+ ///
+ /// @return an array of all types this annotation can be used for
Class>[] value();
}
diff --git a/src/main/java/com/github/kaktushose/jda/commands/annotations/constraints/Max.java b/src/main/java/com/github/kaktushose/jda/commands/annotations/constraints/Max.java
index 222a92f30..76ba440a8 100644
--- a/src/main/java/com/github/kaktushose/jda/commands/annotations/constraints/Max.java
+++ b/src/main/java/com/github/kaktushose/jda/commands/annotations/constraints/Max.java
@@ -5,28 +5,21 @@
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
-/**
- * The annotated element must be a number whose value must be lower or equal to the specified maximum.
- *
- * @see Constraint
- * @since 2.0.0
- */
+/// The annotated element must be a number whose value must be less or equal to the specified maximum.
+///
+/// @see Constraint
@Target(ElementType.PARAMETER)
@Retention(RetentionPolicy.RUNTIME)
@Constraint({Byte.class, Short.class, Integer.class, Long.class, Float.class, Double.class})
public @interface Max {
- /**
- * Returns the value the element must be lower or equal to.
- *
- * @return Returns the value the element must be lower or equal to
- */
+ /// Returns the value the element must be less or equal to.
+ ///
+ /// @return Returns the value the element must be less or equal to
long value();
- /**
- * Returns the error message that will be displayed if the constraint fails.
- *
- * @return the error message
- */
+ /// Returns the error message that will be displayed if the constraint fails.
+ ///
+ /// @return the error message
String message() default "Parameter exceeds maximum value";
}
diff --git a/src/main/java/com/github/kaktushose/jda/commands/annotations/constraints/Min.java b/src/main/java/com/github/kaktushose/jda/commands/annotations/constraints/Min.java
index 84af82013..7706fa846 100644
--- a/src/main/java/com/github/kaktushose/jda/commands/annotations/constraints/Min.java
+++ b/src/main/java/com/github/kaktushose/jda/commands/annotations/constraints/Min.java
@@ -5,28 +5,21 @@
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
-/**
- * The annotated element must be a number whose value must be greater or equal to the specified minimum.
- *
- * @see Constraint
- * @since 2.0.0
- */
+/// The annotated element must be a number whose value must be greater or equal to the specified minimum.
+///
+/// @see Constraint
@Target(ElementType.PARAMETER)
@Retention(RetentionPolicy.RUNTIME)
@Constraint({Byte.class, Short.class, Integer.class, Long.class, Float.class, Double.class})
public @interface Min {
- /**
- * Returns the value the element must be greater or equal to.
- *
- * @return Returns the value the element must be greater or equal to
- */
+ /// Returns the value the element must be greater or equal to.
+ ///
+ /// @return Returns the value the element must be greater or equal to
long value();
- /**
- * Returns the error message that will be displayed if the constraint fails.
- *
- * @return the error message
- */
+ /// Returns the error message that will be displayed if the constraint fails.
+ ///
+ /// @return the error message
String message() default "Parameter falls below minimum value";
}
diff --git a/src/main/java/com/github/kaktushose/jda/commands/annotations/constraints/NotPerm.java b/src/main/java/com/github/kaktushose/jda/commands/annotations/constraints/NotPerm.java
index 68e6fa8a7..8268572f2 100644
--- a/src/main/java/com/github/kaktushose/jda/commands/annotations/constraints/NotPerm.java
+++ b/src/main/java/com/github/kaktushose/jda/commands/annotations/constraints/NotPerm.java
@@ -8,28 +8,21 @@
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
-/**
- * The annotated element must be a user or member that doesn't have the specified discord permission.
- *
- * @see Constraint
- * @since 2.0.0
- */
+/// The annotated element must be a user or member that **doesn't** have the specified discord permission.
+///
+/// @see Constraint
@Target(ElementType.PARAMETER)
@Retention(RetentionPolicy.RUNTIME)
@Constraint({Member.class, User.class})
public @interface NotPerm {
- /**
- * Returns the discord permission(s) the element must not have.
- *
- * @return the discord permission(s) the element must not have.
- */
+ /// Returns the discord permission(s) the element must not have.
+ ///
+ /// @return the discord permission(s) the element must not have.
String[] value();
- /**
- * Returns the error message that will be displayed if the constraint fails.
- *
- * @return the error message
- */
+ /// Returns the error message that will be displayed if the constraint fails.
+ ///
+ /// @return the error message
String message() default "Member or User has at least one permission that isn't allowed";
}
diff --git a/src/main/java/com/github/kaktushose/jda/commands/annotations/constraints/NotRole.java b/src/main/java/com/github/kaktushose/jda/commands/annotations/constraints/NotRole.java
index c2b8c06f0..32adef342 100644
--- a/src/main/java/com/github/kaktushose/jda/commands/annotations/constraints/NotRole.java
+++ b/src/main/java/com/github/kaktushose/jda/commands/annotations/constraints/NotRole.java
@@ -1,5 +1,6 @@
package com.github.kaktushose.jda.commands.annotations.constraints;
+import com.github.kaktushose.jda.commands.dispatching.adapter.TypeAdapterRegistry;
import net.dv8tion.jda.api.entities.Member;
import java.lang.annotation.ElementType;
@@ -7,31 +8,23 @@
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
-/**
- * The annotated element must be member that doesn't have the specified guild role. This constraint will use the
- * {@link com.github.kaktushose.jda.commands.dispatching.adapter.TypeAdapterRegistry TypeAdapterRegistry} to determine
- * the role.
- *
- * @see Constraint
- * @see com.github.kaktushose.jda.commands.dispatching.adapter.impl.RoleAdapter RoleAdapter
- * @since 2.0.0
- */
+/// The annotated element must be member that **doesn't** have the specified guild role. This constraint will use the
+/// [TypeAdapterRegistry] to determine the role.
+///
+/// @see Constraint
+/// @see com.github.kaktushose.jda.commands.dispatching.adapter.impl.RoleAdapter RoleAdapter
@Target(ElementType.PARAMETER)
@Retention(RetentionPolicy.RUNTIME)
@Constraint({Member.class})
public @interface NotRole {
- /**
- * Returns the guild role the element must not have.
- *
- * @return the guild role the element must not have.
- */
+ /// Returns the guild role the element must not have.
+ ///
+ /// @return the guild role the element must not have.
String value();
- /**
- * Returns the error message that will be displayed if the constraint fails.
- *
- * @return the error message
- */
+ /// Returns the error message that will be displayed if the constraint fails.
+ ///
+ /// @return the error message
String message() default "Member has at least one role that isn't allowed";
}
diff --git a/src/main/java/com/github/kaktushose/jda/commands/annotations/constraints/NotUser.java b/src/main/java/com/github/kaktushose/jda/commands/annotations/constraints/NotUser.java
index 1f55b3698..809e22045 100644
--- a/src/main/java/com/github/kaktushose/jda/commands/annotations/constraints/NotUser.java
+++ b/src/main/java/com/github/kaktushose/jda/commands/annotations/constraints/NotUser.java
@@ -1,5 +1,7 @@
package com.github.kaktushose.jda.commands.annotations.constraints;
+import com.github.kaktushose.jda.commands.dispatching.adapter.TypeAdapterRegistry;
+import com.github.kaktushose.jda.commands.dispatching.adapter.impl.RoleAdapter;
import net.dv8tion.jda.api.entities.Member;
import net.dv8tion.jda.api.entities.User;
@@ -8,31 +10,23 @@
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
-/**
- * The annotated element must not be the specified user or member. This constraint will use the
- * {@link com.github.kaktushose.jda.commands.dispatching.adapter.TypeAdapterRegistry TypeAdapterRegistry} to
- * determine the user or member.
- *
- * @see Constraint
- * @see com.github.kaktushose.jda.commands.dispatching.adapter.impl.RoleAdapter RoleAdapter
- * @since 2.0.0
- */
+/// The annotated element must **not** be the specified user or member. This constraint will use the
+/// [TypeAdapterRegistry] to determine the user or member.
+///
+/// @see Constraint
+/// @see RoleAdapter
@Target(ElementType.PARAMETER)
@Retention(RetentionPolicy.RUNTIME)
@Constraint({Member.class, User.class})
public @interface NotUser {
- /**
- * Returns the user or member the element must not be equals to.
- *
- * @return the user or member the element must not be equals to
- */
+ /// Returns the user or member the element must not be equals to.
+ ///
+ /// @return the user or member the element must not be equals to
String value();
- /**
- * Returns the error message that will be displayed if the constraint fails.
- *
- * @return the error message
- */
+ /// Returns the error message that will be displayed if the constraint fails.
+ ///
+ /// @return the error message
String message() default "The given Member or User is invalid as a parameter";
}
diff --git a/src/main/java/com/github/kaktushose/jda/commands/annotations/constraints/Perm.java b/src/main/java/com/github/kaktushose/jda/commands/annotations/constraints/Perm.java
index 59dc22409..bdf42ea4e 100644
--- a/src/main/java/com/github/kaktushose/jda/commands/annotations/constraints/Perm.java
+++ b/src/main/java/com/github/kaktushose/jda/commands/annotations/constraints/Perm.java
@@ -8,28 +8,21 @@
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
-/**
- * The annotated element must be a user or member that have the specified discord permission.
- *
- * @see Constraint
- * @since 2.0.0
- */
+/// The annotated element must be a user or member that have the specified discord permission.
+///
+/// @see Constraint
@Target(ElementType.PARAMETER)
@Retention(RetentionPolicy.RUNTIME)
@Constraint({Member.class, User.class})
public @interface Perm {
- /**
- * Returns the discord permission(s) the element must have.
- *
- * @return the discord permission(s) the element must have.
- */
+ /// Returns the discord permission(s) the element must have.
+ ///
+ /// @return the discord permission(s) the element must have.
String[] value();
- /**
- * Returns the error message that will be displayed if the constraint fails.
- *
- * @return the error message
- */
+ /// Returns the error message that will be displayed if the constraint fails.
+ ///
+ /// @return the error message
String message() default "Member or User is missing at least one permission that is required";
}
diff --git a/src/main/java/com/github/kaktushose/jda/commands/annotations/constraints/Role.java b/src/main/java/com/github/kaktushose/jda/commands/annotations/constraints/Role.java
index 0cfc01ef3..58a1a8108 100644
--- a/src/main/java/com/github/kaktushose/jda/commands/annotations/constraints/Role.java
+++ b/src/main/java/com/github/kaktushose/jda/commands/annotations/constraints/Role.java
@@ -1,5 +1,7 @@
package com.github.kaktushose.jda.commands.annotations.constraints;
+import com.github.kaktushose.jda.commands.dispatching.adapter.TypeAdapterRegistry;
+import com.github.kaktushose.jda.commands.dispatching.adapter.impl.RoleAdapter;
import net.dv8tion.jda.api.entities.Member;
import java.lang.annotation.ElementType;
@@ -7,30 +9,23 @@
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
-/**
- * The annotated element must be member that have the specified guild role. This constraint will use the
- * {@link com.github.kaktushose.jda.commands.dispatching.adapter.TypeAdapterRegistry} to determine the role.
- *
- * @see Constraint
- * @see com.github.kaktushose.jda.commands.dispatching.adapter.impl.RoleAdapter RoleAdapter
- * @since 2.0.0
- */
+/// The annotated element must be member that have the specified guild role. This constraint will use the
+/// [TypeAdapterRegistry] to determine the role.
+///
+/// @see Constraint
+/// @see RoleAdapter
@Target(ElementType.PARAMETER)
@Retention(RetentionPolicy.RUNTIME)
@Constraint({Member.class})
public @interface Role {
- /**
- * Returns the guild role the element must have.
- *
- * @return the guild role the element must have.
- */
+ /// Returns the guild role the element must have.
+ ///
+ /// @return the guild role the element must have.
String value();
- /**
- * Returns the error message that will be displayed if the constraint fails.
- *
- * @return the error message
- */
+ /// Returns the error message that will be displayed if the constraint fails.
+ ///
+ /// @return the error message
String message() default "Member or User is missing at least one role that is required";
}
diff --git a/src/main/java/com/github/kaktushose/jda/commands/annotations/constraints/User.java b/src/main/java/com/github/kaktushose/jda/commands/annotations/constraints/User.java
index 96c3e5f13..048cad8b1 100644
--- a/src/main/java/com/github/kaktushose/jda/commands/annotations/constraints/User.java
+++ b/src/main/java/com/github/kaktushose/jda/commands/annotations/constraints/User.java
@@ -1,5 +1,7 @@
package com.github.kaktushose.jda.commands.annotations.constraints;
+import com.github.kaktushose.jda.commands.dispatching.adapter.TypeAdapterRegistry;
+import com.github.kaktushose.jda.commands.dispatching.adapter.impl.RoleAdapter;
import net.dv8tion.jda.api.entities.Member;
import java.lang.annotation.ElementType;
@@ -7,31 +9,23 @@
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
-/**
- * The annotated element must be the specified user or member. This constraint will use the
- * {@link com.github.kaktushose.jda.commands.dispatching.adapter.TypeAdapterRegistry TypeAdapterRegistry} to determine
- * the user or member.
- *
- * @see Constraint
- * @see com.github.kaktushose.jda.commands.dispatching.adapter.impl.RoleAdapter RoleAdapter
- * @since 2.0.0
- */
+/// The annotated element must be the specified user or member. This constraint will use the
+/// [TypeAdapterRegistry] to determine the user or member.
+///
+/// @see Constraint
+/// @see RoleAdapter
@Target(ElementType.PARAMETER)
@Retention(RetentionPolicy.RUNTIME)
@Constraint({Member.class, net.dv8tion.jda.api.entities.User.class})
public @interface User {
- /**
- * Returns the user or member the element must be equals to.
- *
- * @return the user or member the element must be equals to
- */
+ /// Returns the user or member the element must be equals to.
+ ///
+ /// @return the user or member the element must be equals to
String value();
- /**
- * Returns the error message that will be displayed if the constraint fails.
- *
- * @return the error message
- */
+ /// Returns the error message that will be displayed if the constraint fails.
+ ///
+ /// @return the error message
String message() default "The given Member or User is invalid as a parameter";
}
diff --git a/src/main/java/com/github/kaktushose/jda/commands/annotations/constraints/package-info.java b/src/main/java/com/github/kaktushose/jda/commands/annotations/constraints/package-info.java
index 44c9ff02b..88abd9075 100644
--- a/src/main/java/com/github/kaktushose/jda/commands/annotations/constraints/package-info.java
+++ b/src/main/java/com/github/kaktushose/jda/commands/annotations/constraints/package-info.java
@@ -1,4 +1,2 @@
-/**
- * All annotations needed for parameter validation.
- */
+/// All annotations needed for parameter validation.
package com.github.kaktushose.jda.commands.annotations.constraints;
diff --git a/src/main/java/com/github/kaktushose/jda/commands/annotations/interactions/AutoComplete.java b/src/main/java/com/github/kaktushose/jda/commands/annotations/interactions/AutoComplete.java
index 5af595b39..28fa08b8f 100644
--- a/src/main/java/com/github/kaktushose/jda/commands/annotations/interactions/AutoComplete.java
+++ b/src/main/java/com/github/kaktushose/jda/commands/annotations/interactions/AutoComplete.java
@@ -23,18 +23,14 @@
/// event.replyChoices(...);
/// }
/// ```
-///
/// @see SlashCommand
-/// @since 4.0.0
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface AutoComplete {
- /**
- * Returns the name of the slash commands this autocomplete should handle.
- *
- * @return the slash commands
- */
+ /// Returns the name of the slash commands this autocomplete should handle.
+ ///
+ /// @return the slash commands
String[] value();
}
diff --git a/src/main/java/com/github/kaktushose/jda/commands/annotations/interactions/Button.java b/src/main/java/com/github/kaktushose/jda/commands/annotations/interactions/Button.java
index 8d51a4073..61573d7d0 100644
--- a/src/main/java/com/github/kaktushose/jda/commands/annotations/interactions/Button.java
+++ b/src/main/java/com/github/kaktushose/jda/commands/annotations/interactions/Button.java
@@ -28,37 +28,28 @@
/// ```
///
/// @see Interaction
-/// @since 2.3.0
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Button {
- /**
- * Gets the label of the button.
- *
- * @return the label of the button
- */
+ /// Gets the label of the button.
+ ///
+ /// @return the label of the button
String value() default "";
- /**
- * Gets the {@link ButtonStyle}.
- *
- * @return the {@link ButtonStyle}
- */
+ /// Gets the [ButtonStyle].
+ ///
+ /// @return the [ButtonStyle]
ButtonStyle style() default ButtonStyle.PRIMARY;
- /**
- * Gets the {@link Emoji} of the button.
- *
- * @return the {@link Emoji}
- */
+ /// Gets the [Emoji] of the button.
+ ///
+ /// @return the [Emoji]
String emoji() default "";
- /**
- * Gets the link of the button.
- *
- * @return the link of the button
- */
+ /// Gets the link of the button.
+ ///
+ /// @return the link of the button
String link() default "";
}
diff --git a/src/main/java/com/github/kaktushose/jda/commands/annotations/interactions/Choices.java b/src/main/java/com/github/kaktushose/jda/commands/annotations/interactions/Choices.java
index bc04a52c3..52f4ac2e4 100644
--- a/src/main/java/com/github/kaktushose/jda/commands/annotations/interactions/Choices.java
+++ b/src/main/java/com/github/kaktushose/jda/commands/annotations/interactions/Choices.java
@@ -5,21 +5,16 @@
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
-/**
- * Annotation used to add choices to parameters.
- *
- * @see SlashCommand
- * @since 2.3.0
- */
+/// Annotation used to add choices to parameters.
+///
+/// @see SlashCommand
@Target(ElementType.PARAMETER)
@Retention(RetentionPolicy.RUNTIME)
public @interface Choices {
- /**
- * Returns the choices of a parameter. This value will only be used for slash commands.
- *
- * @return the choices of the parameter
- */
+ /// Returns the choices of a parameter. This value will only be used for slash commands.
+ ///
+ /// @return the choices of the parameter
String[] value();
}
diff --git a/src/main/java/com/github/kaktushose/jda/commands/annotations/interactions/CommandScope.java b/src/main/java/com/github/kaktushose/jda/commands/annotations/interactions/CommandScope.java
new file mode 100644
index 000000000..e12319159
--- /dev/null
+++ b/src/main/java/com/github/kaktushose/jda/commands/annotations/interactions/CommandScope.java
@@ -0,0 +1,10 @@
+package com.github.kaktushose.jda.commands.annotations.interactions;
+
+/// Enum describing the two possible scopes a command can be registered for.
+///
+/// @see SlashCommand#scope()
+/// @see ContextCommand#scope()
+public enum CommandScope {
+ GUILD,
+ GLOBAL
+}
diff --git a/src/main/java/com/github/kaktushose/jda/commands/annotations/interactions/ContextCommand.java b/src/main/java/com/github/kaktushose/jda/commands/annotations/interactions/ContextCommand.java
index 602081004..56d498795 100644
--- a/src/main/java/com/github/kaktushose/jda/commands/annotations/interactions/ContextCommand.java
+++ b/src/main/java/com/github/kaktushose/jda/commands/annotations/interactions/ContextCommand.java
@@ -28,59 +28,45 @@
/// @ContextCommand(value = "user context command", type = Command.Type.USER)
/// public void onCommand(CommandEvent event, User target) { ... }
/// ```
-///
/// @see Interaction
-/// @since 4.0.0
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface ContextCommand {
- /**
- * Returns the name of the command.
- *
- * @return the name of the command
- */
+ /// Returns the name of the command.
+ ///
+ /// @return the name of the command
String value() default "";
- /**
- * Returns whether this command is only usable in a guild.
- * This only has an effect if this command is registered globally.
- *
- * @return {@code true} if this command is only usable in a guild
- */
+ /// Returns whether this command is only usable in a guild.
+ /// This only has an effect if this command is registered globally.
+ ///
+ /// @return `true` if this command is only usable in a guild
boolean isGuildOnly() default false;
- /**
- * Returns whether this command can only be executed in NSFW channels.
- *
- * @return {@code true} if this command can only be executed in NSFW channels
- */
+ /// Returns whether this command can only be executed in NSFW channels.
+ ///
+ /// @return `true` if this command can only be executed in NSFW channels
boolean isNSFW() default false;
- /**
- * Returns an array of {@link net.dv8tion.jda.api.Permission Permissions} this command
- * should be enabled for by default. Note that guild admins can modify this at any time.
- *
- * @return an array of permissions this command will be enabled for by default
- * @see Permissions Permission
- * @see net.dv8tion.jda.api.interactions.commands.DefaultMemberPermissions DefaultMemberPermissions.ENABLED
- * @see net.dv8tion.jda.api.interactions.commands.DefaultMemberPermissions DefaultMemberPermissions.DISABLED
- */
+ /// Returns an array of [Permission] this command
+ /// should be enabled for by default. Note that guild admins can modify this at any time.
+ ///
+ /// @return an array of permissions this command will be enabled for by default
+ /// @see Permissions Permission
+ /// @see net.dv8tion.jda.api.interactions.commands.DefaultMemberPermissions DefaultMemberPermissions.ENABLED
+ /// @see net.dv8tion.jda.api.interactions.commands.DefaultMemberPermissions DefaultMemberPermissions.DISABLED
Permission[] enabledFor() default Permission.UNKNOWN;
- /**
- * Returns whether this command should be registered as a global or as a guild command.
- *
- * @return whether this command should be registered as a global or as a guild command
- * @see SlashCommand.CommandScope
- */
- SlashCommand.CommandScope scope() default SlashCommand.CommandScope.GLOBAL;
+ /// Returns whether this command should be registered as a global or as a guild command.
+ ///
+ /// @return whether this command should be registered as a global or as a guild command
+ /// @see CommandScope
+ CommandScope scope() default CommandScope.GLOBAL;
- /**
- * Gets the type of this command.
- *
- * @return the type of the command
- */
+ /// Gets the type of this command.
+ ///
+ /// @return the type of the command
Command.Type type();
}
diff --git a/src/main/java/com/github/kaktushose/jda/commands/annotations/interactions/Cooldown.java b/src/main/java/com/github/kaktushose/jda/commands/annotations/interactions/Cooldown.java
index c7c7f1dc4..6ffeac8dd 100644
--- a/src/main/java/com/github/kaktushose/jda/commands/annotations/interactions/Cooldown.java
+++ b/src/main/java/com/github/kaktushose/jda/commands/annotations/interactions/Cooldown.java
@@ -6,28 +6,21 @@
import java.lang.annotation.Target;
import java.util.concurrent.TimeUnit;
-/**
- * Commands annotated with Cooldown will have a per-user cooldown.
- *
- * @see com.github.kaktushose.jda.commands.dispatching.middleware.impl.CooldownMiddleware CooldownMiddleware
- * @since 1.0.0
- */
+/// Commands annotated with Cooldown will have a per-user cooldown.
+///
+/// @see com.github.kaktushose.jda.commands.dispatching.middleware.impl.CooldownMiddleware CooldownMiddleware
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface Cooldown {
- /**
- * Returns the delay of the cooldown.
- *
- * @return the delay of the cooldown
- */
+ /// Returns the delay of the cooldown.
+ ///
+ /// @return the delay of the cooldown
long value();
- /**
- * Returns the {@link TimeUnit} of the specified delay.
- *
- * @return the {@link TimeUnit} of the specified delay
- */
+ /// Returns the [TimeUnit] of the specified delay.
+ ///
+ /// @return the [TimeUnit] of the specified delay
TimeUnit timeUnit();
}
diff --git a/src/main/java/com/github/kaktushose/jda/commands/annotations/interactions/EntitySelectMenu.java b/src/main/java/com/github/kaktushose/jda/commands/annotations/interactions/EntitySelectMenu.java
index 5a68978fc..45b253854 100644
--- a/src/main/java/com/github/kaktushose/jda/commands/annotations/interactions/EntitySelectMenu.java
+++ b/src/main/java/com/github/kaktushose/jda/commands/annotations/interactions/EntitySelectMenu.java
@@ -29,75 +29,60 @@
/// public void onMenu(ComponentEvent event, Mentions mentions) { ... }
/// ```
/// @see Interaction
-/// @since 2.3.0
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface EntitySelectMenu {
- /**
- * Supported {@link SelectTarget SelectTargets}.
- *
- * @return an array of supported {@link SelectTarget SelectTargets}
- */
+ /// Supported [SelectTarget]s.
+ ///
+ /// @return an array of supported [SelectTarget]s
SelectTarget[] value();
- /**
- * The {@link net.dv8tion.jda.api.interactions.components.selections.EntitySelectMenu.DefaultValue default values}
- * for roles that will be shown to the user.
- *
- * @return the {@link net.dv8tion.jda.api.interactions.components.selections.EntitySelectMenu.DefaultValue default values}
- */
+ /// The [default values][net.dv8tion.jda.api.interactions.components.selections.EntitySelectMenu.DefaultValue]
+ /// for roles that will be shown to the user.
+ ///
+ /// @return the [default values][net.dv8tion.jda.api.interactions.components.selections.EntitySelectMenu.DefaultValue]
long[] defaultRoles() default -1;
- /**
- * The {@link net.dv8tion.jda.api.interactions.components.selections.EntitySelectMenu.DefaultValue default values}
- * for channels that will be shown to the user.
- *
- * @return the {@link net.dv8tion.jda.api.interactions.components.selections.EntitySelectMenu.DefaultValue default values}
- */
+ /// The [default values][net.dv8tion.jda.api.interactions.components.selections.EntitySelectMenu.DefaultValue]
+ /// for channels that will be shown to the user.
+ ///
+ /// @return the [default values][net.dv8tion.jda.api.interactions.components.selections.EntitySelectMenu.DefaultValue]
long[] defaultChannels() default -1;
- /**
- * The {@link net.dv8tion.jda.api.interactions.components.selections.EntitySelectMenu.DefaultValue default values}
- * for users that will be shown to the user.
- *
- * @return the {@link net.dv8tion.jda.api.interactions.components.selections.EntitySelectMenu.DefaultValue default values}
- */
+ /// The [default values][net.dv8tion.jda.api.interactions.components.selections.EntitySelectMenu.DefaultValue]
+ /// for users that will be shown to the user.
+ ///
+ /// @return the [default values][net.dv8tion.jda.api.interactions.components.selections.EntitySelectMenu.DefaultValue]
long[] defaultUsers() default -1;
- /**
- * The {@link ChannelType ChannelTypes} that should be supported by this menu.
- * This is only relevant for menus that allow CHANNEL targets.
- *
- * @return the {@link ChannelType ChannelTypes} that should be supported by this menu
- */
+ /// The [ChannelType]s that should be supported by this menu.
+ /// This is only relevant for menus that allow CHANNEL targets.
+ ///
+ /// @return the [ChannelType]s that should be supported by this menu
ChannelType[] channelTypes() default ChannelType.UNKNOWN;
- /**
- * Configure the placeholder which is displayed when no selections have been made yet.
- *
- * @return the placeholder which is displayed when no selections have been made yet
- */
+ /// Configure the placeholder which is displayed when no selections have been made yet.
+ ///
+ /// @return the placeholder which is displayed when no selections have been made yet
String placeholder() default "";
- /**
- * The minimum amount of values a user has to select.
- * Default: {@code 1}
- *
- *
The minimum must not exceed the amount of available options.
- *
- * @return the minimum amount of values a user has to select
- */
+ /// The minimum amount of values a user has to select.
+ ///
+ /// Default: `1`
+ ///
+ /// The minimum must not exceed the amount of available options.
+ ///
+ /// @return the minimum amount of values a user has to select
int minValue() default 1;
- /**
- * The maximum amount of values a user can select.
- * Default: {@code 1}
- *
- *
The maximum must not exceed the amount of available options.
- *
- * @return the maximum amount of values a user can select
- */
+ /// The maximum amount of values a user can select.
+ ///
+ /// Default: `1`
+ ///
+ /// The maximum must not exceed the amount of available options.
+ ///
+ /// @return the maximum amount of values a user can select
int maxValue() default 1;
}
diff --git a/src/main/java/com/github/kaktushose/jda/commands/annotations/interactions/Interaction.java b/src/main/java/com/github/kaktushose/jda/commands/annotations/interactions/Interaction.java
index 32c010799..4af52daf6 100644
--- a/src/main/java/com/github/kaktushose/jda/commands/annotations/interactions/Interaction.java
+++ b/src/main/java/com/github/kaktushose/jda/commands/annotations/interactions/Interaction.java
@@ -22,17 +22,13 @@
/// }
/// }
/// ```
-///
-/// @since 4.0.0
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface Interaction {
- /**
- * Returns the base name for slash commands.
- *
- * @return the base name for slash commands
- */
+ /// Returns the base name for slash commands.
+ ///
+ /// @return the base name for slash commands
String value() default "";
}
diff --git a/src/main/java/com/github/kaktushose/jda/commands/annotations/interactions/Modal.java b/src/main/java/com/github/kaktushose/jda/commands/annotations/interactions/Modal.java
index a9d86b105..ca56dbfbe 100644
--- a/src/main/java/com/github/kaktushose/jda/commands/annotations/interactions/Modal.java
+++ b/src/main/java/com/github/kaktushose/jda/commands/annotations/interactions/Modal.java
@@ -19,19 +19,15 @@
/// @Modal("My Modal")
/// public void onModal(ModalEvent event, @TextInput("Type here") String input) { ... }
/// ```
-///
/// @see Interaction
/// @see TextInput
-/// @since 4.0.0
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Modal {
- /**
- * Gets the title of this modal.
- *
- * @return the title of the modal
- */
+ /// Gets the title of this modal.
+ ///
+ /// @return the title of the modal
String value();
}
diff --git a/src/main/java/com/github/kaktushose/jda/commands/annotations/interactions/Optional.java b/src/main/java/com/github/kaktushose/jda/commands/annotations/interactions/Optional.java
index 0e5fc05b6..ecf9c1860 100644
--- a/src/main/java/com/github/kaktushose/jda/commands/annotations/interactions/Optional.java
+++ b/src/main/java/com/github/kaktushose/jda/commands/annotations/interactions/Optional.java
@@ -1,33 +1,28 @@
package com.github.kaktushose.jda.commands.annotations.interactions;
+import com.github.kaktushose.jda.commands.dispatching.adapter.TypeAdapterRegistry;
+
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
-/**
- * Parameters annotated with Optional are as the name says optional.
- *
- *
More formally if a command has an optional parameter the argument doesn't need to be present to execute the
- * command.
- *
- *
It is also possible to pass a default value which will be used instead if the argument isn't present.
- * The default value will be handled as a normal input and thus the
- * {@link com.github.kaktushose.jda.commands.dispatching.adapter.TypeAdapterRegistry TypeAdapterRegistry}
- * will try to parse it. If the parsing fails the command will still be executed but with empty or
- * possible {@code null} values.
- *
- * @see SlashCommand
- * @since 1.0.0
- */
+/// Parameters annotated with Optional are as the name says optional.
+///
+/// More formally if a command has an optional parameter the argument doesn't need to be present to execute the
+/// command.
+///
+/// It is also possible to pass a default value which will be used instead if the argument isn't present.
+/// The default value will be handled as a normal input and thus the [TypeAdapterRegistry] will try to parse it.
+/// If the parsing fails the command will still be executed but with empty or possible `null` values.
+///
+/// @see SlashCommand
@Target(ElementType.PARAMETER)
@Retention(RetentionPolicy.RUNTIME)
public @interface Optional {
- /**
- * Returns the default value.
- *
- * @return the default value
- */
+ /// Returns the default value.
+ ///
+ /// @return the default value
String value() default "";
}
diff --git a/src/main/java/com/github/kaktushose/jda/commands/annotations/interactions/Param.java b/src/main/java/com/github/kaktushose/jda/commands/annotations/interactions/Param.java
index 43077100f..97fdff79d 100644
--- a/src/main/java/com/github/kaktushose/jda/commands/annotations/interactions/Param.java
+++ b/src/main/java/com/github/kaktushose/jda/commands/annotations/interactions/Param.java
@@ -5,29 +5,22 @@
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
-/**
- * Annotation used to add a name and description to slash command parameters.
- *
- * @see SlashCommand
- * @since 2.3.0
- */
+/// Annotation used to add a name and description to slash command parameters.
+///
+/// @see SlashCommand
@Target(ElementType.PARAMETER)
@Retention(RetentionPolicy.RUNTIME)
public @interface Param {
- /**
- * Returns the description of the parameter. This value will only be used for slash commands.
- *
- * @return the description of the parameter
- */
+ /// Returns the description of the parameter. This value will only be used for slash commands.
+ ///
+ /// @return the description of the parameter
String value() default "";
- /**
- * Returns the name of the parameter. Use the compiler flag {@code -parameters} to have the parameter name resolved
- * at runtime making this field redundant.
- *
- * @return the name of the parameter
- */
+ /// Returns the name of the parameter. Use the compiler flag `-parameters` to have the parameter name resolved
+ /// at runtime making this field redundant.
+ ///
+ /// @return the name of the parameter
String name() default "";
}
diff --git a/src/main/java/com/github/kaktushose/jda/commands/annotations/interactions/Permissions.java b/src/main/java/com/github/kaktushose/jda/commands/annotations/interactions/Permissions.java
index 792a564a8..99940d58d 100644
--- a/src/main/java/com/github/kaktushose/jda/commands/annotations/interactions/Permissions.java
+++ b/src/main/java/com/github/kaktushose/jda/commands/annotations/interactions/Permissions.java
@@ -1,33 +1,38 @@
package com.github.kaktushose.jda.commands.annotations.interactions;
+import com.github.kaktushose.jda.commands.dispatching.middleware.impl.PermissionsMiddleware;
+import com.github.kaktushose.jda.commands.permissions.PermissionsProvider;
+import net.dv8tion.jda.api.Permission;
+
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
-/**
- * {@link com.github.kaktushose.jda.commands.annotations.interactions.Interaction Interaction} classes or
- * interaction methods (commands, components or modals) annotated with Permission will
- * require the user to have the given permissions in order to execute the command.
- *
- *
The default implementation of this framework can only handle discord permissions.
- * However, the {@link com.github.kaktushose.jda.commands.permissions.PermissionsProvider PermissionsProvider} interface
- * allows custom implementations.
- *
- *
If a class is annotated with Permission all methods or respectively all interactions will require the given
- * permission level.
- *
- * @see com.github.kaktushose.jda.commands.permissions.PermissionsProvider PermissionsProvider
- * @since 1.0.0
- */
+/// [Interaction] classes or
+/// interaction methods (commands, components or modals) annotated with Permission will
+/// require the user to have the given permissions in order to execute the command.
+///
+/// @apiNote This annotation should not be confused with [SlashCommand#enabledFor()] or [ContextCommand#enabledFor()].
+/// The `enabledFor` permissions will be client-side checked by Discord directly, while the [Permissions] annotation
+/// will be used for the own permission system of jda-commands.
+/// @implNote The [PermissionsMiddleware] will validate the permissions during the middleware phase of the execution
+/// chain. The [PermissionsProvider] will be called to check the respective user. The default implementation of the
+/// [PermissionsProvider] can only handle Discord permissions([Permission]).
+///
+/// ## Example:
+/// ```
+/// @Permissions("BAN_MEMBERS")
+/// public class BanCommand { ... }
+/// ```
+///
+/// @see PermissionsProvider
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface Permissions {
- /**
- * Returns a String array of all required permissions.
- *
- * @return a String array of all required permissions.
- */
+ /// Returns a String array of all required permissions.
+ ///
+ /// @return a String array of all required permissions.
String[] value();
}
diff --git a/src/main/java/com/github/kaktushose/jda/commands/annotations/interactions/ReplyConfig.java b/src/main/java/com/github/kaktushose/jda/commands/annotations/interactions/ReplyConfig.java
index d624a0b74..6189759b6 100644
--- a/src/main/java/com/github/kaktushose/jda/commands/annotations/interactions/ReplyConfig.java
+++ b/src/main/java/com/github/kaktushose/jda/commands/annotations/interactions/ReplyConfig.java
@@ -26,7 +26,6 @@
/// 4. [GlobalReplyConfig]
///
/// @see ReplyableEvent
-/// @since 4.0.0
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface ReplyConfig {
diff --git a/src/main/java/com/github/kaktushose/jda/commands/annotations/interactions/SelectOption.java b/src/main/java/com/github/kaktushose/jda/commands/annotations/interactions/SelectOption.java
index de03b476e..e1b7f26c3 100644
--- a/src/main/java/com/github/kaktushose/jda/commands/annotations/interactions/SelectOption.java
+++ b/src/main/java/com/github/kaktushose/jda/commands/annotations/interactions/SelectOption.java
@@ -5,51 +5,38 @@
import java.lang.annotation.*;
-/**
- * Used to define {@link net.dv8tion.jda.api.interactions.components.selections.SelectOption SelectOptions}
- * for {@link StringSelectMenu StringSelectMenus}.
- *
- * @see StringSelectMenu
- * @since 4.0.0
- */
+/// Used to define [`SelectOptions`][net.dv8tion.jda.api.interactions.components.selections.SelectOption]
+/// for [StringSelectMenu]s.
+///
+/// @see StringSelectMenu
@Repeatable(SelectOptionContainer.class)
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface SelectOption {
- /**
- * Gets the label of an option.
- *
- * @return the label
- */
+ /// Gets the label of an option.
+ ///
+ /// @return the label
String label();
- /**
- * Gets the value of an option.
- *
- * @return the value
- */
+ /// Gets the value of an option.
+ ///
+ /// @return the value
String value();
- /**
- * Gets the description of an option.
- *
- * @return the description
- */
+ /// Gets the description of an option.
+ ///
+ /// @return the description
String description() default "";
- /**
- * Gets the {@link Emoji} of an option.
- *
- * @return the {@link Emoji}
- */
+ /// Gets the [Emoji] of an option.
+ ///
+ /// @return the [Emoji]
String emoji() default "";
- /**
- * Gets whether this option is a default option.
- *
- * @return {@code true} if this SelectOption is a default option
- */
+ /// Gets whether this option is a default option.
+ ///
+ /// @return `true` if this SelectOption is a default option
boolean isDefault() default false;
}
diff --git a/src/main/java/com/github/kaktushose/jda/commands/annotations/interactions/SlashCommand.java b/src/main/java/com/github/kaktushose/jda/commands/annotations/interactions/SlashCommand.java
index 177f3786d..de40f4898 100644
--- a/src/main/java/com/github/kaktushose/jda/commands/annotations/interactions/SlashCommand.java
+++ b/src/main/java/com/github/kaktushose/jda/commands/annotations/interactions/SlashCommand.java
@@ -37,72 +37,47 @@
/// public void onCommand(CommandEvent event, String[] arguments) {}
/// }
/// ```
-///
/// @see Interaction
/// @see com.github.kaktushose.jda.commands.annotations.interactions.Interaction Interaction
/// @see com.github.kaktushose.jda.commands.annotations.constraints.Constraint Constraint
-/// @since 1.0.0
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface SlashCommand {
- /**
- * Returns the name of the command.
- *
- * @return the name of the command
- */
+ /// Returns the name of the command.
+ ///
+ /// @return the name of the command
String value() default "";
- /**
- * Returns whether this command is only usable in a guild.
- * This only has an effect if this command is registered globally.
- *
- * @return {@code true} if this command is only usable in a guild
- */
+ /// Returns whether this command is only usable in a guild.
+ /// This only has an effect if this command is registered globally.
+ ///
+ /// @return `true` if this command is only usable in a guild
boolean isGuildOnly() default false;
- /**
- * Returns the description of the command.
- *
- * @return the description of the command
- */
+ /// Returns the description of the command.
+ ///
+ /// @return the description of the command
String desc() default "N/A";
- /**
- * Returns whether this command can only be executed in NSFW channels.
- *
- * @return {@code true} if this command can only be executed in NSFW channels
- */
+ /// Returns whether this command can only be executed in NSFW channels.
+ ///
+ /// @return `true` if this command can only be executed in NSFW channels
boolean isNSFW() default false;
- /**
- * Returns an array of {@link net.dv8tion.jda.api.Permission Permissions} this command
- * should be enabled for by default. Note that guild admins can modify this at any time.
- *
- * @return an array of permissions this command will be enabled for by default
- * @see Permissions Permission
- * @see net.dv8tion.jda.api.interactions.commands.DefaultMemberPermissions DefaultMemberPermissions.ENABLED
- * @see net.dv8tion.jda.api.interactions.commands.DefaultMemberPermissions DefaultMemberPermissions.DISABLED
- */
+ /// Returns an array of [Permission]s this command should be enabled for by default. Note that guild admins can
+ /// modify this at any time.
+ ///
+ /// @return an array of permissions this command will be enabled for by default
+ /// @see Permissions Permission
+ /// @see net.dv8tion.jda.api.interactions.commands.DefaultMemberPermissions DefaultMemberPermissions.ENABLED
+ /// @see net.dv8tion.jda.api.interactions.commands.DefaultMemberPermissions DefaultMemberPermissions.DISABLED
Permission[] enabledFor() default Permission.UNKNOWN;
- /**
- * Returns whether this command should be registered as a global or as a guild command.
- *
- * @return whether this command should be registered as a global or as a guild command
- * @see CommandScope
- */
+ /// Returns whether this command should be registered as a global or as a guild command.
+ ///
+ /// @return whether this command should be registered as a global or as a guild command
+ /// @see CommandScope
CommandScope scope() default CommandScope.GLOBAL;
- /**
- * Enum describing the two possible scopes a command can be registered for.
- *
- * @see SlashCommand#scope()
- * @since 4.0.0
- */
- enum CommandScope {
- GUILD,
- GLOBAL
- }
-
}
diff --git a/src/main/java/com/github/kaktushose/jda/commands/annotations/interactions/StringSelectMenu.java b/src/main/java/com/github/kaktushose/jda/commands/annotations/interactions/StringSelectMenu.java
index 688f622a6..73ce8ce78 100644
--- a/src/main/java/com/github/kaktushose/jda/commands/annotations/interactions/StringSelectMenu.java
+++ b/src/main/java/com/github/kaktushose/jda/commands/annotations/interactions/StringSelectMenu.java
@@ -31,36 +31,31 @@
/// ```
/// @see Interaction
/// @see SelectOption
-/// @since 4.0.0
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface StringSelectMenu {
- /**
- * Configure the placeholder which is displayed when no selections have been made yet.
- *
- * @return the placeholder which is displayed when no selections have been made yet
- */
+ /// Configure the placeholder which is displayed when no selections have been made yet.
+ ///
+ /// @return the placeholder which is displayed when no selections have been made yet
String value();
- /**
- * The minimum amount of values a user has to select.
- * Default: {@code 1}
- *
- *
The minimum must not exceed the amount of available options.
- *
- * @return the minimum amount of values a user has to select
- */
+ /// The minimum amount of values a user has to select.
+ ///
+ /// Default: `1`
+ ///
+ /// The minimum must not exceed the amount of available options.
+ ///
+ /// @return the minimum amount of values a user has to select
int minValue() default 1;
- /**
- * The maximum amount of values a user can select.
- * Default: {@code 1}
- *
- *
The maximum must not exceed the amount of available options.
- *
- * @return the maximum amount of values a user can select
- */
+ /// The maximum amount of values a user can select.
+ ///
+ /// Default: `1`
+ ///
+ /// The maximum must not exceed the amount of available options.
+ ///
+ /// @return the maximum amount of values a user can select
int maxValue() default 1;
}
diff --git a/src/main/java/com/github/kaktushose/jda/commands/annotations/interactions/TextInput.java b/src/main/java/com/github/kaktushose/jda/commands/annotations/interactions/TextInput.java
index c1de71bc1..156b597b1 100644
--- a/src/main/java/com/github/kaktushose/jda/commands/annotations/interactions/TextInput.java
+++ b/src/main/java/com/github/kaktushose/jda/commands/annotations/interactions/TextInput.java
@@ -7,67 +7,53 @@
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
-/**
- * Annotation used to add TextInputs to {@link Modal Modals}.
- *
- * @see Modal
- * @since 4.0.0
- */
+/// Annotation used to add TextInputs to [Modal]s.
+///
+/// @see Modal
@Target(ElementType.PARAMETER)
@Retention(RetentionPolicy.RUNTIME)
public @interface TextInput {
- /**
- * The placeholder of this TextInput
- * This is the short hint that describes the expected value of the TextInput field.
- *
- * @return Placeholder
- */
+ /// The placeholder of this TextInput
+ ///
+ /// This is the short hint that describes the expected value of the TextInput field.
+ ///
+ /// @return Placeholder
String value();
- /**
- * The label shown above this text input box
- *
- * @return Label for the input
- */
+ /// The label shown above this text input box
+ ///
+ /// @return Label for the input
String label() default "";
- /**
- * The default value of this TextInput.
- * This sets a pre-populated text for this TextInput field
- *
- * @return default value
- */
+ /// The default value of this TextInput.
+ ///
+ /// This sets a pre-populated text for this TextInput field
+ ///
+ /// @return default value
String defaultValue() default "";
- /**
- * The minimum length. This is -1 if none has been set.
- *
- * @return Minimum length or -1
- */
+ /// The minimum length. This is -1 if none has been set.
+ ///
+ /// @return Minimum length or -1
int minValue() default -1;
- /**
- * The maximum length. This is -1 if none has been set.
- *
- * @return Maximum length or -1
- */
+ /// The maximum length. This is -1 if none has been set.
+ ///
+ /// @return Maximum length or -1
int maxValue() default -1;
- /**
- * The {@link TextInputStyle TextInputStyle}. The default value is {@link TextInputStyle#PARAGRAPH}.
- *
- * @return The TextInputStyle
- */
+ /// The [TextInputStyle]. The default value is [TextInputStyle#PARAGRAPH].
+ ///
+ /// @return The TextInputStyle
TextInputStyle style() default TextInputStyle.PARAGRAPH;
- /**
- * Whether this TextInput is required.
- * If this is True, the user must populate this TextInput field before they can submit the Modal.
- *
- * @return True if this TextInput is required
- * @see net.dv8tion.jda.api.interactions.components.text.TextInput#isRequired()
- */
+ /// Whether this TextInput is required.
+ ///
+ /// If this is True, the user must populate this TextInput field before they can submit the Modal.
+ ///
+ /// @return True if this TextInput is required
+ /// @see net.dv8tion.jda.api.interactions.components.text.TextInput#isRequired()
boolean required() default true;
}
diff --git a/src/main/java/com/github/kaktushose/jda/commands/annotations/internal/SelectOptionContainer.java b/src/main/java/com/github/kaktushose/jda/commands/annotations/internal/SelectOptionContainer.java
index beab34365..83866dd03 100644
--- a/src/main/java/com/github/kaktushose/jda/commands/annotations/internal/SelectOptionContainer.java
+++ b/src/main/java/com/github/kaktushose/jda/commands/annotations/internal/SelectOptionContainer.java
@@ -1,20 +1,19 @@
package com.github.kaktushose.jda.commands.annotations.internal;
import com.github.kaktushose.jda.commands.annotations.interactions.SelectOption;
+import org.jetbrains.annotations.ApiStatus;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
-/**
- * Internal wrapper for repeating {@link SelectOption SelectOptions}.
- *
- * @see SelectOption
- * @since 4.0.0
- */
+/// Internal wrapper for repeating [SelectOption]s.
+///
+/// @see SelectOption
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
+@ApiStatus.Internal
public @interface SelectOptionContainer {
SelectOption[] value();
diff --git a/src/main/java/com/github/kaktushose/jda/commands/annotations/internal/package-info.java b/src/main/java/com/github/kaktushose/jda/commands/annotations/internal/package-info.java
index 91bae5373..7c13bc512 100644
--- a/src/main/java/com/github/kaktushose/jda/commands/annotations/internal/package-info.java
+++ b/src/main/java/com/github/kaktushose/jda/commands/annotations/internal/package-info.java
@@ -1,4 +1,2 @@
-/**
- * Annotations that are only used for internal purposes and aren't intended to use in production.
- */
+/// Annotations that are only used for internal purposes and aren't intended to use in production.
package com.github.kaktushose.jda.commands.annotations.internal;
diff --git a/src/main/java/com/github/kaktushose/jda/commands/annotations/package-info.java b/src/main/java/com/github/kaktushose/jda/commands/annotations/package-info.java
index 9b50e4c46..9485e3173 100644
--- a/src/main/java/com/github/kaktushose/jda/commands/annotations/package-info.java
+++ b/src/main/java/com/github/kaktushose/jda/commands/annotations/package-info.java
@@ -1,4 +1,2 @@
-/**
- * All annotations that are needed to use this framework.
- */
+/// All annotations that are needed to use this framework.
package com.github.kaktushose.jda.commands.annotations;
diff --git a/src/main/java/com/github/kaktushose/jda/commands/definitions/Definition.java b/src/main/java/com/github/kaktushose/jda/commands/definitions/Definition.java
new file mode 100644
index 000000000..a1ec7cca8
--- /dev/null
+++ b/src/main/java/com/github/kaktushose/jda/commands/definitions/Definition.java
@@ -0,0 +1,27 @@
+package com.github.kaktushose.jda.commands.definitions;
+
+import com.github.kaktushose.jda.commands.definitions.features.CustomIdJDAEntity;
+import com.github.kaktushose.jda.commands.definitions.features.JDAEntity;
+import com.github.kaktushose.jda.commands.definitions.features.internal.Invokable;
+import com.github.kaktushose.jda.commands.definitions.interactions.InteractionDefinition;
+import com.github.kaktushose.jda.commands.definitions.interactions.ModalDefinition;
+import com.github.kaktushose.jda.commands.definitions.interactions.command.ParameterDefinition;
+import com.github.kaktushose.jda.commands.definitions.interactions.command.SlashCommandDefinition;
+import com.github.kaktushose.jda.commands.definitions.interactions.component.menu.StringSelectMenuDefinition;
+import org.jetbrains.annotations.NotNull;
+
+/// The common interface for all interaction definitions and their sub parts, such as parameters or text inputs, etc.
+public sealed interface Definition permits CustomIdJDAEntity, Invokable, JDAEntity, InteractionDefinition,
+ ModalDefinition.TextInputDefinition, ParameterDefinition, ParameterDefinition.ConstraintDefinition,
+ SlashCommandDefinition.CooldownDefinition, StringSelectMenuDefinition.SelectOptionDefinition {
+
+ /// The id for this definition. Per default this is the hash code of the [#toString()] method.
+ @NotNull
+ default String definitionId() {
+ return String.valueOf(toString().hashCode());
+ }
+
+ /// The human-readable name of this definition.
+ @NotNull
+ String displayName();
+}
diff --git a/src/main/java/com/github/kaktushose/jda/commands/definitions/description/ClassDescription.java b/src/main/java/com/github/kaktushose/jda/commands/definitions/description/ClassDescription.java
new file mode 100644
index 000000000..e64468bc6
--- /dev/null
+++ b/src/main/java/com/github/kaktushose/jda/commands/definitions/description/ClassDescription.java
@@ -0,0 +1,19 @@
+package com.github.kaktushose.jda.commands.definitions.description;
+
+import org.jetbrains.annotations.NotNull;
+
+import java.lang.annotation.Annotation;
+import java.util.Collection;
+
+/// A [Description] that describes a class.
+///
+/// @param clazz the [Class] this [Description] describes.
+/// @param name the name of the class
+/// @param annotations a [Collection] of all [Annotation]s this class is annotated with
+/// @param methods a [Collection] of all the public [`methods`][MethodDescription] of this class
+public record ClassDescription(
+ @NotNull Class> clazz,
+ @NotNull String name,
+ @NotNull Collection annotations,
+ @NotNull Collection methods
+) implements Description {}
diff --git a/src/main/java/com/github/kaktushose/jda/commands/definitions/description/Description.java b/src/main/java/com/github/kaktushose/jda/commands/definitions/description/Description.java
new file mode 100644
index 000000000..a12c469d7
--- /dev/null
+++ b/src/main/java/com/github/kaktushose/jda/commands/definitions/description/Description.java
@@ -0,0 +1,31 @@
+package com.github.kaktushose.jda.commands.definitions.description;
+
+import org.jetbrains.annotations.NotNull;
+
+import java.lang.annotation.Annotation;
+import java.util.Collection;
+import java.util.Optional;
+
+/// The common interface of all [Description] types.
+///
+/// A [Description] is, as the name says, a description of a class, method or parameter, similar to how
+/// `java.lang.reflect` works.
+///
+/// @see ClassDescription
+/// @see MethodDescription
+/// @see ParameterDescription
+public sealed interface Description permits ClassDescription, MethodDescription, ParameterDescription {
+
+ /// a possibly-empty [Collection] of all [Annotation]s this element is annotated with.
+ @NotNull
+ Collection annotations();
+
+ /// Gets this element's [Annotation] for the specified type if such an annotation is present
+ ///
+ /// @param type the type of the annotation to get
+ /// @return an [Optional] holding the [Annotation] if present at this element or else an empty [Optional]
+ @NotNull
+ default Optional annotation(@NotNull Class type) {
+ return annotations().stream().filter(type::isInstance).map(type::cast).findFirst();
+ }
+}
diff --git a/src/main/java/com/github/kaktushose/jda/commands/definitions/description/Descriptor.java b/src/main/java/com/github/kaktushose/jda/commands/definitions/description/Descriptor.java
new file mode 100644
index 000000000..34fdcd01b
--- /dev/null
+++ b/src/main/java/com/github/kaktushose/jda/commands/definitions/description/Descriptor.java
@@ -0,0 +1,8 @@
+package com.github.kaktushose.jda.commands.definitions.description;
+
+import java.util.function.Function;
+
+/// A [Descriptor] takes a [Class] as input and transforms it into a [ClassDescription].
+@FunctionalInterface
+public interface Descriptor extends Function, ClassDescription> {
+}
diff --git a/src/main/java/com/github/kaktushose/jda/commands/definitions/description/Invoker.java b/src/main/java/com/github/kaktushose/jda/commands/definitions/description/Invoker.java
new file mode 100644
index 000000000..0d956aa54
--- /dev/null
+++ b/src/main/java/com/github/kaktushose/jda/commands/definitions/description/Invoker.java
@@ -0,0 +1,20 @@
+package com.github.kaktushose.jda.commands.definitions.description;
+
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.lang.reflect.InvocationTargetException;
+import java.util.SequencedCollection;
+
+/// A functional interface, that allows the invocation of a [MethodDescription].
+@FunctionalInterface
+public interface Invoker {
+
+ /// @param instance an instance of the declaring class of the method
+ /// @param arguments a [SequencedCollection] of the arguments the method should be invoked with
+ /// @return the result of the method invocation
+ /// @throws IllegalAccessException if this Method object is enforcing Java language access control and the
+ /// underlying method is inaccessible
+ /// @throws InvocationTargetException if an exception was thrown by the invoked method or constructor
+ @Nullable Object invoke(@NotNull Object instance, @NotNull SequencedCollection arguments) throws IllegalAccessException, InvocationTargetException;
+}
diff --git a/src/main/java/com/github/kaktushose/jda/commands/definitions/description/MethodDescription.java b/src/main/java/com/github/kaktushose/jda/commands/definitions/description/MethodDescription.java
new file mode 100644
index 000000000..acc28bcc2
--- /dev/null
+++ b/src/main/java/com/github/kaktushose/jda/commands/definitions/description/MethodDescription.java
@@ -0,0 +1,25 @@
+package com.github.kaktushose.jda.commands.definitions.description;
+
+import org.jetbrains.annotations.NotNull;
+
+import java.lang.annotation.Annotation;
+import java.util.Collection;
+import java.util.SequencedCollection;
+
+/// A [Description] that describes a method.
+///
+/// @param declaringClass the declaring [Class] of this method
+/// @param returnType the [Class] this method returns
+/// @param name the name of the method
+/// @param parameters a [SequencedCollection] of the [ParameterDescription]s of this method
+/// @param annotations a [Collection] of all [Annotation]s this method is annotated with
+/// @param invoker the corresponding [Invoker], used to invoke this method
+public record MethodDescription(
+ @NotNull Class> declaringClass,
+ @NotNull Class> returnType,
+ @NotNull String name,
+ @NotNull SequencedCollection parameters,
+ @NotNull Collection annotations,
+ @NotNull Invoker invoker
+) implements Description {
+}
diff --git a/src/main/java/com/github/kaktushose/jda/commands/definitions/description/ParameterDescription.java b/src/main/java/com/github/kaktushose/jda/commands/definitions/description/ParameterDescription.java
new file mode 100644
index 000000000..3816c2273
--- /dev/null
+++ b/src/main/java/com/github/kaktushose/jda/commands/definitions/description/ParameterDescription.java
@@ -0,0 +1,17 @@
+package com.github.kaktushose.jda.commands.definitions.description;
+
+import org.jetbrains.annotations.NotNull;
+
+import java.lang.annotation.Annotation;
+import java.util.Collection;
+
+/// A [Description] that describes a parameter.
+///
+/// @param type the [Class] representing the type of this parameter
+/// @param name the name of the parameter
+/// @param annotations a [Collection] of all [Annotation]s this parameter is annotated with
+public record ParameterDescription(
+ @NotNull Class> type,
+ @NotNull String name,
+ @NotNull Collection annotations
+) implements Description {}
diff --git a/src/main/java/com/github/kaktushose/jda/commands/definitions/description/package-info.java b/src/main/java/com/github/kaktushose/jda/commands/definitions/description/package-info.java
new file mode 100644
index 000000000..da7dd094b
--- /dev/null
+++ b/src/main/java/com/github/kaktushose/jda/commands/definitions/description/package-info.java
@@ -0,0 +1,6 @@
+/// This packages includes different types of [`Descriptions`][com.github.kaktushose.jda.commands.definitions.description.Description]
+/// that contain meta information about classes, methods und parameters, similar to reflections.
+///
+/// Descriptions are created by an implementation of [`Descriptions`][com.github.kaktushose.jda.commands.definitions.description.Description]
+/// and are used in many places of this framework, resulting in the possible avoidance of java reflections.
+package com.github.kaktushose.jda.commands.definitions.description;
diff --git a/src/main/java/com/github/kaktushose/jda/commands/definitions/description/reflective/ReflectiveClassFinder.java b/src/main/java/com/github/kaktushose/jda/commands/definitions/description/reflective/ReflectiveClassFinder.java
new file mode 100644
index 000000000..3da9ea859
--- /dev/null
+++ b/src/main/java/com/github/kaktushose/jda/commands/definitions/description/reflective/ReflectiveClassFinder.java
@@ -0,0 +1,28 @@
+package com.github.kaktushose.jda.commands.definitions.description.reflective;
+
+import com.github.kaktushose.jda.commands.annotations.interactions.Interaction;
+import org.jetbrains.annotations.ApiStatus;
+import org.reflections.Reflections;
+import org.reflections.scanners.Scanners;
+import org.reflections.util.ClasspathHelper;
+import org.reflections.util.ConfigurationBuilder;
+import org.reflections.util.FilterBuilder;
+
+// temp class
+@ApiStatus.Internal
+public class ReflectiveClassFinder {
+
+ public static Iterable> find(Class> clazz, String[] packages) {
+ var filter = new FilterBuilder();
+ for (String pkg : packages) {
+ filter.includePackage(pkg);
+ }
+
+ var config = new ConfigurationBuilder()
+ .setScanners(Scanners.SubTypes, Scanners.TypesAnnotated)
+ .setUrls(ClasspathHelper.forClass(clazz))
+ .filterInputsBy(filter);
+ var reflections = new Reflections(config);
+ return reflections.getTypesAnnotatedWith(Interaction.class);
+ }
+}
diff --git a/src/main/java/com/github/kaktushose/jda/commands/definitions/description/reflective/ReflectiveDescriptor.java b/src/main/java/com/github/kaktushose/jda/commands/definitions/description/reflective/ReflectiveDescriptor.java
new file mode 100644
index 000000000..f289f3d9d
--- /dev/null
+++ b/src/main/java/com/github/kaktushose/jda/commands/definitions/description/reflective/ReflectiveDescriptor.java
@@ -0,0 +1,72 @@
+package com.github.kaktushose.jda.commands.definitions.description.reflective;
+
+import com.github.kaktushose.jda.commands.definitions.description.ClassDescription;
+import com.github.kaktushose.jda.commands.definitions.description.Descriptor;
+import com.github.kaktushose.jda.commands.definitions.description.MethodDescription;
+import com.github.kaktushose.jda.commands.definitions.description.ParameterDescription;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.lang.reflect.Parameter;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.List;
+import java.util.Objects;
+
+/// An [Descriptor] implementation that uses `java.lang.reflect` to create the [ClassDescription].
+public class ReflectiveDescriptor implements Descriptor {
+
+ /// Transforms the given [Class] into a [ClassDescription].
+ ///
+ /// @param clazz the [Class] to transform
+ /// @return the [ClassDescription] built from the given [Class]
+ @NotNull
+ @Override
+ public ClassDescription apply(@NotNull Class> clazz) {
+ List methods = Arrays.stream(clazz.getMethods())
+ .map(this::method)
+ .filter(Objects::nonNull)
+ .toList();
+
+ return new ClassDescription(
+ clazz,
+ clazz.getName(),
+ toList(clazz.getAnnotations()),
+ methods
+ );
+ }
+
+ @Nullable
+ private MethodDescription method(@NotNull Method method) {
+ if (!Modifier.isPublic(method.getModifiers())) return null;
+ List parameters = Arrays.stream(method.getParameters())
+ .map(this::parameter)
+ .toList();
+
+
+ return new MethodDescription(
+ method.getDeclaringClass(),
+ method.getReturnType(),
+ method.getName(),
+ parameters,
+ toList(method.getAnnotations()),
+ (instance, arguments) -> method.invoke(instance, arguments.toArray())
+ );
+ }
+
+ @NotNull
+ private ParameterDescription parameter(@NotNull Parameter parameter) {
+ return new ParameterDescription(
+ parameter.getType(),
+ parameter.getName(),
+ toList(parameter.getAnnotations())
+ );
+ }
+
+ @NotNull
+ private Collection toList(@NotNull T[] array) {
+ return Arrays.stream(array).toList();
+ }
+}
diff --git a/src/main/java/com/github/kaktushose/jda/commands/definitions/description/reflective/package-info.java b/src/main/java/com/github/kaktushose/jda/commands/definitions/description/reflective/package-info.java
new file mode 100644
index 000000000..1a7e340de
--- /dev/null
+++ b/src/main/java/com/github/kaktushose/jda/commands/definitions/description/reflective/package-info.java
@@ -0,0 +1,3 @@
+/// Contains [`Descriptors`][com.github.kaktushose.jda.commands.definitions.description.Descriptor] that use
+/// `java.lang.reflect` to build [`Descriptions][com.github.kaktushose.jda.commands.definitions.description.Description].
+package com.github.kaktushose.jda.commands.definitions.description.reflective;
diff --git a/src/main/java/com/github/kaktushose/jda/commands/definitions/features/CustomIdJDAEntity.java b/src/main/java/com/github/kaktushose/jda/commands/definitions/features/CustomIdJDAEntity.java
new file mode 100644
index 000000000..b4d76995a
--- /dev/null
+++ b/src/main/java/com/github/kaktushose/jda/commands/definitions/features/CustomIdJDAEntity.java
@@ -0,0 +1,27 @@
+package com.github.kaktushose.jda.commands.definitions.features;
+
+import com.github.kaktushose.jda.commands.definitions.Definition;
+import com.github.kaktushose.jda.commands.definitions.interactions.CustomId;
+import com.github.kaktushose.jda.commands.definitions.interactions.ModalDefinition;
+import com.github.kaktushose.jda.commands.definitions.interactions.component.ButtonDefinition;
+import com.github.kaktushose.jda.commands.definitions.interactions.component.ComponentDefinition;
+import com.github.kaktushose.jda.commands.definitions.interactions.component.menu.EntitySelectMenuDefinition;
+import com.github.kaktushose.jda.commands.definitions.interactions.component.menu.StringSelectMenuDefinition;
+import org.jetbrains.annotations.NotNull;
+
+/// Indicates that the implementing [Definition] can be transformed into a JDA entity that has a [CustomId].
+///
+/// @see ButtonDefinition
+/// @see EntitySelectMenuDefinition
+/// @see StringSelectMenuDefinition
+/// @see ModalDefinition
+public sealed interface CustomIdJDAEntity extends Definition permits ComponentDefinition, ModalDefinition {
+
+ /// Transforms this [Definition] into a JDA entity of the given type [T].
+ ///
+ /// @param customId the [CustomId] to use to build this JDA entity
+ /// @return a JDA entity of type [T]
+ @NotNull
+ T toJDAEntity(@NotNull CustomId customId);
+
+}
diff --git a/src/main/java/com/github/kaktushose/jda/commands/definitions/features/JDAEntity.java b/src/main/java/com/github/kaktushose/jda/commands/definitions/features/JDAEntity.java
new file mode 100644
index 000000000..dd2fd6202
--- /dev/null
+++ b/src/main/java/com/github/kaktushose/jda/commands/definitions/features/JDAEntity.java
@@ -0,0 +1,35 @@
+package com.github.kaktushose.jda.commands.definitions.features;
+
+import com.github.kaktushose.jda.commands.definitions.Definition;
+import com.github.kaktushose.jda.commands.definitions.interactions.ModalDefinition.TextInputDefinition;
+import com.github.kaktushose.jda.commands.definitions.interactions.command.CommandDefinition;
+import com.github.kaktushose.jda.commands.definitions.interactions.command.ContextCommandDefinition;
+import com.github.kaktushose.jda.commands.definitions.interactions.command.ParameterDefinition;
+import com.github.kaktushose.jda.commands.definitions.interactions.command.SlashCommandDefinition;
+import com.github.kaktushose.jda.commands.definitions.interactions.component.ButtonDefinition;
+import com.github.kaktushose.jda.commands.definitions.interactions.component.ComponentDefinition;
+import com.github.kaktushose.jda.commands.definitions.interactions.component.menu.EntitySelectMenuDefinition;
+import com.github.kaktushose.jda.commands.definitions.interactions.component.menu.StringSelectMenuDefinition;
+import com.github.kaktushose.jda.commands.definitions.interactions.component.menu.StringSelectMenuDefinition.SelectOptionDefinition;
+import org.jetbrains.annotations.NotNull;
+
+/// Indicates that the implementing [Definition] can be transformed into a JDA entity.
+///
+/// @see ButtonDefinition
+/// @see EntitySelectMenuDefinition
+/// @see StringSelectMenuDefinition
+/// @see SlashCommandDefinition
+/// @see ContextCommandDefinition
+/// @see ParameterDefinition
+/// @see SelectOptionDefinition
+/// @see TextInputDefinition
+public sealed interface JDAEntity extends Definition
+ permits ComponentDefinition, TextInputDefinition, CommandDefinition, ParameterDefinition, SelectOptionDefinition {
+
+ /// Transforms this [Definition] into a JDA entity of the given type [T].
+ ///
+ /// @return a JDA entity of type [T]
+ @NotNull
+ T toJDAEntity();
+
+}
diff --git a/src/main/java/com/github/kaktushose/jda/commands/definitions/features/internal/Invokable.java b/src/main/java/com/github/kaktushose/jda/commands/definitions/features/internal/Invokable.java
new file mode 100644
index 000000000..0ee833dae
--- /dev/null
+++ b/src/main/java/com/github/kaktushose/jda/commands/definitions/features/internal/Invokable.java
@@ -0,0 +1,51 @@
+package com.github.kaktushose.jda.commands.definitions.features.internal;
+
+import com.github.kaktushose.jda.commands.definitions.Definition;
+import com.github.kaktushose.jda.commands.definitions.description.ClassDescription;
+import com.github.kaktushose.jda.commands.definitions.description.MethodDescription;
+import com.github.kaktushose.jda.commands.definitions.interactions.InteractionDefinition;
+import com.github.kaktushose.jda.commands.dispatching.context.InvocationContext;
+import com.github.kaktushose.jda.commands.dispatching.handling.EventHandler;
+import org.jetbrains.annotations.ApiStatus;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.lang.reflect.InvocationTargetException;
+import java.util.SequencedCollection;
+
+/// Indicates that the implementing [Definition] is bound to a method that can be invoked.
+@ApiStatus.Internal
+public sealed interface Invokable extends Definition permits InteractionDefinition {
+
+ Logger log = LoggerFactory.getLogger(Invokable.class);
+
+ /// Invokes the method that this [Definition] is bound to.
+ ///
+ /// @param instance an instance of the declaring class of the method
+ /// @param invocation the corresponding [InvocationContext]
+ /// @return the result of the method invocation
+ /// @throws IllegalStateException if the definition must not be invoked at the moment this method gets called
+ /// @throws IllegalAccessException if the method object is enforcing Java language access control and the
+ /// underlying method is inaccessible
+ /// @throws InvocationTargetException if an exception was thrown by the invoked method or constructor
+ @Nullable
+ default Object invoke(@NotNull Object instance, @NotNull InvocationContext> invocation) throws IllegalAccessException, InvocationTargetException {
+ if (!EventHandler.INVOCATION_PERMITTED.get()) {
+ throw new IllegalStateException("The Definition must not be invoked at this point.");
+ }
+ SequencedCollection arguments = invocation.arguments();
+
+ EventHandler.INVOCATION_PERMITTED.set(false);
+ return methodDescription().invoker().invoke(instance, arguments);
+ }
+
+ /// The [ClassDescription] of the declaring class of the [#methodDescription()].
+ @NotNull
+ ClassDescription clazzDescription();
+
+ /// The [MethodDescription] of the method this [Definition] is bound to.
+ @NotNull
+ MethodDescription methodDescription();
+}
diff --git a/src/main/java/com/github/kaktushose/jda/commands/definitions/features/package-info.java b/src/main/java/com/github/kaktushose/jda/commands/definitions/features/package-info.java
new file mode 100644
index 000000000..d4202ea90
--- /dev/null
+++ b/src/main/java/com/github/kaktushose/jda/commands/definitions/features/package-info.java
@@ -0,0 +1,2 @@
+/// This package contains interfaces that implement some form of functionality for a definition, that not all definitions might share.
+package com.github.kaktushose.jda.commands.definitions.features;
\ No newline at end of file
diff --git a/src/main/java/com/github/kaktushose/jda/commands/definitions/interactions/AutoCompleteDefinition.java b/src/main/java/com/github/kaktushose/jda/commands/definitions/interactions/AutoCompleteDefinition.java
new file mode 100644
index 000000000..bb60afb20
--- /dev/null
+++ b/src/main/java/com/github/kaktushose/jda/commands/definitions/interactions/AutoCompleteDefinition.java
@@ -0,0 +1,51 @@
+package com.github.kaktushose.jda.commands.definitions.interactions;
+
+import com.github.kaktushose.jda.commands.annotations.interactions.AutoComplete;
+import com.github.kaktushose.jda.commands.definitions.description.ClassDescription;
+import com.github.kaktushose.jda.commands.definitions.description.MethodDescription;
+import com.github.kaktushose.jda.commands.dispatching.events.interactions.AutoCompleteEvent;
+import com.github.kaktushose.jda.commands.internal.Helpers;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.*;
+import java.util.stream.Collectors;
+
+/// Representation of an auto complete handler.
+///
+/// @param clazzDescription the [ClassDescription] of the declaring class of the [#methodDescription()]
+/// @param methodDescription the [MethodDescription] of the method this definition is bound to
+/// @param commands the commands this autocomplete handler can handle
+public record AutoCompleteDefinition(@NotNull ClassDescription clazzDescription,
+ @NotNull MethodDescription methodDescription,
+ @NotNull Set commands)
+ implements InteractionDefinition {
+
+ /// Builds a new [AutoCompleteDefinition] from the given class and method description.
+ ///
+ /// @param clazz the corresponding [ClassDescription]
+ /// @param method the corresponding [MethodDescription]
+ /// @return an [Optional] holding the [AutoCompleteDefinition]
+ @NotNull
+ public static Optional build(@NotNull ClassDescription clazz, @NotNull MethodDescription method) {
+ if (Helpers.checkSignature(method, List.of(AutoCompleteEvent.class))) {
+ return Optional.empty();
+ }
+ return method.annotation(AutoComplete.class).map(complete ->
+ new AutoCompleteDefinition(clazz, method, Arrays.stream(complete.value()).collect(Collectors.toSet()))
+ );
+
+ }
+
+ @NotNull
+ @Override
+ public String displayName() {
+ return "%s.%s".formatted(methodDescription.declaringClass().getName(), methodDescription.name());
+ }
+
+ @NotNull
+ @Override
+ public Collection permissions() {
+ return Collections.emptyList();
+ }
+
+}
diff --git a/src/main/java/com/github/kaktushose/jda/commands/definitions/interactions/CustomId.java b/src/main/java/com/github/kaktushose/jda/commands/definitions/interactions/CustomId.java
new file mode 100644
index 000000000..979f83798
--- /dev/null
+++ b/src/main/java/com/github/kaktushose/jda/commands/definitions/interactions/CustomId.java
@@ -0,0 +1,105 @@
+package com.github.kaktushose.jda.commands.definitions.interactions;
+
+import com.github.kaktushose.jda.commands.definitions.Definition;
+import net.dv8tion.jda.api.events.interaction.GenericInteractionCreateEvent;
+import net.dv8tion.jda.api.events.interaction.ModalInteractionEvent;
+import net.dv8tion.jda.api.events.interaction.component.GenericComponentInteractionCreateEvent;
+import org.jetbrains.annotations.NotNull;
+
+/// Representation of a custom id used in modals, buttons or select menus.
+///
+/// @param runtimeId the id of the [`Runtime`]({@docRoot}/index.html#runtime-concept-heading) this custom id is bound to
+/// or the literal `independent`.
+/// @param definitionId the [Definition#definitionId()]
+/// @implNote the custom id has the following format: `jdac.runtimeId.definitionId`
+public record CustomId(@NotNull String runtimeId, @NotNull String definitionId) {
+ private static final String PREFIX = "jdac";
+ private static final String INDEPENDENT_ID = "independent";
+ public static final String BOUND_CUSTOM_ID_REGEX = "^jdac\\.[0-9a-fA-F-]{36}\\.-?\\d+$";
+ public static final String INDEPENDENT_CUSTOM_ID_REGEX = "^jdac\\.%s\\.-?\\d+$".formatted(INDEPENDENT_ID);
+
+ public CustomId {
+ if (!runtimeId.matches("[0-9a-fA-F-]{36}") && !runtimeId.equals(INDEPENDENT_ID)) {
+ throw new IllegalArgumentException("Invalid runtime id! Must either be a UUID or \"%s\"".formatted(INDEPENDENT_ID));
+ }
+ }
+
+ /// Constructs a new [CustomId] from the given [GenericInteractionCreateEvent].
+ ///
+ /// @param event the [GenericInteractionCreateEvent]
+ /// @return the [CustomId]
+ @NotNull
+ public static CustomId fromEvent(@NotNull GenericComponentInteractionCreateEvent event) {
+ return fromEvent(event.getComponentId());
+ }
+
+ /// Constructs a new [CustomId] from the given [ModalInteractionEvent].
+ ///
+ /// @param event the [ModalInteractionEvent]
+ /// @return the [CustomId]
+ @NotNull
+ public static CustomId fromEvent(@NotNull ModalInteractionEvent event) {
+ return fromEvent(event.getModalId());
+ }
+
+ /// Constructs a new [CustomId] from the given String.
+ ///
+ /// @param customId the custom id String
+ /// @return the [CustomId]
+ @NotNull
+ private static CustomId fromEvent(@NotNull String customId) {
+ if (isInvalid(customId)) {
+ throw new IllegalArgumentException("Provided custom id is invalid!");
+ }
+ var split = customId.split("\\.");
+ return new CustomId(split[1], split[2]);
+ }
+
+ /// Constructs a new runtime-independent [CustomId] from the given definition id.
+ ///
+ /// @param definitionId the definition id to construct the [CustomId] from
+ /// @return a new runtime-independent [CustomId]
+ @NotNull
+ public static CustomId independent(@NotNull String definitionId) {
+ return new CustomId(INDEPENDENT_ID, definitionId);
+ }
+
+ /// Checks if the passed custom id *doesn't* conform to the defined format of jda-commands.
+ ///
+ /// @return `true` if the passed custom id *doesn't* conform to the jda-commands format
+ public static boolean isInvalid(@NotNull String customId) {
+ return !(customId.matches(BOUND_CUSTOM_ID_REGEX) || customId.matches(INDEPENDENT_CUSTOM_ID_REGEX));
+ }
+
+ /// The String representation of this custom id.
+ @NotNull
+ public String id() {
+ return "%s.%s.%s".formatted(PREFIX, runtimeId, definitionId);
+ }
+
+ /// Gets the runtime id of this custom id.
+ ///
+ /// @return the runtime id
+ /// @throws IllegalStateException if this custom id is runtime-independent
+ @NotNull
+ public String runtimeId() {
+ if (isIndependent()) {
+ throw new IllegalStateException("Provided custom id is runtime-independent!");
+ }
+ return runtimeId;
+ }
+
+ /// Checks if the passed custom id is runtime-independent.
+ ///
+ /// @return `true` if the custom id is runtime-independent
+ public boolean isIndependent() {
+ return runtimeId.equals(INDEPENDENT_ID);
+ }
+
+ /// Checks if the passed custom id is runtime-bound.
+ ///
+ /// @return `true` if the custom id is runtime-bound
+ public boolean isBound() {
+ return !isIndependent();
+ }
+}
diff --git a/src/main/java/com/github/kaktushose/jda/commands/definitions/interactions/InteractionDefinition.java b/src/main/java/com/github/kaktushose/jda/commands/definitions/interactions/InteractionDefinition.java
new file mode 100644
index 000000000..4ac5c32a8
--- /dev/null
+++ b/src/main/java/com/github/kaktushose/jda/commands/definitions/interactions/InteractionDefinition.java
@@ -0,0 +1,93 @@
+package com.github.kaktushose.jda.commands.definitions.interactions;
+
+import com.github.kaktushose.jda.commands.annotations.interactions.Interaction;
+import com.github.kaktushose.jda.commands.definitions.Definition;
+import com.github.kaktushose.jda.commands.definitions.features.internal.Invokable;
+import com.github.kaktushose.jda.commands.definitions.interactions.command.CommandDefinition;
+import com.github.kaktushose.jda.commands.definitions.interactions.command.ContextCommandDefinition;
+import com.github.kaktushose.jda.commands.definitions.interactions.command.SlashCommandDefinition;
+import com.github.kaktushose.jda.commands.definitions.interactions.component.ButtonDefinition;
+import com.github.kaktushose.jda.commands.definitions.interactions.component.ComponentDefinition;
+import com.github.kaktushose.jda.commands.definitions.interactions.component.menu.EntitySelectMenuDefinition;
+import com.github.kaktushose.jda.commands.definitions.interactions.component.menu.StringSelectMenuDefinition;
+import com.github.kaktushose.jda.commands.dispatching.middleware.impl.PermissionsMiddleware;
+import com.github.kaktushose.jda.commands.dispatching.reply.GlobalReplyConfig;
+import org.jetbrains.annotations.ApiStatus;
+import org.jetbrains.annotations.NotNull;
+
+import java.lang.reflect.InvocationTargetException;
+import java.util.Collection;
+
+/// Common interface for all definitions that represent an interaction.
+///
+/// @see AutoCompleteDefinition
+/// @see ModalDefinition
+/// @see ContextCommandDefinition
+/// @see SlashCommandDefinition
+/// @see ButtonDefinition
+/// @see EntitySelectMenuDefinition
+/// @see StringSelectMenuDefinition
+public sealed interface InteractionDefinition extends Definition, Invokable
+ permits AutoCompleteDefinition, ModalDefinition, CommandDefinition, ComponentDefinition {
+
+ /// The id for this definition. For interaction definition this is the hash code of the full class name and method
+ /// name combined.
+ @NotNull
+ @Override
+ default String definitionId() {
+ return String.valueOf((clazzDescription().clazz().getName() + methodDescription().name()).hashCode());
+ }
+
+ /// Creates a new instance of the [Interaction] class.
+ ///
+ /// @return a new instance of the declaring class of the method this definition is bound to.
+ /// @throws InvocationTargetException if the object creation fails
+ /// @throws InstantiationException if the object creation fails
+ /// @throws IllegalAccessException if the object creation fails
+ @ApiStatus.Internal
+ default Object newInstance() throws InvocationTargetException, InstantiationException, IllegalAccessException {
+ return clazzDescription().clazz().getConstructors()[0].newInstance();
+ }
+
+ /// A possibly-empty [Collection] of permissions for this interaction.
+ ///
+ /// @apiNote The [PermissionsMiddleware] will validate the provided permissions.
+ @NotNull
+ Collection permissions();
+
+ /// The [ReplyConfig] that should be used when sending replies.
+ ///
+ /// @implNote This will first attempt to use the [`ReplyConfig`][com.github.kaktushose.jda.commands.annotations.interactions.ReplyConfig]
+ /// annotation of the method and then of the class. If neither is present will fall back to the [GlobalReplyConfig].
+ @NotNull
+ default ReplyConfig replyConfig() {
+ var global = clazzDescription().annotation(com.github.kaktushose.jda.commands.annotations.interactions.ReplyConfig.class);
+ var local = methodDescription().annotation(com.github.kaktushose.jda.commands.annotations.interactions.ReplyConfig.class);
+
+ if (global.isEmpty() && local.isEmpty()) {
+ return new ReplyConfig();
+ }
+
+ return local.map(ReplyConfig::new).orElseGet(() -> new ReplyConfig(global.get()));
+
+ }
+
+ /// Stores the configuration values for sending replies. This acts as a representation of
+ /// [`ReplyConfig`][com.github.kaktushose.jda.commands.annotations.interactions.ReplyConfig].
+ ///
+ /// @see com.github.kaktushose.jda.commands.annotations.interactions.ReplyConfig ReplyConfig
+ record ReplyConfig(boolean ephemeral, boolean keepComponents, boolean editReply) {
+
+ /// Constructs a new ReplyConfig using the default values specified by [GlobalReplyConfig].
+ public ReplyConfig() {
+ this(GlobalReplyConfig.ephemeral, GlobalReplyConfig.keepComponents, GlobalReplyConfig.editReply);
+ }
+
+ /// Constructs a new ReplyConfig.
+ ///
+ /// @param replyConfig the [`ReplyConfig`][com.github.kaktushose.jda.commands.annotations.interactions.ReplyConfig] to represent
+ public ReplyConfig(@NotNull com.github.kaktushose.jda.commands.annotations.interactions.ReplyConfig replyConfig) {
+ this(replyConfig.ephemeral(), replyConfig.keepComponents(), replyConfig.editReply());
+ }
+ }
+}
diff --git a/src/main/java/com/github/kaktushose/jda/commands/definitions/interactions/InteractionRegistry.java b/src/main/java/com/github/kaktushose/jda/commands/definitions/interactions/InteractionRegistry.java
new file mode 100644
index 000000000..67bce5390
--- /dev/null
+++ b/src/main/java/com/github/kaktushose/jda/commands/definitions/interactions/InteractionRegistry.java
@@ -0,0 +1,203 @@
+package com.github.kaktushose.jda.commands.definitions.interactions;
+
+import com.github.kaktushose.jda.commands.annotations.Inject;
+import com.github.kaktushose.jda.commands.annotations.interactions.*;
+import com.github.kaktushose.jda.commands.definitions.Definition;
+import com.github.kaktushose.jda.commands.definitions.description.ClassDescription;
+import com.github.kaktushose.jda.commands.definitions.description.Descriptor;
+import com.github.kaktushose.jda.commands.definitions.description.MethodDescription;
+import com.github.kaktushose.jda.commands.definitions.interactions.command.ContextCommandDefinition;
+import com.github.kaktushose.jda.commands.definitions.interactions.command.SlashCommandDefinition;
+import com.github.kaktushose.jda.commands.definitions.interactions.component.ButtonDefinition;
+import com.github.kaktushose.jda.commands.definitions.interactions.component.menu.EntitySelectMenuDefinition;
+import com.github.kaktushose.jda.commands.definitions.interactions.component.menu.StringSelectMenuDefinition;
+import com.github.kaktushose.jda.commands.dependency.DependencyInjector;
+import com.github.kaktushose.jda.commands.dispatching.validation.ValidatorRegistry;
+import net.dv8tion.jda.api.interactions.commands.localization.LocalizationFunction;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.Optional;
+import java.util.*;
+import java.util.function.Predicate;
+
+import static com.github.kaktushose.jda.commands.definitions.interactions.command.SlashCommandDefinition.CooldownDefinition;
+
+/// Central registry for all [InteractionDefinition]s.
+public record InteractionRegistry(DependencyInjector dependencyInjector,
+ ValidatorRegistry validatorRegistry,
+ LocalizationFunction localizationFunction,
+ Descriptor descriptor,
+ Set definitions
+) {
+
+ private static final Logger log = LoggerFactory.getLogger(InteractionRegistry.class);
+
+ /// Constructs a new [InteractionRegistry]
+ ///
+ /// @param injector the [DependencyInjector] to use
+ /// @param registry the corresponding [ValidatorRegistry]
+ /// @param function the [LocalizationFunction] to use
+ /// @param descriptor the [Descriptor] to use
+ public InteractionRegistry(DependencyInjector injector, ValidatorRegistry registry, LocalizationFunction function, Descriptor descriptor) {
+ this(injector, registry, function, descriptor, new HashSet<>());
+ }
+
+ /// Scans all given classes and registers the interactions defined in them.
+ ///
+ /// @param classes the [Class]es to build the interactions from
+ public void index(Iterable> classes) {
+ int oldSize = definitions.size();
+
+ int count = 0;
+ for (Class> clazz : classes) {
+ log.debug("Found interaction controller {}", clazz.getName());
+ definitions.addAll(indexInteractionClass(descriptor.apply(clazz)));
+ count++;
+ }
+
+ log.debug("Successfully registered {} interaction controller(s) with a total of {} interaction(s)!",
+ count,
+ definitions.size() - oldSize);
+ }
+
+ private Collection indexInteractionClass(ClassDescription clazz) {
+ var interaction = clazz.annotation(Interaction.class).orElseThrow();
+
+ var fields = Arrays.stream(clazz.clazz().getDeclaredFields())
+ .filter(field -> field.isAnnotationPresent(Inject.class))
+ .toList();
+ dependencyInjector.registerDependencies(clazz.clazz(), fields);
+
+ final Set permissions = clazz.annotation(Permissions.class).map(value -> Set.of(value.value())).orElseGet(Set::of);
+ // get controller level cooldown and use it if no command level cooldown is present
+ CooldownDefinition cooldown = clazz.annotation(Cooldown.class).map(CooldownDefinition::build).orElse(null);
+
+ var autoCompletes = autoCompleteDefinitions(clazz);
+
+ // index interactions
+ var interactionDefinitions = interactionDefinitions(
+ clazz,
+ validatorRegistry,
+ localizationFunction,
+ interaction,
+ permissions,
+ cooldown,
+ autoCompletes
+ );
+
+ // validate auto completes
+ var commandDefinitions = interactionDefinitions.stream()
+ .filter(SlashCommandDefinition.class::isInstance)
+ .map(SlashCommandDefinition.class::cast)
+ .toList();
+
+ autoCompletes.stream()
+ .map(AutoCompleteDefinition::commands)
+ .flatMap(Collection::stream)
+ .filter(name -> commandDefinitions.stream().noneMatch(command -> command.name().startsWith(name)))
+ .forEach(s -> log.warn("No Command found for auto complete {}", s));
+
+ return interactionDefinitions;
+ }
+
+ private Collection autoCompleteDefinitions(ClassDescription clazz) {
+ return clazz.methods().stream()
+ .filter(it -> it.annotation(AutoComplete.class).isPresent())
+ .map(method -> AutoCompleteDefinition.build(clazz, method))
+ .filter(Optional::isPresent)
+ .map(Optional::get)
+ .toList();
+ }
+
+ private Set interactionDefinitions(ClassDescription clazz,
+ ValidatorRegistry validatorRegistry,
+ LocalizationFunction localizationFunction,
+ Interaction interaction,
+ Set permissions,
+ CooldownDefinition cooldown,
+ Collection autocompletes) {
+ Set definitions = new HashSet<>(autocompletes);
+ for (MethodDescription method : clazz.methods()) {
+ final MethodBuildContext context = new MethodBuildContext(
+ validatorRegistry,
+ localizationFunction,
+ interaction,
+ permissions,
+ cooldown,
+ clazz,
+ method,
+ autocompletes
+ );
+
+ Optional extends Definition> definition = Optional.empty();
+ // index commands
+ if (method.annotation(SlashCommand.class).isPresent()) {
+ definition = SlashCommandDefinition.build(context);
+ }
+ if (method.annotation(ContextCommand.class).isPresent()) {
+ definition = ContextCommandDefinition.build(context);
+ }
+
+ // index components
+ if (method.annotation(Button.class).isPresent()) {
+ definition = ButtonDefinition.build(context);
+ }
+ if (method.annotation(EntitySelectMenu.class).isPresent()) {
+ definition = EntitySelectMenuDefinition.build(context);
+ }
+ if (method.annotation(StringSelectMenu.class).isPresent()) {
+ definition = StringSelectMenuDefinition.build(context);
+ }
+
+ //index modals
+ if (method.annotation(Modal.class).isPresent()) {
+ definition = ModalDefinition.build(context);
+ }
+
+ definition.ifPresent(definitions::add);
+ }
+ return definitions;
+ }
+
+ /// Attempts to find a [Definition] of type [T] based on the given [Predicate].
+ ///
+ /// @param type the type of the [Definition] to find
+ /// @param internalError `true` if the [Definition] must be found and not finding it
+ /// indicates a framework bug
+ /// @param predicate the [Predicate] used to find the [Definition]
+ /// @param a subtype of [Definition]
+ /// @return [T]
+ /// @throws IllegalStateException if no [Definition] was found, although this mandatory should have been the case.
+ /// This is a rare occasion and can be considered a framework bug
+ /// @throws IllegalArgumentException if no [Definition] was found, because the [Predicate] didn't include any elements
+ public T find(Class type, boolean internalError, Predicate predicate) {
+ return definitions.stream()
+ .filter(type::isInstance)
+ .map(type::cast)
+ .filter(predicate)
+ .findFirst()
+ .orElseThrow(() -> internalError
+ ? new IllegalStateException("No interaction found! Please report this error the the devs of jda-commands.")
+ : new IllegalArgumentException("No interaction found! Please check that the referenced interaction method exists.")
+ );
+ }
+
+ /// Attempts to find all [Definition]s of type [T] based on the given [Predicate].
+ ///
+ /// @param type the type of the [Definition] to find
+ /// indicates a framework bug
+ /// @param predicate the [Predicate] used to find the [Definition]s
+ /// @param a subtype of [Definition]
+ /// @return a possibly-empty [Collection] of all [Definition]s that match the given [Predicate]
+ /// @throws IllegalStateException if no [Definition] was found, although this mandatory should have been the case.
+ /// This is a rare occasion and can be considered a framework bug
+ /// @throws IllegalArgumentException if no [Definition] was found, because the [Predicate] didn't include any elements
+ public Collection find(Class type, Predicate predicate) {
+ return definitions.stream()
+ .filter(type::isInstance)
+ .map(type::cast)
+ .filter(predicate)
+ .toList();
+ }
+}
diff --git a/src/main/java/com/github/kaktushose/jda/commands/definitions/interactions/MethodBuildContext.java b/src/main/java/com/github/kaktushose/jda/commands/definitions/interactions/MethodBuildContext.java
new file mode 100644
index 000000000..5f7c0717f
--- /dev/null
+++ b/src/main/java/com/github/kaktushose/jda/commands/definitions/interactions/MethodBuildContext.java
@@ -0,0 +1,27 @@
+package com.github.kaktushose.jda.commands.definitions.interactions;
+
+import com.github.kaktushose.jda.commands.annotations.interactions.Interaction;
+import com.github.kaktushose.jda.commands.definitions.description.ClassDescription;
+import com.github.kaktushose.jda.commands.definitions.description.MethodDescription;
+import com.github.kaktushose.jda.commands.definitions.interactions.command.SlashCommandDefinition.CooldownDefinition;
+import com.github.kaktushose.jda.commands.dispatching.validation.ValidatorRegistry;
+import net.dv8tion.jda.api.interactions.commands.localization.LocalizationFunction;
+import org.jetbrains.annotations.ApiStatus;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.Collection;
+import java.util.Set;
+
+/// Holds all objects needed to create an [InteractionDefinition].
+@ApiStatus.Internal
+public record MethodBuildContext(
+ @NotNull ValidatorRegistry validatorRegistry,
+ @NotNull LocalizationFunction localizationFunction,
+ Interaction interaction,
+ @NotNull Set permissions,
+ @Nullable CooldownDefinition cooldownDefinition,
+ @NotNull ClassDescription clazz,
+ @NotNull MethodDescription method,
+ @NotNull Collection autoCompleteDefinitions
+) {}
diff --git a/src/main/java/com/github/kaktushose/jda/commands/definitions/interactions/ModalDefinition.java b/src/main/java/com/github/kaktushose/jda/commands/definitions/interactions/ModalDefinition.java
new file mode 100644
index 000000000..dc95bc45c
--- /dev/null
+++ b/src/main/java/com/github/kaktushose/jda/commands/definitions/interactions/ModalDefinition.java
@@ -0,0 +1,168 @@
+package com.github.kaktushose.jda.commands.definitions.interactions;
+
+import com.github.kaktushose.jda.commands.definitions.Definition;
+import com.github.kaktushose.jda.commands.definitions.description.ClassDescription;
+import com.github.kaktushose.jda.commands.definitions.description.MethodDescription;
+import com.github.kaktushose.jda.commands.definitions.description.ParameterDescription;
+import com.github.kaktushose.jda.commands.definitions.features.CustomIdJDAEntity;
+import com.github.kaktushose.jda.commands.definitions.features.JDAEntity;
+import com.github.kaktushose.jda.commands.definitions.interactions.command.ParameterDefinition;
+import com.github.kaktushose.jda.commands.dispatching.events.interactions.ModalEvent;
+import com.github.kaktushose.jda.commands.internal.Helpers;
+import net.dv8tion.jda.api.interactions.components.text.TextInput;
+import net.dv8tion.jda.api.interactions.components.text.TextInputStyle;
+import net.dv8tion.jda.api.interactions.modals.Modal;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.*;
+
+/// Representation of a modal.
+///
+/// @param clazzDescription the [ClassDescription] of the declaring class of the [#methodDescription()]
+/// @param methodDescription the [MethodDescription] of the method this definition is bound to
+/// @param permissions a [Collection] of permissions for this modal
+/// @param title the title of the modal
+/// @param textInputs the [`TextInputs`][TextInputDefinition] of this modal
+public record ModalDefinition(
+ @NotNull ClassDescription clazzDescription,
+ @NotNull MethodDescription methodDescription,
+ @NotNull Collection permissions,
+ @NotNull String title,
+ @NotNull SequencedCollection textInputs
+) implements InteractionDefinition, CustomIdJDAEntity {
+
+ /// Builds a new [ModalDefinition] from the given [MethodBuildContext].
+ ///
+ /// @return an [Optional] holding the [ModalDefinition]
+ public static Optional build(MethodBuildContext context) {
+ var method = context.method();
+ var modal = method.annotation(com.github.kaktushose.jda.commands.annotations.interactions.Modal.class).orElseThrow();
+
+ // Modals support up to 5 TextInputs
+ if (method.parameters().isEmpty() || method.parameters().size() > 6) {
+ log.error("An error has occurred! Skipping Modal {}.{}:",
+ method.declaringClass().getName(),
+ method.name(),
+ new IllegalArgumentException("Invalid amount of parameters! Modals need between 1 and 5 TextInputs"));
+ return Optional.empty();
+ }
+
+ if (Helpers.isIncorrectParameterType(method, 0, ModalEvent.class)) {
+ return Optional.empty();
+ }
+
+ List textInputs = new ArrayList<>();
+ for (int i = 1; i < method.parameters().size(); i++) {
+ var parameter = List.copyOf(method.parameters()).get(i);
+ TextInputDefinition.build(parameter).ifPresent(textInputs::add);
+ }
+
+ if (textInputs.isEmpty()) {
+ log.error("An error has occurred! Skipping Modal {}.{}:",
+ method.declaringClass().getName(),
+ method.name(),
+ new IllegalArgumentException("Modals need at least one valid TextInput"));
+ return Optional.empty();
+ }
+
+ List> signature = new ArrayList<>();
+ signature.add(ModalEvent.class);
+ textInputs.forEach(_ -> signature.add(String.class));
+ if (Helpers.checkSignature(method, signature)) {
+ return Optional.empty();
+ }
+
+
+ return Optional.of(new ModalDefinition(context.clazz(), method, Helpers.permissions(context), modal.value(), textInputs));
+ }
+
+ /// Transforms this definition to an [Modal] with the given custom id.
+ ///
+ /// @return the [Modal]
+ /// @see CustomId#independent(String)
+ @NotNull
+ @Override
+ public Modal toJDAEntity(@NotNull CustomId customId) {
+ var modal = Modal.create(customId.id(), title);
+
+ textInputs.forEach(textInput -> modal.addActionRow(textInput.toJDAEntity()));
+
+ return modal.build();
+ }
+
+ @NotNull
+ @Override
+ public String displayName() {
+ return title;
+ }
+
+ /// Representation of a modal text input defined by
+ /// [`TextInput`][com.github.kaktushose.jda.commands.annotations.interactions.TextInput]
+ public record TextInputDefinition(
+ @NotNull String label,
+ @NotNull String placeholder,
+ @NotNull String defaultValue,
+ int minValue,
+ int maxValue,
+ @NotNull TextInputStyle style,
+ boolean required
+ ) implements JDAEntity, Definition {
+
+ /// Builds a new [TextInputDefinition] from the given [ParameterDefinition]
+ ///
+ /// @param parameter the [ParameterDefinition] to build the [TextInputDefinition] from
+ /// @return the new [TextInputDefinition]
+ public static Optional build(ParameterDescription parameter) {
+ var optional = parameter.annotation(com.github.kaktushose.jda.commands.annotations.interactions.TextInput.class);
+
+ if (optional.isEmpty()) {
+ return Optional.empty();
+ }
+
+ // TODO for now we only allow Strings, maybe add type adapting in the future
+ if (!String.class.isAssignableFrom(parameter.type())) {
+ return Optional.empty();
+ }
+ var textInput = optional.get();
+
+ return Optional.of(new TextInputDefinition(
+ textInput.label().isEmpty() ? parameter.name() : textInput.label(),
+ textInput.value(),
+ textInput.defaultValue(),
+ textInput.minValue(),
+ textInput.maxValue(),
+ textInput.style(),
+ textInput.required()
+ ));
+ }
+
+ @Override
+ public @NotNull String displayName() {
+ return label;
+ }
+
+ /// Transforms this definition into a [TextInput].
+ ///
+ /// @return the [TextInput]
+ @NotNull
+ @Override
+ public TextInput toJDAEntity() {
+ var textInput = TextInput.create(label, label, style).setRequired(required);
+
+ if (minValue != -1) {
+ textInput.setMinLength(minValue);
+ }
+ if (maxValue != -1) {
+ textInput.setMaxLength(maxValue);
+ }
+ if (!placeholder.isBlank()) {
+ textInput.setPlaceholder(placeholder);
+ }
+ if (!defaultValue.isBlank()) {
+ textInput.setValue(defaultValue);
+ }
+
+ return textInput.build();
+ }
+ }
+}
diff --git a/src/main/java/com/github/kaktushose/jda/commands/definitions/interactions/command/CommandDefinition.java b/src/main/java/com/github/kaktushose/jda/commands/definitions/interactions/command/CommandDefinition.java
new file mode 100644
index 000000000..b92a64da9
--- /dev/null
+++ b/src/main/java/com/github/kaktushose/jda/commands/definitions/interactions/command/CommandDefinition.java
@@ -0,0 +1,40 @@
+package com.github.kaktushose.jda.commands.definitions.interactions.command;
+
+import com.github.kaktushose.jda.commands.annotations.interactions.CommandScope;
+import com.github.kaktushose.jda.commands.definitions.features.JDAEntity;
+import com.github.kaktushose.jda.commands.definitions.interactions.InteractionDefinition;
+import net.dv8tion.jda.api.Permission;
+import net.dv8tion.jda.api.interactions.commands.Command;
+import net.dv8tion.jda.api.interactions.commands.build.CommandData;
+import net.dv8tion.jda.api.interactions.commands.localization.LocalizationFunction;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.Set;
+
+/// Common interface for command interaction definitions.
+///
+/// @see SlashCommandDefinition
+/// @see ContextCommandDefinition
+public sealed interface CommandDefinition extends InteractionDefinition, JDAEntity permits ContextCommandDefinition, SlashCommandDefinition {
+
+ /// The name of the command.
+ @NotNull String name();
+
+ /// Whether this command can only be executed in guilds.
+ boolean guildOnly();
+
+ /// Whether this command is nsfw.
+ boolean nsfw();
+
+ /// The [Command.Type] of this command.
+ @NotNull Command.Type commandType();
+
+ /// A possibly-empty [Set] of [Permission]s this command will be enabled for.
+ @NotNull Set enabledPermissions();
+
+ /// The [CommandScope] of this command.
+ @NotNull CommandScope scope();
+
+ /// The [LocalizationFunction] to use for this command.
+ @NotNull LocalizationFunction localizationFunction();
+}
diff --git a/src/main/java/com/github/kaktushose/jda/commands/definitions/interactions/command/ContextCommandDefinition.java b/src/main/java/com/github/kaktushose/jda/commands/definitions/interactions/command/ContextCommandDefinition.java
new file mode 100644
index 000000000..ffb63a009
--- /dev/null
+++ b/src/main/java/com/github/kaktushose/jda/commands/definitions/interactions/command/ContextCommandDefinition.java
@@ -0,0 +1,108 @@
+package com.github.kaktushose.jda.commands.definitions.interactions.command;
+
+import com.github.kaktushose.jda.commands.annotations.interactions.ContextCommand;
+import com.github.kaktushose.jda.commands.definitions.description.ClassDescription;
+import com.github.kaktushose.jda.commands.definitions.description.MethodDescription;
+import com.github.kaktushose.jda.commands.definitions.interactions.MethodBuildContext;
+import com.github.kaktushose.jda.commands.dispatching.events.interactions.CommandEvent;
+import com.github.kaktushose.jda.commands.internal.Helpers;
+import net.dv8tion.jda.api.Permission;
+import net.dv8tion.jda.api.entities.Message;
+import net.dv8tion.jda.api.entities.User;
+import net.dv8tion.jda.api.interactions.commands.Command;
+import net.dv8tion.jda.api.interactions.commands.DefaultMemberPermissions;
+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.localization.LocalizationFunction;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.*;
+import java.util.stream.Collectors;
+
+import com.github.kaktushose.jda.commands.annotations.interactions.CommandScope;
+
+/// Representation of a context command.
+///
+/// @param clazzDescription the [ClassDescription] of the declaring class of the [#methodDescription()]
+/// @param methodDescription the [MethodDescription] of the method this definition is bound to
+/// @param permissions a [Collection] of permissions for this command
+/// @param name the name of the command
+/// @param commandType the [Command.Type] of this command
+/// @param scope the [CommandScope] of this command
+/// @param guildOnly whether this command can only be executed in guilds
+/// @param nsfw whether this command is nsfw
+/// @param enabledPermissions a possibly-empty [Set] of [Permission]s this command will be enabled for
+/// @param localizationFunction the [LocalizationFunction] to use for this command
+public record ContextCommandDefinition(
+ @NotNull ClassDescription clazzDescription,
+ @NotNull MethodDescription methodDescription,
+ @NotNull Collection permissions,
+ @NotNull String name,
+ @NotNull Command.Type commandType,
+ @NotNull CommandScope scope,
+ boolean guildOnly,
+ boolean nsfw,
+ @NotNull Set enabledPermissions,
+ @NotNull LocalizationFunction localizationFunction
+) implements CommandDefinition {
+
+ /// Builds a new [ContextCommandDefinition] from the given [MethodBuildContext].
+ ///
+ /// @return an [Optional] holding the [ContextCommandDefinition]
+ @NotNull
+ public static Optional build(MethodBuildContext context) {
+ var method = context.method();
+ ContextCommand command = method.annotation(ContextCommand.class).orElseThrow();
+
+ var type = switch (command.type()) {
+ case USER -> User.class;
+ case MESSAGE -> Message.class;
+ default -> null;
+ };
+ if (type == null) {
+ log.error("Invalid command type for context command! Must either be USER or MESSAGE");
+ return Optional.empty();
+ }
+ if (Helpers.checkSignature(method, List.of(CommandEvent.class, type))) {
+ return Optional.empty();
+ }
+
+ Set enabledFor = Arrays.stream(command.enabledFor()).collect(Collectors.toSet());
+ if (enabledFor.size() == 1 && enabledFor.contains(Permission.UNKNOWN)) {
+ enabledFor.clear();
+ }
+
+ return Optional.of(new ContextCommandDefinition(
+ context.clazz(),
+ method,
+ Helpers.permissions(context),
+ command.value(),
+ command.type(),
+ command.scope(),
+ command.isGuildOnly(),
+ command.isNSFW(),
+ enabledFor,
+ context.localizationFunction()
+ ));
+ }
+
+ /// Transforms this definition into [CommandData].
+ ///
+ /// @return the [CommandData]
+ @NotNull
+ @Override
+ public CommandData toJDAEntity() {
+ var command = Commands.context(commandType, name);
+ command.setGuildOnly(guildOnly)
+ .setNSFW(nsfw)
+ .setDefaultPermissions(DefaultMemberPermissions.enabledFor(enabledPermissions))
+ .setLocalizationFunction(localizationFunction);
+ return command;
+ }
+
+ @NotNull
+ @Override
+ public String displayName() {
+ return name;
+ }
+}
diff --git a/src/main/java/com/github/kaktushose/jda/commands/reflect/ParameterDefinition.java b/src/main/java/com/github/kaktushose/jda/commands/definitions/interactions/command/ParameterDefinition.java
similarity index 54%
rename from src/main/java/com/github/kaktushose/jda/commands/reflect/ParameterDefinition.java
rename to src/main/java/com/github/kaktushose/jda/commands/definitions/interactions/command/ParameterDefinition.java
index 1e9eee659..0aa4e7953 100644
--- a/src/main/java/com/github/kaktushose/jda/commands/reflect/ParameterDefinition.java
+++ b/src/main/java/com/github/kaktushose/jda/commands/definitions/interactions/command/ParameterDefinition.java
@@ -1,11 +1,13 @@
-package com.github.kaktushose.jda.commands.reflect;
+package com.github.kaktushose.jda.commands.definitions.interactions.command;
import com.github.kaktushose.jda.commands.annotations.constraints.Constraint;
import com.github.kaktushose.jda.commands.annotations.constraints.Max;
import com.github.kaktushose.jda.commands.annotations.constraints.Min;
import com.github.kaktushose.jda.commands.annotations.interactions.Choices;
-import com.github.kaktushose.jda.commands.annotations.interactions.Optional;
import com.github.kaktushose.jda.commands.annotations.interactions.Param;
+import com.github.kaktushose.jda.commands.definitions.Definition;
+import com.github.kaktushose.jda.commands.definitions.description.ParameterDescription;
+import com.github.kaktushose.jda.commands.definitions.features.JDAEntity;
import com.github.kaktushose.jda.commands.dispatching.validation.Validator;
import com.github.kaktushose.jda.commands.dispatching.validation.ValidatorRegistry;
import net.dv8tion.jda.api.entities.Member;
@@ -16,39 +18,44 @@
import net.dv8tion.jda.api.entities.channel.middleman.AudioChannel;
import net.dv8tion.jda.api.entities.channel.middleman.GuildChannel;
import net.dv8tion.jda.api.entities.channel.middleman.GuildMessageChannel;
-import net.dv8tion.jda.api.interactions.commands.Command.Choice;
+import net.dv8tion.jda.api.interactions.commands.Command;
import net.dv8tion.jda.api.interactions.commands.OptionType;
import net.dv8tion.jda.api.interactions.commands.build.OptionData;
+import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
import java.lang.annotation.Annotation;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
-import java.lang.reflect.Parameter;
import java.util.*;
import static java.util.Map.entry;
-/**
- * Representation of a command parameter.
- *
- * @see Constraint
- * @see Choices
- * @see Param
- * @since 2.0.0
- */
+/// Representation of a slash command parameter.
+///
+/// @param type the [Class] type of the parameter
+/// @param optional whether this parameter is optional
+/// @param autoComplete whether this parameter supports autocomplete
+/// @param defaultValue the default value of this parameter or `null`
+/// @param name the name of the parameter
+/// @param description the description of the parameter
+/// @param choices a [SequencedCollection] of possible [Command.Choice]s for this parameter
+/// @param constraints a [Collection] of [ConstraintDefinition]s of this parameter
public record ParameterDefinition(
- Class> type,
- boolean isOptional,
- String defaultValue,
- boolean isPrimitive,
- String name,
- String description,
- List choices,
- List constraints
-) {
-
- private static final Map, Class>> TYPE_MAPPINGS = Map.ofEntries(
+ @NotNull Class> type,
+ boolean optional,
+ boolean autoComplete,
+ @Nullable String defaultValue,
+ @NotNull String name,
+ @NotNull String description,
+ @NotNull SequencedCollection choices,
+ @NotNull Collection constraints
+) implements Definition, JDAEntity {
+
+ /// A mapping of primitive types and their wrapper classes.
+ @ApiStatus.Internal
+ public static final Map, Class>> TYPE_MAPPINGS = Map.ofEntries(
entry(byte.class, Byte.class),
entry(short.class, Short.class),
entry(int.class, Integer.class),
@@ -69,7 +76,6 @@ public record ParameterDefinition(
entry(Boolean.class, OptionType.BOOLEAN),
entry(Character.class, OptionType.STRING),
entry(String.class, OptionType.STRING),
- entry(String[].class, OptionType.STRING),
entry(User.class, OptionType.USER),
entry(Member.class, OptionType.USER),
entry(GuildChannel.class, OptionType.CHANNEL),
@@ -97,27 +103,22 @@ public record ParameterDefinition(
))
);
- /**
- * Builds a new ParameterDefinition.
- *
- * @param parameter the {@link Parameter} of the command method
- * @param registry an instance of the corresponding {@link ValidatorRegistry}
- * @return a new ParameterDefinition
- */
+ /// Builds a new [ParameterDefinition].
+ ///
+ /// @param parameter the [ParameterDescription] to build the [ParameterDefinition] from
+ /// @param autoComplete whether the [ParameterDescription] should support autocomplete
+ /// @param validatorRegistry the corresponding [ValidatorRegistry]
+ /// @return the [ParameterDefinition]
@NotNull
- public static ParameterDefinition build(@NotNull Parameter parameter, @NotNull ValidatorRegistry registry) {
- if (parameter.isVarArgs()) {
- throw new IllegalArgumentException("VarArgs is not supported for parameters!");
- }
-
- Class> parameterType = parameter.getType();
- parameterType = TYPE_MAPPINGS.getOrDefault(parameterType, parameterType);
-
- // Optional
- final boolean isOptional = parameter.isAnnotationPresent(Optional.class);
- String defaultValue = "";
- if (isOptional) {
- defaultValue = parameter.getAnnotation(Optional.class).value();
+ public static ParameterDefinition build(ParameterDescription parameter,
+ boolean autoComplete,
+ @NotNull ValidatorRegistry validatorRegistry) {
+ final var parameterType = TYPE_MAPPINGS.getOrDefault(parameter.type(), parameter.type());
+
+ var optional = parameter.annotation(com.github.kaktushose.jda.commands.annotations.interactions.Optional.class);
+ var defaultValue = "";
+ if (optional.isPresent()) {
+ defaultValue = optional.get().value();
}
if (defaultValue.isEmpty()) {
defaultValue = null;
@@ -125,90 +126,75 @@ public static ParameterDefinition build(@NotNull Parameter parameter, @NotNull V
// index constraints
List constraints = new ArrayList<>();
- for (Annotation annotation : parameter.getAnnotations()) {
- Class> annotationType = annotation.annotationType();
- if (!annotationType.isAnnotationPresent(Constraint.class)) {
- continue;
- }
-
- // annotation object is always different, so we cannot cast it. Thus, we need to get the custom error message via reflection
- String message = "";
- try {
- Method method = annotationType.getDeclaredMethod("message");
- message = (String) method.invoke(annotation);
- } catch (NoSuchMethodException | InvocationTargetException | IllegalAccessException ignored) {
- }
- if (message.isEmpty()) {
- message = "Parameter validation failed";
- }
-
- java.util.Optional optional = registry.get(annotationType, parameterType);
- if (optional.isPresent()) {
- constraints.add(new ConstraintDefinition(optional.get(), message, annotation));
- }
- }
+ parameter.annotations().stream()
+ .filter(it -> it.annotationType().isAnnotationPresent(Constraint.class))
+ .forEach(it -> {
+ var validator = validatorRegistry.get(it.annotationType(), parameterType);
+ validator.ifPresent(value -> constraints.add(ConstraintDefinition.build(value, it)));
+ });
// Param
- String name = parameter.getName();
+ String name = parameter.name();
String description = "empty description";
- if (parameter.isAnnotationPresent(Param.class)) {
- Param param = parameter.getAnnotation(Param.class);
- name = param.name().isEmpty() ? name : param.name();
- description = param.value();
+ var param = parameter.annotation(Param.class);
+ if (param.isPresent()) {
+ name = param.get().name().isEmpty() ? name : param.get().name();
+ description = param.get().value();
}
name = name.replaceAll("([a-z])([A-Z]+)", "$1_$2").toLowerCase();
- List choices = new ArrayList<>();
+ List commandChoices = new ArrayList<>();
// Options
- if (parameter.isAnnotationPresent(Choices.class)) {
- Choices opt = parameter.getAnnotation(Choices.class);
- for (String option : opt.value()) {
+ var choices = parameter.annotation(Choices.class);
+ if (choices.isPresent()) {
+ for (String option : choices.get().value()) {
String[] parsed = option.split(":", 2);
if (parsed.length < 1) {
continue;
}
if (parsed.length < 2) {
- choices.add(new Choice(parsed[0], parsed[0]));
+ commandChoices.add(new Command.Choice(parsed[0], parsed[0]));
continue;
}
- choices.add(new Choice(parsed[0], parsed[1]));
+ commandChoices.add(new Command.Choice(parsed[0], parsed[1]));
}
}
-
- // this value is only used to determine if a default value must be present (primitives cannot be null)
- boolean usesPrimitives = TYPE_MAPPINGS.containsKey(parameter.getType());
-
return new ParameterDefinition(
parameterType,
- isOptional,
+ optional.isPresent(),
+ autoComplete,
defaultValue,
- usesPrimitives,
name,
description,
- choices,
+ commandChoices,
constraints
);
}
- /**
- * Transforms this parameter definition to a {@link OptionData}.
- *
- * @param isAutoComplete whether this {@link OptionData} should support auto complete
- * @return the transformed {@link OptionData}
- */
- public OptionData toOptionData(boolean isAutoComplete) {
+ @NotNull
+ @Override
+ public String displayName() {
+ return name;
+ }
+
+ /// Transforms this definition into [OptionData].
+ ///
+ /// @return the [OptionData]
+ @NotNull
+ @Override
+ public OptionData toJDAEntity() {
OptionType optionType = OPTION_TYPE_MAPPINGS.getOrDefault(type, OptionType.STRING);
OptionData optionData = new OptionData(
optionType,
name,
description,
- !isOptional
+ !optional
);
optionData.addChoices(choices);
if (optionType.canSupportChoices() && choices.isEmpty()) {
- optionData.setAutoComplete(isAutoComplete);
+ optionData.setAutoComplete(autoComplete);
}
constraints.stream().filter(constraint ->
@@ -223,4 +209,36 @@ public OptionData toOptionData(boolean isAutoComplete) {
return optionData;
}
+
+ /// Representation of a parameter constraint defined by a constraint annotation.
+ ///
+ /// @param validator the corresponding [Validator]
+ /// @param message the message to display if the constraint fails
+ /// @param annotation the corresponding annotation object
+ public record ConstraintDefinition(Validator validator, String message, Object annotation) implements Definition {
+
+ /// Builds a new [ConstraintDefinition].
+ ///
+ /// @param validator the corresponding [Validator]
+ /// @param annotation the corresponding annotation object
+ public static ConstraintDefinition build(@NotNull Validator validator, @NotNull Annotation annotation) {
+ // annotation object is always different, so we cannot cast it. Thus, we need to get the custom error message via reflection
+ var message = "";
+ try {
+ Method method = annotation.getClass().getDeclaredMethod("message");
+ message = (String) method.invoke(annotation);
+ } catch (NoSuchMethodException | InvocationTargetException | IllegalAccessException _) {
+ }
+ if (message.isEmpty()) {
+ message = "Parameter validation failed";
+ }
+ return new ConstraintDefinition(validator, message, annotation);
+ }
+
+ @NotNull
+ @Override
+ public String displayName() {
+ return validator.getClass().getName();
+ }
+ }
}
diff --git a/src/main/java/com/github/kaktushose/jda/commands/definitions/interactions/command/SlashCommandDefinition.java b/src/main/java/com/github/kaktushose/jda/commands/definitions/interactions/command/SlashCommandDefinition.java
new file mode 100644
index 000000000..34a911cec
--- /dev/null
+++ b/src/main/java/com/github/kaktushose/jda/commands/definitions/interactions/command/SlashCommandDefinition.java
@@ -0,0 +1,192 @@
+package com.github.kaktushose.jda.commands.definitions.interactions.command;
+
+import com.github.kaktushose.jda.commands.annotations.interactions.CommandScope;
+import com.github.kaktushose.jda.commands.annotations.interactions.Cooldown;
+import com.github.kaktushose.jda.commands.annotations.interactions.SlashCommand;
+import com.github.kaktushose.jda.commands.definitions.Definition;
+import com.github.kaktushose.jda.commands.definitions.description.ClassDescription;
+import com.github.kaktushose.jda.commands.definitions.description.MethodDescription;
+import com.github.kaktushose.jda.commands.definitions.interactions.AutoCompleteDefinition;
+import com.github.kaktushose.jda.commands.definitions.interactions.MethodBuildContext;
+import com.github.kaktushose.jda.commands.dispatching.events.interactions.CommandEvent;
+import com.github.kaktushose.jda.commands.internal.Helpers;
+import net.dv8tion.jda.api.Permission;
+import net.dv8tion.jda.api.interactions.commands.Command;
+import net.dv8tion.jda.api.interactions.commands.DefaultMemberPermissions;
+import net.dv8tion.jda.api.interactions.commands.build.Commands;
+import net.dv8tion.jda.api.interactions.commands.build.SlashCommandData;
+import net.dv8tion.jda.api.interactions.commands.build.SubcommandData;
+import net.dv8tion.jda.api.interactions.commands.localization.LocalizationFunction;
+import net.dv8tion.jda.internal.utils.Checks;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.*;
+import java.util.concurrent.TimeUnit;
+
+/// Representation of a slash command.
+///
+/// @param clazzDescription the [ClassDescription] of the declaring class of the [#methodDescription()]
+/// @param methodDescription the [MethodDescription] of the method this definition is bound to
+/// @param permissions a [Collection] of permissions for this command
+/// @param name the name of the command
+/// @param scope the [CommandScope] of this command
+/// @param guildOnly whether this command can only be executed in guilds
+/// @param nsfw whether this command is nsfw
+/// @param enabledPermissions a possibly-empty [Set] of [Permission]s this command will be enabled for
+/// @param localizationFunction the [LocalizationFunction] to use for this command
+/// @param description the command description
+/// @param commandParameters a [SequencedCollection] of [ParameterDefinition]s
+/// @param cooldown the corresponding [CooldownDefinition]
+/// @param isAutoComplete whether this command supports auto complete
+public record SlashCommandDefinition(
+ @NotNull ClassDescription clazzDescription,
+ @NotNull MethodDescription methodDescription,
+ @NotNull Collection permissions,
+ @NotNull String name,
+ @NotNull CommandScope scope,
+ boolean guildOnly,
+ boolean nsfw,
+ @NotNull Set enabledPermissions,
+ @NotNull LocalizationFunction localizationFunction,
+ @NotNull String description,
+ @NotNull SequencedCollection commandParameters,
+ @NotNull CooldownDefinition cooldown,
+ boolean isAutoComplete
+) implements CommandDefinition {
+
+ /// Builds a new [SlashCommandDefinition] from the given [MethodBuildContext].
+ ///
+ /// @return an [Optional] holding the [SlashCommandDefinition]
+ @NotNull
+ public static Optional build(MethodBuildContext context) {
+ var method = context.method();
+ var interaction = context.interaction();
+ var command = method.annotation(SlashCommand.class).orElseThrow();
+
+ String name = String.join(" ", interaction.value(), command.value())
+ .replaceAll(" +", " ")
+ .trim();
+
+ if (name.isEmpty()) {
+ Checks.notBlank(name, "Command name");
+ return Optional.empty();
+ }
+
+ boolean autoComplete = context.autoCompleteDefinitions().stream()
+ .map(AutoCompleteDefinition::commands)
+ .flatMap(Collection::stream)
+ .anyMatch(name::startsWith);
+
+ // build parameter definitions
+ List parameters = method.parameters().stream()
+ .filter(it -> !(CommandEvent.class.isAssignableFrom(it.type())))
+ .map(parameter -> ParameterDefinition.build(parameter, autoComplete, context.validatorRegistry()))
+ .toList();
+
+ Set enabledFor = Set.of(command.enabledFor());
+ if (enabledFor.size() == 1 && enabledFor.contains(Permission.UNKNOWN)) {
+ enabledFor = Set.of();
+ }
+
+ List> signature = new ArrayList<>();
+ signature.add(CommandEvent.class);
+ parameters.forEach(it -> signature.add(it.type()));
+ if (Helpers.checkSignature(method, signature)) {
+ return Optional.empty();
+ }
+
+ CooldownDefinition cooldownDefinition = CooldownDefinition.build(method.annotation(Cooldown.class).orElse(null));
+ if (cooldownDefinition.delay() == 0 && context.cooldownDefinition() != null) {
+ cooldownDefinition = context.cooldownDefinition();
+ }
+
+ return Optional.of(new SlashCommandDefinition(
+ context.clazz(),
+ method,
+ Helpers.permissions(context),
+ name,
+ command.scope(),
+ command.isGuildOnly(),
+ command.isNSFW(),
+ enabledFor,
+ context.localizationFunction(),
+ command.desc(),
+ parameters,
+ cooldownDefinition,
+ autoComplete
+ ));
+ }
+
+ /// Transforms this definition into [SlashCommandData].
+ ///
+ /// @return the [SlashCommandData]
+ @NotNull
+ @Override
+ public SlashCommandData toJDAEntity() {
+ SlashCommandData command = Commands.slash(
+ name,
+ description.replaceAll("N/A", "no description")
+ );
+ command.setGuildOnly(guildOnly)
+ .setNSFW(nsfw)
+ .setLocalizationFunction(localizationFunction)
+ .setDefaultPermissions(DefaultMemberPermissions.enabledFor(enabledPermissions));
+ commandParameters.forEach(parameter -> {
+ if (CommandEvent.class.isAssignableFrom(parameter.type())) {
+ return;
+ }
+ command.addOptions(parameter.toJDAEntity());
+ });
+ return command;
+ }
+
+ /// Transforms this definition into [SubcommandData].
+ ///
+ /// @return the [SubcommandData]
+ public SubcommandData toSubCommandData(String label) {
+ SubcommandData command = new SubcommandData(
+ label,
+ description.replaceAll("N/A", "no description")
+
+ );
+ commandParameters.forEach(parameter -> {
+ command.addOptions(parameter.toJDAEntity());
+ });
+ return command;
+ }
+
+ @NotNull
+ @Override
+ public String displayName() {
+ return "/%s".formatted(name);
+ }
+
+ @NotNull
+ @Override
+ public Command.Type commandType() {
+ return Command.Type.SLASH;
+ }
+
+ /// Representation of a cooldown definition defined by [Cooldown].
+ ///
+ /// @param delay the delay of the cooldown
+ /// @param timeUnit the [TimeUnit] of the specified delay
+ public record CooldownDefinition(long delay, TimeUnit timeUnit) implements Definition {
+
+ /// Builds a new [CooldownDefinition] from the given [Cooldown] annotation.
+ @NotNull
+ public static CooldownDefinition build(@Nullable Cooldown cooldown) {
+ if (cooldown == null) {
+ return new CooldownDefinition(0, TimeUnit.MILLISECONDS);
+ }
+ return new CooldownDefinition(cooldown.value(), cooldown.timeUnit());
+ }
+
+ @NotNull
+ @Override
+ public String displayName() {
+ return "Cooldown of %d %s".formatted(delay, timeUnit.name());
+ }
+ }
+}
diff --git a/src/main/java/com/github/kaktushose/jda/commands/definitions/interactions/command/package-info.java b/src/main/java/com/github/kaktushose/jda/commands/definitions/interactions/command/package-info.java
new file mode 100644
index 000000000..ccc62de37
--- /dev/null
+++ b/src/main/java/com/github/kaktushose/jda/commands/definitions/interactions/command/package-info.java
@@ -0,0 +1,2 @@
+/// [`Definitions`][com.github.kaktushose.jda.commands.definitions.Definition] that represent a command interaction.
+package com.github.kaktushose.jda.commands.definitions.interactions.command;
diff --git a/src/main/java/com/github/kaktushose/jda/commands/definitions/interactions/component/ButtonDefinition.java b/src/main/java/com/github/kaktushose/jda/commands/definitions/interactions/component/ButtonDefinition.java
new file mode 100644
index 000000000..54bdd943f
--- /dev/null
+++ b/src/main/java/com/github/kaktushose/jda/commands/definitions/interactions/component/ButtonDefinition.java
@@ -0,0 +1,100 @@
+package com.github.kaktushose.jda.commands.definitions.interactions.component;
+
+import com.github.kaktushose.jda.commands.definitions.description.ClassDescription;
+import com.github.kaktushose.jda.commands.definitions.description.MethodDescription;
+import com.github.kaktushose.jda.commands.definitions.interactions.CustomId;
+import com.github.kaktushose.jda.commands.definitions.interactions.MethodBuildContext;
+import com.github.kaktushose.jda.commands.definitions.interactions.component.menu.StringSelectMenuDefinition;
+import com.github.kaktushose.jda.commands.dispatching.events.interactions.ComponentEvent;
+import com.github.kaktushose.jda.commands.internal.Helpers;
+import net.dv8tion.jda.api.entities.emoji.Emoji;
+import net.dv8tion.jda.api.interactions.components.buttons.Button;
+import net.dv8tion.jda.api.interactions.components.buttons.ButtonStyle;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.Collection;
+import java.util.List;
+import java.util.Optional;
+
+/// Representation of a button.
+///
+/// @param clazzDescription the [ClassDescription] of the declaring class of the [#methodDescription()]
+/// @param methodDescription the [MethodDescription] of the method this definition is bound to
+/// @param permissions a [Collection] of permissions for this button
+/// @param label the label of this button
+/// @param emoji the [Emoji] of this button or `null`
+/// @param link the link of this button or `null`
+/// @param style the [ButtonStyle] of this button
+public record ButtonDefinition(
+ @NotNull ClassDescription clazzDescription,
+ @NotNull MethodDescription methodDescription,
+ @NotNull Collection permissions,
+ @NotNull String label,
+ @Nullable Emoji emoji,
+ @Nullable String link,
+ @NotNull ButtonStyle style
+) implements ComponentDefinition {
+
+ /// Constructs a new [ButtonDefinition] from the given [MethodBuildContext].
+ ///
+ /// @return an [ButtonDefinition] holding the [StringSelectMenuDefinition]
+ public static Optional build(MethodBuildContext context) {
+ var method = context.method();
+ com.github.kaktushose.jda.commands.annotations.interactions.Button button =
+ method.annotation(com.github.kaktushose.jda.commands.annotations.interactions.Button.class).orElseThrow();
+
+ if (Helpers.checkSignature(method, List.of(ComponentEvent.class))) {
+ return Optional.empty();
+ }
+
+ Emoji emoji;
+ String emojiString = button.emoji();
+ if (emojiString.isEmpty()) {
+ emoji = null;
+ } else {
+ emoji = Emoji.fromFormatted(emojiString);
+ }
+
+ return Optional.of(new ButtonDefinition(
+ context.clazz(),
+ method,
+ Helpers.permissions(context),
+ button.value(),
+ emoji,
+ button.link().isEmpty() ? null : button.link(),
+ button.style()
+ ));
+ }
+
+ /// Transforms this definition to an [Button] with an independent custom id.
+ ///
+ /// @return the [Button]
+ /// @see CustomId#independent(String)
+ @NotNull
+ @Override
+ public Button toJDAEntity() {
+ return toJDAEntity(CustomId.independent(definitionId()));
+ }
+
+ /// Transforms this definition to an [Button] with the given [CustomId].
+ ///
+ /// @param customId the [CustomId] to use
+ /// @return the [Button]
+ @NotNull
+ @Override
+ public Button toJDAEntity(@NotNull CustomId customId) {
+ String idOrUrl = Optional.ofNullable(link).orElse(customId.id());
+ if (emoji == null) {
+ return Button.of(style, idOrUrl, label);
+ } else {
+ return Button.of(style, idOrUrl, label, emoji);
+ }
+ }
+
+ @NotNull
+ @Override
+ public String displayName() {
+ return label.isEmpty() ? definitionId() : label;
+ }
+}
diff --git a/src/main/java/com/github/kaktushose/jda/commands/definitions/interactions/component/ComponentDefinition.java b/src/main/java/com/github/kaktushose/jda/commands/definitions/interactions/component/ComponentDefinition.java
new file mode 100644
index 000000000..aee6ad5bb
--- /dev/null
+++ b/src/main/java/com/github/kaktushose/jda/commands/definitions/interactions/component/ComponentDefinition.java
@@ -0,0 +1,27 @@
+package com.github.kaktushose.jda.commands.definitions.interactions.component;
+
+import com.github.kaktushose.jda.commands.definitions.description.ClassDescription;
+import com.github.kaktushose.jda.commands.definitions.description.MethodDescription;
+import com.github.kaktushose.jda.commands.definitions.features.CustomIdJDAEntity;
+import com.github.kaktushose.jda.commands.definitions.features.JDAEntity;
+import com.github.kaktushose.jda.commands.definitions.interactions.InteractionDefinition;
+import com.github.kaktushose.jda.commands.definitions.interactions.component.menu.EntitySelectMenuDefinition;
+import com.github.kaktushose.jda.commands.definitions.interactions.component.menu.SelectMenuDefinition;
+import com.github.kaktushose.jda.commands.definitions.interactions.component.menu.StringSelectMenuDefinition;
+import org.jetbrains.annotations.NotNull;
+
+/// Common interface for component interaction definitions.
+///
+/// @see ButtonDefinition
+/// @see EntitySelectMenuDefinition
+/// @see StringSelectMenuDefinition
+public sealed interface ComponentDefinition extends InteractionDefinition, JDAEntity, CustomIdJDAEntity
+ permits ButtonDefinition, SelectMenuDefinition {
+
+ /// The [ClassDescription] of the declaring class of the [#methodDescription()]
+ @NotNull ClassDescription clazzDescription();
+
+ /// The [MethodDescription] of the method this definition is bound to
+ @NotNull MethodDescription methodDescription();
+
+}
diff --git a/src/main/java/com/github/kaktushose/jda/commands/definitions/interactions/component/menu/EntitySelectMenuDefinition.java b/src/main/java/com/github/kaktushose/jda/commands/definitions/interactions/component/menu/EntitySelectMenuDefinition.java
new file mode 100644
index 000000000..24c6d3654
--- /dev/null
+++ b/src/main/java/com/github/kaktushose/jda/commands/definitions/interactions/component/menu/EntitySelectMenuDefinition.java
@@ -0,0 +1,115 @@
+package com.github.kaktushose.jda.commands.definitions.interactions.component.menu;
+
+import com.github.kaktushose.jda.commands.definitions.description.ClassDescription;
+import com.github.kaktushose.jda.commands.definitions.description.MethodDescription;
+import com.github.kaktushose.jda.commands.definitions.interactions.CustomId;
+import com.github.kaktushose.jda.commands.definitions.interactions.MethodBuildContext;
+import com.github.kaktushose.jda.commands.dispatching.events.interactions.ComponentEvent;
+import com.github.kaktushose.jda.commands.internal.Helpers;
+import net.dv8tion.jda.api.entities.Mentions;
+import net.dv8tion.jda.api.entities.channel.ChannelType;
+import net.dv8tion.jda.api.interactions.components.selections.EntitySelectMenu;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.*;
+
+/// Representation of an entity select menu.
+///
+/// @param clazzDescription the [ClassDescription] of the declaring class of the [#methodDescription()]
+/// @param methodDescription the [MethodDescription] of the method this definition is bound to
+/// @param permissions a [Collection] of permissions for this menu
+/// @param selectTargets the [EntitySelectMenu.SelectTarget]s of this menu
+/// @param defaultValues the [EntitySelectMenu.DefaultValue]s of this menu
+/// @param channelTypes the [ChannelType]s that should be supported by this menu.
+/// @param placeholder the placeholder text of this menu
+/// @param minValue the minimum amount of choices
+/// @param maxValue the maximum amount of choices
+public record EntitySelectMenuDefinition(
+ @NotNull ClassDescription clazzDescription,
+ @NotNull MethodDescription methodDescription,
+ @NotNull Collection permissions,
+ @NotNull Set selectTargets,
+ @NotNull Set defaultValues,
+ @NotNull Set channelTypes,
+ @NotNull String placeholder,
+ int minValue,
+ int maxValue
+) implements SelectMenuDefinition {
+
+ /// Builds a new [EntitySelectMenuDefinition] from the given [MethodBuildContext].
+ ///
+ /// @return an [Optional] holding the [EntitySelectMenuDefinition]
+ public static Optional build(MethodBuildContext context) {
+ var method = context.method();
+ com.github.kaktushose.jda.commands.annotations.interactions.EntitySelectMenu selectMenu =
+ method.annotation(com.github.kaktushose.jda.commands.annotations.interactions.EntitySelectMenu.class).orElseThrow();
+
+ if (Helpers.checkSignature(method, List.of(ComponentEvent.class, Mentions.class))) {
+ return Optional.empty();
+ }
+
+ Set defaultValueSet = new HashSet<>();
+ for (long id : selectMenu.defaultChannels()) {
+ if (id < 0) continue;
+ defaultValueSet.add(EntitySelectMenu.DefaultValue.channel(id));
+ }
+ for (long id : selectMenu.defaultUsers()) {
+ if (id < 0) continue;
+ defaultValueSet.add(EntitySelectMenu.DefaultValue.user(id));
+ }
+ for (long id : selectMenu.defaultRoles()) {
+ if (id < 0) continue;
+ defaultValueSet.add(EntitySelectMenu.DefaultValue.role(id));
+ }
+
+ return Optional.of(new EntitySelectMenuDefinition(
+ context.clazz(),
+ method,
+ Helpers.permissions(context),
+ Set.of(selectMenu.value()),
+ defaultValueSet,
+ new HashSet<>(Set.of(selectMenu.channelTypes())),
+ selectMenu.placeholder(),
+ selectMenu.minValue(),
+ selectMenu.maxValue()
+ ));
+ }
+
+ /// Transforms this definition to an [EntitySelectMenu] with an independent custom id.
+ ///
+ /// @return the [EntitySelectMenu]
+ /// @see CustomId#independent(String)
+ @NotNull
+ @Override
+ public EntitySelectMenu toJDAEntity() {
+ return toJDAEntity(CustomId.independent(definitionId()));
+ }
+
+ /// Transforms this definition to an [EntitySelectMenu] with the given [CustomId].
+ ///
+ /// @param customId the [CustomId] to use
+ /// @return the [EntitySelectMenu]
+ @NotNull
+ @Override
+ public EntitySelectMenu toJDAEntity(@NotNull CustomId customId) {
+ var menu = EntitySelectMenu.create(customId.id(), selectTargets)
+ .setDefaultValues(defaultValues)
+ .setPlaceholder(placeholder)
+ .setRequiredRange(minValue, maxValue);
+
+ // ChannelType.UNKNOWN is the default value inside the annotation. if this statement is true, we can assume that
+ // no channel type was selected
+ channelTypes.remove(ChannelType.UNKNOWN);
+ if (!channelTypes.isEmpty()) {
+ menu.setChannelTypes(channelTypes);
+ }
+ return menu.build();
+ }
+
+ @NotNull
+ @Override
+ public String displayName() {
+ return "Select Menu: %s".formatted(placeholder);
+ }
+
+}
diff --git a/src/main/java/com/github/kaktushose/jda/commands/definitions/interactions/component/menu/SelectMenuDefinition.java b/src/main/java/com/github/kaktushose/jda/commands/definitions/interactions/component/menu/SelectMenuDefinition.java
new file mode 100644
index 000000000..ce7fffbac
--- /dev/null
+++ b/src/main/java/com/github/kaktushose/jda/commands/definitions/interactions/component/menu/SelectMenuDefinition.java
@@ -0,0 +1,24 @@
+package com.github.kaktushose.jda.commands.definitions.interactions.component.menu;
+
+import com.github.kaktushose.jda.commands.definitions.interactions.component.ComponentDefinition;
+import net.dv8tion.jda.api.interactions.components.selections.SelectMenu;
+import org.jetbrains.annotations.NotNull;
+
+/// Common interface for select menu definitions.
+///
+/// @see EntitySelectMenuDefinition
+/// @see StringSelectMenuDefinition
+public sealed interface SelectMenuDefinition extends ComponentDefinition
+ permits EntitySelectMenuDefinition, StringSelectMenuDefinition {
+
+ /// the placeholder text of this menu
+ @NotNull
+ String placeholder();
+
+ /// the minimum amount of choices
+ int minValue();
+
+ /// the maximum amount of choices
+ int maxValue();
+
+}
diff --git a/src/main/java/com/github/kaktushose/jda/commands/definitions/interactions/component/menu/StringSelectMenuDefinition.java b/src/main/java/com/github/kaktushose/jda/commands/definitions/interactions/component/menu/StringSelectMenuDefinition.java
new file mode 100644
index 000000000..d0a0466f1
--- /dev/null
+++ b/src/main/java/com/github/kaktushose/jda/commands/definitions/interactions/component/menu/StringSelectMenuDefinition.java
@@ -0,0 +1,148 @@
+package com.github.kaktushose.jda.commands.definitions.interactions.component.menu;
+
+import com.github.kaktushose.jda.commands.definitions.Definition;
+import com.github.kaktushose.jda.commands.definitions.description.ClassDescription;
+import com.github.kaktushose.jda.commands.definitions.description.MethodDescription;
+import com.github.kaktushose.jda.commands.definitions.features.JDAEntity;
+import com.github.kaktushose.jda.commands.definitions.interactions.CustomId;
+import com.github.kaktushose.jda.commands.definitions.interactions.MethodBuildContext;
+import com.github.kaktushose.jda.commands.dispatching.events.interactions.ComponentEvent;
+import com.github.kaktushose.jda.commands.internal.Helpers;
+import net.dv8tion.jda.api.entities.emoji.Emoji;
+import net.dv8tion.jda.api.interactions.components.selections.SelectOption;
+import net.dv8tion.jda.api.interactions.components.selections.StringSelectMenu;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.*;
+import java.util.stream.Collectors;
+
+/// Representation of a string select menu.
+///
+/// @param clazzDescription the [ClassDescription] of the declaring class of the [#methodDescription()]
+/// @param methodDescription the [MethodDescription] of the method this definition is bound to
+/// @param permissions a [Collection] of permissions for this menu
+/// @param selectOptions the [SelectOptions][SelectOptionDefinition] of this menu
+/// @param placeholder the placeholder text of this menu
+/// @param minValue the minimum amount of choices
+/// @param maxValue the maximum amount of choices
+public record StringSelectMenuDefinition(
+ @NotNull ClassDescription clazzDescription,
+ @NotNull MethodDescription methodDescription,
+ @NotNull Collection permissions,
+ @NotNull Set selectOptions,
+ @NotNull String placeholder,
+ int minValue,
+ int maxValue
+) implements SelectMenuDefinition {
+
+ /// Builds a new [StringSelectMenuDefinition] from the given [MethodBuildContext].
+ ///
+ /// @return an [Optional] holding the [StringSelectMenuDefinition]
+ public static Optional build(MethodBuildContext context) {
+ var method = context.method();
+ com.github.kaktushose.jda.commands.annotations.interactions.StringSelectMenu selectMenu =
+ method.annotation(com.github.kaktushose.jda.commands.annotations.interactions.StringSelectMenu.class).orElseThrow();
+
+ if (Helpers.checkSignature(method, List.of(ComponentEvent.class, List.class))) {
+ return Optional.empty();
+ }
+
+ Set selectOptions = new HashSet<>();
+ method.annotations().stream()
+ .filter(com.github.kaktushose.jda.commands.annotations.interactions.SelectOption.class::isInstance)
+ .map(com.github.kaktushose.jda.commands.annotations.interactions.SelectOption.class::cast)
+ .forEach(it -> {
+ selectOptions.add(SelectOptionDefinition.build(it));
+ });
+
+ return Optional.of(new StringSelectMenuDefinition(
+ context.clazz(),
+ method,
+ Helpers.permissions(context),
+ selectOptions,
+ selectMenu.value(),
+ selectMenu.minValue(),
+ selectMenu.maxValue()
+ ));
+ }
+
+ /// Transforms this definition to an [StringSelectMenu] with an independent custom id.
+ ///
+ /// @return the [StringSelectMenu]
+ /// @see CustomId#independent(String)
+ @NotNull
+ @Override
+ public StringSelectMenu toJDAEntity() {
+ return toJDAEntity(CustomId.independent(definitionId()));
+ }
+
+ /// Transforms this definition to an [StringSelectMenu] with the given [CustomId].
+ ///
+ /// @param customId the [CustomId] to use
+ /// @return the [StringSelectMenu]
+ @NotNull
+ @Override
+ public StringSelectMenu toJDAEntity(@NotNull CustomId customId) {
+ return StringSelectMenu.create(customId.id())
+ .setPlaceholder(placeholder)
+ .setRequiredRange(minValue, maxValue)
+ .addOptions(selectOptions.stream().map(SelectOptionDefinition::toJDAEntity).collect(Collectors.toSet()))
+ .setDefaultOptions(selectOptions.stream()
+ .filter(SelectOptionDefinition::isDefault)
+ .map(SelectOptionDefinition::toJDAEntity)
+ .collect(Collectors.toSet())
+ )
+ .build();
+ }
+
+ @NotNull
+ @Override
+ public String displayName() {
+ return "Select Menu: %s".formatted(placeholder);
+ }
+
+ /// Representation of a select option for a string select menu defined by a
+ /// [`SelectOption`][com.github.kaktushose.jda.commands.annotations.interactions.SelectOption].
+ ///
+ /// @param value the value of the select option
+ /// @param label the label of the select option
+ /// @param description the description of the select option
+ /// @param emoji the [Emoji] of the select option or `null`
+ /// @param isDefault whether the select option is a default value
+ public record SelectOptionDefinition(@NotNull String value,
+ @NotNull String label,
+ @Nullable String description,
+ @Nullable Emoji emoji,
+ boolean isDefault
+ ) implements JDAEntity, Definition {
+
+ /// Constructs a new [SelectOptionDefinition] from the given
+ /// [`SelectOption`][com.github.kaktushose.jda.commands.annotations.interactions.SelectOption].
+ public static SelectOptionDefinition build(com.github.kaktushose.jda.commands.annotations.interactions.SelectOption option) {
+ Emoji emoji;
+ String emojiString = option.emoji();
+ if (emojiString.isEmpty()) {
+ emoji = null;
+ } else {
+ emoji = Emoji.fromFormatted(emojiString);
+ }
+ return new SelectOptionDefinition(option.value(), option.label(), option.description(), emoji, option.isDefault());
+ }
+
+ @NotNull
+ @Override
+ public String displayName() {
+ return value;
+ }
+
+ /// Transforms this definition into a [SelectOption].
+ @NotNull
+ @Override
+ public SelectOption toJDAEntity() {
+ return SelectOption.of(label, value)
+ .withDescription(description)
+ .withEmoji(emoji);
+ }
+ }
+}
diff --git a/src/main/java/com/github/kaktushose/jda/commands/definitions/interactions/component/menu/package-info.java b/src/main/java/com/github/kaktushose/jda/commands/definitions/interactions/component/menu/package-info.java
new file mode 100644
index 000000000..501644021
--- /dev/null
+++ b/src/main/java/com/github/kaktushose/jda/commands/definitions/interactions/component/menu/package-info.java
@@ -0,0 +1,2 @@
+/// [`Definitions`][com.github.kaktushose.jda.commands.definitions.Definition] that represent select menu interactions.
+package com.github.kaktushose.jda.commands.definitions.interactions.component.menu;
diff --git a/src/main/java/com/github/kaktushose/jda/commands/definitions/interactions/component/package-info.java b/src/main/java/com/github/kaktushose/jda/commands/definitions/interactions/component/package-info.java
new file mode 100644
index 000000000..4326873dc
--- /dev/null
+++ b/src/main/java/com/github/kaktushose/jda/commands/definitions/interactions/component/package-info.java
@@ -0,0 +1,2 @@
+/// [`Definitions`][com.github.kaktushose.jda.commands.definitions.Definition] that represent component interactions.
+package com.github.kaktushose.jda.commands.definitions.interactions.component;
diff --git a/src/main/java/com/github/kaktushose/jda/commands/definitions/interactions/package-info.java b/src/main/java/com/github/kaktushose/jda/commands/definitions/interactions/package-info.java
new file mode 100644
index 000000000..5b16f3f48
--- /dev/null
+++ b/src/main/java/com/github/kaktushose/jda/commands/definitions/interactions/package-info.java
@@ -0,0 +1,2 @@
+/// [`Definitions`][com.github.kaktushose.jda.commands.definitions.Definition] that represent any type interaction.
+package com.github.kaktushose.jda.commands.definitions.interactions;
diff --git a/src/main/java/com/github/kaktushose/jda/commands/dependency/DefaultDependencyInjector.java b/src/main/java/com/github/kaktushose/jda/commands/dependency/DefaultDependencyInjector.java
index 135c5446b..f3db50810 100644
--- a/src/main/java/com/github/kaktushose/jda/commands/dependency/DefaultDependencyInjector.java
+++ b/src/main/java/com/github/kaktushose/jda/commands/dependency/DefaultDependencyInjector.java
@@ -15,22 +15,17 @@
import java.lang.reflect.Modifier;
import java.util.*;
-/**
- * Default implementation of {@link DependencyInjector}.
- *
- * @see Produces
- * @see com.github.kaktushose.jda.commands.annotations.Inject Inject
- * @since 1.0.0
- */
+/// Default implementation of [DependencyInjector].
+///
+/// @see Produces
+/// @see com.github.kaktushose.jda.commands.annotations.Inject Inject
public class DefaultDependencyInjector implements DependencyInjector {
private final Map, Object> providedObjects;
private final Logger log = LoggerFactory.getLogger(DefaultDependencyInjector.class);
private final Map, List> dependencies;
- /**
- * Create a new DependencyInjector.
- */
+ /// Create a new DependencyInjector.
public DefaultDependencyInjector() {
providedObjects = new HashMap<>();
dependencies = new HashMap<>();
diff --git a/src/main/java/com/github/kaktushose/jda/commands/dependency/DependencyInjector.java b/src/main/java/com/github/kaktushose/jda/commands/dependency/DependencyInjector.java
index 937db317e..c8885d280 100644
--- a/src/main/java/com/github/kaktushose/jda/commands/dependency/DependencyInjector.java
+++ b/src/main/java/com/github/kaktushose/jda/commands/dependency/DependencyInjector.java
@@ -6,46 +6,35 @@
import java.lang.reflect.Field;
import java.util.List;
-/**
- * Central registry for dependencies and producing methods. Registered dependencies will be injected with the
- * corresponding values if present, else null.
- *
- * @see Produces
- * @see com.github.kaktushose.jda.commands.annotations.Inject Inject
- * @since 1.0.0
- */
+/// Central registry for dependencies and producing methods. Registered dependencies will be injected with the
+/// corresponding values if present, else null.
+///
+/// @see Produces
+/// @see com.github.kaktushose.jda.commands.annotations.Inject Inject
public interface DependencyInjector {
- /**
- * Scans the whole classpath for methods annotated with {@link Produces}. If found, creates a new instance of
- * the declaring class and will call the method to retrieve the object and register it as a dependency. If the method
- * is declared as static, no instance will be created. Use {@link #registerProvider(Object)} if no new instance of
- * the declaring class should be created.
- *
- * @param packages package(s) to exclusively scan
- * @param clazz a class of the classpath to scan
- */
+ /// Scans the whole classpath for methods annotated with [Produces]. If found, creates a new instance of
+ /// the declaring class and will call the method to retrieve the object and register it as a dependency. If the method
+ /// is declared as static, no instance will be created. Use [#registerProvider(Object)] if no new instance of
+ /// the declaring class should be created.
+ ///
+ /// @param packages package(s) to exclusively scan
+ /// @param clazz a class of the classpath to scan
void index(@NotNull Class> clazz, @NotNull String... packages);
- /**
- * Takes an instance of a class and scans it for methods annotated with {@link Produces}. If found, will call
- * the method to retrieve the object and register it as a dependency.
- *
- * @param provider instance of the class to scan
- */
+ /// Takes an instance of a class and scans it for methods annotated with [Produces]. If found, will call
+ /// the method to retrieve the object and register it as a dependency.
+ ///
+ /// @param provider instance of the class to scan
void registerProvider(@NotNull Object provider);
- /**
- * Registers fields inside a class as dependencies.
- *
- * @param clazz the declaring class
- * @param fields the dependencies to register
- */
+ /// Registers fields inside a class as dependencies.
+ ///
+ /// @param clazz the declaring class
+ /// @param fields the dependencies to register
void registerDependencies(@NotNull Class> clazz, @NotNull List fields);
- /**
- * Injects all registered dependencies with the corresponding value. If no value is present {@code null} gets injected.
- */
+ /// Injects all registered dependencies with the corresponding value. If no value is present `null` gets injected.
void inject(Object instance);
}
diff --git a/src/main/java/com/github/kaktushose/jda/commands/dependency/package-info.java b/src/main/java/com/github/kaktushose/jda/commands/dependency/package-info.java
index cf6192e8b..26a1346a5 100644
--- a/src/main/java/com/github/kaktushose/jda/commands/dependency/package-info.java
+++ b/src/main/java/com/github/kaktushose/jda/commands/dependency/package-info.java
@@ -1,4 +1,2 @@
-/**
- * The Dependency Injection feature of jda-commands.
- */
+/// The Dependency Injection feature of jda-commands.
package com.github.kaktushose.jda.commands.dependency;
diff --git a/src/main/java/com/github/kaktushose/jda/commands/reflect/ImplementationRegistry.java b/src/main/java/com/github/kaktushose/jda/commands/dispatching/ImplementationRegistry.java
similarity index 83%
rename from src/main/java/com/github/kaktushose/jda/commands/reflect/ImplementationRegistry.java
rename to src/main/java/com/github/kaktushose/jda/commands/dispatching/ImplementationRegistry.java
index ff3f4eaa9..b929b6096 100644
--- a/src/main/java/com/github/kaktushose/jda/commands/reflect/ImplementationRegistry.java
+++ b/src/main/java/com/github/kaktushose/jda/commands/dispatching/ImplementationRegistry.java
@@ -1,4 +1,4 @@
-package com.github.kaktushose.jda.commands.reflect;
+package com.github.kaktushose.jda.commands.dispatching;
import com.github.kaktushose.jda.commands.annotations.Implementation;
import com.github.kaktushose.jda.commands.annotations.Inject;
@@ -17,6 +17,7 @@
import com.github.kaktushose.jda.commands.permissions.PermissionsProvider;
import com.github.kaktushose.jda.commands.scope.DefaultGuildScopeProvider;
import com.github.kaktushose.jda.commands.scope.GuildScopeProvider;
+import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.NotNull;
import org.reflections.Reflections;
import org.reflections.scanners.Scanners;
@@ -32,21 +33,18 @@
import java.lang.reflect.ParameterizedType;
import java.util.*;
-/**
- * Central registry for all custom user implementations. This class will look for custom implementations that
- * override the default implementation of this framework. Supports the following interfaces:
- *
- * {@link PermissionsProvider}
- * {@link ErrorMessageFactory}
- * {@link GuildScopeProvider}
- * {@link TypeAdapter}
- * {@link Middleware}
- * {@link Validator}
- *
- *
- * @see Implementation
- * @since 2.0.0
- */
+/// Central registry for all custom user implementations. This class will look for custom implementations that
+/// override the default implementation of this framework. Supports the following interfaces:
+///
+/// - [PermissionsProvider]
+/// - [ErrorMessageFactory]
+/// - [GuildScopeProvider]
+/// - [TypeAdapter]
+/// - [Middleware]
+/// - [Validator]
+///
+/// @see Implementation
+@ApiStatus.Internal
public class ImplementationRegistry {
private static final Logger log = LoggerFactory.getLogger(ImplementationRegistry.class);
@@ -59,14 +57,12 @@ public class ImplementationRegistry {
private ErrorMessageFactory errorMessageFactory;
private GuildScopeProvider guildScopeProvider;
- /**
- * Constructs a new ImplementationRegistry.
- *
- * @param dependencyInjector the corresponding {@link DependencyInjector}
- * @param middlewareRegistry the corresponding {@link MiddlewareRegistry}
- * @param typeAdapterRegistry the corresponding {@link TypeAdapterRegistry}
- * @param validatorRegistry the corresponding {@link ValidatorRegistry}
- */
+ /// Constructs a new ImplementationRegistry.
+ ///
+ /// @param dependencyInjector the corresponding [DependencyInjector]
+ /// @param middlewareRegistry the corresponding [MiddlewareRegistry]
+ /// @param typeAdapterRegistry the corresponding [TypeAdapterRegistry]
+ /// @param validatorRegistry the corresponding [ValidatorRegistry]
public ImplementationRegistry(DependencyInjector dependencyInjector,
MiddlewareRegistry middlewareRegistry,
TypeAdapterRegistry typeAdapterRegistry,
@@ -81,12 +77,10 @@ public ImplementationRegistry(DependencyInjector dependencyInjector,
this.validatorRegistry = validatorRegistry;
}
- /**
- * Scans the whole classpath for custom implementations.
- *
- * @param packages package(s) to exclusively scan
- * @param clazz a class of the classpath to scan
- */
+ /// Scans the whole classpath for custom implementations.
+ ///
+ /// @param packages package(s) to exclusively scan
+ /// @param clazz a class of the classpath to scan
public void index(@NotNull Class> clazz, @NotNull String... packages) {
log.debug("Indexing custom implementations...");
@@ -110,57 +104,45 @@ public void index(@NotNull Class> clazz, @NotNull String... packages) {
findValidators().forEach(validatorRegistry::register);
}
- /**
- * Gets the {@link PermissionsProvider}.
- *
- * @return the {@link PermissionsProvider}
- */
+ /// Gets the [PermissionsProvider].
+ ///
+ /// @return the [PermissionsProvider]
public PermissionsProvider getPermissionsProvider() {
return permissionsProvider;
}
- /**
- * Sets the {@link PermissionsProvider}.
- *
- * @param permissionsProvider the new {@link PermissionsProvider}
- */
+ /// Sets the [PermissionsProvider].
+ ///
+ /// @param permissionsProvider the new [PermissionsProvider]
public void setPermissionsProvider(PermissionsProvider permissionsProvider) {
this.permissionsProvider = permissionsProvider;
}
- /**
- * Gets the {@link ErrorMessageFactory}.
- *
- * @return the {@link ErrorMessageFactory}
- */
+ /// Gets the [ErrorMessageFactory].
+ ///
+ /// @return the [ErrorMessageFactory]
public ErrorMessageFactory getErrorMessageFactory() {
return errorMessageFactory;
}
- /**
- * Sets the {@link ErrorMessageFactory}
- *
- * @param errorMessageFactory the new {@link ErrorMessageFactory}
- */
+ /// Sets the [ErrorMessageFactory]
+ ///
+ /// @param errorMessageFactory the new [ErrorMessageFactory]
public void setErrorMessageFactory(ErrorMessageFactory errorMessageFactory) {
this.errorMessageFactory = errorMessageFactory;
}
- /**
- * Gets the {@link GuildScopeProvider}.
- *
- * @return the {@link GuildScopeProvider}
- */
+ /// Gets the [GuildScopeProvider].
+ ///
+ /// @return the [GuildScopeProvider]
public GuildScopeProvider getGuildScopeProvider() {
return guildScopeProvider;
}
- /**
- * Sets the {@link GuildScopeProvider}
- *
- * @param guildScopeProvider the new {@link GuildScopeProvider}
- */
+ /// Sets the [GuildScopeProvider]
+ ///
+ /// @param guildScopeProvider the new [GuildScopeProvider]
public void setGuildScopeProvider(GuildScopeProvider guildScopeProvider) {
this.guildScopeProvider = guildScopeProvider;
}
diff --git a/src/main/java/com/github/kaktushose/jda/commands/dispatching/internal/JDAEventListener.java b/src/main/java/com/github/kaktushose/jda/commands/dispatching/JDAEventListener.java
similarity index 86%
rename from src/main/java/com/github/kaktushose/jda/commands/dispatching/internal/JDAEventListener.java
rename to src/main/java/com/github/kaktushose/jda/commands/dispatching/JDAEventListener.java
index 33c62f51b..eb8619485 100644
--- a/src/main/java/com/github/kaktushose/jda/commands/dispatching/internal/JDAEventListener.java
+++ b/src/main/java/com/github/kaktushose/jda/commands/dispatching/JDAEventListener.java
@@ -1,7 +1,7 @@
-package com.github.kaktushose.jda.commands.dispatching.internal;
+package com.github.kaktushose.jda.commands.dispatching;
+import com.github.kaktushose.jda.commands.definitions.interactions.CustomId;
import com.github.kaktushose.jda.commands.dispatching.handling.DispatchingContext;
-import com.github.kaktushose.jda.commands.reflect.interactions.CustomId;
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;
@@ -39,13 +39,13 @@ public void onGenericInteractionCreate(@NotNull GenericInteractionCreateEvent jd
runtimes.compute(UUID.randomUUID().toString(), (id, _) -> Runtime.startNew(id, context));
// always fetch runtime (bound to runtime)
- case GenericComponentInteractionCreateEvent event when CustomId.isBound(event.getComponentId()) ->
- runtimes.get(CustomId.runtimeId(event.getComponentId()));
- case ModalInteractionEvent event when CustomId.isBound(event.getModalId()) ->
- runtimes.get(CustomId.runtimeId(event.getModalId()));
+ case GenericComponentInteractionCreateEvent event when CustomId.fromEvent(event).isBound() ->
+ runtimes.get(CustomId.fromEvent(event).runtimeId());
+ case ModalInteractionEvent event when CustomId.fromEvent(event).isBound() ->
+ runtimes.get(CustomId.fromEvent(event).runtimeId());
// independent components always get their own runtime
- case GenericComponentInteractionCreateEvent event when CustomId.isIndependent(event.getComponentId()) ->
+ case GenericComponentInteractionCreateEvent event when CustomId.fromEvent(event).isIndependent() ->
runtimes.compute(UUID.randomUUID().toString(), (id, _) -> Runtime.startNew(id, context));
default -> null;
};
diff --git a/src/main/java/com/github/kaktushose/jda/commands/dispatching/internal/Runtime.java b/src/main/java/com/github/kaktushose/jda/commands/dispatching/Runtime.java
similarity index 94%
rename from src/main/java/com/github/kaktushose/jda/commands/dispatching/internal/Runtime.java
rename to src/main/java/com/github/kaktushose/jda/commands/dispatching/Runtime.java
index 12082da78..88dc6e966 100644
--- a/src/main/java/com/github/kaktushose/jda/commands/dispatching/internal/Runtime.java
+++ b/src/main/java/com/github/kaktushose/jda/commands/dispatching/Runtime.java
@@ -1,11 +1,11 @@
-package com.github.kaktushose.jda.commands.dispatching.internal;
+package com.github.kaktushose.jda.commands.dispatching;
-import com.github.kaktushose.jda.commands.dispatching.ExpirationStrategy;
+import com.github.kaktushose.jda.commands.definitions.interactions.InteractionDefinition;
import com.github.kaktushose.jda.commands.dispatching.context.KeyValueStore;
+import com.github.kaktushose.jda.commands.dispatching.expiration.ExpirationStrategy;
import com.github.kaktushose.jda.commands.dispatching.handling.*;
import com.github.kaktushose.jda.commands.dispatching.handling.command.ContextCommandHandler;
import com.github.kaktushose.jda.commands.dispatching.handling.command.SlashCommandHandler;
-import com.github.kaktushose.jda.commands.reflect.interactions.GenericInteractionDefinition;
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;
@@ -120,8 +120,8 @@ public KeyValueStore keyValueStore() {
return keyValueStore;
}
- public Object instance(GenericInteractionDefinition definition) {
- return instances.computeIfAbsent(definition.getMethod().getClass(), _ -> {
+ public Object instance(InteractionDefinition definition) {
+ return instances.computeIfAbsent(definition.methodDescription().declaringClass(), _ -> {
try {
return definition.newInstance();
} catch (InvocationTargetException | InstantiationException | IllegalAccessException e) {
diff --git a/src/main/java/com/github/kaktushose/jda/commands/dispatching/adapter/TypeAdapter.java b/src/main/java/com/github/kaktushose/jda/commands/dispatching/adapter/TypeAdapter.java
index d164331fa..6646d2d39 100644
--- a/src/main/java/com/github/kaktushose/jda/commands/dispatching/adapter/TypeAdapter.java
+++ b/src/main/java/com/github/kaktushose/jda/commands/dispatching/adapter/TypeAdapter.java
@@ -6,23 +6,18 @@
import java.util.Optional;
import java.util.function.BiFunction;
-/**
- * Generic top level interface for type adapting.
- *
- * @param the type the adapter parses
- * @see com.github.kaktushose.jda.commands.annotations.Implementation Implementation
- * @since 2.0.0
- */
+/// Generic top level interface for type adapting.
+///
+/// @param the type the adapter parses
+/// @see com.github.kaktushose.jda.commands.annotations.Implementation Implementation
@FunctionalInterface
public interface TypeAdapter extends BiFunction> {
- /**
- * Attempts to parse a String to the given type.
- *
- * @param raw the String to parse
- * @param event the {@link GenericInteractionCreateEvent}
- * @return the parsed type or an empty Optional if the parsing fails
- */
+ /// Attempts to parse a String to the given type.
+ ///
+ /// @param raw the String to parse
+ /// @param event the [GenericInteractionCreateEvent]
+ /// @return the parsed type or an empty Optional if the parsing fails
@NotNull Optional apply(@NotNull String raw, @NotNull GenericInteractionCreateEvent event);
}
diff --git a/src/main/java/com/github/kaktushose/jda/commands/dispatching/adapter/TypeAdapterRegistry.java b/src/main/java/com/github/kaktushose/jda/commands/dispatching/adapter/TypeAdapterRegistry.java
index 0289c12f6..9f181c0f8 100644
--- a/src/main/java/com/github/kaktushose/jda/commands/dispatching/adapter/TypeAdapterRegistry.java
+++ b/src/main/java/com/github/kaktushose/jda/commands/dispatching/adapter/TypeAdapterRegistry.java
@@ -8,6 +8,7 @@
import net.dv8tion.jda.api.entities.channel.middleman.AudioChannel;
import net.dv8tion.jda.api.entities.channel.middleman.GuildChannel;
import net.dv8tion.jda.api.entities.channel.middleman.GuildMessageChannel;
+import net.dv8tion.jda.api.entities.channel.middleman.MessageChannel;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.slf4j.Logger;
@@ -17,12 +18,9 @@
import java.util.Map;
import java.util.Optional;
-/**
- * Central registry for all type adapters.
- *
- * @see TypeAdapter
- * @since 2.0.0
- */
+/// Central registry for all type adapters.
+///
+/// @see TypeAdapter
public class TypeAdapterRegistry {
public static final Map, Object> DEFAULT_MAPPINGS = Map.of(
@@ -38,18 +36,15 @@ public class TypeAdapterRegistry {
private static final Logger log = LoggerFactory.getLogger(TypeAdapterRegistry.class);
private final Map, TypeAdapter>> parameterAdapters;
- /**
- * Constructs a new TypeAdapterRegistry. This will register default type adapters for:
- *
- * all primitive data types
- * String
- * String Array
- * {@link Member}
- * {@link User}
- * {@link net.dv8tion.jda.api.entities.channel.middleman.MessageChannel MessageChannel} and subtypes
- * {@link Role}
- *
- */
+ /// Constructs a new TypeAdapterRegistry. This will register default type adapters for:
+ ///
+ /// - all primitive data types
+ /// - [String]
+ /// - [String] Array
+ /// - [Member]
+ /// - [User]
+ /// - [MessageChannel] and subtypes
+ /// - [Role]
public TypeAdapterRegistry() {
parameterAdapters = new HashMap<>();
@@ -79,43 +74,35 @@ public TypeAdapterRegistry() {
register(Role.class, new RoleAdapter());
}
- /**
- * Registers a new type adapter.
- *
- * @param type the type the adapter is for
- * @param adapter the {@link TypeAdapter}
- */
+ /// Registers a new type adapter.
+ ///
+ /// @param type the type the adapter is for
+ /// @param adapter the [TypeAdapter]
public void register(@NotNull Class> type, @NotNull TypeAdapter> adapter) {
parameterAdapters.put(type, adapter);
log.debug("Registered adapter {} for type {}", adapter.getClass().getName(), type.getName());
}
- /**
- * Unregisters a new type adapter.
- *
- * @param type the type the adapter is for
- */
+ /// Unregisters a new type adapter.
+ ///
+ /// @param type the type the adapter is for
public void unregister(@NotNull Class> type) {
parameterAdapters.remove(type);
log.debug("Unregistered adapter for type {}", type.getName());
}
- /**
- * Checks if a type adapter for the given type exists.
- *
- * @param type the type to check
- * @return {@code true} if a type adapter exists
- */
+ /// Checks if a type adapter for the given type exists.
+ ///
+ /// @param type the type to check
+ /// @return `true` if a type adapter exists
public boolean exists(@Nullable Class> type) {
return parameterAdapters.containsKey(type);
}
- /**
- * Retrieves a type adapter.
- *
- * @param type the type to get the adapter for
- * @return the type adapter or an empty Optional if none found
- */
+ /// Retrieves a type adapter.
+ ///
+ /// @param type the type to get the adapter for
+ /// @return the type adapter or an empty Optional if none found
public Optional> get(@Nullable Class> type) {
return Optional.ofNullable(parameterAdapters.get(type));
}
diff --git a/src/main/java/com/github/kaktushose/jda/commands/dispatching/adapter/impl/AudioChannelAdapter.java b/src/main/java/com/github/kaktushose/jda/commands/dispatching/adapter/impl/AudioChannelAdapter.java
index 828c83134..f60fba4af 100644
--- a/src/main/java/com/github/kaktushose/jda/commands/dispatching/adapter/impl/AudioChannelAdapter.java
+++ b/src/main/java/com/github/kaktushose/jda/commands/dispatching/adapter/impl/AudioChannelAdapter.java
@@ -1,7 +1,7 @@
package com.github.kaktushose.jda.commands.dispatching.adapter.impl;
-import com.github.kaktushose.jda.commands.internal.Helpers;
import com.github.kaktushose.jda.commands.dispatching.adapter.TypeAdapter;
+import com.github.kaktushose.jda.commands.internal.Helpers;
import net.dv8tion.jda.api.entities.channel.Channel;
import net.dv8tion.jda.api.entities.channel.middleman.AudioChannel;
import net.dv8tion.jda.api.events.interaction.GenericInteractionCreateEvent;
@@ -9,20 +9,14 @@
import java.util.Optional;
-/**
- * Type adapter for JDAs {@link AudioChannel}.
- *
- * @since 2.3.0
- */
+/// Type adapter for JDAs [AudioChannel].
public class AudioChannelAdapter implements TypeAdapter {
- /**
- * Attempts to parse a String to a {@link AudioChannel}. Accepts both the channel id and name.
- *
- * @param raw the String to parse
- * @param event the {@link GenericInteractionCreateEvent}
- * @return the parsed {@link AudioChannel} or an empty Optional if the parsing fails
- */
+ /// Attempts to parse a String to a [AudioChannel]. Accepts both the channel id and name.
+ ///
+ /// @param raw the String to parse
+ /// @param event the [GenericInteractionCreateEvent]
+ /// @return the parsed [AudioChannel] or an empty Optional if the parsing fails
@NotNull
@Override
public Optional apply(@NotNull String raw, @NotNull GenericInteractionCreateEvent event) {
diff --git a/src/main/java/com/github/kaktushose/jda/commands/dispatching/adapter/impl/BooleanAdapter.java b/src/main/java/com/github/kaktushose/jda/commands/dispatching/adapter/impl/BooleanAdapter.java
index ceed0a002..aede137c8 100644
--- a/src/main/java/com/github/kaktushose/jda/commands/dispatching/adapter/impl/BooleanAdapter.java
+++ b/src/main/java/com/github/kaktushose/jda/commands/dispatching/adapter/impl/BooleanAdapter.java
@@ -6,21 +6,15 @@
import java.util.Optional;
-/**
- * Type adapter for boolean values.
- *
- * @since 2.0.0
- */
+/// Type adapter for boolean values.
public class BooleanAdapter implements TypeAdapter {
- /**
- * Attempts to parse a String to a Boolean. Accepts both String literals and {@code 0} or {@code 1}.
- * Parsing is case-insensitive .
- *
- * @param raw the String to parse
- * @param event the {@link GenericInteractionCreateEvent}
- * @return the parsed boolean or an empty Optional if the parsing fails
- */
+ /// Attempts to parse a String to a Boolean. Accepts both String literals and `0` or `1`.
+ /// Parsing is _case-insensitive_.
+ ///
+ /// @param raw the String to parse
+ /// @param event the [GenericInteractionCreateEvent]
+ /// @return the parsed boolean or an empty Optional if the parsing fails
@NotNull
@Override
public Optional apply(@NotNull String raw, @NotNull GenericInteractionCreateEvent event) {
diff --git a/src/main/java/com/github/kaktushose/jda/commands/dispatching/adapter/impl/ByteAdapter.java b/src/main/java/com/github/kaktushose/jda/commands/dispatching/adapter/impl/ByteAdapter.java
index 761e0cb25..65a360e49 100644
--- a/src/main/java/com/github/kaktushose/jda/commands/dispatching/adapter/impl/ByteAdapter.java
+++ b/src/main/java/com/github/kaktushose/jda/commands/dispatching/adapter/impl/ByteAdapter.java
@@ -6,20 +6,14 @@
import java.util.Optional;
-/**
- * Type adapter for byte values.
- *
- * @since 2.0.0
- */
+/// Type adapter for byte values.
public class ByteAdapter implements TypeAdapter {
- /**
- * Attempts to parse a String to a Byte.
- *
- * @param raw the String to parse
- * @param event the {@link GenericInteractionCreateEvent}
- * @return the parsed Byte or an empty Optional if the parsing fails
- */
+ /// Attempts to parse a String to a Byte.
+ ///
+ /// @param raw the String to parse
+ /// @param event the [GenericInteractionCreateEvent]
+ /// @return the parsed Byte or an empty Optional if the parsing fails
@NotNull
@Override
public Optional apply(@NotNull String raw, @NotNull GenericInteractionCreateEvent event) {
diff --git a/src/main/java/com/github/kaktushose/jda/commands/dispatching/adapter/impl/CharacterAdapter.java b/src/main/java/com/github/kaktushose/jda/commands/dispatching/adapter/impl/CharacterAdapter.java
index a58a30923..5b6c80186 100644
--- a/src/main/java/com/github/kaktushose/jda/commands/dispatching/adapter/impl/CharacterAdapter.java
+++ b/src/main/java/com/github/kaktushose/jda/commands/dispatching/adapter/impl/CharacterAdapter.java
@@ -6,20 +6,14 @@
import java.util.Optional;
-/**
- * Type adapter for character values.
- *
- * @since 2.0.0
- */
+/// Type adapter for character values.
public class CharacterAdapter implements TypeAdapter {
- /**
- * Casts a String to a Char if and only if {@code raw.length == 1}. Else, returns an empty Optional.
- *
- * @param raw the String to parse
- * @param event the {@link GenericInteractionCreateEvent}
- * @return the parsed Char or an empty Optional if the parsing fails
- */
+ /// Casts a String to a Char if and only if `raw.length == 1`. Else, returns an empty Optional.
+ ///
+ /// @param raw the String to parse
+ /// @param event the [GenericInteractionCreateEvent]
+ /// @return the parsed Char or an empty Optional if the parsing fails
@NotNull
@Override
public Optional apply(@NotNull String raw, @NotNull GenericInteractionCreateEvent event) {
diff --git a/src/main/java/com/github/kaktushose/jda/commands/dispatching/adapter/impl/DoubleAdapter.java b/src/main/java/com/github/kaktushose/jda/commands/dispatching/adapter/impl/DoubleAdapter.java
index 93da24305..38e6c145d 100644
--- a/src/main/java/com/github/kaktushose/jda/commands/dispatching/adapter/impl/DoubleAdapter.java
+++ b/src/main/java/com/github/kaktushose/jda/commands/dispatching/adapter/impl/DoubleAdapter.java
@@ -6,20 +6,14 @@
import java.util.Optional;
-/**
- * Type adapter for double values.
- *
- * @since 2.0.0
- */
+/// Type adapter for double values.
public class DoubleAdapter implements TypeAdapter {
- /**
- * Attempts to parse a String to a Double.
- *
- * @param raw the String to parse
- * @param event the {@link GenericInteractionCreateEvent}
- * @return the parsed Double or an empty Optional if the parsing fails
- */
+ /// Attempts to parse a String to a Double.
+ ///
+ /// @param raw the String to parse
+ /// @param event the [GenericInteractionCreateEvent]
+ /// @return the parsed Double or an empty Optional if the parsing fails
@NotNull
@Override
public Optional apply(@NotNull String raw, @NotNull GenericInteractionCreateEvent event) {
diff --git a/src/main/java/com/github/kaktushose/jda/commands/dispatching/adapter/impl/FloatAdapter.java b/src/main/java/com/github/kaktushose/jda/commands/dispatching/adapter/impl/FloatAdapter.java
index cdf56c273..4b6cea205 100644
--- a/src/main/java/com/github/kaktushose/jda/commands/dispatching/adapter/impl/FloatAdapter.java
+++ b/src/main/java/com/github/kaktushose/jda/commands/dispatching/adapter/impl/FloatAdapter.java
@@ -6,20 +6,14 @@
import java.util.Optional;
-/**
- * Type adapter for float values.
- *
- * @since 2.0.0
- */
+/// Type adapter for float values.
public class FloatAdapter implements TypeAdapter {
- /**
- * Attempts to parse a String to a Float.
- *
- * @param raw the String to parse
- * @param event the {@link GenericInteractionCreateEvent}
- * @return the parsed Float or an empty Optional if the parsing fails
- */
+ /// Attempts to parse a String to a Float.
+ ///
+ /// @param raw the String to parse
+ /// @param event the [GenericInteractionCreateEvent]
+ /// @return the parsed Float or an empty Optional if the parsing fails
@NotNull
@Override
public Optional apply(@NotNull String raw, @NotNull GenericInteractionCreateEvent event) {
diff --git a/src/main/java/com/github/kaktushose/jda/commands/dispatching/adapter/impl/GuildChannelAdapter.java b/src/main/java/com/github/kaktushose/jda/commands/dispatching/adapter/impl/GuildChannelAdapter.java
index 3fa37a155..01271958c 100644
--- a/src/main/java/com/github/kaktushose/jda/commands/dispatching/adapter/impl/GuildChannelAdapter.java
+++ b/src/main/java/com/github/kaktushose/jda/commands/dispatching/adapter/impl/GuildChannelAdapter.java
@@ -1,7 +1,7 @@
package com.github.kaktushose.jda.commands.dispatching.adapter.impl;
-import com.github.kaktushose.jda.commands.internal.Helpers;
import com.github.kaktushose.jda.commands.dispatching.adapter.TypeAdapter;
+import com.github.kaktushose.jda.commands.internal.Helpers;
import net.dv8tion.jda.api.entities.channel.Channel;
import net.dv8tion.jda.api.entities.channel.middleman.GuildChannel;
import net.dv8tion.jda.api.events.interaction.GenericInteractionCreateEvent;
@@ -9,20 +9,14 @@
import java.util.Optional;
-/**
- * Type adapter for JDAs {@link GuildChannel}.
- *
- * @since 2.3.0
- */
+/// Type adapter for JDAs [GuildChannel].
public class GuildChannelAdapter implements TypeAdapter {
- /**
- * Attempts to parse a String to a {@link GuildChannel}. Accepts both the channel id and name.
- *
- * @param raw the String to parse
- * @param event the {@link GenericInteractionCreateEvent}
- * @return the parsed {@link GuildChannel} or an empty Optional if the parsing fails
- */
+ /// Attempts to parse a String to a [GuildChannel]. Accepts both the channel id and name.
+ ///
+ /// @param raw the String to parse
+ /// @param event the [GenericInteractionCreateEvent]
+ /// @return the parsed [GuildChannel] or an empty Optional if the parsing fails
@NotNull
@Override
public Optional apply(@NotNull String raw, @NotNull GenericInteractionCreateEvent event) {
diff --git a/src/main/java/com/github/kaktushose/jda/commands/dispatching/adapter/impl/GuildMessageChannelAdapter.java b/src/main/java/com/github/kaktushose/jda/commands/dispatching/adapter/impl/GuildMessageChannelAdapter.java
index 93607c0a9..389ddbfce 100644
--- a/src/main/java/com/github/kaktushose/jda/commands/dispatching/adapter/impl/GuildMessageChannelAdapter.java
+++ b/src/main/java/com/github/kaktushose/jda/commands/dispatching/adapter/impl/GuildMessageChannelAdapter.java
@@ -1,7 +1,7 @@
package com.github.kaktushose.jda.commands.dispatching.adapter.impl;
-import com.github.kaktushose.jda.commands.internal.Helpers;
import com.github.kaktushose.jda.commands.dispatching.adapter.TypeAdapter;
+import com.github.kaktushose.jda.commands.internal.Helpers;
import net.dv8tion.jda.api.entities.channel.Channel;
import net.dv8tion.jda.api.entities.channel.middleman.GuildMessageChannel;
import net.dv8tion.jda.api.events.interaction.GenericInteractionCreateEvent;
@@ -9,20 +9,14 @@
import java.util.Optional;
-/**
- * Type adapter for JDAs {@link GuildMessageChannel}.
- *
- * @since 2.3.0
- */
+/// Type adapter for JDAs [GuildMessageChannel].
public class GuildMessageChannelAdapter implements TypeAdapter {
- /**
- * Attempts to parse a String to a {@link GuildMessageChannel}. Accepts both the channel id and name.
- *
- * @param raw the String to parse
- * @param event the {@link GenericInteractionCreateEvent}
- * @return the parsed {@link GuildMessageChannel} or an empty Optional if the parsing fails
- */
+ /// Attempts to parse a String to a [GuildMessageChannel]. Accepts both the channel id and name.
+ ///
+ /// @param raw the String to parse
+ /// @param event the [GenericInteractionCreateEvent]
+ /// @return the parsed [GuildMessageChannel] or an empty Optional if the parsing fails
@NotNull
@Override
public Optional apply(@NotNull String raw, @NotNull GenericInteractionCreateEvent event) {
diff --git a/src/main/java/com/github/kaktushose/jda/commands/dispatching/adapter/impl/IntegerAdapter.java b/src/main/java/com/github/kaktushose/jda/commands/dispatching/adapter/impl/IntegerAdapter.java
index 8ad95d21c..89e8aa824 100644
--- a/src/main/java/com/github/kaktushose/jda/commands/dispatching/adapter/impl/IntegerAdapter.java
+++ b/src/main/java/com/github/kaktushose/jda/commands/dispatching/adapter/impl/IntegerAdapter.java
@@ -6,20 +6,14 @@
import java.util.Optional;
-/**
- * Type adapter for integer values.
- *
- * @since 2.0.0
- */
+/// Type adapter for integer values.
public class IntegerAdapter implements TypeAdapter {
- /**
- * Attempts to parse a String to an Integer.
- *
- * @param raw the String to parse
- * @param event the {@link GenericInteractionCreateEvent}
- * @return the parsed Integer or an empty Optional if the parsing fails
- */
+ /// Attempts to parse a String to an Integer.
+ ///
+ /// @param raw the String to parse
+ /// @param event the [GenericInteractionCreateEvent]
+ /// @return the parsed Integer or an empty Optional if the parsing fails
@NotNull
@Override
public Optional apply(@NotNull String raw, @NotNull GenericInteractionCreateEvent event) {
diff --git a/src/main/java/com/github/kaktushose/jda/commands/dispatching/adapter/impl/LongAdapter.java b/src/main/java/com/github/kaktushose/jda/commands/dispatching/adapter/impl/LongAdapter.java
index 53151a042..3fead02f0 100644
--- a/src/main/java/com/github/kaktushose/jda/commands/dispatching/adapter/impl/LongAdapter.java
+++ b/src/main/java/com/github/kaktushose/jda/commands/dispatching/adapter/impl/LongAdapter.java
@@ -6,20 +6,14 @@
import java.util.Optional;
-/**
- * Type adapter for long values.
- *
- * @since 2.0.0
- */
+/// Type adapter for long values.
public class LongAdapter implements TypeAdapter {
- /**
- * Attempts to parse a String to a Long.
- *
- * @param raw the String to parse
- * @param event the {@link GenericInteractionCreateEvent}
- * @return the parsed Long or an empty Optional if the parsing fails
- */
+ /// Attempts to parse a String to a Long.
+ ///
+ /// @param raw the String to parse
+ /// @param event the [GenericInteractionCreateEvent]
+ /// @return the parsed Long or an empty Optional if the parsing fails
@NotNull
@Override
public Optional apply(@NotNull String raw, @NotNull GenericInteractionCreateEvent event) {
diff --git a/src/main/java/com/github/kaktushose/jda/commands/dispatching/adapter/impl/MemberAdapter.java b/src/main/java/com/github/kaktushose/jda/commands/dispatching/adapter/impl/MemberAdapter.java
index cde583edf..838117ebd 100644
--- a/src/main/java/com/github/kaktushose/jda/commands/dispatching/adapter/impl/MemberAdapter.java
+++ b/src/main/java/com/github/kaktushose/jda/commands/dispatching/adapter/impl/MemberAdapter.java
@@ -1,7 +1,7 @@
package com.github.kaktushose.jda.commands.dispatching.adapter.impl;
-import com.github.kaktushose.jda.commands.internal.Helpers;
import com.github.kaktushose.jda.commands.dispatching.adapter.TypeAdapter;
+import com.github.kaktushose.jda.commands.internal.Helpers;
import net.dv8tion.jda.api.entities.Guild;
import net.dv8tion.jda.api.entities.Member;
import net.dv8tion.jda.api.events.interaction.GenericInteractionCreateEvent;
@@ -10,20 +10,14 @@
import java.util.Optional;
-/**
- * Type adapter for JDAs {@link Member}.
- *
- * @since 2.0.0
- */
+/// Type adapter for JDAs [Member].
public class MemberAdapter implements TypeAdapter {
- /**
- * Attempts to parse a String to a {@link Member}. Accepts both the member id and name.
- *
- * @param raw the String to parse
- * @param event the {@link GenericInteractionCreateEvent}
- * @return the parsed {@link Member} or an empty Optional if the parsing fails
- */
+ /// Attempts to parse a String to a [Member]. Accepts both the member id and name.
+ ///
+ /// @param raw the String to parse
+ /// @param event the [GenericInteractionCreateEvent]
+ /// @return the parsed [Member] or an empty Optional if the parsing fails
@NotNull
@Override
public Optional apply(@NotNull String raw, @NotNull GenericInteractionCreateEvent event) {
diff --git a/src/main/java/com/github/kaktushose/jda/commands/dispatching/adapter/impl/NewsChannelAdapter.java b/src/main/java/com/github/kaktushose/jda/commands/dispatching/adapter/impl/NewsChannelAdapter.java
index 7f5bf70d2..f9b68b602 100644
--- a/src/main/java/com/github/kaktushose/jda/commands/dispatching/adapter/impl/NewsChannelAdapter.java
+++ b/src/main/java/com/github/kaktushose/jda/commands/dispatching/adapter/impl/NewsChannelAdapter.java
@@ -1,7 +1,7 @@
package com.github.kaktushose.jda.commands.dispatching.adapter.impl;
-import com.github.kaktushose.jda.commands.internal.Helpers;
import com.github.kaktushose.jda.commands.dispatching.adapter.TypeAdapter;
+import com.github.kaktushose.jda.commands.internal.Helpers;
import net.dv8tion.jda.api.entities.channel.Channel;
import net.dv8tion.jda.api.entities.channel.concrete.NewsChannel;
import net.dv8tion.jda.api.events.interaction.GenericInteractionCreateEvent;
@@ -9,20 +9,14 @@
import java.util.Optional;
-/**
- * Type adapter for JDAs {@link NewsChannel}.
- *
- * @since 2.3.0
- */
+/// Type adapter for JDAs [NewsChannel].
public class NewsChannelAdapter implements TypeAdapter {
- /**
- * Attempts to parse a String to a {@link NewsChannel}. Accepts both the channel id and name.
- *
- * @param raw the String to parse
- * @param event the {@link GenericInteractionCreateEvent}
- * @return the parsed {@link NewsChannel} or an empty Optional if the parsing fails
- */
+ /// Attempts to parse a String to a [NewsChannel]. Accepts both the channel id and name.
+ ///
+ /// @param raw the String to parse
+ /// @param event the [GenericInteractionCreateEvent]
+ /// @return the parsed [NewsChannel] or an empty Optional if the parsing fails
@NotNull
@Override
public Optional apply(@NotNull String raw, @NotNull GenericInteractionCreateEvent event) {
diff --git a/src/main/java/com/github/kaktushose/jda/commands/dispatching/adapter/impl/RoleAdapter.java b/src/main/java/com/github/kaktushose/jda/commands/dispatching/adapter/impl/RoleAdapter.java
index 2c550bd4c..9d8aff560 100644
--- a/src/main/java/com/github/kaktushose/jda/commands/dispatching/adapter/impl/RoleAdapter.java
+++ b/src/main/java/com/github/kaktushose/jda/commands/dispatching/adapter/impl/RoleAdapter.java
@@ -1,7 +1,7 @@
package com.github.kaktushose.jda.commands.dispatching.adapter.impl;
-import com.github.kaktushose.jda.commands.internal.Helpers;
import com.github.kaktushose.jda.commands.dispatching.adapter.TypeAdapter;
+import com.github.kaktushose.jda.commands.internal.Helpers;
import net.dv8tion.jda.api.entities.Guild;
import net.dv8tion.jda.api.entities.Role;
import net.dv8tion.jda.api.events.interaction.GenericInteractionCreateEvent;
@@ -9,20 +9,14 @@
import java.util.Optional;
-/**
- * Type adapter for JDAs {@link Role}.
- *
- * @since 2.0.0
- */
+/// Type adapter for JDAs [Role].
public class RoleAdapter implements TypeAdapter {
- /**
- * Attempts to parse a String to a {@link Role}. Accepts both the role id and name.
- *
- * @param raw the String to parse
- * @param event the {@link GenericInteractionCreateEvent}
- * @return the parsed {@link Role} or an empty Optional if the parsing fails
- */
+ /// Attempts to parse a String to a [Role]. Accepts both the role id and name.
+ ///
+ /// @param raw the String to parse
+ /// @param event the [GenericInteractionCreateEvent]
+ /// @return the parsed [Role] or an empty Optional if the parsing fails
@NotNull
@Override
public Optional apply(@NotNull String raw, @NotNull GenericInteractionCreateEvent event) {
diff --git a/src/main/java/com/github/kaktushose/jda/commands/dispatching/adapter/impl/ShortAdapter.java b/src/main/java/com/github/kaktushose/jda/commands/dispatching/adapter/impl/ShortAdapter.java
index dbf9bb271..d5403c8e9 100644
--- a/src/main/java/com/github/kaktushose/jda/commands/dispatching/adapter/impl/ShortAdapter.java
+++ b/src/main/java/com/github/kaktushose/jda/commands/dispatching/adapter/impl/ShortAdapter.java
@@ -6,20 +6,14 @@
import java.util.Optional;
-/**
- * Type adapter for short values.
- *
- * @since 2.0.0
- */
+/// Type adapter for short values.
public class ShortAdapter implements TypeAdapter {
- /**
- * Attempts to parse a String to a Short.
- *
- * @param raw the String to parse
- * @param event the {@link GenericInteractionCreateEvent}
- * @return the parsed Short or an empty Optional if the parsing fails
- */
+ /// Attempts to parse a String to a Short.
+ ///
+ /// @param raw the String to parse
+ /// @param event the [GenericInteractionCreateEvent]
+ /// @return the parsed Short or an empty Optional if the parsing fails
@NotNull
@Override
public Optional apply(@NotNull String raw, @NotNull GenericInteractionCreateEvent event) {
diff --git a/src/main/java/com/github/kaktushose/jda/commands/dispatching/adapter/impl/StageChannelAdapter.java b/src/main/java/com/github/kaktushose/jda/commands/dispatching/adapter/impl/StageChannelAdapter.java
index 8f7dba30a..70675babf 100644
--- a/src/main/java/com/github/kaktushose/jda/commands/dispatching/adapter/impl/StageChannelAdapter.java
+++ b/src/main/java/com/github/kaktushose/jda/commands/dispatching/adapter/impl/StageChannelAdapter.java
@@ -1,7 +1,7 @@
package com.github.kaktushose.jda.commands.dispatching.adapter.impl;
-import com.github.kaktushose.jda.commands.internal.Helpers;
import com.github.kaktushose.jda.commands.dispatching.adapter.TypeAdapter;
+import com.github.kaktushose.jda.commands.internal.Helpers;
import net.dv8tion.jda.api.entities.channel.Channel;
import net.dv8tion.jda.api.entities.channel.concrete.StageChannel;
import net.dv8tion.jda.api.events.interaction.GenericInteractionCreateEvent;
@@ -9,20 +9,14 @@
import java.util.Optional;
-/**
- * Type adapter for JDAs {@link StageChannel}.
- *
- * @since 2.3.0
- */
+/// Type adapter for JDAs [StageChannel].
public class StageChannelAdapter implements TypeAdapter {
- /**
- * Attempts to parse a String to a {@link StageChannel}. Accepts both the channel id and name.
- *
- * @param raw the String to parse
- * @param event the {@link GenericInteractionCreateEvent}
- * @return the parsed {@link StageChannel} or an empty Optional if the parsing fails
- */
+ /// Attempts to parse a String to a [StageChannel]. Accepts both the channel id and name.
+ ///
+ /// @param raw the String to parse
+ /// @param event the [GenericInteractionCreateEvent]
+ /// @return the parsed [StageChannel] or an empty Optional if the parsing fails
@NotNull
@Override
public Optional apply(@NotNull String raw, @NotNull GenericInteractionCreateEvent event) {
diff --git a/src/main/java/com/github/kaktushose/jda/commands/dispatching/adapter/impl/TextChannelAdapter.java b/src/main/java/com/github/kaktushose/jda/commands/dispatching/adapter/impl/TextChannelAdapter.java
index 7732b244e..151bdccb8 100644
--- a/src/main/java/com/github/kaktushose/jda/commands/dispatching/adapter/impl/TextChannelAdapter.java
+++ b/src/main/java/com/github/kaktushose/jda/commands/dispatching/adapter/impl/TextChannelAdapter.java
@@ -1,27 +1,21 @@
package com.github.kaktushose.jda.commands.dispatching.adapter.impl;
-import com.github.kaktushose.jda.commands.internal.Helpers;
import com.github.kaktushose.jda.commands.dispatching.adapter.TypeAdapter;
+import com.github.kaktushose.jda.commands.internal.Helpers;
import net.dv8tion.jda.api.entities.channel.concrete.TextChannel;
import net.dv8tion.jda.api.events.interaction.GenericInteractionCreateEvent;
import org.jetbrains.annotations.NotNull;
import java.util.Optional;
-/**
- * Type adapter for JDAs {@link TextChannel}.
- *
- * @since 2.0.0
- */
+/// Type adapter for JDAs [TextChannel].
public class TextChannelAdapter implements TypeAdapter {
- /**
- * Attempts to parse a String to a {@link TextChannel}. Accepts both the channel id and name.
- *
- * @param raw the String to parse
- * @param event the {@link GenericInteractionCreateEvent}
- * @return the parsed {@link TextChannel} or an empty Optional if the parsing fails
- */
+ /// Attempts to parse a String to a [TextChannel]. Accepts both the channel id and name.
+ ///
+ /// @param raw the String to parse
+ /// @param event the [GenericInteractionCreateEvent]
+ /// @return the parsed [TextChannel] or an empty Optional if the parsing fails
@NotNull
@Override
public Optional apply(@NotNull String raw, @NotNull GenericInteractionCreateEvent event) {
diff --git a/src/main/java/com/github/kaktushose/jda/commands/dispatching/adapter/impl/ThreadChannelAdapter.java b/src/main/java/com/github/kaktushose/jda/commands/dispatching/adapter/impl/ThreadChannelAdapter.java
index d0c3fd180..c74c6d81f 100644
--- a/src/main/java/com/github/kaktushose/jda/commands/dispatching/adapter/impl/ThreadChannelAdapter.java
+++ b/src/main/java/com/github/kaktushose/jda/commands/dispatching/adapter/impl/ThreadChannelAdapter.java
@@ -1,7 +1,7 @@
package com.github.kaktushose.jda.commands.dispatching.adapter.impl;
-import com.github.kaktushose.jda.commands.internal.Helpers;
import com.github.kaktushose.jda.commands.dispatching.adapter.TypeAdapter;
+import com.github.kaktushose.jda.commands.internal.Helpers;
import net.dv8tion.jda.api.entities.channel.Channel;
import net.dv8tion.jda.api.entities.channel.concrete.ThreadChannel;
import net.dv8tion.jda.api.events.interaction.GenericInteractionCreateEvent;
@@ -9,20 +9,14 @@
import java.util.Optional;
-/**
- * Type adapter for JDAs {@link ThreadChannel}.
- *
- * @since 2.3.0
- */
+/// Type adapter for JDAs [ThreadChannel].
public class ThreadChannelAdapter implements TypeAdapter {
- /**
- * Attempts to parse a String to a {@link ThreadChannel}. Accepts both the channel id and name.
- *
- * @param raw the String to parse
- * @param event the {@link GenericInteractionCreateEvent}
- * @return the parsed {@link ThreadChannel} or an empty Optional if the parsing fails
- */
+ /// Attempts to parse a String to a [ThreadChannel]. Accepts both the channel id and name.
+ ///
+ /// @param raw the String to parse
+ /// @param event the [GenericInteractionCreateEvent]
+ /// @return the parsed [ThreadChannel] or an empty Optional if the parsing fails
@NotNull
@Override
public Optional apply(@NotNull String raw, @NotNull GenericInteractionCreateEvent event) {
diff --git a/src/main/java/com/github/kaktushose/jda/commands/dispatching/adapter/impl/UserAdapter.java b/src/main/java/com/github/kaktushose/jda/commands/dispatching/adapter/impl/UserAdapter.java
index c812e0505..6e818ba48 100644
--- a/src/main/java/com/github/kaktushose/jda/commands/dispatching/adapter/impl/UserAdapter.java
+++ b/src/main/java/com/github/kaktushose/jda/commands/dispatching/adapter/impl/UserAdapter.java
@@ -1,7 +1,7 @@
package com.github.kaktushose.jda.commands.dispatching.adapter.impl;
-import com.github.kaktushose.jda.commands.internal.Helpers;
import com.github.kaktushose.jda.commands.dispatching.adapter.TypeAdapter;
+import com.github.kaktushose.jda.commands.internal.Helpers;
import net.dv8tion.jda.api.JDA;
import net.dv8tion.jda.api.entities.User;
import net.dv8tion.jda.api.events.interaction.GenericInteractionCreateEvent;
@@ -10,20 +10,14 @@
import java.util.Optional;
-/**
- * Type adapter for JDAs {@link User}.
- *
- * @since 2.0.0
- */
+/// Type adapter for JDAs [User].
public class UserAdapter implements TypeAdapter {
- /**
- * Attempts to parse a String to a {@link User}. Accepts both the user id and name.
- *
- * @param raw the String to parse
- * @param event the {@link GenericInteractionCreateEvent}
- * @return the parsed {@link User} or an empty Optional if the parsing fails
- */
+ /// Attempts to parse a String to a [User]. Accepts both the user id and name.
+ ///
+ /// @param raw the String to parse
+ /// @param event the [GenericInteractionCreateEvent]
+ /// @return the parsed [User] or an empty Optional if the parsing fails
@NotNull
@Override
public Optional apply(@NotNull String raw, @NotNull GenericInteractionCreateEvent event) {
diff --git a/src/main/java/com/github/kaktushose/jda/commands/dispatching/adapter/impl/VoiceChannelAdapter.java b/src/main/java/com/github/kaktushose/jda/commands/dispatching/adapter/impl/VoiceChannelAdapter.java
index 21562b260..c458c83b8 100644
--- a/src/main/java/com/github/kaktushose/jda/commands/dispatching/adapter/impl/VoiceChannelAdapter.java
+++ b/src/main/java/com/github/kaktushose/jda/commands/dispatching/adapter/impl/VoiceChannelAdapter.java
@@ -1,7 +1,7 @@
package com.github.kaktushose.jda.commands.dispatching.adapter.impl;
-import com.github.kaktushose.jda.commands.internal.Helpers;
import com.github.kaktushose.jda.commands.dispatching.adapter.TypeAdapter;
+import com.github.kaktushose.jda.commands.internal.Helpers;
import net.dv8tion.jda.api.entities.channel.Channel;
import net.dv8tion.jda.api.entities.channel.concrete.VoiceChannel;
import net.dv8tion.jda.api.events.interaction.GenericInteractionCreateEvent;
@@ -9,20 +9,14 @@
import java.util.Optional;
-/**
- * Type adapter for JDAs {@link VoiceChannel}.
- *
- * @since 2.3.0
- */
+/// Type adapter for JDAs [VoiceChannel].
public class VoiceChannelAdapter implements TypeAdapter {
- /**
- * Attempts to parse a String to a {@link VoiceChannel}. Accepts both the channel id and name.
- *
- * @param raw the String to parse
- * @param event the {@link GenericInteractionCreateEvent}
- * @return the parsed {@link VoiceChannel} or an empty Optional if the parsing fails
- */
+ /// Attempts to parse a String to a [VoiceChannel]. Accepts both the channel id and name.
+ ///
+ /// @param raw the String to parse
+ /// @param event the [GenericInteractionCreateEvent]
+ /// @return the parsed [VoiceChannel] or an empty Optional if the parsing fails
@NotNull
@Override
public Optional apply(@NotNull String raw, @NotNull GenericInteractionCreateEvent event) {
diff --git a/src/main/java/com/github/kaktushose/jda/commands/dispatching/adapter/impl/package-info.java b/src/main/java/com/github/kaktushose/jda/commands/dispatching/adapter/impl/package-info.java
index 2aca4eac9..ef563cb80 100644
--- a/src/main/java/com/github/kaktushose/jda/commands/dispatching/adapter/impl/package-info.java
+++ b/src/main/java/com/github/kaktushose/jda/commands/dispatching/adapter/impl/package-info.java
@@ -1,4 +1,2 @@
-/**
- * Default implementations for frequently used types.
- */
+/// Default implementations for frequently used types.
package com.github.kaktushose.jda.commands.dispatching.adapter.impl;
diff --git a/src/main/java/com/github/kaktushose/jda/commands/dispatching/adapter/package-info.java b/src/main/java/com/github/kaktushose/jda/commands/dispatching/adapter/package-info.java
index 5580899fc..9f4e380a4 100644
--- a/src/main/java/com/github/kaktushose/jda/commands/dispatching/adapter/package-info.java
+++ b/src/main/java/com/github/kaktushose/jda/commands/dispatching/adapter/package-info.java
@@ -1,4 +1,2 @@
-/**
- * Generic type adapting system.
- */
+/// Generic type adapting system.
package com.github.kaktushose.jda.commands.dispatching.adapter;
diff --git a/src/main/java/com/github/kaktushose/jda/commands/dispatching/context/InvocationContext.java b/src/main/java/com/github/kaktushose/jda/commands/dispatching/context/InvocationContext.java
index 95e9cafd8..1fef49ef4 100644
--- a/src/main/java/com/github/kaktushose/jda/commands/dispatching/context/InvocationContext.java
+++ b/src/main/java/com/github/kaktushose/jda/commands/dispatching/context/InvocationContext.java
@@ -1,8 +1,8 @@
package com.github.kaktushose.jda.commands.dispatching.context;
+import com.github.kaktushose.jda.commands.definitions.features.internal.Invokable;
+import com.github.kaktushose.jda.commands.definitions.interactions.InteractionDefinition;
import com.github.kaktushose.jda.commands.dispatching.reply.MessageReply;
-import com.github.kaktushose.jda.commands.reflect.interactions.GenericInteractionDefinition;
-import com.github.kaktushose.jda.commands.reflect.interactions.ReplyConfig;
import net.dv8tion.jda.api.events.interaction.GenericInteractionCreateEvent;
import net.dv8tion.jda.api.utils.messages.MessageCreateData;
@@ -13,20 +13,20 @@
/// @param The used type of [GenericInteractionCreateEvent]
/// @param event the underlying jda event
/// @param keyValueStore the [KeyValueStore] belonging to this interaction over its whole lifetime
-/// @param arguments the arguments used to call the final user defined method via [GenericInteractionDefinition#invoke(java.lang.Object, com.github.kaktushose.jda.commands.dispatching.context.InvocationContext)]
-/// @param definition the [GenericInteractionDefinition] defining this interaction (referring to the user defined method)
+/// @param arguments the arguments used to call the final user defined method via [Invokable#invoke(java.lang.Object, com.github.kaktushose.jda.commands.dispatching.context.InvocationContext)]
+/// @param definition the [InteractionDefinition] defining this interaction (referring to the user defined method)
public record InvocationContext(
T event,
KeyValueStore keyValueStore,
- GenericInteractionDefinition definition,
+ InteractionDefinition definition,
SequencedCollection arguments
) {
/// Stops further execution of this invocation at the next suitable moment.
///
- /// @implNote This will interrupt the current event thread
/// @param errorMessage the error message that should be sent to the user as a reply
+ /// @implNote This will interrupt the current event thread
public void cancel(MessageCreateData errorMessage) {
- new MessageReply(event, definition, new ReplyConfig()).reply(errorMessage);
+ new MessageReply(event, definition, new InteractionDefinition.ReplyConfig()).reply(errorMessage);
Thread.currentThread().interrupt();
}
diff --git a/src/main/java/com/github/kaktushose/jda/commands/dispatching/context/KeyValueStore.java b/src/main/java/com/github/kaktushose/jda/commands/dispatching/context/KeyValueStore.java
index cb4377f68..49346920e 100644
--- a/src/main/java/com/github/kaktushose/jda/commands/dispatching/context/KeyValueStore.java
+++ b/src/main/java/com/github/kaktushose/jda/commands/dispatching/context/KeyValueStore.java
@@ -6,65 +6,51 @@
import java.util.Map;
import java.util.Optional;
-/**
- * A simple key-value-store to store variables between events.
- *
- * @since 4.0.0
- */
+/// A simple key-value-store to store variables between events.
public class KeyValueStore {
private final Map values = new HashMap<>();
- /**
- * Gets a value.
- *
- * @param key the key
- * @param clazz the class of the value
- * @param the type of the value
- * @return an {@link Optional} holding the value
- */
+ /// Gets a value.
+ ///
+ /// @param key the key
+ /// @param clazz the class of the value
+ /// @param the type of the value
+ /// @return an [Optional] holding the value
public Optional get(String key, @NotNull Class extends T> clazz) {
return Optional.ofNullable(values.get(key)).filter(it -> it.getClass().isAssignableFrom(clazz)).map(clazz::cast);
}
- /**
- * Associates the specified value with the specified key.
- *
- * @param key the key
- * @param value the value
- * @return this instance for fluent interface
- */
+ /// Associates the specified value with the specified key.
+ ///
+ /// @param key the key
+ /// @param value the value
+ /// @return this instance for fluent interface
public KeyValueStore put(String key, Object value) {
values.put(key, value);
return this;
}
- /**
- * Whether this StateSection has a value mapped to the key.
- *
- * @param key the key
- * @return {@code true} if this StateSection has a value mapped to the key
- */
+ /// Whether this StateSection has a value mapped to the key.
+ ///
+ /// @param key the key
+ /// @return `true` if this StateSection has a value mapped to the key
public boolean contains(String key) {
return values.containsKey(key);
}
- /**
- * Removes the value mapping for a key.
- *
- * @param key key whose mapping is to be removed
- * @return this instance for fluent interface
- */
+ /// Removes the value mapping for a key.
+ ///
+ /// @param key key whose mapping is to be removed
+ /// @return this instance for fluent interface
public KeyValueStore remove(String key) {
values.remove(key);
return this;
}
- /**
- * Removes all the value mappings.
- *
- * @return this instance for fluent interface
- */
+ /// Removes all the value mappings.
+ ///
+ /// @return this instance for fluent interface
public KeyValueStore clear() {
values.clear();
return this;
diff --git a/src/main/java/com/github/kaktushose/jda/commands/dispatching/events/Event.java b/src/main/java/com/github/kaktushose/jda/commands/dispatching/events/Event.java
index ac3f2db1e..e080bf434 100644
--- a/src/main/java/com/github/kaktushose/jda/commands/dispatching/events/Event.java
+++ b/src/main/java/com/github/kaktushose/jda/commands/dispatching/events/Event.java
@@ -1,17 +1,14 @@
package com.github.kaktushose.jda.commands.dispatching.events;
-import com.github.kaktushose.jda.commands.annotations.interactions.EntitySelectMenu;
-import com.github.kaktushose.jda.commands.annotations.interactions.StringSelectMenu;
-import com.github.kaktushose.jda.commands.dispatching.events.interactions.ComponentEvent;
-import com.github.kaktushose.jda.commands.dispatching.events.interactions.ModalEvent;
-import com.github.kaktushose.jda.commands.dispatching.internal.Runtime;
+import com.github.kaktushose.jda.commands.definitions.interactions.InteractionRegistry;
+import com.github.kaktushose.jda.commands.dispatching.Runtime;
import com.github.kaktushose.jda.commands.dispatching.context.KeyValueStore;
import com.github.kaktushose.jda.commands.dispatching.events.interactions.AutoCompleteEvent;
import com.github.kaktushose.jda.commands.dispatching.events.interactions.CommandEvent;
+import com.github.kaktushose.jda.commands.dispatching.events.interactions.ComponentEvent;
+import com.github.kaktushose.jda.commands.dispatching.events.interactions.ModalEvent;
+import com.github.kaktushose.jda.commands.dispatching.expiration.ExpirationStrategy;
import com.github.kaktushose.jda.commands.dispatching.middleware.Middleware;
-import com.github.kaktushose.jda.commands.reflect.InteractionRegistry;
-import com.github.kaktushose.jda.commands.reflect.interactions.components.ButtonDefinition;
-import com.github.kaktushose.jda.commands.reflect.interactions.components.menus.GenericSelectMenuDefinition;
import net.dv8tion.jda.api.JDA;
import net.dv8tion.jda.api.entities.Entitlement;
import net.dv8tion.jda.api.entities.Guild;
@@ -21,8 +18,6 @@
import net.dv8tion.jda.api.events.interaction.GenericInteractionCreateEvent;
import net.dv8tion.jda.api.interactions.DiscordLocale;
import net.dv8tion.jda.api.interactions.Interaction;
-import net.dv8tion.jda.api.interactions.components.buttons.Button;
-import net.dv8tion.jda.api.interactions.components.selections.SelectMenu;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -40,22 +35,21 @@
/// @see CommandEvent
/// @see ComponentEvent
/// @see ModalEvent
-/// @since 4.0.0
public abstract sealed class Event implements Interaction
permits ReplyableEvent, AutoCompleteEvent {
protected final T event;
- protected final InteractionRegistry interactionRegistry;
+ protected final InteractionRegistry registry;
private final Runtime runtime;
/// Constructs a new Event.
///
- /// @param event the subtype [T] of [GenericInteractionCreateEvent]
- /// @param interactionRegistry the corresponding [InteractionRegistry]
- /// @param runtime the [Runtime] this event lives in
- protected Event(@NotNull T event, @NotNull InteractionRegistry interactionRegistry, @NotNull Runtime runtime) {
+ /// @param event the subtype [T] of [GenericInteractionCreateEvent]
+ /// @param registry the corresponding [InteractionRegistry]
+ /// @param runtime the [Runtime] this event lives in
+ protected Event(@NotNull T event, @NotNull InteractionRegistry registry, @NotNull Runtime runtime) {
this.event = event;
- this.interactionRegistry = interactionRegistry;
+ this.registry = registry;
this.runtime = runtime;
}
@@ -67,49 +61,6 @@ public T jdaEvent() {
return this.event;
}
- /// Gets a [`Button`][com.github.kaktushose.jda.commands.annotations.interactions.Button] based on the method name
- /// and transforms it into a JDA [Button].
- ///
- /// The button will be linked to the current [`Runtime`]({@docRoot}/index.html#runtime-concept-heading). This may be useful if you want to send a component without
- /// using the framework.
- ///
- /// @param button the name of the button
- /// @return the JDA [Button]
- @NotNull
- public Button getButton(@NotNull String button) {
- if (!button.matches("[a-zA-Z]+\\.[a-zA-Z]+")) {
- throw new IllegalArgumentException("Unknown Button");
- }
-
- String sanitizedId = button.replaceAll("\\.", "");
- ButtonDefinition buttonDefinition = interactionRegistry.getButtons().stream()
- .filter(it -> it.getDefinitionId().equals(sanitizedId))
- .findFirst().orElseThrow(() -> new IllegalArgumentException("Unknown Button"));
-
- return buttonDefinition.toButton().withId(buttonDefinition.boundCustomId(runtimeId()));
- }
-
- /// Gets a [StringSelectMenu] or [EntitySelectMenu] based on the method name and transforms it into a JDA [SelectMenu].
- ///
- /// The select menu will be linked to the current [`Runtime`]({@docRoot}/index.html#runtime-concept-heading). This may be useful if you want to send a component
- /// without using the framework.
- ///
- /// @param menu the name of the select menu
- /// @return the JDA [SelectMenu]
- @NotNull
- public SelectMenu getSelectMenu(@NotNull String menu) {
- if (!menu.matches("[a-zA-Z]+\\.[a-zA-Z]+")) {
- throw new IllegalArgumentException("Unknown Select Menu");
- }
-
- String sanitizedId = menu.replaceAll("\\.", "");
- GenericSelectMenuDefinition> selectMenuDefinition = interactionRegistry.getSelectMenus().stream()
- .filter(it -> it.getDefinitionId().equals(sanitizedId))
- .findFirst().orElseThrow(() -> new IllegalArgumentException("Unknown Select Menu"));
-
- return selectMenuDefinition.toSelectMenu(runtimeId(), true);
- }
-
/// Returns the id of the [`Runtime`]({@docRoot}/index.html#runtime-concept-heading) this event is dispatched in.
///
///
@@ -123,7 +74,7 @@ public String runtimeId() {
/// in the freeing of occupied resources for gc.
///
/// This is only needed if the expiration strategy
- /// [com.github.kaktushose.jda.commands.dispatching.ExpirationStrategy.Explicit] is used.
+ /// [ExpirationStrategy.Explicit] is used.
public void closeRuntime() {
runtime.close();
}
diff --git a/src/main/java/com/github/kaktushose/jda/commands/dispatching/events/ModalReplyableEvent.java b/src/main/java/com/github/kaktushose/jda/commands/dispatching/events/ModalReplyableEvent.java
index 670eec8f1..8efd9e0cd 100644
--- a/src/main/java/com/github/kaktushose/jda/commands/dispatching/events/ModalReplyableEvent.java
+++ b/src/main/java/com/github/kaktushose/jda/commands/dispatching/events/ModalReplyableEvent.java
@@ -1,12 +1,13 @@
package com.github.kaktushose.jda.commands.dispatching.events;
import com.github.kaktushose.jda.commands.annotations.interactions.Modal;
-import com.github.kaktushose.jda.commands.dispatching.internal.Runtime;
+import com.github.kaktushose.jda.commands.definitions.interactions.CustomId;
+import com.github.kaktushose.jda.commands.definitions.interactions.InteractionDefinition;
+import com.github.kaktushose.jda.commands.definitions.interactions.InteractionRegistry;
+import com.github.kaktushose.jda.commands.definitions.interactions.ModalDefinition;
+import com.github.kaktushose.jda.commands.dispatching.Runtime;
import com.github.kaktushose.jda.commands.dispatching.events.interactions.CommandEvent;
import com.github.kaktushose.jda.commands.dispatching.events.interactions.ComponentEvent;
-import com.github.kaktushose.jda.commands.reflect.InteractionRegistry;
-import com.github.kaktushose.jda.commands.reflect.interactions.EphemeralInteractionDefinition;
-import com.github.kaktushose.jda.commands.reflect.interactions.ModalDefinition;
import net.dv8tion.jda.api.events.interaction.GenericInteractionCreateEvent;
import net.dv8tion.jda.api.interactions.callbacks.IModalCallback;
import org.jetbrains.annotations.NotNull;
@@ -19,7 +20,6 @@
/// @param the type of [GenericInteractionCreateEvent] this event represents
/// @see CommandEvent
/// @see ComponentEvent
-/// @since 4.0.0
public abstract sealed class ModalReplyableEvent
extends ReplyableEvent
permits CommandEvent, ComponentEvent {
@@ -28,15 +28,15 @@ public abstract sealed class ModalReplyableEvent
- it.getDefinitionId().equals(definitionId)
+ var definitionId = String.valueOf((definition.clazzDescription().name() + modal).hashCode());
+ var modalDefinition = registry.find(ModalDefinition.class, false, it ->
+ it.definitionId().equals(definitionId)
);
- log.debug("Replying to interaction \"{}\" with Modal: \"{}\". [Runtime={}]", definition.getDisplayName(), modalDefinition.getDisplayName(), runtimeId());
- callback.replyModal(modalDefinition.toModal(runtimeId())).queue();
+ log.debug("Replying to interaction \"{}\" with Modal: \"{}\". [Runtime={}]", definition.displayName(), modalDefinition.displayName(), runtimeId());
+ callback.replyModal(modalDefinition.toJDAEntity(new CustomId(runtimeId(), definitionId))).queue();
} else {
throw new IllegalStateException(
String.format("Cannot reply to '%s'! Please report this error to the jda-commands devs!", event.getClass().getName())
diff --git a/src/main/java/com/github/kaktushose/jda/commands/dispatching/events/ReplyableEvent.java b/src/main/java/com/github/kaktushose/jda/commands/dispatching/events/ReplyableEvent.java
index 79832ab65..aa7d0a419 100644
--- a/src/main/java/com/github/kaktushose/jda/commands/dispatching/events/ReplyableEvent.java
+++ b/src/main/java/com/github/kaktushose/jda/commands/dispatching/events/ReplyableEvent.java
@@ -1,19 +1,25 @@
package com.github.kaktushose.jda.commands.dispatching.events;
+import com.github.kaktushose.jda.commands.annotations.interactions.EntitySelectMenu;
+import com.github.kaktushose.jda.commands.annotations.interactions.StringSelectMenu;
+import com.github.kaktushose.jda.commands.definitions.interactions.CustomId;
+import com.github.kaktushose.jda.commands.definitions.interactions.InteractionDefinition;
+import com.github.kaktushose.jda.commands.definitions.interactions.InteractionRegistry;
+import com.github.kaktushose.jda.commands.definitions.interactions.component.ButtonDefinition;
+import com.github.kaktushose.jda.commands.definitions.interactions.component.menu.SelectMenuDefinition;
+import com.github.kaktushose.jda.commands.dispatching.Runtime;
import com.github.kaktushose.jda.commands.dispatching.events.interactions.CommandEvent;
import com.github.kaktushose.jda.commands.dispatching.events.interactions.ComponentEvent;
-import com.github.kaktushose.jda.commands.dispatching.internal.Runtime;
import com.github.kaktushose.jda.commands.dispatching.events.interactions.ModalEvent;
import com.github.kaktushose.jda.commands.dispatching.reply.ConfigurableReply;
import com.github.kaktushose.jda.commands.dispatching.reply.MessageReply;
import com.github.kaktushose.jda.commands.dispatching.reply.Reply;
-import com.github.kaktushose.jda.commands.reflect.InteractionRegistry;
-import com.github.kaktushose.jda.commands.reflect.interactions.EphemeralInteractionDefinition;
-import com.github.kaktushose.jda.commands.reflect.interactions.ReplyConfig;
import net.dv8tion.jda.api.EmbedBuilder;
import net.dv8tion.jda.api.entities.Message;
import net.dv8tion.jda.api.events.interaction.GenericInteractionCreateEvent;
import net.dv8tion.jda.api.interactions.callbacks.IReplyCallback;
+import net.dv8tion.jda.api.interactions.components.buttons.Button;
+import net.dv8tion.jda.api.interactions.components.selections.SelectMenu;
import net.dv8tion.jda.api.utils.messages.MessageCreateData;
import org.jetbrains.annotations.NotNull;
import org.slf4j.Logger;
@@ -31,29 +37,26 @@
/// event.reply("Hello World");
/// }
/// ```
-///
-/// @since 4.0.0
/// @see ModalEvent
/// @see CommandEvent
/// @see ComponentEvent
-/// @since 4.0.0
public sealed abstract class ReplyableEvent extends Event implements Reply
permits ModalEvent, ModalReplyableEvent {
private static final Logger log = LoggerFactory.getLogger(ReplyableEvent.class);
- protected final EphemeralInteractionDefinition definition;
- private final ReplyConfig replyConfig;
+ protected final InteractionDefinition definition;
+ private final InteractionDefinition.ReplyConfig replyConfig;
/// Constructs a new ReplyableEvent.
///
/// @param event the subtype [T] of [GenericInteractionCreateEvent]
/// @param interactionRegistry the corresponding [InteractionRegistry]
/// @param runtime the [Runtime] this event lives in
- /// @param definition the [EphemeralInteractionDefinition] this event belongs to
+ /// @param definition the [InteractionDefinition] this event belongs to
protected ReplyableEvent(T event,
InteractionRegistry interactionRegistry,
Runtime runtime,
- EphemeralInteractionDefinition definition) {
+ InteractionDefinition definition) {
super(event, interactionRegistry, runtime);
this.replyConfig = definition.replyConfig();
this.definition = definition;
@@ -72,6 +75,35 @@ public void removeComponents() {
}
}
+ /// Gets a [`Button`][com.github.kaktushose.jda.commands.annotations.interactions.Button] based on the method name
+ /// and transforms it into a JDA [Button].
+ ///
+ /// The button will be linked to the current [`Runtime`]({@docRoot}/index.html#runtime-concept-heading).
+ /// This may be useful if you want to send a component without using the framework.
+ ///
+ /// @param button the name of the button
+ /// @return the JDA [Button]
+ @NotNull
+ public Button getButton(@NotNull String button) {
+ var id = String.valueOf(("%s%s".formatted(definition.clazzDescription().name(), button)).hashCode());
+ var definition = registry.find(ButtonDefinition.class, false, it -> it.definitionId().equals(id));
+ return definition.toJDAEntity(new CustomId(runtimeId(), definition.definitionId()));
+ }
+
+ /// Gets a [StringSelectMenu] or [EntitySelectMenu] based on the method name and transforms it into a JDA [SelectMenu].
+ ///
+ /// The select menu will be linked to the current [`Runtime`]({@docRoot}/index.html#runtime-concept-heading). This may be useful if you want to send a component
+ /// without using the framework.
+ ///
+ /// @param menu the name of the select menu
+ /// @return the JDA [SelectMenu]
+ @NotNull
+ public SelectMenu getSelectMenu(@NotNull String menu) {
+ var id = String.valueOf(("%s%s".formatted(definition.clazzDescription().name(), menu)).hashCode());
+ var definition = registry.find(SelectMenuDefinition.class, false, it -> it.definitionId().equals(id));
+ return (SelectMenu) definition.toJDAEntity(new CustomId(runtimeId(), definition.definitionId()));
+ }
+
/// Entry point for configuring a reply.
///
/// Returns a new [ConfigurableReply] that can be used to append components or override reply settings.
@@ -80,7 +112,7 @@ public void removeComponents() {
/// @see [ConfigurableReply]
@NotNull
public ConfigurableReply with() {
- return new ConfigurableReply(newReply(), interactionRegistry, runtimeId());
+ return new ConfigurableReply(newReply(), registry, runtimeId());
}
@NotNull
diff --git a/src/main/java/com/github/kaktushose/jda/commands/dispatching/events/interactions/AutoCompleteEvent.java b/src/main/java/com/github/kaktushose/jda/commands/dispatching/events/interactions/AutoCompleteEvent.java
index 8484a9f37..8c6a03a5f 100644
--- a/src/main/java/com/github/kaktushose/jda/commands/dispatching/events/interactions/AutoCompleteEvent.java
+++ b/src/main/java/com/github/kaktushose/jda/commands/dispatching/events/interactions/AutoCompleteEvent.java
@@ -1,8 +1,8 @@
package com.github.kaktushose.jda.commands.dispatching.events.interactions;
-import com.github.kaktushose.jda.commands.dispatching.internal.Runtime;
+import com.github.kaktushose.jda.commands.definitions.interactions.InteractionRegistry;
+import com.github.kaktushose.jda.commands.dispatching.Runtime;
import com.github.kaktushose.jda.commands.dispatching.events.Event;
-import com.github.kaktushose.jda.commands.reflect.InteractionRegistry;
import net.dv8tion.jda.api.events.interaction.command.CommandAutoCompleteInteractionEvent;
import net.dv8tion.jda.api.interactions.commands.Command;
import net.dv8tion.jda.api.interactions.commands.CommandAutoCompleteInteraction;
@@ -15,26 +15,21 @@
import java.util.Collection;
import java.util.stream.Collectors;
-/**
- * This class is a subclass of {@link Event}.
- * It provides additional features for replying to a {@link CommandAutoCompleteInteractionEvent}.
- *
- * @see Event
- * @since 4.0.0
- */
+/// This class is a subclass of [Event].
+/// It provides additional features for replying to a [CommandAutoCompleteInteractionEvent].
+///
+/// @see Event
public final class AutoCompleteEvent extends Event {
- /**
- * Constructs a new AutoCompleteEvent.
- *
- * @param event the {@link CommandAutoCompleteInteractionEvent} this event holds
- * @param interactionRegistry the corresponding {@link InteractionRegistry}
- * @param runtime the corresponding {@link Runtime}
- */
+ /// Constructs a new AutoCompleteEvent.
+ ///
+ /// @param event the [CommandAutoCompleteInteractionEvent] this event holds
+ /// @param registry the corresponding [InteractionRegistry]
+ /// @param runtime the corresponding [Runtime]
public AutoCompleteEvent(@NotNull CommandAutoCompleteInteractionEvent event,
- @NotNull InteractionRegistry interactionRegistry,
+ @NotNull InteractionRegistry registry,
@NotNull Runtime runtime) {
- super(event, interactionRegistry, runtime);
+ super(event, registry, runtime);
}
/**
@@ -238,34 +233,28 @@ public void replyChoiceDoubles(@NotNull Collection choices) {
replyChoices(choices.stream().map(it -> new Command.Choice(String.valueOf(it), it)).collect(Collectors.toList()));
}
- /**
- * The name of the input field, usually an option name in {@link CommandAutoCompleteInteraction}.
- *
- * @return The option name
- */
+ /// The name of the input field, usually an option name in [CommandAutoCompleteInteraction].
+ ///
+ /// @return The option name
@NotNull
public String getName() {
return event.getFocusedOption().getName();
}
- /**
- * The query value that the user is currently typing.
- *
- * This is not validated and may not be a valid value for an actual command.
- * For instance, a user may input invalid numbers for {@link OptionType#NUMBER}.
- *
- * @return The current auto-completable query value
- */
+ /// The query value that the user is currently typing.
+ ///
+ /// This is not validated and may not be a valid value for an actual command.
+ /// For instance, a user may input invalid numbers for [#NUMBER].
+ ///
+ /// @return The current auto-completable query value
@NotNull
public String getValue() {
return event.getFocusedOption().getValue();
}
- /**
- * The expected option type for this query.
- *
- * @return The option type expected from this auto-complete response
- */
+ /// The expected option type for this query.
+ ///
+ /// @return The option type expected from this auto-complete response
@NotNull
public OptionType getOptionType() {
return event.getFocusedOption().getType();
diff --git a/src/main/java/com/github/kaktushose/jda/commands/dispatching/events/interactions/CommandEvent.java b/src/main/java/com/github/kaktushose/jda/commands/dispatching/events/interactions/CommandEvent.java
index 9bd940fcc..4ad709e5e 100644
--- a/src/main/java/com/github/kaktushose/jda/commands/dispatching/events/interactions/CommandEvent.java
+++ b/src/main/java/com/github/kaktushose/jda/commands/dispatching/events/interactions/CommandEvent.java
@@ -1,10 +1,10 @@
package com.github.kaktushose.jda.commands.dispatching.events.interactions;
-import com.github.kaktushose.jda.commands.dispatching.internal.Runtime;
+import com.github.kaktushose.jda.commands.definitions.interactions.InteractionDefinition;
+import com.github.kaktushose.jda.commands.definitions.interactions.InteractionRegistry;
+import com.github.kaktushose.jda.commands.dispatching.Runtime;
import com.github.kaktushose.jda.commands.dispatching.events.Event;
import com.github.kaktushose.jda.commands.dispatching.events.ModalReplyableEvent;
-import com.github.kaktushose.jda.commands.reflect.InteractionRegistry;
-import com.github.kaktushose.jda.commands.reflect.interactions.EphemeralInteractionDefinition;
import net.dv8tion.jda.api.events.interaction.command.GenericCommandInteractionEvent;
import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent;
import org.jetbrains.annotations.NotNull;
@@ -13,20 +13,19 @@
///
/// @see Event
/// @see ModalReplyableEvent
-/// @since 4.0.0
public final class CommandEvent extends ModalReplyableEvent {
/// Constructs a new CommandEvent.
///
- /// @param event the [GenericCommandInteractionEvent] this event holds
- /// @param interactionRegistry the corresponding [InteractionRegistry]
- /// @param runtime the corresponding [Runtime]
- /// @param definition the corresponding [EphemeralInteractionDefinition]
+ /// @param event the [GenericCommandInteractionEvent] this event holds
+ /// @param registry the corresponding [InteractionRegistry]
+ /// @param runtime the corresponding [Runtime]
+ /// @param definition the corresponding [InteractionDefinition]
public CommandEvent(@NotNull GenericCommandInteractionEvent event,
- @NotNull InteractionRegistry interactionRegistry,
+ @NotNull InteractionRegistry registry,
@NotNull Runtime runtime,
- @NotNull EphemeralInteractionDefinition definition) {
- super(event, interactionRegistry, runtime, definition);
+ @NotNull InteractionDefinition definition) {
+ super(event, registry, runtime, definition);
}
/// Returns the underlying [GenericCommandInteractionEvent] and casts it to the given type.
diff --git a/src/main/java/com/github/kaktushose/jda/commands/dispatching/events/interactions/ComponentEvent.java b/src/main/java/com/github/kaktushose/jda/commands/dispatching/events/interactions/ComponentEvent.java
index 067744cf4..54a95854e 100644
--- a/src/main/java/com/github/kaktushose/jda/commands/dispatching/events/interactions/ComponentEvent.java
+++ b/src/main/java/com/github/kaktushose/jda/commands/dispatching/events/interactions/ComponentEvent.java
@@ -1,10 +1,10 @@
package com.github.kaktushose.jda.commands.dispatching.events.interactions;
-import com.github.kaktushose.jda.commands.dispatching.internal.Runtime;
+import com.github.kaktushose.jda.commands.definitions.interactions.InteractionDefinition;
+import com.github.kaktushose.jda.commands.definitions.interactions.InteractionRegistry;
+import com.github.kaktushose.jda.commands.dispatching.Runtime;
import com.github.kaktushose.jda.commands.dispatching.events.Event;
import com.github.kaktushose.jda.commands.dispatching.events.ModalReplyableEvent;
-import com.github.kaktushose.jda.commands.reflect.InteractionRegistry;
-import com.github.kaktushose.jda.commands.reflect.interactions.EphemeralInteractionDefinition;
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.GenericComponentInteractionCreateEvent;
@@ -15,26 +15,25 @@
///
/// @see Event
/// @see ModalReplyableEvent
-/// @since 4.0.0
public final class ComponentEvent extends ModalReplyableEvent {
/// Constructs a new CommandEvent.
///
- /// @param event the [GenericComponentInteractionCreateEvent] this event holds
- /// @param interactionRegistry the corresponding [InteractionRegistry]
- /// @param runtime the corresponding [Runtime]
- /// @param definition the corresponding [EphemeralInteractionDefinition]
+ /// @param event the [GenericComponentInteractionCreateEvent] this event holds
+ /// @param registry the corresponding [InteractionRegistry]
+ /// @param runtime the corresponding [Runtime]
+ /// @param definition the corresponding [InteractionDefinition]
public ComponentEvent(@NotNull GenericComponentInteractionCreateEvent event,
- @NotNull InteractionRegistry interactionRegistry,
+ @NotNull InteractionRegistry registry,
@NotNull Runtime runtime,
- @NotNull EphemeralInteractionDefinition definition) {
- super(event, interactionRegistry, runtime, definition);
+ @NotNull InteractionDefinition definition) {
+ super(event, registry, runtime, definition);
}
/// Returns the underlying [GenericComponentInteractionCreateEvent] and casts it to the given type.
///
/// @param type a subtype of [GenericComponentInteractionCreateEvent], namely [ButtonInteractionEvent],
- /// [EntitySelectInteractionEvent] or [StringSelectInteractionEvent]
+ /// [EntitySelectInteractionEvent] or [StringSelectInteractionEvent]
/// @param a subtype of [GenericComponentInteractionCreateEvent]
/// @return [T]
public T jdaEvent(Class type) {
diff --git a/src/main/java/com/github/kaktushose/jda/commands/dispatching/events/interactions/ModalEvent.java b/src/main/java/com/github/kaktushose/jda/commands/dispatching/events/interactions/ModalEvent.java
index c8f60a9a6..1401293b4 100644
--- a/src/main/java/com/github/kaktushose/jda/commands/dispatching/events/interactions/ModalEvent.java
+++ b/src/main/java/com/github/kaktushose/jda/commands/dispatching/events/interactions/ModalEvent.java
@@ -1,10 +1,10 @@
package com.github.kaktushose.jda.commands.dispatching.events.interactions;
-import com.github.kaktushose.jda.commands.dispatching.internal.Runtime;
+import com.github.kaktushose.jda.commands.definitions.interactions.InteractionDefinition;
+import com.github.kaktushose.jda.commands.definitions.interactions.InteractionRegistry;
+import com.github.kaktushose.jda.commands.dispatching.Runtime;
import com.github.kaktushose.jda.commands.dispatching.events.Event;
import com.github.kaktushose.jda.commands.dispatching.events.ReplyableEvent;
-import com.github.kaktushose.jda.commands.reflect.InteractionRegistry;
-import com.github.kaktushose.jda.commands.reflect.interactions.EphemeralInteractionDefinition;
import net.dv8tion.jda.api.events.interaction.ModalInteractionEvent;
import net.dv8tion.jda.api.events.interaction.command.GenericCommandInteractionEvent;
import org.jetbrains.annotations.NotNull;
@@ -13,20 +13,19 @@
///
/// @see Event
/// @see ReplyableEvent
-/// @since 4.0.0
public final class ModalEvent extends ReplyableEvent {
/// Constructs a new CommandEvent.
///
- /// @param event the [GenericCommandInteractionEvent] this event holds
- /// @param interactionRegistry the corresponding [InteractionRegistry]
- /// @param runtime the corresponding [Runtime]
- /// @param definition the corresponding [EphemeralInteractionDefinition]
+ /// @param event the [GenericCommandInteractionEvent] this event holds
+ /// @param registry the corresponding [InteractionRegistry]
+ /// @param runtime the corresponding [Runtime]
+ /// @param definition the corresponding [InteractionDefinition]
public ModalEvent(@NotNull ModalInteractionEvent event,
- @NotNull InteractionRegistry interactionRegistry,
+ @NotNull InteractionRegistry registry,
@NotNull Runtime runtime,
- @NotNull EphemeralInteractionDefinition definition) {
- super(event, interactionRegistry, runtime, definition);
+ @NotNull InteractionDefinition definition) {
+ super(event, registry, runtime, definition);
}
}
diff --git a/src/main/java/com/github/kaktushose/jda/commands/dispatching/events/interactions/package-info.java b/src/main/java/com/github/kaktushose/jda/commands/dispatching/events/interactions/package-info.java
index 323ac6561..d6ab0f93a 100644
--- a/src/main/java/com/github/kaktushose/jda/commands/dispatching/events/interactions/package-info.java
+++ b/src/main/java/com/github/kaktushose/jda/commands/dispatching/events/interactions/package-info.java
@@ -1,4 +1,2 @@
/// Event classes that represent an interaction execution.
-///
-/// @since 4.0.0
package com.github.kaktushose.jda.commands.dispatching.events.interactions;
\ No newline at end of file
diff --git a/src/main/java/com/github/kaktushose/jda/commands/dispatching/events/package-info.java b/src/main/java/com/github/kaktushose/jda/commands/dispatching/events/package-info.java
index ea31d952d..7b75133c6 100644
--- a/src/main/java/com/github/kaktushose/jda/commands/dispatching/events/package-info.java
+++ b/src/main/java/com/github/kaktushose/jda/commands/dispatching/events/package-info.java
@@ -1,2 +1,2 @@
/// Abstract event classes that build the foundation for specific event implementations.
-package com.github.kaktushose.jda.commands.dispatching.events;
\ No newline at end of file
+package com.github.kaktushose.jda.commands.dispatching.events;
diff --git a/src/main/java/com/github/kaktushose/jda/commands/dispatching/ExpirationStrategy.java b/src/main/java/com/github/kaktushose/jda/commands/dispatching/expiration/ExpirationStrategy.java
similarity index 95%
rename from src/main/java/com/github/kaktushose/jda/commands/dispatching/ExpirationStrategy.java
rename to src/main/java/com/github/kaktushose/jda/commands/dispatching/expiration/ExpirationStrategy.java
index 78ffd3951..cd1d21f0b 100644
--- a/src/main/java/com/github/kaktushose/jda/commands/dispatching/ExpirationStrategy.java
+++ b/src/main/java/com/github/kaktushose/jda/commands/dispatching/expiration/ExpirationStrategy.java
@@ -1,4 +1,4 @@
-package com.github.kaktushose.jda.commands.dispatching;
+package com.github.kaktushose.jda.commands.dispatching.expiration;
import com.github.kaktushose.jda.commands.dispatching.events.Event;
@@ -10,7 +10,6 @@
///
/// @implNote The [Inactivity] strategy will check all active [`Runtimes`]({@docRoot}/index.html#runtime-concept-heading) at every incoming jda event. If a
/// [`Runtime`]({@docRoot}/index.html#runtime-concept-heading) didn't handle any events in the last *x* minutes, it will be closed.
-/// @since 4.0.0
public sealed interface ExpirationStrategy {
/// Default [ExpirationStrategy] of [Inactivity], that closes [`Runtimes`]({@docRoot}/index.html#runtime-concept-heading) after *15* minutes of inactivity.
diff --git a/src/main/java/com/github/kaktushose/jda/commands/dispatching/handling/AutoCompleteHandler.java b/src/main/java/com/github/kaktushose/jda/commands/dispatching/handling/AutoCompleteHandler.java
index cc10b7d86..4c68629ae 100644
--- a/src/main/java/com/github/kaktushose/jda/commands/dispatching/handling/AutoCompleteHandler.java
+++ b/src/main/java/com/github/kaktushose/jda/commands/dispatching/handling/AutoCompleteHandler.java
@@ -1,6 +1,7 @@
package com.github.kaktushose.jda.commands.dispatching.handling;
-import com.github.kaktushose.jda.commands.dispatching.internal.Runtime;
+import com.github.kaktushose.jda.commands.definitions.interactions.AutoCompleteDefinition;
+import com.github.kaktushose.jda.commands.dispatching.Runtime;
import com.github.kaktushose.jda.commands.dispatching.context.InvocationContext;
import com.github.kaktushose.jda.commands.dispatching.events.interactions.AutoCompleteEvent;
import net.dv8tion.jda.api.events.interaction.command.CommandAutoCompleteInteractionEvent;
@@ -21,10 +22,11 @@ public AutoCompleteHandler(DispatchingContext dispatchingContext) {
protected InvocationContext prepare(@NotNull CommandAutoCompleteInteractionEvent event, @NotNull Runtime runtime) {
CommandAutoCompleteInteraction interaction = event.getInteraction();
- return interactionRegistry.getAutoCompletes().stream()
- .filter(it -> it.getCommandNames().stream().anyMatch(name -> interaction.getFullCommandName().startsWith(name)))
+ return registry.find(AutoCompleteDefinition.class,
+ it -> it.commands().stream().anyMatch(name -> interaction.getFullCommandName().startsWith(name))
+ ).stream()
.findFirst()
- .map(autoComplete -> new InvocationContext<>(event, runtime.keyValueStore(), autoComplete, List.of(new AutoCompleteEvent(event, interactionRegistry, runtime))))
+ .map(autoComplete -> new InvocationContext<>(event, runtime.keyValueStore(), autoComplete, List.of(new AutoCompleteEvent(event, registry, runtime))))
.orElseGet(() -> {
log.debug("No auto complete handler found for {}", interaction.getFullCommandName());
return null;
diff --git a/src/main/java/com/github/kaktushose/jda/commands/dispatching/handling/ComponentHandler.java b/src/main/java/com/github/kaktushose/jda/commands/dispatching/handling/ComponentHandler.java
index 1093eaad4..c4d6854fb 100644
--- a/src/main/java/com/github/kaktushose/jda/commands/dispatching/handling/ComponentHandler.java
+++ b/src/main/java/com/github/kaktushose/jda/commands/dispatching/handling/ComponentHandler.java
@@ -1,10 +1,10 @@
package com.github.kaktushose.jda.commands.dispatching.handling;
-import com.github.kaktushose.jda.commands.dispatching.internal.Runtime;
+import com.github.kaktushose.jda.commands.definitions.interactions.CustomId;
+import com.github.kaktushose.jda.commands.definitions.interactions.component.ComponentDefinition;
+import com.github.kaktushose.jda.commands.dispatching.Runtime;
import com.github.kaktushose.jda.commands.dispatching.context.InvocationContext;
import com.github.kaktushose.jda.commands.dispatching.events.interactions.ComponentEvent;
-import com.github.kaktushose.jda.commands.reflect.interactions.CustomId;
-import com.github.kaktushose.jda.commands.reflect.interactions.components.GenericComponentDefinition;
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.GenericComponentInteractionCreateEvent;
@@ -29,8 +29,8 @@ protected InvocationContext prepare(@Not
return null;
}
- var component = interactionRegistry.find(GenericComponentDefinition.class, true, it ->
- it.getDefinitionId().equals(CustomId.definitionId(genericEvent.getComponentId()))
+ var component = registry.find(ComponentDefinition.class, true, it ->
+ it.definitionId().equals(CustomId.fromEvent(genericEvent).definitionId())
);
List arguments = switch (genericEvent) {
@@ -40,7 +40,7 @@ protected InvocationContext prepare(@Not
default ->
throw new IllegalStateException("Should not occur. Please report this error the the devs of jda-commands.");
};
- arguments.addFirst(new ComponentEvent(genericEvent, interactionRegistry, runtime, component));
+ arguments.addFirst(new ComponentEvent(genericEvent, registry, runtime, component));
return new InvocationContext<>(
genericEvent,
diff --git a/src/main/java/com/github/kaktushose/jda/commands/dispatching/handling/DispatchingContext.java b/src/main/java/com/github/kaktushose/jda/commands/dispatching/handling/DispatchingContext.java
index 83f5f09f5..74112bf20 100644
--- a/src/main/java/com/github/kaktushose/jda/commands/dispatching/handling/DispatchingContext.java
+++ b/src/main/java/com/github/kaktushose/jda/commands/dispatching/handling/DispatchingContext.java
@@ -1,17 +1,17 @@
package com.github.kaktushose.jda.commands.dispatching.handling;
-import com.github.kaktushose.jda.commands.dispatching.ExpirationStrategy;
+import com.github.kaktushose.jda.commands.definitions.interactions.InteractionRegistry;
+import com.github.kaktushose.jda.commands.dispatching.ImplementationRegistry;
import com.github.kaktushose.jda.commands.dispatching.adapter.TypeAdapterRegistry;
+import com.github.kaktushose.jda.commands.dispatching.expiration.ExpirationStrategy;
import com.github.kaktushose.jda.commands.dispatching.middleware.MiddlewareRegistry;
-import com.github.kaktushose.jda.commands.reflect.ImplementationRegistry;
-import com.github.kaktushose.jda.commands.reflect.InteractionRegistry;
import org.jetbrains.annotations.ApiStatus;
/// A collection of classes relevant for [EventHandler]s.
@ApiStatus.Internal
public record DispatchingContext(MiddlewareRegistry middlewareRegistry,
ImplementationRegistry implementationRegistry,
- InteractionRegistry interactionRegistry,
+ InteractionRegistry registry,
TypeAdapterRegistry adapterRegistry,
ExpirationStrategy expirationStrategy) {
}
diff --git a/src/main/java/com/github/kaktushose/jda/commands/dispatching/handling/EventHandler.java b/src/main/java/com/github/kaktushose/jda/commands/dispatching/handling/EventHandler.java
index 2919128e9..3b3d1175e 100644
--- a/src/main/java/com/github/kaktushose/jda/commands/dispatching/handling/EventHandler.java
+++ b/src/main/java/com/github/kaktushose/jda/commands/dispatching/handling/EventHandler.java
@@ -1,6 +1,9 @@
package com.github.kaktushose.jda.commands.dispatching.handling;
-import com.github.kaktushose.jda.commands.dispatching.internal.Runtime;
+import com.github.kaktushose.jda.commands.definitions.interactions.InteractionDefinition;
+import com.github.kaktushose.jda.commands.definitions.interactions.InteractionRegistry;
+import com.github.kaktushose.jda.commands.dispatching.ImplementationRegistry;
+import com.github.kaktushose.jda.commands.dispatching.Runtime;
import com.github.kaktushose.jda.commands.dispatching.adapter.TypeAdapterRegistry;
import com.github.kaktushose.jda.commands.dispatching.context.InvocationContext;
import com.github.kaktushose.jda.commands.dispatching.handling.command.ContextCommandHandler;
@@ -8,9 +11,6 @@
import com.github.kaktushose.jda.commands.dispatching.middleware.Middleware;
import com.github.kaktushose.jda.commands.dispatching.middleware.MiddlewareRegistry;
import com.github.kaktushose.jda.commands.dispatching.middleware.Priority;
-import com.github.kaktushose.jda.commands.reflect.ImplementationRegistry;
-import com.github.kaktushose.jda.commands.reflect.InteractionRegistry;
-import com.github.kaktushose.jda.commands.reflect.interactions.GenericInteractionDefinition;
import net.dv8tion.jda.api.events.interaction.GenericInteractionCreateEvent;
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.NotNull;
@@ -32,25 +32,28 @@
/// are executed ordered by their [Priority].
///
/// 3. Invocation ([EventHandler#invoke(InvocationContext, Runtime)]):
-/// In this step the user implemented method is called with help of the right [GenericInteractionDefinition]
+/// In this step the user implemented method is called with help of the right [InteractionDefinition]
@ApiStatus.Internal
public abstract sealed class EventHandler
implements BiConsumer
permits AutoCompleteHandler, ComponentHandler, ModalHandler, ContextCommandHandler, SlashCommandHandler {
+ // will be replaced with ScopedValues when available
+ public static final ThreadLocal INVOCATION_PERMITTED = ThreadLocal.withInitial(() -> false);
+
public static final Logger log = LoggerFactory.getLogger(EventHandler.class);
protected final DispatchingContext dispatchingContext;
protected final MiddlewareRegistry middlewareRegistry;
protected final ImplementationRegistry implementationRegistry;
- protected final InteractionRegistry interactionRegistry;
+ protected final InteractionRegistry registry;
protected final TypeAdapterRegistry adapterRegistry;
public EventHandler(DispatchingContext dispatchingContext) {
this.dispatchingContext = dispatchingContext;
this.middlewareRegistry = dispatchingContext.middlewareRegistry();
this.implementationRegistry = dispatchingContext.implementationRegistry();
- this.interactionRegistry = dispatchingContext.interactionRegistry();
+ this.registry = dispatchingContext.registry();
this.adapterRegistry = dispatchingContext.adapterRegistry();
}
@@ -87,14 +90,16 @@ private void invoke(@NotNull InvocationContext invocation, @NotNull Runtime r
var definition = invocation.definition();
- log.info("Executing interaction \"{}\" for user \"{}\"", definition.getDisplayName(), invocation.event().getUser().getEffectiveName());
+ log.info("Executing interaction \"{}\" for user \"{}\"", definition.displayName(), invocation.event().getUser().getEffectiveName());
try {
log.debug("Invoking method \"{}.{}\" with following arguments: {}",
- definition.getMethod().getDeclaringClass().getName(),
- definition.getMethod().getName(),
+ definition.clazzDescription().name(),
+ definition.methodDescription().name(),
arguments
);
Object instance = runtime.instance(definition);
+
+ INVOCATION_PERMITTED.set(true);
definition.invoke(instance, invocation);
} catch (Exception exception) {
log.error("Interaction execution failed!", exception);
diff --git a/src/main/java/com/github/kaktushose/jda/commands/dispatching/handling/ModalHandler.java b/src/main/java/com/github/kaktushose/jda/commands/dispatching/handling/ModalHandler.java
index b055c33f1..c0f723773 100644
--- a/src/main/java/com/github/kaktushose/jda/commands/dispatching/handling/ModalHandler.java
+++ b/src/main/java/com/github/kaktushose/jda/commands/dispatching/handling/ModalHandler.java
@@ -1,10 +1,10 @@
package com.github.kaktushose.jda.commands.dispatching.handling;
-import com.github.kaktushose.jda.commands.dispatching.internal.Runtime;
+import com.github.kaktushose.jda.commands.definitions.interactions.CustomId;
+import com.github.kaktushose.jda.commands.definitions.interactions.ModalDefinition;
+import com.github.kaktushose.jda.commands.dispatching.Runtime;
import com.github.kaktushose.jda.commands.dispatching.context.InvocationContext;
import com.github.kaktushose.jda.commands.dispatching.events.interactions.ModalEvent;
-import com.github.kaktushose.jda.commands.reflect.interactions.CustomId;
-import com.github.kaktushose.jda.commands.reflect.interactions.ModalDefinition;
import net.dv8tion.jda.api.events.interaction.ModalInteractionEvent;
import net.dv8tion.jda.api.interactions.modals.ModalMapping;
import org.jetbrains.annotations.NotNull;
@@ -26,12 +26,12 @@ protected InvocationContext prepare(@NotNull ModalInterac
return null;
}
- var modal = interactionRegistry.find(ModalDefinition.class, true, it ->
- it.getDefinitionId().equals(CustomId.definitionId(event.getModalId()))
+ var modal = registry.find(ModalDefinition.class, true, it ->
+ it.definitionId().equals(CustomId.fromEvent(event).definitionId())
);
List arguments = event.getValues().stream().map(ModalMapping::getAsString).collect(Collectors.toList());
- arguments.addFirst(new ModalEvent(event, interactionRegistry, runtime, modal));
+ arguments.addFirst(new ModalEvent(event, registry, runtime, modal));
return new InvocationContext<>(
event,
diff --git a/src/main/java/com/github/kaktushose/jda/commands/dispatching/handling/command/ContextCommandHandler.java b/src/main/java/com/github/kaktushose/jda/commands/dispatching/handling/command/ContextCommandHandler.java
index 5b782917c..bf7e7c741 100644
--- a/src/main/java/com/github/kaktushose/jda/commands/dispatching/handling/command/ContextCommandHandler.java
+++ b/src/main/java/com/github/kaktushose/jda/commands/dispatching/handling/command/ContextCommandHandler.java
@@ -1,11 +1,12 @@
package com.github.kaktushose.jda.commands.dispatching.handling.command;
-import com.github.kaktushose.jda.commands.dispatching.internal.Runtime;
+import com.github.kaktushose.jda.commands.definitions.interactions.command.CommandDefinition;
+import com.github.kaktushose.jda.commands.definitions.interactions.command.ContextCommandDefinition;
+import com.github.kaktushose.jda.commands.dispatching.Runtime;
import com.github.kaktushose.jda.commands.dispatching.context.InvocationContext;
import com.github.kaktushose.jda.commands.dispatching.events.interactions.CommandEvent;
-import com.github.kaktushose.jda.commands.dispatching.handling.EventHandler;
import com.github.kaktushose.jda.commands.dispatching.handling.DispatchingContext;
-import com.github.kaktushose.jda.commands.reflect.interactions.commands.ContextCommandDefinition;
+import com.github.kaktushose.jda.commands.dispatching.handling.EventHandler;
import net.dv8tion.jda.api.events.interaction.command.GenericContextInteractionEvent;
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.NotNull;
@@ -21,12 +22,12 @@ public ContextCommandHandler(DispatchingContext dispatchingContext) {
@Override
protected InvocationContext> prepare(@NotNull GenericContextInteractionEvent> event, @NotNull Runtime runtime) {
- ContextCommandDefinition command = interactionRegistry.find(ContextCommandDefinition.class, true, it ->
- it.getName().equals(event.getFullCommandName())
+ CommandDefinition command = registry.find(ContextCommandDefinition.class, true, it ->
+ it.name().equals(event.getFullCommandName())
);
return new InvocationContext<>(event, runtime.keyValueStore(), command,
- List.of(new CommandEvent(event, interactionRegistry, runtime, command), event.getTarget())
+ List.of(new CommandEvent(event, registry, runtime, command), event.getTarget())
);
}
}
diff --git a/src/main/java/com/github/kaktushose/jda/commands/dispatching/handling/command/SlashCommandHandler.java b/src/main/java/com/github/kaktushose/jda/commands/dispatching/handling/command/SlashCommandHandler.java
index 34f1efa65..f13135fb3 100644
--- a/src/main/java/com/github/kaktushose/jda/commands/dispatching/handling/command/SlashCommandHandler.java
+++ b/src/main/java/com/github/kaktushose/jda/commands/dispatching/handling/command/SlashCommandHandler.java
@@ -1,16 +1,15 @@
package com.github.kaktushose.jda.commands.dispatching.handling.command;
-import com.github.kaktushose.jda.commands.dispatching.internal.Runtime;
+import com.github.kaktushose.jda.commands.definitions.interactions.command.SlashCommandDefinition;
+import com.github.kaktushose.jda.commands.dispatching.Runtime;
import com.github.kaktushose.jda.commands.dispatching.adapter.TypeAdapter;
import com.github.kaktushose.jda.commands.dispatching.adapter.TypeAdapterRegistry;
import com.github.kaktushose.jda.commands.dispatching.context.InvocationContext;
import com.github.kaktushose.jda.commands.dispatching.events.interactions.CommandEvent;
-import com.github.kaktushose.jda.commands.dispatching.handling.EventHandler;
import com.github.kaktushose.jda.commands.dispatching.handling.DispatchingContext;
+import com.github.kaktushose.jda.commands.dispatching.handling.EventHandler;
import com.github.kaktushose.jda.commands.dispatching.reply.MessageReply;
import com.github.kaktushose.jda.commands.embeds.error.ErrorMessageFactory;
-import com.github.kaktushose.jda.commands.reflect.ParameterDefinition;
-import com.github.kaktushose.jda.commands.reflect.interactions.commands.SlashCommandDefinition;
import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent;
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.NotNull;
@@ -29,8 +28,8 @@ public SlashCommandHandler(DispatchingContext dispatchingContext) {
@Override
protected InvocationContext prepare(@NotNull SlashCommandInteractionEvent event, @NotNull Runtime runtime) {
- SlashCommandDefinition command = interactionRegistry.find(SlashCommandDefinition.class, true, it ->
- it.getName().equals(event.getFullCommandName())
+ SlashCommandDefinition command = registry.find(SlashCommandDefinition.class, true, it ->
+ it.name().equals(event.getFullCommandName())
);
return parseArguments(command, event, runtime)
@@ -40,18 +39,19 @@ protected InvocationContext prepare(@NotNull Slash
}
private Optional> parseArguments(SlashCommandDefinition command, SlashCommandInteractionEvent event, Runtime runtime) {
- var input = command.getActualParameters().stream()
+ var input = command.commandParameters().stream()
.map(it -> event.getOption(it.name()).getAsString())
.toArray(String[]::new);
List arguments = new ArrayList<>();
- arguments.addFirst(new CommandEvent(event, interactionRegistry, runtime, command));
+ arguments.addFirst(new CommandEvent(event, registry, runtime, command));
ErrorMessageFactory messageFactory = implementationRegistry.getErrorMessageFactory();
log.debug("Type adapting arguments...");
- for (int i = 0; i < command.getActualParameters().size(); i++) {
- ParameterDefinition parameter = command.getActualParameters().get(i);
+ var parameters = List.copyOf(command.commandParameters());
+ for (int i = 0; i < parameters.size(); i++) {
+ var parameter = parameters.get(i);
// if parameter is array don't parse
if (String[].class.isAssignableFrom(parameter.type())) {
@@ -63,7 +63,7 @@ private Optional> parseArguments(SlashCommandDefinition command, Sl
String raw;
// current parameter index == total amount of input, check if it's optional else cancel context
if (i >= input.length) {
- if (!parameter.isOptional()) {
+ if (!parameter.optional()) {
throw new IllegalStateException(
"Command input doesn't match parameter length! Please report this error the the devs of jda-commands."
);
diff --git a/src/main/java/com/github/kaktushose/jda/commands/dispatching/middleware/Middleware.java b/src/main/java/com/github/kaktushose/jda/commands/dispatching/middleware/Middleware.java
index 302867b57..9721bea98 100644
--- a/src/main/java/com/github/kaktushose/jda/commands/dispatching/middleware/Middleware.java
+++ b/src/main/java/com/github/kaktushose/jda/commands/dispatching/middleware/Middleware.java
@@ -1,29 +1,23 @@
package com.github.kaktushose.jda.commands.dispatching.middleware;
+import com.github.kaktushose.jda.commands.annotations.Implementation;
import com.github.kaktushose.jda.commands.dispatching.context.InvocationContext;
import net.dv8tion.jda.api.utils.messages.MessageCreateData;
import java.util.function.Consumer;
-/**
- * Middlewares run just before an interaction event gets dispatched. They are used to perform additional checks or add
- * more info the {@link InvocationContext}. Either register them at the {@link MiddlewareRegistry} or use the
- * {@link com.github.kaktushose.jda.commands.annotations.Implementation Implementation} annotation. Middlewares can have
- * different {@link Priority Priorities} dictating their priority on execution.
- *
- * @see com.github.kaktushose.jda.commands.annotations.Implementation Implementation
- * @see MiddlewareRegistry
- * @since 4.0.0
- */
+/// Middlewares run just before an interaction event gets dispatched. They are used to perform additional checks or add
+/// more info the [InvocationContext]. Either register them at the [MiddlewareRegistry] or use the [Implementation]
+/// annotation. Middlewares can have different [Priorities][Priority] dictating their priority on execution.
+///
+/// @see Implementation Implementation
+/// @see MiddlewareRegistry
@FunctionalInterface
public interface Middleware extends Consumer> {
- /**
- * Executes this middleware with the given {@link InvocationContext}. Use {@link InvocationContext#cancel(MessageCreateData)}
- * to cancel the execution chain.
- *
- * @param context the {@link InvocationContext} of the current interaction event
- */
+ /// Executes this middleware with the given [InvocationContext]. Use [#cancel(MessageCreateData)] to cancel the execution chain.
+ ///
+ /// @param context the [InvocationContext] of the current interaction event
void accept(InvocationContext> context);
}
diff --git a/src/main/java/com/github/kaktushose/jda/commands/dispatching/middleware/MiddlewareRegistry.java b/src/main/java/com/github/kaktushose/jda/commands/dispatching/middleware/MiddlewareRegistry.java
index d98c94883..8334e1bdb 100644
--- a/src/main/java/com/github/kaktushose/jda/commands/dispatching/middleware/MiddlewareRegistry.java
+++ b/src/main/java/com/github/kaktushose/jda/commands/dispatching/middleware/MiddlewareRegistry.java
@@ -8,11 +8,7 @@
import java.util.stream.Collectors;
import java.util.stream.Stream;
-/**
- * Central registry for all {@link Middleware Middlewares}.
- *
- * @since 4.0.0
- */
+/// Central registry for all [Middleware]s.
public class MiddlewareRegistry {
private static final Logger log = LoggerFactory.getLogger(MiddlewareRegistry.class);
@@ -23,63 +19,53 @@ public class MiddlewareRegistry {
Priority.LOW, new HashSet<>()
));
- /**
- * Register {@link Middleware Middleware(s)} with the given {@link Priority}.
- *
- * @param priority the {@link Priority} to register the {@link Middleware Middleware(s)} with
- * @param first the first {@link Middleware} to register
- * @param middlewares additional {@link Middleware Middlewares} to register
- * @return this instance for fluent interface
- */
+ /// Register [Middleware(s)][Middleware] with the given [Priority].
+ ///
+ /// @param priority the [Priority] to register the [Middleware(s)][Middleware] with
+ /// @param first the first [Middleware] to register
+ /// @param middlewares additional [Middleware]s to register
+ /// @return this instance for fluent interface
public MiddlewareRegistry register(Priority priority, Middleware first, Middleware... middlewares) {
register(priority, Stream.concat(Stream.of(first), Arrays.stream(middlewares)).collect(Collectors.toList()));
return this;
}
- /**
- * Register {@link Middleware Middleware(s)} with the given {@link Priority}.
- *
- * @param priority the {@link Priority} to register the {@link Middleware Middleware(s)} with
- * @param middlewares the {@link Middleware Middleware(s)} to register
- * @return this instance for fluent interface
- */
+ /// Register [Middleware(s)][Middleware] with the given [Priority].
+ ///
+ /// @param priority the [Priority] to register the [Middleware(s)][Middleware] with
+ /// @param middlewares the [Middleware(s)][Middleware] to register
+ /// @return this instance for fluent interface
public MiddlewareRegistry register(Priority priority, Collection middlewares) {
this.middlewares.get(priority).addAll(middlewares);
log.debug("Registered middleware(s) {} with priority {}", middlewares, priority);
return this;
}
- /**
- * Unregister {@link Middleware Middleware(s)} with the given {@link Priority}.
- *
- * @param priority the {@link Priority} to unregister the {@link Middleware Middleware(s)} with
- * @param first the first {@link Middleware} to unregister
- * @param middlewares additional {@link Middleware Middlewares} to unregister
- * @return this instance for fluent interface
- */
+ /// Unregister [Middleware(s)][Middleware] with the given [Priority].
+ ///
+ /// @param priority the [Priority] to unregister the [Middleware(s)][Middleware] with
+ /// @param first the first [Middleware] to unregister
+ /// @param middlewares additional [Middlewares][Middleware] to unregister
+ /// @return this instance for fluent interface
public MiddlewareRegistry unregister(Priority priority, Middleware first, Middleware... middlewares) {
unregister(priority, Stream.concat(Stream.of(first), Arrays.stream(middlewares)).collect(Collectors.toList()));
return this;
}
- /**
- * Unregister {@link Middleware Middleware(s)} with the given {@link Priority}.
- *
- * @param priority the {@link Priority} to unregister the {@link Middleware Middleware(s)} with
- * @param middlewares the {@link Middleware Middleware(s)} to unregister
- * @return this instance for fluent interface
- */
+ /// Unregister [Middleware(s)][Middleware] with the given [Priority].
+ ///
+ /// @param priority the [Priority] to unregister the [Middleware(s)][Middleware] with
+ /// @param middlewares the [Middleware(s)][Middleware] to unregister
+ /// @return this instance for fluent interface
public MiddlewareRegistry unregister(Priority priority, Collection middlewares) {
this.middlewares.get(priority).removeAll(middlewares);
log.debug("Unregistered middleware(s) {}", middlewares);
return this;
}
- /**
- * Returns a set of all registered {@link Middleware Middlewares}, regardless of their priority.
- *
- * @return a set of all registered middlewares {@link Middleware Middlewares}
- */
+ /// Returns a set of all registered [Middlewares][Middleware], regardless of their priority.
+ ///
+ /// @return a set of all registered middlewares [Middlewares][Middleware]
public Set getMiddlewares() {
return middlewares.sequencedValues()
.stream()
@@ -93,11 +79,9 @@ public void forAllOrdered(Consumer task) {
}
}
- /**
- * Returns a possibly-empty set of all registered {@link Middleware Middlewares} with the given {@link Priority}.
- *
- * @return a set of all registered middlewares {@link Middleware Middlewares} with the given {@link Priority}
- */
+ /// Returns a possibly-empty set of all registered [Middlewares][Middleware] with the given [Priority].
+ ///
+ /// @return a set of all registered middlewares [Middlewares][Middleware] with the given [Priority]
public Set getMiddlewares(Priority priority) {
return Collections.unmodifiableSet(middlewares.get(priority));
}
diff --git a/src/main/java/com/github/kaktushose/jda/commands/dispatching/middleware/Priority.java b/src/main/java/com/github/kaktushose/jda/commands/dispatching/middleware/Priority.java
index b2586056a..02bd02046 100644
--- a/src/main/java/com/github/kaktushose/jda/commands/dispatching/middleware/Priority.java
+++ b/src/main/java/com/github/kaktushose/jda/commands/dispatching/middleware/Priority.java
@@ -1,27 +1,16 @@
package com.github.kaktushose.jda.commands.dispatching.middleware;
-/**
- * Enum to define with witch priority a {@link Middleware} should be executed.
- *
- * @see MiddlewareRegistry
- * @since 4.0.0
- */
+/// Enum to define with witch priority a [Middleware] should be executed.
+///
+/// @see MiddlewareRegistry
// !! order matters, because enums are compared by ordinal number (java.lang.Comparable)
public enum Priority {
- /**
- * Middlewares with priority PERMISSIONS will always be executed first
- */
+ /// Middlewares with priority PERMISSIONS will always be executed first
PERMISSIONS,
- /**
- * Highest priority for custom implementation, will be executed right after internal middlewares.
- */
+ /// Highest priority for custom implementation, will be executed right after internal middlewares.
HIGH,
- /**
- * Default priority.
- */
+ /// Default priority.
NORMAL,
- /**
- * Lowest priority, will be executed at the end
- */
+ /// Lowest priority, will be executed at the end
LOW
}
diff --git a/src/main/java/com/github/kaktushose/jda/commands/dispatching/middleware/impl/ConstraintMiddleware.java b/src/main/java/com/github/kaktushose/jda/commands/dispatching/middleware/impl/ConstraintMiddleware.java
index 92be28ce9..d28587235 100644
--- a/src/main/java/com/github/kaktushose/jda/commands/dispatching/middleware/impl/ConstraintMiddleware.java
+++ b/src/main/java/com/github/kaktushose/jda/commands/dispatching/middleware/impl/ConstraintMiddleware.java
@@ -1,11 +1,10 @@
package com.github.kaktushose.jda.commands.dispatching.middleware.impl;
+import com.github.kaktushose.jda.commands.definitions.interactions.command.ParameterDefinition;
+import com.github.kaktushose.jda.commands.definitions.interactions.command.SlashCommandDefinition;
+import com.github.kaktushose.jda.commands.dispatching.ImplementationRegistry;
import com.github.kaktushose.jda.commands.dispatching.context.InvocationContext;
import com.github.kaktushose.jda.commands.dispatching.middleware.Middleware;
-import com.github.kaktushose.jda.commands.reflect.ConstraintDefinition;
-import com.github.kaktushose.jda.commands.reflect.ImplementationRegistry;
-import com.github.kaktushose.jda.commands.reflect.ParameterDefinition;
-import com.github.kaktushose.jda.commands.reflect.interactions.commands.SlashCommandDefinition;
import org.jetbrains.annotations.NotNull;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -13,13 +12,10 @@
import java.util.ArrayList;
import java.util.List;
-/**
- * A {@link Middleware} implementation that will check the parameter constraints a
- * {@link SlashCommandDefinition} might have.
- *
- * @see com.github.kaktushose.jda.commands.dispatching.validation.ValidatorRegistry ValidatorRegistry
- * @since 2.0.0
- */
+/// A [Middleware] implementation that will check the parameter constraints a
+/// [SlashCommandDefinition] might have.
+///
+/// @see com.github.kaktushose.jda.commands.dispatching.validation.ValidatorRegistry ValidatorRegistry
public class ConstraintMiddleware implements Middleware {
private static final Logger log = LoggerFactory.getLogger(ConstraintMiddleware.class);
@@ -30,25 +26,23 @@ public ConstraintMiddleware(ImplementationRegistry implementationRegistry) {
this.implementationRegistry = implementationRegistry;
}
- /**
- * Checks if all parameters fulfill their constraints. Will cancel the {@link InvocationContext} if a parameter
- * constraint fails.
- *
- * @param context the {@link InvocationContext} to filter
- */
+ /// Checks if all parameters fulfill their constraints. Will cancel the [InvocationContext] if a parameter
+ /// constraint fails.
+ ///
+ /// @param context the [InvocationContext] to filter
@Override
public void accept(@NotNull InvocationContext> context) {
if (!(context.definition() instanceof SlashCommandDefinition command))
return;
var arguments = new ArrayList<>(context.arguments());
- List parameters = command.getParameters();
+ List parameters = List.copyOf(command.commandParameters());
log.debug("Applying parameter constraints...");
for (int i = 1; i < arguments.size(); i++) {
Object argument = arguments.get(i);
ParameterDefinition parameter = parameters.get(i);
- for (ConstraintDefinition constraint : parameter.constraints()) {
+ for (ParameterDefinition.ConstraintDefinition constraint : parameter.constraints()) {
log.debug("Found constraint {} for parameter {}", constraint, parameter.type().getName());
boolean validated = constraint.validator().apply(argument, constraint.annotation(), context);
diff --git a/src/main/java/com/github/kaktushose/jda/commands/dispatching/middleware/impl/CooldownMiddleware.java b/src/main/java/com/github/kaktushose/jda/commands/dispatching/middleware/impl/CooldownMiddleware.java
index f56be324f..13d9a3818 100644
--- a/src/main/java/com/github/kaktushose/jda/commands/dispatching/middleware/impl/CooldownMiddleware.java
+++ b/src/main/java/com/github/kaktushose/jda/commands/dispatching/middleware/impl/CooldownMiddleware.java
@@ -1,11 +1,11 @@
package com.github.kaktushose.jda.commands.dispatching.middleware.impl;
import com.github.kaktushose.jda.commands.annotations.interactions.Cooldown;
+import com.github.kaktushose.jda.commands.definitions.interactions.command.SlashCommandDefinition;
+import com.github.kaktushose.jda.commands.definitions.interactions.command.SlashCommandDefinition.CooldownDefinition;
+import com.github.kaktushose.jda.commands.dispatching.ImplementationRegistry;
import com.github.kaktushose.jda.commands.dispatching.context.InvocationContext;
import com.github.kaktushose.jda.commands.dispatching.middleware.Middleware;
-import com.github.kaktushose.jda.commands.reflect.CooldownDefinition;
-import com.github.kaktushose.jda.commands.reflect.ImplementationRegistry;
-import com.github.kaktushose.jda.commands.reflect.interactions.commands.SlashCommandDefinition;
import org.jetbrains.annotations.NotNull;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -16,15 +16,12 @@
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
-/**
- * A {@link Middleware} implementation that contains the business logic behind command cooldowns.
- * If the command isn't annotated with {@link Cooldown Cooldown} or more
- * formally if the {@link SlashCommandDefinition} doesn't hold a {@link CooldownDefinition} or the delay of the
- * {@link CooldownDefinition} amounts to {@code 0} this filter has no effect.
- *
- * @see Cooldown
- * @since 2.0.0
- */
+/// A [Middleware] implementation that contains the business logic behind command cooldowns.
+/// If the command isn't annotated with [Cooldown] or more
+/// formally if the [SlashCommandDefinition] doesn't hold a [CooldownDefinition] or the delay of the
+/// [CooldownDefinition] amounts to `0` this filter has no effect.
+///
+/// @see Cooldown
public class CooldownMiddleware implements Middleware {
private static final Logger log = LoggerFactory.getLogger(CooldownMiddleware.class);
@@ -36,15 +33,14 @@ public CooldownMiddleware(ImplementationRegistry implementationRegistry) {
this.implementationRegistry = implementationRegistry;
}
- /**
- * Checks if an active cooldown for the given {@link SlashCommandDefinition} exists and will eventually cancel the
- * context.
- *
- * @param context the {@link InvocationContext} to filter
- */
+ /// Checks if an active cooldown for the given [SlashCommandDefinition] exists and will eventually cancel the
+ /// context.
+ ///
+ /// @param context the [InvocationContext] to filter
@Override
public void accept(@NotNull InvocationContext> context) {
- if (!(context.definition() instanceof SlashCommandDefinition command) || !command.hasCooldown()) return;
+ if (!(context.definition() instanceof SlashCommandDefinition command) || command.cooldown().delay() <= 0)
+ return;
long id = context.event().getUser().getIdLong();
@@ -64,34 +60,13 @@ public void accept(@NotNull InvocationContext> context) {
}
}
- CooldownDefinition cooldown = command.getCooldown();
+ CooldownDefinition cooldown = command.cooldown();
long startTime = System.currentTimeMillis();
long duration = cooldown.timeUnit().toMillis(cooldown.delay());
activeCooldowns.get(id).add(new CooldownEntry(command, startTime, duration));
log.debug("Added new cooldown entry for this user");
}
- private static class CooldownEntry {
- private final SlashCommandDefinition command;
- private final long startTime;
- private final long duration;
-
- public CooldownEntry(SlashCommandDefinition command, long startTime, long duration) {
- this.command = command;
- this.startTime = startTime;
- this.duration = duration;
- }
-
- public SlashCommandDefinition getCommand() {
- return command;
- }
-
- public long getStartTime() {
- return startTime;
- }
-
- public long getDuration() {
- return duration;
- }
+ private record CooldownEntry(SlashCommandDefinition command, long startTime, long duration) {
}
}
diff --git a/src/main/java/com/github/kaktushose/jda/commands/dispatching/middleware/impl/PermissionsMiddleware.java b/src/main/java/com/github/kaktushose/jda/commands/dispatching/middleware/impl/PermissionsMiddleware.java
index aa8149205..2908691f7 100644
--- a/src/main/java/com/github/kaktushose/jda/commands/dispatching/middleware/impl/PermissionsMiddleware.java
+++ b/src/main/java/com/github/kaktushose/jda/commands/dispatching/middleware/impl/PermissionsMiddleware.java
@@ -1,10 +1,10 @@
package com.github.kaktushose.jda.commands.dispatching.middleware.impl;
import com.github.kaktushose.jda.commands.annotations.interactions.Permissions;
+import com.github.kaktushose.jda.commands.dispatching.ImplementationRegistry;
import com.github.kaktushose.jda.commands.dispatching.context.InvocationContext;
import com.github.kaktushose.jda.commands.dispatching.middleware.Middleware;
import com.github.kaktushose.jda.commands.permissions.PermissionsProvider;
-import com.github.kaktushose.jda.commands.reflect.ImplementationRegistry;
import net.dv8tion.jda.api.entities.Member;
import net.dv8tion.jda.api.entities.User;
import net.dv8tion.jda.api.events.interaction.GenericInteractionCreateEvent;
@@ -12,19 +12,16 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-/**
- * A {@link Middleware} implementation that will check permissions.
- * The default implementation can only handle discord permissions. However, the {@link PermissionsProvider} can be
- * used for own implementations.
- * This filter will first check against {@link PermissionsProvider#hasPermission(User, InvocationContext)} with a
- * {@link User} object. This can be used for global permissions. Afterward
- * {@link PermissionsProvider#hasPermission(User, InvocationContext)} will be called. Since the {@link Member} is
- * available this might be used for guild related permissions.
- *
- * @see Permissions
- * @see PermissionsProvider
- * @since 2.0.0
- */
+/// A [Middleware] implementation that will check permissions.
+/// The default implementation can only handle discord permissions. However, the [PermissionsProvider] can be
+/// used for own implementations.
+/// This filter will first check against [#hasPermission(User,InvocationContext)] with a
+/// [User] object. This can be used for global permissions. Afterward
+/// [#hasPermission(User,InvocationContext)] will be called. Since the [Member] is
+/// available this might be used for guild related permissions.
+///
+/// @see Permissions
+/// @see PermissionsProvider
public class PermissionsMiddleware implements Middleware {
private static final Logger log = LoggerFactory.getLogger(PermissionsMiddleware.class);
@@ -35,11 +32,9 @@ public PermissionsMiddleware(ImplementationRegistry implementationRegistry) {
this.implementationRegistry = implementationRegistry;
}
- /**
- * Checks if the {@link User} and respectively the {@link Member} has the permission to execute the command.
- *
- * @param context the {@link InvocationContext} to filter
- */
+ /// Checks if the [User] and respectively the [Member] has the permission to execute the command.
+ ///
+ /// @param context the [InvocationContext] to filter
@Override
public void accept(@NotNull InvocationContext> context) {
log.debug("Checking permissions...");
diff --git a/src/main/java/com/github/kaktushose/jda/commands/dispatching/package-info.java b/src/main/java/com/github/kaktushose/jda/commands/dispatching/package-info.java
index e5ccf54b2..5c21dd980 100644
--- a/src/main/java/com/github/kaktushose/jda/commands/dispatching/package-info.java
+++ b/src/main/java/com/github/kaktushose/jda/commands/dispatching/package-info.java
@@ -1,4 +1,2 @@
-/**
- * Top-level package for all parts of the execution chain.
- */
+/// Top-level package for all parts of the execution chain.
package com.github.kaktushose.jda.commands.dispatching;
diff --git a/src/main/java/com/github/kaktushose/jda/commands/dispatching/reply/Component.java b/src/main/java/com/github/kaktushose/jda/commands/dispatching/reply/Component.java
index b7ffc4fe6..54ef65cbc 100644
--- a/src/main/java/com/github/kaktushose/jda/commands/dispatching/reply/Component.java
+++ b/src/main/java/com/github/kaktushose/jda/commands/dispatching/reply/Component.java
@@ -25,7 +25,6 @@
/// event.with().components(Components.of(true, false, "onButton")).reply();
/// }
///```
-/// @since 2.3.0
public record Component(boolean enabled, boolean independent, String name) {
/// Adds enabled, runtime-bound [Component]s to the reply.
diff --git a/src/main/java/com/github/kaktushose/jda/commands/dispatching/reply/ComponentReply.java b/src/main/java/com/github/kaktushose/jda/commands/dispatching/reply/ComponentReply.java
index 459223fc3..ab4286347 100644
--- a/src/main/java/com/github/kaktushose/jda/commands/dispatching/reply/ComponentReply.java
+++ b/src/main/java/com/github/kaktushose/jda/commands/dispatching/reply/ComponentReply.java
@@ -4,8 +4,6 @@
import org.jetbrains.annotations.NotNull;
/// Subtype of [ConfigurableReply] that allows replying only with a name without a message.
-///
-/// @since 4.0.0
public final class ComponentReply extends ConfigurableReply {
/// Constructs a new ComponentReply.
diff --git a/src/main/java/com/github/kaktushose/jda/commands/dispatching/reply/ConfigurableReply.java b/src/main/java/com/github/kaktushose/jda/commands/dispatching/reply/ConfigurableReply.java
index 2d0177b60..e1d52f3fe 100644
--- a/src/main/java/com/github/kaktushose/jda/commands/dispatching/reply/ConfigurableReply.java
+++ b/src/main/java/com/github/kaktushose/jda/commands/dispatching/reply/ConfigurableReply.java
@@ -1,11 +1,13 @@
package com.github.kaktushose.jda.commands.dispatching.reply;
import com.github.kaktushose.jda.commands.annotations.interactions.ReplyConfig;
-import com.github.kaktushose.jda.commands.dispatching.internal.Runtime;
-import com.github.kaktushose.jda.commands.reflect.InteractionRegistry;
-import com.github.kaktushose.jda.commands.reflect.interactions.components.ButtonDefinition;
-import com.github.kaktushose.jda.commands.reflect.interactions.components.GenericComponentDefinition;
-import com.github.kaktushose.jda.commands.reflect.interactions.components.menus.GenericSelectMenuDefinition;
+import com.github.kaktushose.jda.commands.definitions.interactions.CustomId;
+import com.github.kaktushose.jda.commands.definitions.interactions.InteractionDefinition;
+import com.github.kaktushose.jda.commands.definitions.interactions.InteractionRegistry;
+import com.github.kaktushose.jda.commands.definitions.interactions.component.ButtonDefinition;
+import com.github.kaktushose.jda.commands.definitions.interactions.component.ComponentDefinition;
+import com.github.kaktushose.jda.commands.definitions.interactions.component.menu.SelectMenuDefinition;
+import com.github.kaktushose.jda.commands.dispatching.Runtime;
import net.dv8tion.jda.api.interactions.components.ActionRow;
import net.dv8tion.jda.api.interactions.components.ItemComponent;
import org.jetbrains.annotations.NotNull;
@@ -31,11 +33,9 @@
/// }
/// }
/// ```
-///
-/// @since 4.0.0
public sealed class ConfigurableReply extends MessageReply permits ComponentReply {
- protected final InteractionRegistry interactionRegistry;
+ protected final InteractionRegistry registry;
protected final String runtimeId;
/// Constructs a new ConfigurableReply.
@@ -45,7 +45,7 @@ public sealed class ConfigurableReply extends MessageReply permits ComponentRepl
/// @param runtimeId the corresponding [Runtime]
public ConfigurableReply(@NotNull MessageReply reply, @NotNull InteractionRegistry registry, @NotNull String runtimeId) {
super(reply);
- this.interactionRegistry = registry;
+ this.registry = registry;
this.runtimeId = runtimeId;
}
@@ -54,7 +54,7 @@ public ConfigurableReply(@NotNull MessageReply reply, @NotNull InteractionRegist
/// @param reply the [ConfigurableReply] to copy
public ConfigurableReply(@NotNull ConfigurableReply reply) {
super(reply);
- this.interactionRegistry = reply.interactionRegistry;
+ this.registry = reply.registry;
this.runtimeId = reply.runtimeId;
}
@@ -131,7 +131,6 @@ public ConfigurableReply keepComponents(boolean keepComponents) {
/// }
/// }
/// ```
- ///
/// @param components the name of the components to add
/// @return the current instance for fluent interface
@NotNull
@@ -159,7 +158,6 @@ public ComponentReply components(@NotNull String... components) {
/// }
/// }
/// ```
- ///
/// @see Component
/// @param components the [Component] to add
/// @return the current instance for fluent interface
@@ -167,19 +165,21 @@ public ComponentReply components(@NotNull String... components) {
public ComponentReply components(@NotNull Component... components) {
List items = new ArrayList<>();
for (Component component : components) {
- var definitionId = String.valueOf((definition.getMethod().getDeclaringClass().getName() + component.name()).hashCode());
- var definition = interactionRegistry.find(GenericComponentDefinition.class, false, it ->
- it.getDefinitionId().equals(definitionId)
+ var definitionId = String.valueOf((definition.methodDescription().declaringClass().getName() + component.name()).hashCode());
+ var definition = registry.find(ComponentDefinition.class, false, it ->
+ it.definitionId().equals(definitionId)
);
- log.debug("Reply Debug: Adding component \"{}\" to the reply", definition.getDisplayName());
+ log.debug("Reply Debug: Adding component \"{}\" to the reply", definition.displayName());
switch (definition) {
case ButtonDefinition buttonDefinition -> {
- var button = buttonDefinition.toButton().withDisabled(!component.enabled());
+ var button = buttonDefinition.toJDAEntity().withDisabled(!component.enabled());
//only assign ids to non-link buttons
- items.add(button.getUrl() == null ? button.withId(createId(definition, component.independent())) : button);
+ items.add(button.getUrl() == null ? button.withId(createId(definition, component.independent()).id()) : button);
+ }
+ case SelectMenuDefinition> menuDefinition -> {
+ var menu = menuDefinition.toJDAEntity(createId(definition, component.independent()));
+ items.add(menu.withDisabled(!component.enabled()));
}
- case GenericSelectMenuDefinition> menuDefinition ->
- items.add(menuDefinition.toSelectMenu(createId(definition, component.independent()), component.enabled()));
}
}
if (!items.isEmpty()) {
@@ -189,10 +189,10 @@ public ComponentReply components(@NotNull Component... components) {
return new ComponentReply(this);
}
- private String createId(GenericComponentDefinition definition, boolean staticComponent) {
+ private CustomId createId(InteractionDefinition definition, boolean staticComponent) {
return staticComponent
- ? definition.independentCustomId()
- : definition.boundCustomId(runtimeId);
+ ? CustomId.independent(definition.definitionId())
+ : new CustomId(runtimeId, definition.definitionId());
}
}
diff --git a/src/main/java/com/github/kaktushose/jda/commands/dispatching/reply/MessageReply.java b/src/main/java/com/github/kaktushose/jda/commands/dispatching/reply/MessageReply.java
index b5cf325d3..59327768d 100644
--- a/src/main/java/com/github/kaktushose/jda/commands/dispatching/reply/MessageReply.java
+++ b/src/main/java/com/github/kaktushose/jda/commands/dispatching/reply/MessageReply.java
@@ -1,9 +1,7 @@
package com.github.kaktushose.jda.commands.dispatching.reply;
+import com.github.kaktushose.jda.commands.definitions.interactions.InteractionDefinition;
import com.github.kaktushose.jda.commands.dispatching.events.ReplyableEvent;
-import com.github.kaktushose.jda.commands.reflect.interactions.EphemeralInteractionDefinition;
-import com.github.kaktushose.jda.commands.reflect.interactions.GenericInteractionDefinition;
-import com.github.kaktushose.jda.commands.reflect.interactions.ReplyConfig;
import net.dv8tion.jda.api.EmbedBuilder;
import net.dv8tion.jda.api.entities.Message;
import net.dv8tion.jda.api.events.interaction.GenericInteractionCreateEvent;
@@ -31,12 +29,11 @@
///
/// @see ConfigurableReply
/// @see ReplyableEvent
-/// @since 4.0.0
public sealed class MessageReply implements Reply permits ConfigurableReply {
protected static final Logger log = LoggerFactory.getLogger(MessageReply.class);
protected final GenericInteractionCreateEvent event;
- protected final GenericInteractionDefinition definition;
+ protected final InteractionDefinition definition;
protected final MessageCreateBuilder builder;
protected boolean ephemeral;
protected boolean editReply;
@@ -45,12 +42,11 @@ public sealed class MessageReply implements Reply permits ConfigurableReply {
/// Constructs a new MessageReply.
///
/// @param event the corresponding [GenericInteractionCreateEvent]
- /// @param definition the corresponding [GenericInteractionDefinition]. This is mostly needed by the
- /// [ConfigurableReply]
- /// @param replyConfig the [ReplyConfig] to use
+ /// @param definition the corresponding [InteractionDefinition]. This is mostly needed by the [ConfigurableReply]
+ /// @param replyConfig the [InteractionDefinition.ReplyConfig] to use
public MessageReply(@NotNull GenericInteractionCreateEvent event,
- @NotNull GenericInteractionDefinition definition,
- @NotNull ReplyConfig replyConfig) {
+ @NotNull InteractionDefinition definition,
+ @NotNull InteractionDefinition.ReplyConfig replyConfig) {
this.event = event;
this.definition = definition;
this.ephemeral = replyConfig.ephemeral();
@@ -62,9 +58,8 @@ public MessageReply(@NotNull GenericInteractionCreateEvent event,
/// Constructs a new MessageReply.
///
/// @param event the corresponding [GenericInteractionCreateEvent]
- /// @param definition the corresponding [EphemeralInteractionDefinition]. This is mostly needed by the
- /// [ConfigurableReply]
- public MessageReply(@NotNull GenericInteractionCreateEvent event, @NotNull EphemeralInteractionDefinition definition) {
+ /// @param definition the corresponding [InteractionDefinition]. This is mostly needed by the [ConfigurableReply]
+ public MessageReply(@NotNull GenericInteractionCreateEvent event, @NotNull InteractionDefinition definition) {
this(event, definition, definition.replyConfig());
}
@@ -121,7 +116,7 @@ protected Message complete() {
}
log.debug(
"Replying to interaction \"{}\" with content: {} [ephemeral={}, editReply={}, keepComponents={}]",
- definition.getDisplayName(), builder.build().toData(), ephemeral, editReply, keepComponents
+ definition.displayName(), builder.build().toData(), ephemeral, editReply, keepComponents
);
var hook = ((IDeferrableCallback) event).getHook();
if (editReply) {
diff --git a/src/main/java/com/github/kaktushose/jda/commands/dispatching/reply/Reply.java b/src/main/java/com/github/kaktushose/jda/commands/dispatching/reply/Reply.java
index b11c0ae39..cfe673258 100644
--- a/src/main/java/com/github/kaktushose/jda/commands/dispatching/reply/Reply.java
+++ b/src/main/java/com/github/kaktushose/jda/commands/dispatching/reply/Reply.java
@@ -1,7 +1,7 @@
package com.github.kaktushose.jda.commands.dispatching.reply;
-import com.github.kaktushose.jda.commands.embeds.EmbedDTO;
import com.github.kaktushose.jda.commands.dispatching.events.ReplyableEvent;
+import com.github.kaktushose.jda.commands.embeds.EmbedDTO;
import net.dv8tion.jda.api.EmbedBuilder;
import net.dv8tion.jda.api.entities.Message;
import net.dv8tion.jda.api.events.interaction.GenericInteractionCreateEvent;
@@ -15,27 +15,20 @@
/// always share the same reply methods.
///
/// @see ReplyableEvent
-/// @since 4.0.0
public sealed interface Reply permits MessageReply, ReplyableEvent {
/// Acknowledgement of this event with a text message.
///
+ /// @param message the message to send
+ /// @return the [Message] that got created
/// @implSpec Internally this method must call [RestAction#complete()], thus the [Message] object can get
/// returned directly.
///
/// This might throw [RuntimeException]s if JDA fails to send the message.
- ///
- /// @param message the message to send
- /// @return the [Message] that got created
Message reply(@NotNull String message);
/// Acknowledgement of this event with a text message.
///
- /// @implSpec Internally this method must call [RestAction#complete()], thus the [Message] object can get
- /// returned directly.
- ///
- /// This might throw [RuntimeException]s if JDA fails to send the message.
- ///
/// @param format the message to send
/// @param args Arguments referenced by the format specifiers in the format string. If there are more arguments than
/// format specifiers, the extra arguments are ignored. The number of arguments is variable and may be
@@ -52,35 +45,32 @@ default Message reply(@NotNull String format, @NotNull Object... args) {
/// Acknowledgement of this event with a text message.
///
+ /// @param message the [MessageCreateData] to send
+ /// @return the [Message] that got created
/// @implSpec Internally this method must call [RestAction#complete()], thus the [Message] object can get
/// returned directly.
///
/// This might throw [RuntimeException]s if JDA fails to send the message.
- ///
- /// @param message the [MessageCreateData] to send
- /// @return the [Message] that got created
Message reply(@NotNull MessageCreateData message);
/// Acknowledgement of this event with a text message.
///
+ /// @param builder the [EmbedBuilder] to send
+ /// @return the [Message] that got created
/// @implSpec Internally this method must call [RestAction#complete()], thus the [Message] object can get
/// returned directly.
///
/// This might throw [RuntimeException]s if JDA fails to send the message.
- ///
- /// @param builder the [EmbedBuilder] to send
- /// @return the [Message] that got created
Message reply(@NotNull EmbedBuilder builder);
/// Acknowledgement of this event with a text message.
///
+ /// @param embedDTO the [EmbedDTO] to send
+ /// @return the [Message] that got created
/// @implSpec Internally this method must call [RestAction#complete()], thus the [Message] object can get
/// returned directly.
///
/// This might throw [RuntimeException]s if JDA fails to send the message.
- ///
- /// @param embedDTO the [EmbedDTO] to send
- /// @return the [Message] that got created
default Message reply(@NotNull EmbedDTO embedDTO) {
return reply(embedDTO.toEmbedBuilder());
}
diff --git a/src/main/java/com/github/kaktushose/jda/commands/dispatching/reply/package-info.java b/src/main/java/com/github/kaktushose/jda/commands/dispatching/reply/package-info.java
index 8415d4fbe..1d2cd2627 100644
--- a/src/main/java/com/github/kaktushose/jda/commands/dispatching/reply/package-info.java
+++ b/src/main/java/com/github/kaktushose/jda/commands/dispatching/reply/package-info.java
@@ -1,4 +1,2 @@
-/**
- * Classes for sending bot messages.
- */
+/// Classes for sending bot messages.
package com.github.kaktushose.jda.commands.dispatching.reply;
diff --git a/src/main/java/com/github/kaktushose/jda/commands/dispatching/validation/Validator.java b/src/main/java/com/github/kaktushose/jda/commands/dispatching/validation/Validator.java
index 0ff78da04..6a09c0fc5 100644
--- a/src/main/java/com/github/kaktushose/jda/commands/dispatching/validation/Validator.java
+++ b/src/main/java/com/github/kaktushose/jda/commands/dispatching/validation/Validator.java
@@ -3,24 +3,19 @@
import com.github.kaktushose.jda.commands.dispatching.context.InvocationContext;
import org.jetbrains.annotations.NotNull;
-/**
- * Generic top level interface for validators. A validator checks if a command argument fulfills the given constraint.
- *
- * @see com.github.kaktushose.jda.commands.annotations.Implementation
- * @see com.github.kaktushose.jda.commands.annotations.constraints.Constraint Constraint
- * @since 2.0.0
- */
+/// Generic top level interface for validators. A validator checks if a command argument fulfills the given constraint.
+///
+/// @see com.github.kaktushose.jda.commands.annotations.Implementation Implementation
+/// @see com.github.kaktushose.jda.commands.annotations.constraints.Constraint Constraint
@FunctionalInterface
public interface Validator {
- /**
- * Validates an argument.
- *
- * @param argument the argument to validate
- * @param annotation the corresponding annotation
- * @param context the corresponding {@link InvocationContext}
- * @return {@code true} if the argument passes the constraints
- */
+ /// Validates an argument.
+ ///
+ /// @param argument the argument to validate
+ /// @param annotation the corresponding annotation
+ /// @param context the corresponding [InvocationContext]
+ /// @return `true` if the argument passes the constraints
boolean apply(@NotNull Object argument, @NotNull Object annotation, @NotNull InvocationContext> context);
}
diff --git a/src/main/java/com/github/kaktushose/jda/commands/dispatching/validation/ValidatorRegistry.java b/src/main/java/com/github/kaktushose/jda/commands/dispatching/validation/ValidatorRegistry.java
index 4a7683c09..339357657 100644
--- a/src/main/java/com/github/kaktushose/jda/commands/dispatching/validation/ValidatorRegistry.java
+++ b/src/main/java/com/github/kaktushose/jda/commands/dispatching/validation/ValidatorRegistry.java
@@ -12,30 +12,24 @@
import java.util.Map;
import java.util.Optional;
-/**
- * Central registry for all {@link Validator Validators}.
- *
- * @see Validator
- * @since 2.0.0
- */
+/// Central registry for all [Validator]s.
+///
+/// @see Validator
public class ValidatorRegistry {
private final Logger log = LoggerFactory.getLogger(ValidatorRegistry.class);
private final Map, Validator> validators;
- /**
- * Constructs a new ValidatorRegistry. This will register the following {@link Validator Validators} by default:
- *
- * {@link MinimumValidator}
- * {@link MaximumValidator}
- * {@link RoleValidator}
- * {@link NotRoleValidator}
- * {@link PermissionValidator}
- * {@link NotPermissionValidator}
- * {@link UserValidator}
- * {@link NotUserValidator}
- *
- */
+ /// Constructs a new ValidatorRegistry. This will register the following [Validator]s by default:
+ ///
+ /// - [MinimumValidator]
+ /// - [MaximumValidator]
+ /// - [RoleValidator]
+ /// - [NotRoleValidator]
+ /// - [PermissionValidator]
+ /// - [NotPermissionValidator]
+ /// - [UserValidator]
+ /// - [NotUserValidator]
public ValidatorRegistry() {
validators = new HashMap<>();
// default types
@@ -51,13 +45,11 @@ public ValidatorRegistry() {
register(NotUser.class, new NotUserValidator());
}
- /**
- * Register a {@link Validator} and map it to an annotation. Each annotation can only map to one {@link Validator}.
- *
- * @param annotation the type of the annotation to map the {@link Validator} to
- * @param validator the {@link Validator} to map
- * @throws IllegalArgumentException if the annotation class isn't annotated with {@link Constraint}
- */
+ /// Register a [Validator] and map it to an annotation. Each annotation can only map to one [Validator].
+ ///
+ /// @param annotation the type of the annotation to map the [Validator] to
+ /// @param validator the [Validator] to map
+ /// @throws IllegalArgumentException if the annotation class isn't annotated with [Constraint]
public void register(@NotNull Class extends Annotation> annotation, @NotNull Validator validator) {
if (!annotation.isAnnotationPresent(Constraint.class)) {
throw new IllegalArgumentException(Constraint.class.getCanonicalName() + " annotation must be present!");
@@ -66,24 +58,20 @@ public void register(@NotNull Class extends Annotation> annotation, @NotNull V
log.debug("Registered validator {} for annotation {}", validator.getClass().getName(), annotation.getName());
}
- /**
- * Unregisters the {@link Validator} mapped to the given annotation.
- *
- * @param annotation the class of the annotation to unregister
- */
+ /// Unregisters the [Validator] mapped to the given annotation.
+ ///
+ /// @param annotation the class of the annotation to unregister
public void unregister(Class> annotation) {
validators.remove(annotation);
log.debug("Unregistered validator for annotation {}", annotation.getName());
}
- /**
- * Gets a {@link Validator} based on the annotation and the type to validate. Returns an empty {@link Optional} if
- * the {@link Validator} cannot validate the given type.
- *
- * @param annotation the class of the annotation
- * @param type the type to validate
- * @return an {@link Optional} holding the {@link Validator}
- */
+ /// Gets a [Validator] based on the annotation and the type to validate. Returns an empty [Optional] if
+ /// the [Validator] cannot validate the given type.
+ ///
+ /// @param annotation the class of the annotation
+ /// @param type the type to validate
+ /// @return an [Optional] holding the [Validator]
public Optional get(@NotNull Class> annotation, @NotNull Class> type) {
Validator validator = validators.get(annotation);
diff --git a/src/main/java/com/github/kaktushose/jda/commands/dispatching/validation/impl/MaximumValidator.java b/src/main/java/com/github/kaktushose/jda/commands/dispatching/validation/impl/MaximumValidator.java
index aa7db9d91..8d5a99838 100644
--- a/src/main/java/com/github/kaktushose/jda/commands/dispatching/validation/impl/MaximumValidator.java
+++ b/src/main/java/com/github/kaktushose/jda/commands/dispatching/validation/impl/MaximumValidator.java
@@ -5,22 +5,17 @@
import com.github.kaktushose.jda.commands.dispatching.validation.Validator;
import org.jetbrains.annotations.NotNull;
-/**
- * A {@link Validator} implementation that checks the {@link Max} constraint.
- *
- * @see Max
- * @since 2.0.0
- */
+/// A [Validator] implementation that checks the [Max] constraint.
+///
+/// @see Max
public class MaximumValidator implements Validator {
- /**
- * Validates an argument. The argument must be a number whose value must be lower or equal to the specified maximum.
- *
- * @param argument the argument to validate
- * @param annotation the corresponding annotation
- * @param context the corresponding {@link InvocationContext}
- * @return {@code true} if the argument is a number whose value is lower or equal to the specified maximum
- */
+ /// Validates an argument. The argument must be a number whose value must be less or equal to the specified maximum.
+ ///
+ /// @param argument the argument to validate
+ /// @param annotation the corresponding annotation
+ /// @param context the corresponding [InvocationContext]
+ /// @return `true` if the argument is a number whose value is less or equal to the specified maximum
@Override
public boolean apply(@NotNull Object argument, @NotNull Object annotation, @NotNull InvocationContext> context) {
Max max = (Max) annotation;
diff --git a/src/main/java/com/github/kaktushose/jda/commands/dispatching/validation/impl/MinimumValidator.java b/src/main/java/com/github/kaktushose/jda/commands/dispatching/validation/impl/MinimumValidator.java
index 65146f562..8a0c59f68 100644
--- a/src/main/java/com/github/kaktushose/jda/commands/dispatching/validation/impl/MinimumValidator.java
+++ b/src/main/java/com/github/kaktushose/jda/commands/dispatching/validation/impl/MinimumValidator.java
@@ -5,23 +5,18 @@
import com.github.kaktushose.jda.commands.dispatching.validation.Validator;
import org.jetbrains.annotations.NotNull;
-/**
- * A {@link Validator} implementation that checks the {@link Min} constraint.
- *
- * @see Min
- * @since 2.0.0
- */
+/// A [Validator] implementation that checks the [Min] constraint.
+///
+/// @see Min
public class MinimumValidator implements Validator {
- /**
- * Validates an argument. The argument must be a number whose value must be greater or equal to the specified
- * minimum.
- *
- * @param argument the argument to validate
- * @param annotation the corresponding annotation
- * @param context the corresponding {@link InvocationContext}
- * @return {@code true} if the argument is a number whose value is greater or equal to the specified minimum
- */
+ /// Validates an argument. The argument must be a number whose value must be greater or equal to the specified
+ /// minimum.
+ ///
+ /// @param argument the argument to validate
+ /// @param annotation the corresponding annotation
+ /// @param context the corresponding [InvocationContext]
+ /// @return `true` if the argument is a number whose value is greater or equal to the specified minimum
@Override
public boolean apply(@NotNull Object argument, @NotNull Object annotation, @NotNull InvocationContext> context) {
Min min = (Min) annotation;
diff --git a/src/main/java/com/github/kaktushose/jda/commands/dispatching/validation/impl/NotPermissionValidator.java b/src/main/java/com/github/kaktushose/jda/commands/dispatching/validation/impl/NotPermissionValidator.java
index fceaa5518..5fe64f55f 100644
--- a/src/main/java/com/github/kaktushose/jda/commands/dispatching/validation/impl/NotPermissionValidator.java
+++ b/src/main/java/com/github/kaktushose/jda/commands/dispatching/validation/impl/NotPermissionValidator.java
@@ -10,24 +10,19 @@
import java.util.HashSet;
import java.util.Set;
-/**
- * A {@link Validator} implementation that checks the {@link NotPerm} constraint.
- *
- * @see NotPerm
- * @since 2.0.0
- */
+/// A [Validator] implementation that checks the [NotPerm] constraint.
+///
+/// @see NotPerm
public class NotPermissionValidator implements Validator {
- /**
- * Validates an argument. The argument must be a user or member that doesn't have the specified discord
- * permission.
- *
- * @param argument the argument to validate
- * @param annotation the corresponding annotation
- * @param context the corresponding {@link InvocationContext}
- * @return {@code true} if the argument is a user or member that doesn't have the specified discord
- * permission
- */
+ /// Validates an argument. The argument must be a user or member that **doesn't** have the specified discord
+ /// permission.
+ ///
+ /// @param argument the argument to validate
+ /// @param annotation the corresponding annotation
+ /// @param context the corresponding [InvocationContext]
+ /// @return `true` if the argument is a user or member that **doesn't** have the specified discord
+ /// permission
@Override
public boolean apply(@NotNull Object argument, @NotNull Object annotation, @NotNull InvocationContext> context) {
Set permissions = new HashSet<>();
diff --git a/src/main/java/com/github/kaktushose/jda/commands/dispatching/validation/impl/NotRoleValidator.java b/src/main/java/com/github/kaktushose/jda/commands/dispatching/validation/impl/NotRoleValidator.java
index cc2d53b3d..f9cf159c1 100644
--- a/src/main/java/com/github/kaktushose/jda/commands/dispatching/validation/impl/NotRoleValidator.java
+++ b/src/main/java/com/github/kaktushose/jda/commands/dispatching/validation/impl/NotRoleValidator.java
@@ -10,22 +10,17 @@
import java.util.Optional;
-/**
- * A {@link Validator} implementation that checks the {@link NotRole} constraint.
- *
- * @see NotRole
- * @since 2.0.0
- */
+/// A [Validator] implementation that checks the [NotRole] constraint.
+///
+/// @see NotRole
public class NotRoleValidator implements Validator {
- /**
- * Validates an argument. The argument must be a user or member that doesn't have the specified guild role.
- *
- * @param argument the argument to validate
- * @param annotation the corresponding annotation
- * @param context the corresponding {@link InvocationContext}
- * @return {@code true} if the argument is a user or member that doesn't have the specified guild role
- */
+ /// Validates an argument. The argument must be a user or member that **doesn't**have the specified guild role.
+ ///
+ /// @param argument the argument to validate
+ /// @param annotation the corresponding annotation
+ /// @param context the corresponding [InvocationContext]
+ /// @return `true` if the argument is a user or member that **doesn't** have the specified guild role
@Override
public boolean apply(@NotNull Object argument, @NotNull Object annotation, @NotNull InvocationContext> context) {
NotRole roleAnnotation = (NotRole) annotation;
diff --git a/src/main/java/com/github/kaktushose/jda/commands/dispatching/validation/impl/NotUserValidator.java b/src/main/java/com/github/kaktushose/jda/commands/dispatching/validation/impl/NotUserValidator.java
index b26acaee2..a078f2560 100644
--- a/src/main/java/com/github/kaktushose/jda/commands/dispatching/validation/impl/NotUserValidator.java
+++ b/src/main/java/com/github/kaktushose/jda/commands/dispatching/validation/impl/NotUserValidator.java
@@ -9,22 +9,17 @@
import java.util.Optional;
-/**
- * A {@link Validator} implementation that checks the {@link NotUser} constraint.
- *
- * @see NotUser
- * @since 2.0.0
- */
+/// A [Validator] implementation that checks the [NotUser] constraint.
+///
+/// @see NotUser
public class NotUserValidator implements Validator {
- /**
- * Validates an argument. The argument must not be the specified user or member.
- *
- * @param argument the argument to validate
- * @param annotation the corresponding annotation
- * @param context the corresponding {@link InvocationContext}
- * @return {@code true} if the argument isn't the specified user or member
- */
+ /// Validates an argument. The argument must **not** be the specified user or member.
+ ///
+ /// @param argument the argument to validate
+ /// @param annotation the corresponding annotation
+ /// @param context the corresponding [InvocationContext]
+ /// @return `true` if the argument **isn't** the specified user or member
@Override
public boolean apply(@NotNull Object argument, @NotNull Object annotation, @NotNull InvocationContext> context) {
Member member = (Member) argument;
diff --git a/src/main/java/com/github/kaktushose/jda/commands/dispatching/validation/impl/PermissionValidator.java b/src/main/java/com/github/kaktushose/jda/commands/dispatching/validation/impl/PermissionValidator.java
index 906d1b0c6..cc61c1d25 100644
--- a/src/main/java/com/github/kaktushose/jda/commands/dispatching/validation/impl/PermissionValidator.java
+++ b/src/main/java/com/github/kaktushose/jda/commands/dispatching/validation/impl/PermissionValidator.java
@@ -10,24 +10,18 @@
import java.util.HashSet;
import java.util.Set;
-/**
- * A {@link Validator} implementation that checks the {@link Perm} constraint.
- *
- * @see Perm
- * @since 2.0.0
- */
+/// A [Validator] implementation that checks the [Perm] constraint.
+///
+/// @see Perm
public class PermissionValidator implements Validator {
- /**
- * Validates an argument. The argument must be a user or member that has the specified discord
- * permission.
- *
- * @param argument the argument to validate
- * @param annotation the corresponding annotation
- * @param context the corresponding {@link InvocationContext}
- * @return {@code true} if the argument is a user or member that has the specified discord
- * permission
- */
+ /// Validates an argument. The argument must be a user or member that has the specified discord permission.
+ ///
+ /// @param argument the argument to validate
+ /// @param annotation the corresponding annotation
+ /// @param context the corresponding [InvocationContext]
+ /// @return `true` if the argument is a user or member that has the specified discord
+ /// permission
@Override
public boolean apply(@NotNull Object argument, @NotNull Object annotation, @NotNull InvocationContext> context) {
Set permissions = new HashSet<>();
diff --git a/src/main/java/com/github/kaktushose/jda/commands/dispatching/validation/impl/RoleValidator.java b/src/main/java/com/github/kaktushose/jda/commands/dispatching/validation/impl/RoleValidator.java
index d18c74cc8..c3f16642c 100644
--- a/src/main/java/com/github/kaktushose/jda/commands/dispatching/validation/impl/RoleValidator.java
+++ b/src/main/java/com/github/kaktushose/jda/commands/dispatching/validation/impl/RoleValidator.java
@@ -9,23 +9,18 @@
import java.util.Optional;
-/**
- * A {@link Validator} implementation that checks the
- * {@link com.github.kaktushose.jda.commands.annotations.constraints.Role Role} constraint.
- *
- * @see com.github.kaktushose.jda.commands.annotations.constraints.Role Role
- * @since 2.0.0
- */
+/// A [Validator] implementation that checks the
+/// [Role][com.github.kaktushose.jda.commands.annotations.constraints.Role] constraint.
+///
+/// @see com.github.kaktushose.jda.commands.annotations.constraints.Role Role
public class RoleValidator implements Validator {
- /**
- * Validates an argument. The argument must be a user or member that has the specified guild role.
- *
- * @param argument the argument to validate
- * @param annotation the corresponding annotation
- * @param context the corresponding {@link InvocationContext}
- * @return {@code true} if the argument is a user or member that has the specified guild role
- */
+ /// Validates an argument. The argument must be a user or member that has the specified guild role.
+ ///
+ /// @param argument the argument to validate
+ /// @param annotation the corresponding annotation
+ /// @param context the corresponding [InvocationContext]
+ /// @return `true` if the argument is a user or member that has the specified guild role
@Override
public boolean apply(@NotNull Object argument, @NotNull Object annotation, @NotNull InvocationContext> context) {
com.github.kaktushose.jda.commands.annotations.constraints.Role roleAnnotation =
diff --git a/src/main/java/com/github/kaktushose/jda/commands/dispatching/validation/impl/UserValidator.java b/src/main/java/com/github/kaktushose/jda/commands/dispatching/validation/impl/UserValidator.java
index 7976bc50a..1f898954c 100644
--- a/src/main/java/com/github/kaktushose/jda/commands/dispatching/validation/impl/UserValidator.java
+++ b/src/main/java/com/github/kaktushose/jda/commands/dispatching/validation/impl/UserValidator.java
@@ -9,22 +9,17 @@
import java.util.Optional;
-/**
- * A {@link Validator} implementation that checks the {@link User} constraint.
- *
- * @see User
- * @since 2.0.0
- */
+/// A [Validator] implementation that checks the [User] constraint.
+///
+/// @see User
public class UserValidator implements Validator {
- /**
- * Validates an argument. The argument must be the specified user or member.
- *
- * @param argument the argument to validate
- * @param annotation the corresponding annotation
- * @param context the corresponding {@link InvocationContext}
- * @return {@code true} if the argument is the specified user or member
- */
+ /// Validates an argument. The argument must be the specified user or member.
+ ///
+ /// @param argument the argument to validate
+ /// @param annotation the corresponding annotation
+ /// @param context the corresponding [InvocationContext]
+ /// @return `true` if the argument is the specified user or member
@Override
public boolean apply(@NotNull Object argument, @NotNull Object annotation, @NotNull InvocationContext> context) {
Member member = (Member) argument;
diff --git a/src/main/java/com/github/kaktushose/jda/commands/dispatching/validation/impl/package-info.java b/src/main/java/com/github/kaktushose/jda/commands/dispatching/validation/impl/package-info.java
index 5205ad272..bc27eb106 100644
--- a/src/main/java/com/github/kaktushose/jda/commands/dispatching/validation/impl/package-info.java
+++ b/src/main/java/com/github/kaktushose/jda/commands/dispatching/validation/impl/package-info.java
@@ -1,4 +1,2 @@
-/**
- * Implementations of frequently used validators.
- */
+/// Implementations of frequently used validators.
package com.github.kaktushose.jda.commands.dispatching.validation.impl;
diff --git a/src/main/java/com/github/kaktushose/jda/commands/dispatching/validation/package-info.java b/src/main/java/com/github/kaktushose/jda/commands/dispatching/validation/package-info.java
index 07be39833..db2b8eec4 100644
--- a/src/main/java/com/github/kaktushose/jda/commands/dispatching/validation/package-info.java
+++ b/src/main/java/com/github/kaktushose/jda/commands/dispatching/validation/package-info.java
@@ -1,4 +1,2 @@
-/**
- * Command parameter validation system.
- */
+/// Command parameter validation system.
package com.github.kaktushose.jda.commands.dispatching.validation;
diff --git a/src/main/java/com/github/kaktushose/jda/commands/embeds/EmbedCache.java b/src/main/java/com/github/kaktushose/jda/commands/embeds/EmbedCache.java
index bdccce0be..4543453f6 100644
--- a/src/main/java/com/github/kaktushose/jda/commands/embeds/EmbedCache.java
+++ b/src/main/java/com/github/kaktushose/jda/commands/embeds/EmbedCache.java
@@ -15,12 +15,9 @@
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
-/**
- * This class loads and caches embeds from a json file.
- *
- * @see EmbedDTO
- * @since 1.1.0
- */
+/// This class loads and caches embeds from a json file.
+///
+/// @see EmbedDTO
public class EmbedCache {
private static final Logger log = LoggerFactory.getLogger(EmbedCache.class);
@@ -29,11 +26,9 @@ public class EmbedCache {
private final InputStream stream;
private final Map embedMap;
- /**
- * Constructs a new EmbedCache object.
- *
- * @param file the file to load the embeds from
- */
+ /// Constructs a new EmbedCache object.
+ ///
+ /// @param file the file to load the embeds from
public EmbedCache(File file) {
embedMap = new ConcurrentHashMap<>();
this.file = file;
@@ -41,11 +36,9 @@ public EmbedCache(File file) {
loadEmbeds();
}
- /**
- * Constructs a new EmbedCache object.
- *
- * @param stream the stream to load the embeds from
- */
+ /// Constructs a new EmbedCache object.
+ ///
+ /// @param stream the stream to load the embeds from
public EmbedCache(InputStream stream) {
embedMap = new ConcurrentHashMap<>();
this.stream = stream;
@@ -53,11 +46,9 @@ public EmbedCache(InputStream stream) {
loadEmbeds();
}
- /**
- * Constructs a new EmbedCache object.
- *
- * @param file the path to the file to load the embeds from
- */
+ /// Constructs a new EmbedCache object.
+ ///
+ /// @param file the path to the file to load the embeds from
public EmbedCache(String file) {
embedMap = new ConcurrentHashMap<>();
this.file = new File(file);
@@ -65,20 +56,8 @@ public EmbedCache(String file) {
loadEmbeds();
}
- /**
- * Loads all embeds from a file and caches them.
- *
- * @deprecated This now happens automatically. Use {@link #loadEmbeds()} if you want to reload the cache
- */
- @Deprecated
- public void loadEmbedsToCache() {
- loadEmbeds();
- }
-
- /**
- * Loads all embeds from a file and stores them. This happens automatically each time you construct a new
- * EmbedCache. Thus, it's not needed to call this method manually, unless you want to reload the embeds.
- */
+ /// Loads all embeds from a file and stores them. This happens automatically each time you construct a new
+ /// EmbedCache. Thus, it's **not** needed to call this method manually, unless you want to reload the embeds.
public void loadEmbeds() {
try {
Reader reader;
@@ -100,49 +79,39 @@ public void loadEmbeds() {
}
}
- /**
- * Gets an embed from the cache.
- *
- * @param name the name the {@link EmbedDTO} is mapped to
- * @return the {@link EmbedDTO} or {@code null} if the cache contains no mapping for the key
- */
+ /// Gets an embed from the cache.
+ ///
+ /// @param name the name the [EmbedDTO] is mapped to
+ /// @return the [EmbedDTO] or `null` if the cache contains no mapping for the key
public EmbedDTO getEmbed(@Nonnull String name) {
return new EmbedDTO(embedMap.get(name));
}
- /**
- * Returns {@code true} if this cache contains no {@link EmbedDTO}s.
- *
- * @return {@code true} if this cache contains no {@link EmbedDTO}s.
- */
+ /// Returns `true` if this cache contains no [EmbedDTO]s.
+ ///
+ /// @return `true` if this cache contains no [EmbedDTO]s.
public boolean isEmpty() {
return embedMap.isEmpty();
}
- /**
- * Returns the number of {@link EmbedDTO}s in this cache.
- *
- * @return the number of {@link EmbedDTO}s in this cache.
- */
+ /// Returns the number of [EmbedDTO]s in this cache.
+ ///
+ /// @return the number of [EmbedDTO]s in this cache.
public int size() {
return embedMap.size();
}
- /**
- * Returns {@code true} if this cache contains a mapping for the specified name.
- *
- * @param name the name the {@link EmbedDTO} is mapped to
- * @return {@code true} if this cache contains a mapping for the specified name.
- */
+ /// Returns `true` if this cache contains a mapping for the specified name.
+ ///
+ /// @param name the name the [EmbedDTO] is mapped to
+ /// @return `true` if this cache contains a mapping for the specified name.
public boolean containsEmbed(@Nonnull String name) {
return embedMap.containsKey(name);
}
- /**
- * Returns an unmodifiable List containing all {@link EmbedDTO} of this cache.
- *
- * @return an unmodifiable List containing all {@link EmbedDTO} of this cache.
- */
+ /// Returns an unmodifiable List containing all [EmbedDTO] of this cache.
+ ///
+ /// @return an unmodifiable List containing all [EmbedDTO] of this cache.
public List values() {
return List.copyOf(embedMap.values());
}
diff --git a/src/main/java/com/github/kaktushose/jda/commands/embeds/EmbedDTO.java b/src/main/java/com/github/kaktushose/jda/commands/embeds/EmbedDTO.java
index a48aad66b..bf985df9e 100644
--- a/src/main/java/com/github/kaktushose/jda/commands/embeds/EmbedDTO.java
+++ b/src/main/java/com/github/kaktushose/jda/commands/embeds/EmbedDTO.java
@@ -24,7 +24,6 @@
*
* @see Discord Embed Documentation
* @see EmbedCache
- * @since 1.1.0
*/
public class EmbedDTO implements Serializable {
diff --git a/src/main/java/com/github/kaktushose/jda/commands/embeds/error/DefaultErrorMessageFactory.java b/src/main/java/com/github/kaktushose/jda/commands/embeds/error/DefaultErrorMessageFactory.java
index 39033ac18..961c4e908 100644
--- a/src/main/java/com/github/kaktushose/jda/commands/embeds/error/DefaultErrorMessageFactory.java
+++ b/src/main/java/com/github/kaktushose/jda/commands/embeds/error/DefaultErrorMessageFactory.java
@@ -1,9 +1,9 @@
package com.github.kaktushose.jda.commands.embeds.error;
+import com.github.kaktushose.jda.commands.definitions.interactions.InteractionDefinition;
+import com.github.kaktushose.jda.commands.definitions.interactions.command.ParameterDefinition;
+import com.github.kaktushose.jda.commands.definitions.interactions.command.SlashCommandDefinition;
import com.github.kaktushose.jda.commands.dispatching.events.interactions.CommandEvent;
-import com.github.kaktushose.jda.commands.reflect.ConstraintDefinition;
-import com.github.kaktushose.jda.commands.reflect.interactions.GenericInteractionDefinition;
-import com.github.kaktushose.jda.commands.reflect.interactions.commands.SlashCommandDefinition;
import net.dv8tion.jda.api.EmbedBuilder;
import net.dv8tion.jda.api.entities.MessageEmbed;
import net.dv8tion.jda.api.events.interaction.GenericInteractionCreateEvent;
@@ -16,23 +16,20 @@
import java.util.List;
import java.util.concurrent.TimeUnit;
-/**
- * Implementation of {@link ErrorMessageFactory} with default embeds.
- *
- * @see JsonErrorMessageFactory
- * @since 2.0.0
- */
+/// Implementation of [ErrorMessageFactory] with default embeds.
+///
+/// @see JsonErrorMessageFactory
public class DefaultErrorMessageFactory implements ErrorMessageFactory {
@NotNull
@Override
public MessageCreateData getTypeAdaptingFailedMessage(@NotNull GenericInteractionCreateEvent event,
- @NotNull GenericInteractionDefinition definition,
+ @NotNull InteractionDefinition definition,
@NotNull List userInput) {
StringBuilder sbExpected = new StringBuilder();
SlashCommandDefinition command = (SlashCommandDefinition) definition;
- command.getParameters().forEach(parameter -> {
+ command.commandParameters().forEach(parameter -> {
if (CommandEvent.class.isAssignableFrom(parameter.type())) {
return;
}
@@ -51,7 +48,7 @@ public MessageCreateData getTypeAdaptingFailedMessage(@NotNull GenericInteractio
MessageEmbed embed = new EmbedBuilder()
.setColor(Color.ORANGE)
.setTitle("Syntax Error")
- .setDescription(command.getDisplayName())
+ .setDescription(command.displayName())
.addField("Expected", String.format("`%s`", expected), false)
.addField("Actual", String.format("`%s`", actual), false)
.build();
@@ -61,15 +58,15 @@ public MessageCreateData getTypeAdaptingFailedMessage(@NotNull GenericInteractio
@NotNull
@Override
- public MessageCreateData getInsufficientPermissionsMessage(@NotNull GenericInteractionDefinition interaction) {
+ public MessageCreateData getInsufficientPermissionsMessage(@NotNull InteractionDefinition interaction) {
StringBuilder sbPermissions = new StringBuilder();
- interaction.getPermissions().forEach(permission -> sbPermissions.append(permission).append(", "));
+ interaction.permissions().forEach(permission -> sbPermissions.append(permission).append(", "));
String permissions = sbPermissions.toString().isEmpty() ? "N/A" : sbPermissions.substring(0, sbPermissions.length() - 2);
MessageEmbed embed = new EmbedBuilder()
.setColor(Color.RED)
.setTitle("Insufficient Permissions")
.setDescription(String.format("`%s` requires specific permissions to be executed",
- interaction.getDisplayName()))
+ interaction.displayName()))
.addField("Permissions:",
String.format("`%s`", permissions), false
).build();
@@ -78,7 +75,7 @@ public MessageCreateData getInsufficientPermissionsMessage(@NotNull GenericInter
@NotNull
@Override
- public MessageCreateData getConstraintFailedMessage(@NotNull ConstraintDefinition constraint) {
+ public MessageCreateData getConstraintFailedMessage(@NotNull ParameterDefinition.ConstraintDefinition constraint) {
return new MessageCreateBuilder().setEmbeds(new EmbedBuilder()
.setColor(Color.ORANGE)
.setTitle("Parameter Error")
diff --git a/src/main/java/com/github/kaktushose/jda/commands/embeds/error/ErrorMessageFactory.java b/src/main/java/com/github/kaktushose/jda/commands/embeds/error/ErrorMessageFactory.java
index d765ffc59..763224044 100644
--- a/src/main/java/com/github/kaktushose/jda/commands/embeds/error/ErrorMessageFactory.java
+++ b/src/main/java/com/github/kaktushose/jda/commands/embeds/error/ErrorMessageFactory.java
@@ -1,8 +1,8 @@
package com.github.kaktushose.jda.commands.embeds.error;
import com.github.kaktushose.jda.commands.annotations.Implementation;
-import com.github.kaktushose.jda.commands.reflect.ConstraintDefinition;
-import com.github.kaktushose.jda.commands.reflect.interactions.GenericInteractionDefinition;
+import com.github.kaktushose.jda.commands.definitions.interactions.InteractionDefinition;
+import com.github.kaktushose.jda.commands.definitions.interactions.command.ParameterDefinition.ConstraintDefinition;
import net.dv8tion.jda.api.entities.Message;
import net.dv8tion.jda.api.events.interaction.GenericInteractionCreateEvent;
import net.dv8tion.jda.api.utils.messages.MessageCreateData;
@@ -14,26 +14,25 @@
///
/// @see Implementation
/// @see DefaultErrorMessageFactory
-/// @since 2.0.0
public interface ErrorMessageFactory {
/// Gets a [MessageCreateData] to send when type adapting of the user input failed.
///
- /// @param event the [GenericInteractionCreateEvent] that was attempted to type adapt
- /// @param definition the underlying [GenericInteractionDefinition]
- /// @param userInput the input the user provided
+ /// @param event the [GenericInteractionCreateEvent] that was attempted to type adapt
+ /// @param definition the underlying [InteractionDefinition]
+ /// @param userInput the input the user provided
/// @return a [MessageCreateData] to send when type adapting failed
@NotNull
MessageCreateData getTypeAdaptingFailedMessage(@NotNull GenericInteractionCreateEvent event,
- @NotNull GenericInteractionDefinition definition,
+ @NotNull InteractionDefinition definition,
@NotNull List userInput);
/// Gets a [MessageCreateData] to send when a user is missing permissions.
///
- /// @param definition the corresponding [GenericInteractionDefinition]
+ /// @param definition the corresponding [InteractionDefinition]
/// @return a [MessageCreateData] to send when a user is missing permissions
@NotNull
- MessageCreateData getInsufficientPermissionsMessage(@NotNull GenericInteractionDefinition definition);
+ MessageCreateData getInsufficientPermissionsMessage(@NotNull InteractionDefinition definition);
/// Gets a [MessageCreateData] to send when a parameter constraint fails.
///
diff --git a/src/main/java/com/github/kaktushose/jda/commands/embeds/error/JsonErrorMessageFactory.java b/src/main/java/com/github/kaktushose/jda/commands/embeds/error/JsonErrorMessageFactory.java
index fb0550194..eac74993f 100644
--- a/src/main/java/com/github/kaktushose/jda/commands/embeds/error/JsonErrorMessageFactory.java
+++ b/src/main/java/com/github/kaktushose/jda/commands/embeds/error/JsonErrorMessageFactory.java
@@ -1,10 +1,10 @@
package com.github.kaktushose.jda.commands.embeds.error;
+import com.github.kaktushose.jda.commands.definitions.interactions.InteractionDefinition;
+import com.github.kaktushose.jda.commands.definitions.interactions.command.ParameterDefinition;
+import com.github.kaktushose.jda.commands.definitions.interactions.command.SlashCommandDefinition;
import com.github.kaktushose.jda.commands.dispatching.events.interactions.CommandEvent;
import com.github.kaktushose.jda.commands.embeds.EmbedCache;
-import com.github.kaktushose.jda.commands.reflect.ConstraintDefinition;
-import com.github.kaktushose.jda.commands.reflect.interactions.GenericInteractionDefinition;
-import com.github.kaktushose.jda.commands.reflect.interactions.commands.SlashCommandDefinition;
import net.dv8tion.jda.api.events.interaction.GenericInteractionCreateEvent;
import net.dv8tion.jda.api.utils.messages.MessageCreateData;
import org.jetbrains.annotations.NotNull;
@@ -13,13 +13,10 @@
import java.util.List;
import java.util.concurrent.TimeUnit;
-/**
- * Subtype of {@link DefaultErrorMessageFactory} that can load the embeds from an {@link EmbedCache}.
- *
- * @see DefaultErrorMessageFactory
- * @see EmbedCache
- * @since 2.0.0
- */
+/// Subtype of [DefaultErrorMessageFactory] that can load the embeds from an [EmbedCache].
+///
+/// @see DefaultErrorMessageFactory
+/// @see EmbedCache
public class JsonErrorMessageFactory extends DefaultErrorMessageFactory {
private final EmbedCache embedCache;
@@ -31,7 +28,7 @@ public JsonErrorMessageFactory(EmbedCache embedCache) {
@NotNull
@Override
public MessageCreateData getTypeAdaptingFailedMessage(@NotNull GenericInteractionCreateEvent event,
- @NotNull GenericInteractionDefinition definition,
+ @NotNull InteractionDefinition definition,
@NotNull List userInput) {
if (!embedCache.containsEmbed("typeAdaptingFailed")) {
return super.getTypeAdaptingFailedMessage(event, definition, userInput);
@@ -40,7 +37,7 @@ public MessageCreateData getTypeAdaptingFailedMessage(@NotNull GenericInteractio
StringBuilder sbExpected = new StringBuilder();
SlashCommandDefinition command = (SlashCommandDefinition) definition;
- command.getParameters().forEach(parameter -> {
+ command.commandParameters().forEach(parameter -> {
if (CommandEvent.class.isAssignableFrom(parameter.type())) {
return;
}
@@ -57,7 +54,7 @@ public MessageCreateData getTypeAdaptingFailedMessage(@NotNull GenericInteractio
String actual = sbActual.toString().isEmpty() ? " " : sbActual.substring(0, sbActual.length() - 2);
return embedCache.getEmbed("typeAdaptingFailed")
- .injectValue("usage", command.getDisplayName())
+ .injectValue("usage", command.displayName())
.injectValue("expected", expected)
.injectValue("actual", actual)
.toMessageCreateData();
@@ -65,24 +62,24 @@ public MessageCreateData getTypeAdaptingFailedMessage(@NotNull GenericInteractio
@NotNull
@Override
- public MessageCreateData getInsufficientPermissionsMessage(@NotNull GenericInteractionDefinition interaction) {
+ public MessageCreateData getInsufficientPermissionsMessage(@NotNull InteractionDefinition interaction) {
if (!embedCache.containsEmbed("insufficientPermissions")) {
return super.getInsufficientPermissionsMessage(interaction);
}
StringBuilder sbPermissions = new StringBuilder();
- interaction.getPermissions().forEach(permission -> sbPermissions.append(permission).append(", "));
+ interaction.permissions().forEach(permission -> sbPermissions.append(permission).append(", "));
String permissions = sbPermissions.toString().isEmpty() ? "N/A" : sbPermissions.substring(0, sbPermissions.length() - 2);
return embedCache.getEmbed("insufficientPermissions")
- .injectValue("name", interaction.getDisplayName())
+ .injectValue("name", interaction.displayName())
.injectValue("permissions", permissions)
.toMessageCreateData();
}
@NotNull
@Override
- public MessageCreateData getConstraintFailedMessage(@NotNull ConstraintDefinition constraint) {
+ public MessageCreateData getConstraintFailedMessage(@NotNull ParameterDefinition.ConstraintDefinition constraint) {
if (!embedCache.containsEmbed("constraintFailed")) {
return super.getConstraintFailedMessage(constraint);
}
diff --git a/src/main/java/com/github/kaktushose/jda/commands/embeds/error/package-info.java b/src/main/java/com/github/kaktushose/jda/commands/embeds/error/package-info.java
index f073afe16..df2ef3714 100644
--- a/src/main/java/com/github/kaktushose/jda/commands/embeds/error/package-info.java
+++ b/src/main/java/com/github/kaktushose/jda/commands/embeds/error/package-info.java
@@ -1,4 +1,2 @@
-/**
- * Factory classes for generating error embeds.
- */
+/// Factory classes for generating error embeds.
package com.github.kaktushose.jda.commands.embeds.error;
diff --git a/src/main/java/com/github/kaktushose/jda/commands/internal/Helpers.java b/src/main/java/com/github/kaktushose/jda/commands/internal/Helpers.java
index 9145cc7c2..d5f1135a1 100644
--- a/src/main/java/com/github/kaktushose/jda/commands/internal/Helpers.java
+++ b/src/main/java/com/github/kaktushose/jda/commands/internal/Helpers.java
@@ -2,7 +2,11 @@
import com.github.kaktushose.jda.commands.annotations.interactions.Permissions;
import com.github.kaktushose.jda.commands.annotations.interactions.ReplyConfig;
-import com.github.kaktushose.jda.commands.reflect.MethodBuildContext;
+import com.github.kaktushose.jda.commands.definitions.description.MethodDescription;
+import com.github.kaktushose.jda.commands.definitions.description.ParameterDescription;
+import com.github.kaktushose.jda.commands.definitions.interactions.InteractionDefinition;
+import com.github.kaktushose.jda.commands.definitions.interactions.MethodBuildContext;
+import com.github.kaktushose.jda.commands.dispatching.reply.GlobalReplyConfig;
import net.dv8tion.jda.api.entities.Guild;
import net.dv8tion.jda.api.entities.channel.middleman.GuildChannel;
import net.dv8tion.jda.api.events.interaction.GenericInteractionCreateEvent;
@@ -12,14 +16,11 @@
import org.slf4j.LoggerFactory;
import java.lang.reflect.Method;
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.Optional;
-import java.util.Set;
+import java.util.*;
+
+import static com.github.kaktushose.jda.commands.definitions.interactions.command.ParameterDefinition.TYPE_MAPPINGS;
/// Collection of helper methods that are used inside the framework.
-///
-/// @since 4.0.0
@ApiStatus.Internal
public final class Helpers {
@@ -69,36 +70,33 @@ public static Optional resolveGuildChannel(@NotNull String raw, @N
/// @return a possibly-empty set of all permissions
@NotNull
public static Set permissions(@NotNull MethodBuildContext context) {
- Permissions permission = context.method().getAnnotation(Permissions.class);
+ var permission = context.method().annotation(Permissions.class);
- if (permission != null) {
+ if (permission.isPresent()) {
HashSet mergedPermissions = new HashSet<>(context.permissions());
- mergedPermissions.addAll(Set.of(permission.value()));
+ mergedPermissions.addAll(Set.of(permission.get().value()));
return Collections.unmodifiableSet(mergedPermissions);
}
return context.permissions();
}
- /// Constructs the [com.github.kaktushose.jda.commands.reflect.interactions.ReplyConfig ReplyConfig] based on the
- /// passed [Method].
- ///
- /// This will first attempt to use the [ReplyConfig] annotation of the method and then of the class. If neither is
- /// present will fall back to the
- /// [com.github.kaktushose.jda.commands.dispatching.reply.GlobalReplyConfig GlobalReplyConfig].
+ /// Constructs the [InteractionDefinition.ReplyConfig ReplyConfig] based on the passed [Method].
///
/// @param method the [Method] to use
- /// @return the [com.github.kaktushose.jda.commands.reflect.interactions.ReplyConfig ReplyConfig]
+ /// @return the [InteractionDefinition.ReplyConfig ReplyConfig]
+ /// @implNote This will first attempt to use the [ReplyConfig] annotation of the method and then of the class.
+ /// If neither is present will fall back to the [GlobalReplyConfig].
@NotNull
- public static com.github.kaktushose.jda.commands.reflect.interactions.ReplyConfig replyConfig(@NotNull Method method) {
+ public static InteractionDefinition.ReplyConfig replyConfig(@NotNull Method method) {
var global = method.getDeclaringClass().getAnnotation(ReplyConfig.class);
var local = method.getAnnotation(ReplyConfig.class);
if (global == null && local == null)
- return new com.github.kaktushose.jda.commands.reflect.interactions.ReplyConfig();
+ return new InteractionDefinition.ReplyConfig();
if (local == null)
- return new com.github.kaktushose.jda.commands.reflect.interactions.ReplyConfig(global);
+ return new InteractionDefinition.ReplyConfig(global);
- return new com.github.kaktushose.jda.commands.reflect.interactions.ReplyConfig(local);
+ return new InteractionDefinition.ReplyConfig(local);
}
/// Checks if the given parameter is present at the [Method] at the given index.
@@ -107,30 +105,28 @@ public static com.github.kaktushose.jda.commands.reflect.interactions.ReplyConfi
/// @param index the index the parameter is expected to be at
/// @param type the type of the parameter
/// @return `true` if the parameter is present
- public static boolean isIncorrectParameterType(@NotNull Method method, int index, @NotNull Class> type) {
- if (!type.isAssignableFrom(method.getParameters()[index].getType())) {
+ public static boolean isIncorrectParameterType(@NotNull MethodDescription method, int index, @NotNull Class> type) {
+ if (!type.isAssignableFrom(List.copyOf(method.parameters()).get(index).type())) {
log.error("An error has occurred! Skipping Interaction {}.{}:",
- method.getDeclaringClass().getSimpleName(),
- method.getName(),
+ method.declaringClass().getName(),
+ method.name(),
new IllegalArgumentException(String.format("%d. parameter must be of type %s", index + 1, type.getSimpleName())));
return true;
}
return false;
}
- /// Checks if a [Method] has the given parameter count.
- ///
- /// @param count the parameter count
- /// @return `true` if the method has the given parameter count
- public static boolean isIncorrectParameterAmount(@NotNull Method method, int count) {
- if (method.getParameters().length != count) {
+ public static boolean checkSignature(MethodDescription method, Collection> methodSignature) {
+ var parameters = method.parameters().stream()
+ .map(ParameterDescription::type)
+ .map(it -> TYPE_MAPPINGS.getOrDefault(it, it)).toList();
+ if (!parameters.equals(methodSignature)) {
log.error("An error has occurred! Skipping Interaction {}.{}:",
- method.getDeclaringClass().getSimpleName(),
- method.getName(),
- new IllegalArgumentException(String.format(
- "Invalid amount of parameters!. Expected: %d Actual: %d",
- count,
- method.getParameters().length
+ method.declaringClass().getName(),
+ method.name(),
+ new IllegalArgumentException("Incorrect method signature!\nExpected: %s\nActual: %s".formatted(
+ methodSignature.stream().toList(),
+ method.parameters().stream().map(ParameterDescription::type).toList()
)));
return true;
}
diff --git a/src/main/java/com/github/kaktushose/jda/commands/internal/JDAContext.java b/src/main/java/com/github/kaktushose/jda/commands/internal/JDAContext.java
index 145a57e7e..1faf5447f 100644
--- a/src/main/java/com/github/kaktushose/jda/commands/internal/JDAContext.java
+++ b/src/main/java/com/github/kaktushose/jda/commands/internal/JDAContext.java
@@ -6,34 +6,24 @@
import net.dv8tion.jda.api.utils.cache.SnowflakeCacheView;
import org.jetbrains.annotations.ApiStatus;
-import java.util.List;
import java.util.function.Consumer;
-/**
- * Wrapper class for {@link JDA} and {@link ShardManager}. Use {@link #performTask(Consumer)} when you need to do
- * work with an {@link JDA} object.
- *
- * @since 2.3.0
- */
+/// Wrapper class for [JDA] and [ShardManager]. Use [#performTask(Consumer)] when you need to do work with an [JDA] object.
@ApiStatus.Internal
public final class JDAContext {
private final Object context;
- /**
- * Constructs a new JDAContext.
- *
- * @param context the {@link JDA} or {@link ShardManager} object
- */
+ /// Constructs a new JDAContext.
+ ///
+ /// @param context the [JDA] or [ShardManager] object
public JDAContext(Object context) {
this.context = context;
}
- /**
- * Performs an operation on either the {@link JDA} object or on all shards.
- *
- * @param consumer the operation to perform
- */
+ /// Performs an operation on either the [JDA] object or on all shards.
+ ///
+ /// @param consumer the operation to perform
public void performTask(Consumer consumer) {
switch (context) {
case ShardManager shardManager -> shardManager.getShardCache().forEach(consumer);
@@ -43,29 +33,9 @@ public void performTask(Consumer consumer) {
}
}
- /**
- * An unmodifiable List of all {@link Guild Guilds} that the logged account is connected to.
- * If this account is not connected to any {@link Guild Guilds}, this will return an empty list.
- * This copies the backing store into a list. This means every call creates a new list with O(n) complexity.
- * It is recommended to store this into a local variable or use getGuildCache() and use its more efficient
- * versions of handling these values.
- *
- * @return Possibly-empty list of all the {@link Guild Guilds} that this account is connected to.
- */
- public List getGuilds() {
- return switch (context) {
- case ShardManager shardManager -> shardManager.getGuilds();
- case JDA jda -> jda.getGuilds();
- default ->
- throw new IllegalArgumentException(String.format("Cannot cast %s", context.getClass().getSimpleName()));
- };
- }
-
- /**
- * {@link SnowflakeCacheView} of all cached {@link Guild Guilds}.
- *
- * @return {@link SnowflakeCacheView}
- */
+ /// [SnowflakeCacheView] of all cached [Guild]s.
+ ///
+ /// @return [SnowflakeCacheView]
public SnowflakeCacheView getGuildCache() {
return switch (context) {
case ShardManager shardManager -> shardManager.getGuildCache();
diff --git a/src/main/java/com/github/kaktushose/jda/commands/internal/register/CommandTree.java b/src/main/java/com/github/kaktushose/jda/commands/internal/register/CommandTree.java
index cd492d494..b65b20be8 100644
--- a/src/main/java/com/github/kaktushose/jda/commands/internal/register/CommandTree.java
+++ b/src/main/java/com/github/kaktushose/jda/commands/internal/register/CommandTree.java
@@ -1,57 +1,46 @@
package com.github.kaktushose.jda.commands.internal.register;
-import com.github.kaktushose.jda.commands.reflect.interactions.commands.SlashCommandDefinition;
+import com.github.kaktushose.jda.commands.definitions.interactions.command.SlashCommandDefinition;
import net.dv8tion.jda.api.interactions.commands.build.SlashCommandData;
import org.jetbrains.annotations.ApiStatus;
import java.util.Collection;
import java.util.List;
-/**
- * A tree data structure representing slash commands sorted into Subcommands and SubcommandGroups. Each {@link TreeNode}
- * can have n children, however the maximum level is 3 due to Discords limitations on SubcommandGroups.
- *
- * @see TreeNode
- * @see Discord Subcommands and Subcommand Groups Documentation
- * @since 2.3.0
- */
+/// A tree data structure representing slash commands sorted into Subcommands and SubcommandGroups. Each [TreeNode]
+/// can have _n_ children, however the maximum level is _3_ due to Discords limitations on SubcommandGroups.
+///
+/// @see TreeNode
+/// @see Discord Subcommands and Subcommand Groups Documentation
@ApiStatus.Internal
public record CommandTree(
TreeNode root
) {
- /**
- * Constructs an empty CommandTree.
- */
+ /// Constructs an empty CommandTree.
public CommandTree() {
this(new TreeNode());
}
- /**
- * Constructs a new CommandTree.
- */
+ /// Constructs a new CommandTree.
public CommandTree(Collection commands) {
this(new TreeNode());
addAll(commands);
}
- /**
- * Adds a {@link SlashCommandDefinition} to the {@link CommandTree}. The label of the {@link SlashCommandDefinition} will be
- * sanitized to match the regex {@code ^[\w-]+$}. Furthermore, if the label consists of more than three spaces any
- * additional space will be replaced with {@code _} due to Discords limitations on SubcommandGroups.
- *
- * @param command the {@link SlashCommandDefinition} to add
- */
+ /// Adds a [SlashCommandDefinition] to the [CommandTree]. The label of the [SlashCommandDefinition] will be
+ /// sanitized to match the regex `^[\w-]+$`. Furthermore, if the label consists of more than three spaces any
+ /// additional space will be replaced with `_` due to Discords limitations on SubcommandGroups.
+ ///
+ /// @param command the [SlashCommandDefinition] to add
public void add(SlashCommandDefinition command) {
- root.addChild(resolveLabel(command.getName()), command);
+ root.addChild(resolveLabel(command.name()), command);
}
- /**
- * Adds all {@link SlashCommandDefinition CommandDefinitions} of the {@link Collection} to the {@link CommandTree}.
- *
- * @param commands a {@link Collection} of {@link SlashCommandDefinition CommandDefinitions} to add
- * @see #add(SlashCommandDefinition)
- */
+ /// Adds all [SlashCommandDefinition]s of the [Collection] to the [CommandTree].
+ ///
+ /// @param commands a [Collection] of [SlashCommandDefinition]s to add
+ /// @see #add(SlashCommandDefinition)
public void addAll(Collection commands) {
commands.forEach(this::add);
}
@@ -75,22 +64,18 @@ private String[] resolveLabel(String label) {
return split;
}
- /**
- * Gets all {@link SlashCommandData}.This will only return the {@link SlashCommandData} of the leaf nodes.
- *
- * @return a {@link List} of {@link SlashCommandData}
- */
+ /// Gets all [SlashCommandData].This will only return the [SlashCommandData] of the leaf nodes.
+ ///
+ /// @return a [List] of [SlashCommandData]
public List getCommands() {
return root.getCommandData();
}
- /**
- * Gets the sanitized labels of all {@link SlashCommandData} returned by {@link #getCommands()}.
- * The labels will match the regex {@code ^[\w-]+$}. Furthermore, if the label consists of more than three spaces
- * any additional space will be replaced with {@code _} due to Discords limitations on SubcommandGroups.
- *
- * @return a {@link List} of labels
- */
+ /// Gets the sanitized labels of all [SlashCommandData] returned by [#getCommands()].
+ /// The labels will match the regex `^[\w-]+$`. Furthermore, if the label consists of more than three spaces
+ /// any additional space will be replaced with `_` due to Discords limitations on SubcommandGroups.
+ ///
+ /// @return a [List] of labels
public List getNames() {
return root.getNames();
}
diff --git a/src/main/java/com/github/kaktushose/jda/commands/internal/register/SlashCommandUpdater.java b/src/main/java/com/github/kaktushose/jda/commands/internal/register/SlashCommandUpdater.java
index 2efe3fc4b..6624cb637 100644
--- a/src/main/java/com/github/kaktushose/jda/commands/internal/register/SlashCommandUpdater.java
+++ b/src/main/java/com/github/kaktushose/jda/commands/internal/register/SlashCommandUpdater.java
@@ -1,13 +1,12 @@
package com.github.kaktushose.jda.commands.internal.register;
-import com.github.kaktushose.jda.commands.annotations.interactions.SlashCommand;
+import com.github.kaktushose.jda.commands.annotations.interactions.CommandScope;
+import com.github.kaktushose.jda.commands.definitions.interactions.InteractionRegistry;
+import com.github.kaktushose.jda.commands.definitions.interactions.command.CommandDefinition;
+import com.github.kaktushose.jda.commands.definitions.interactions.command.ContextCommandDefinition;
+import com.github.kaktushose.jda.commands.definitions.interactions.command.SlashCommandDefinition;
import com.github.kaktushose.jda.commands.internal.JDAContext;
-import com.github.kaktushose.jda.commands.reflect.InteractionRegistry;
-import com.github.kaktushose.jda.commands.reflect.interactions.commands.GenericCommandDefinition;
-import com.github.kaktushose.jda.commands.reflect.interactions.commands.SlashCommandDefinition;
import com.github.kaktushose.jda.commands.scope.GuildScopeProvider;
-import net.dv8tion.jda.api.entities.Guild;
-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.SlashCommandData;
import org.jetbrains.annotations.ApiStatus;
@@ -17,110 +16,74 @@
import java.util.*;
import java.util.stream.Collectors;
-/**
- * Class that sends the {@link SlashCommandData} to Discord. Uses a {@link CommandTree} to properly transpile all
- * {@link SlashCommandDefinition CommandDefinitions} to {@link SlashCommandData}.
- *
- * @see CommandTree
- * @since 2.3.0
- */
+/// Class that sends the [CommandData] to Discord.
+///
+/// @implNote Uses a [CommandTree] to properly transpile all [SlashCommandDefinition]s to [SlashCommandData].
+/// @see CommandTree
@ApiStatus.Internal
-public class SlashCommandUpdater {
+public final class SlashCommandUpdater {
private static final Logger log = LoggerFactory.getLogger(SlashCommandUpdater.class);
private final JDAContext jdaContext;
private final GuildScopeProvider guildScopeProvider;
private final InteractionRegistry interactionRegistry;
- /**
- * Constructs a new SlashCommandUpdater.
- */
- public SlashCommandUpdater(JDAContext jdaContext, GuildScopeProvider guildScopeProvider, InteractionRegistry interactionRegistry) {
+ /// Constructs a new SlashCommandUpdater.
+ public SlashCommandUpdater(JDAContext jdaContext, GuildScopeProvider guildScopeProvider, InteractionRegistry registry) {
this.jdaContext = jdaContext;
this.guildScopeProvider = guildScopeProvider;
- this.interactionRegistry = interactionRegistry;
+ this.interactionRegistry = registry;
}
- /**
- * Sends the {@link SlashCommandData} to Discord. This is equivalent to calling {@link #updateGlobalCommands()} and
- * {@link #updateGuildCommands()} each.
- */
+ /// Sends the [SlashCommandData] to Discord. This is equivalent to calling [#updateGlobalCommands()] and
+ /// [#updateGuildCommands()] each.
public void updateAllCommands() {
updateGuildCommands();
updateGlobalCommands();
}
- /**
- * Sends the guild scope {@link SlashCommandData} to Discord.
- */
- public void updateGuildCommands() {
- log.debug("Updating guild commands...");
- Map> guildMapping = getGuildMapping();
- for (Guild guild : jdaContext.getGuildCache()) {
- Set commands = guildMapping.getOrDefault(guild.getIdLong(), Collections.emptySet());
- guild.updateCommands().addCommands(commands).queue();
- log.debug(String.format("Registered guild command(s) %s for %s", commands.stream().map(CommandData::getName).collect(Collectors.toSet()), guild));
- }
+ private Set getCommands(CommandScope scope) {
+ var tree = new CommandTree(
+ interactionRegistry.find(SlashCommandDefinition.class, it -> it.scope() == scope)
+ );
+ Set commands = new HashSet<>(tree.getCommands());
+ log.debug("Generated slash command tree with CommandScope.{}:\n{}", scope, tree);
+ commands.addAll(
+ interactionRegistry.find(ContextCommandDefinition.class, it -> it.scope() == scope)
+ .stream()
+ .map(ContextCommandDefinition::toJDAEntity)
+ .toList()
+ );
+ return commands;
}
- /**
- * Sends the global scope {@link SlashCommandData} to Discord.
- */
+ /// Registers all [CommandDefinition]s with [CommandScope#GLOBAL].
public void updateGlobalCommands() {
log.debug("Updating global commands...");
+ var commands = getCommands(CommandScope.GLOBAL);
+ jdaContext.performTask(jda -> jda.updateCommands().addCommands(commands).queue());
+ log.debug("Registered global command(s): {}", commands.stream().map(CommandData::getName).collect(Collectors.toSet()));
+ }
- Set globalCommands = interactionRegistry.getCommands()
- .stream()
- .filter(it -> it.getCommandScope() == SlashCommand.CommandScope.GLOBAL)
- .collect(Collectors.toSet());
-
- CommandTree tree = new CommandTree(
- globalCommands.stream()
- .filter(it -> it.getCommandType() == Command.Type.SLASH)
- .map(it -> (SlashCommandDefinition) it)
- .collect(Collectors.toSet())
- );
- log.debug("Generated slash command tree with CommandScope.GLOBAL:\n" + tree);
-
- Set result = new HashSet<>();
- result.addAll(tree.getCommands());
- result.addAll(globalCommands.stream().
- filter(it -> (it.getCommandType() == Command.Type.USER || it.getCommandType() == Command.Type.MESSAGE))
- .map(GenericCommandDefinition::toCommandData)
- .collect(Collectors.toSet())
- );
- log.debug("Registered global command(s): " + result.stream().map(CommandData::getName).collect(Collectors.toSet()));
-
- jdaContext.performTask(jda -> jda.updateCommands().addCommands(result).queue());
+ /// Sends the guild scope [SlashCommandData] to Discord.
+ public void updateGuildCommands() {
+ log.debug("Updating guild commands...");
+ var guildMapping = getGuildMapping();
+ for (var guild : jdaContext.getGuildCache()) {
+ var commands = guildMapping.getOrDefault(guild.getIdLong(), Collections.emptySet());
+ guild.updateCommands().addCommands(commands).queue();
+ log.debug("Registered guild command(s) {} for {}", commands.stream().map(CommandData::getName).collect(Collectors.toSet()), guild);
+ }
}
private Map> getGuildMapping() {
- Set guildCommands = interactionRegistry.getCommands()
- .stream()
- .filter(it -> it.getCommandScope() == SlashCommand.CommandScope.GUILD)
- .collect(Collectors.toSet());
-
- CommandTree tree = new CommandTree(
- guildCommands.stream()
- .filter(it -> it.getCommandType() == Command.Type.SLASH)
- .map(it -> (SlashCommandDefinition) it)
- .collect(Collectors.toSet())
- );
- log.debug("Generated slash command tree with CommandScope.GUILD:\n" + tree);
-
- Set result = new HashSet<>();
- result.addAll(tree.getCommands());
- result.addAll(guildCommands.stream().
- filter(it -> (it.getCommandType() == Command.Type.USER || it.getCommandType() == Command.Type.MESSAGE))
- .map(GenericCommandDefinition::toCommandData)
- .collect(Collectors.toSet())
- );
- log.debug("Interactions eligible for registration: " + result.stream().map(CommandData::getName).collect(Collectors.toSet()));
+ var commands = getCommands(CommandScope.GUILD);
+ log.debug("Interactions eligible for registration: {}", commands.stream().map(CommandData::getName).collect(Collectors.toSet()));
Map> guildMapping = new HashMap<>();
- for (CommandData command : result) {
+ for (var command : commands) {
// create a copy so that a user doesn't modify the command data used for registration
- Set guildIds = guildScopeProvider.apply(CommandData.fromData(command.toData()));
+ var guildIds = guildScopeProvider.apply(CommandData.fromData(command.toData()));
if (guildIds.isEmpty()) {
log.debug("No guilds provided for command \"{}\"", command.getName());
} else {
diff --git a/src/main/java/com/github/kaktushose/jda/commands/internal/register/TreeNode.java b/src/main/java/com/github/kaktushose/jda/commands/internal/register/TreeNode.java
index eae95bb9b..feddc13d2 100644
--- a/src/main/java/com/github/kaktushose/jda/commands/internal/register/TreeNode.java
+++ b/src/main/java/com/github/kaktushose/jda/commands/internal/register/TreeNode.java
@@ -1,6 +1,6 @@
package com.github.kaktushose.jda.commands.internal.register;
-import com.github.kaktushose.jda.commands.reflect.interactions.commands.SlashCommandDefinition;
+import com.github.kaktushose.jda.commands.definitions.interactions.command.SlashCommandDefinition;
import net.dv8tion.jda.api.Permission;
import net.dv8tion.jda.api.interactions.commands.DefaultMemberPermissions;
import net.dv8tion.jda.api.interactions.commands.build.Commands;
@@ -15,12 +15,9 @@
import java.util.*;
-/**
- * Single node inside the {@link CommandTree}.
- *
- * @see CommandTree
- * @since 2.3.0
- */
+/// Single node inside the [CommandTree].
+///
+/// @see CommandTree
@ApiStatus.Internal
public record TreeNode(
String name,
@@ -28,38 +25,32 @@ public record TreeNode(
List children
) implements Iterable {
- private static final Logger log = LoggerFactory.getLogger(SlashCommandUpdater.class);
+ private static final Logger log = LoggerFactory.getLogger(TreeNode.class);
- /**
- * Constructs an empty TreeNode. Should only be used for root nodes.
- */
+ /// Constructs an empty TreeNode. Should only be used for root nodes.
public TreeNode() {
this("", null);
}
- /**
- * Constructs a new TreeNode.
- *
- * @param name the name of the command
- * @param command the {@link SlashCommandDefinition}
- */
+ /// Constructs a new TreeNode.
+ ///
+ /// @param name the name of the command
+ /// @param command the [SlashCommandDefinition]
public TreeNode(@NotNull String name, @Nullable SlashCommandDefinition command) {
this(name, command, new ArrayList<>());
}
- /**
- * Adds a child {@link TreeNode} either as a child of this {@link TreeNode} or to one of its children based on the
- * amount of labels.
- *
- * For instance {@code labels[0]} will be added as a child {@link TreeNode} to this
- * {@link TreeNode}, {@code labels[1]} will be added as a child to the child {@link TreeNode} created from
- * {@code labels[0]} and so on.
- *
- *
This guarantees to create a {@link CommandTree} that respects Subcommands and SubcommandGroups.
- *
- * @param labels an Array of all labels, can be empty
- * @param command the {@link SlashCommandDefinition} to add
- */
+ /// Adds a child [TreeNode] either as a child of this [TreeNode] or to one of its children based on the
+ /// amount of labels.
+ ///
+ /// For instance `labels[0]` will be added as a child [TreeNode] to this
+ /// [TreeNode], `labels[1]` will be added as a child to the child [TreeNode] created from
+ /// `labels[0]` and so on.
+ ///
+ /// This guarantees to create a [CommandTree] that respects Subcommands and SubcommandGroups.
+ ///
+ /// @param labels an Array of all labels, can be empty
+ /// @param command the [SlashCommandDefinition] to add
public void addChild(@NotNull String[] labels, @NotNull SlashCommandDefinition command) {
if (labels.length < 1) {
return;
@@ -79,49 +70,39 @@ public void addChild(@NotNull String[] labels, @NotNull SlashCommandDefinition c
}
}
- /**
- * Gets a child {@link TreeNode} based on its name.
- *
- * @param name the label to get the child {@link TreeNode} from
- * @return an {@link Optional} holding the result
- */
+ /// Gets a child [TreeNode] based on its name.
+ ///
+ /// @param name the label to get the child [TreeNode] from
+ /// @return an [Optional] holding the result
public Optional getChild(String name) {
return children.stream().filter(child -> child.name.equals(name)).findFirst();
}
- /**
- * Gets the label of the {@link SlashCommandDefinition} of this {@link TreeNode}.
- *
- * @return the label of the {@link SlashCommandDefinition}
- */
+ /// Gets the name of the [SlashCommandDefinition] of this [TreeNode].
+ ///
+ /// @return the name of the [SlashCommandDefinition]
public String getName() {
return name;
}
- /**
- * Gets all children {@link TreeNode TreeNodes}.
- *
- * @return all children {@link TreeNode TreeNodes}
- */
+ /// Gets all children [TreeNode]s.
+ ///
+ /// @return all children [TreeNode]s
public List getChildren() {
return children;
}
- /**
- * Gets whether this {@link TreeNode} has children.
- *
- * @return {@code true} if this {@link TreeNode} has children
- */
+ /// Gets whether this [TreeNode] has children.
+ ///
+ /// @return `true` if this [TreeNode] has children
public boolean hasChildren() {
return !children.isEmpty();
}
- /**
- * Gets the {@link SlashCommandDefinition} of this {@link TreeNode}. Returns an empty {@link Optional} if one or more
- * children exist or if the {@link SlashCommandDefinition} is {@code null}.
- *
- * @return an {@link Optional} holding the result
- */
+ /// Gets the [SlashCommandDefinition] of this [TreeNode]. Returns an empty [Optional] if one or more
+ /// children exist or if the [SlashCommandDefinition] is `null`.
+ ///
+ /// @return an [Optional] holding the result
public Optional getCommand() {
if (!children.isEmpty()) {
return Optional.empty();
@@ -129,11 +110,9 @@ public Optional getCommand() {
return Optional.ofNullable(command);
}
- /**
- * Gets all names of the leaf nodes.
- *
- * @return a {@link List} of all names of the leaf nodes.
- */
+ /// Gets all names of the leaf nodes.
+ ///
+ /// @return a [List] of all names of the leaf nodes.
public List getNames() {
List result = new ArrayList<>();
toLabel(result, "");
@@ -148,11 +127,9 @@ private void toLabel(List labels, String root) {
}
}
- /**
- * Gets all {@link SlashCommandData of the leaf nodes}.
- *
- * @return a {@link List} of all {@link SlashCommandData of the leaf nodes.
- */
+ /// Gets all [of the leaf nodes][SlashCommandData].
+ ///
+ /// @return a [List] of [SlashCommandData]
public List getCommandData() {
List result = new ArrayList<>();
children.forEach(child -> child.toCommandData(result));
@@ -170,27 +147,24 @@ private void toCommandData(Collection commands) {
return;
}
try {
- commands.add(command.toCommandData());
+ commands.add(command.toJDAEntity());
} catch (Exception e) {
- log.error(String.format("Cannot convert command %s.%s to SlashCommandData!",
- command.getMethod().getDeclaringClass().getSimpleName(),
- command.getMethod().getName()), e
- );
+ log.error("Cannot convert command {}.{} to SlashCommandData!", command.clazzDescription().name(), command.methodDescription().name(), e);
}
}
private SlashCommandData createRootCommand(String name, List children) {
SlashCommandData result = Commands.slash(name, "empty description");
List subCommands = unwrapDefinitions(children);
- LocalizationFunction function = subCommands.getFirst().getLocalizationFunction();
+ LocalizationFunction function = subCommands.getFirst().localizationFunction();
boolean isNSFW = false;
boolean isGuildOnly = false;
Set enabledPermissions = new HashSet<>();
for (SlashCommandDefinition command : subCommands) {
- isNSFW = isNSFW || command.isNSFW();
- isGuildOnly = isGuildOnly || command.isGuildOnly();
- enabledPermissions.addAll(command.getEnabledPermissions());
+ isNSFW = isNSFW || command.nsfw();
+ isGuildOnly = isGuildOnly || command.guildOnly();
+ enabledPermissions.addAll(command.enabledPermissions());
}
return result.setDefaultPermissions(DefaultMemberPermissions.enabledFor(enabledPermissions))
diff --git a/src/main/java/com/github/kaktushose/jda/commands/package-info.java b/src/main/java/com/github/kaktushose/jda/commands/package-info.java
index ea309d268..0fca71228 100644
--- a/src/main/java/com/github/kaktushose/jda/commands/package-info.java
+++ b/src/main/java/com/github/kaktushose/jda/commands/package-info.java
@@ -1,4 +1,2 @@
-/**
- * Root package of JDA-Commands.
- */
+/// Root package of JDA-Commands.
package com.github.kaktushose.jda.commands;
diff --git a/src/main/java/com/github/kaktushose/jda/commands/permissions/DefaultPermissionsProvider.java b/src/main/java/com/github/kaktushose/jda/commands/permissions/DefaultPermissionsProvider.java
index 45240803d..6ee9798fa 100644
--- a/src/main/java/com/github/kaktushose/jda/commands/permissions/DefaultPermissionsProvider.java
+++ b/src/main/java/com/github/kaktushose/jda/commands/permissions/DefaultPermissionsProvider.java
@@ -21,7 +21,6 @@
///
///
/// @see PermissionsProvider
-/// @since 2.0.0
public class DefaultPermissionsProvider implements PermissionsProvider {
private static final Logger log = LoggerFactory.getLogger(DefaultPermissionsProvider.class);
@@ -40,7 +39,7 @@ public boolean hasPermission(@NotNull User user, @NotNull InvocationContext> c
/// Any other permission String will be ignored.
@Override
public boolean hasPermission(@NotNull Member member, @NotNull InvocationContext> context) {
- for (String s : context.definition().getPermissions()) {
+ for (String s : context.definition().permissions()) {
// not a discord perm, continue
if (Arrays.stream(Permission.values()).noneMatch(p -> p.name().equalsIgnoreCase(s))) {
continue;
diff --git a/src/main/java/com/github/kaktushose/jda/commands/permissions/PermissionsProvider.java b/src/main/java/com/github/kaktushose/jda/commands/permissions/PermissionsProvider.java
index 8a4f9ea44..5a83514f9 100644
--- a/src/main/java/com/github/kaktushose/jda/commands/permissions/PermissionsProvider.java
+++ b/src/main/java/com/github/kaktushose/jda/commands/permissions/PermissionsProvider.java
@@ -8,10 +8,9 @@
/// Interface for performing permission checks.
///
-/// @see com.github.kaktushose.jda.commands.annotations.Implementation
+/// @see com.github.kaktushose.jda.commands.annotations.Implementation Implementation
/// @see DefaultPermissionsProvider
/// @see Permissions Permission
-/// @since 2.0.0
public interface PermissionsProvider {
/// Checks if a [User] has permissions. Compared to [#hasPermission(Member, InvocationContext)] this method will be
diff --git a/src/main/java/com/github/kaktushose/jda/commands/permissions/package-info.java b/src/main/java/com/github/kaktushose/jda/commands/permissions/package-info.java
index a73dd84ba..e93e8f9ca 100644
--- a/src/main/java/com/github/kaktushose/jda/commands/permissions/package-info.java
+++ b/src/main/java/com/github/kaktushose/jda/commands/permissions/package-info.java
@@ -1,4 +1,2 @@
-/**
- * Command permission system.
- */
+/// Command permission system.
package com.github.kaktushose.jda.commands.permissions;
diff --git a/src/main/java/com/github/kaktushose/jda/commands/reflect/ConstraintDefinition.java b/src/main/java/com/github/kaktushose/jda/commands/reflect/ConstraintDefinition.java
deleted file mode 100644
index 91c63ed48..000000000
--- a/src/main/java/com/github/kaktushose/jda/commands/reflect/ConstraintDefinition.java
+++ /dev/null
@@ -1,13 +0,0 @@
-package com.github.kaktushose.jda.commands.reflect;
-
-import com.github.kaktushose.jda.commands.dispatching.validation.Validator;
-
-/**
- * Representation of parameter constraint.
- *
- * @see com.github.kaktushose.jda.commands.annotations.constraints.Constraint Constraint
- * @see Validator
- * @since 2.0.0
- */
-public record ConstraintDefinition(Validator validator, String message, Object annotation) {
-}
diff --git a/src/main/java/com/github/kaktushose/jda/commands/reflect/CooldownDefinition.java b/src/main/java/com/github/kaktushose/jda/commands/reflect/CooldownDefinition.java
deleted file mode 100644
index 646a5ea3d..000000000
--- a/src/main/java/com/github/kaktushose/jda/commands/reflect/CooldownDefinition.java
+++ /dev/null
@@ -1,32 +0,0 @@
-package com.github.kaktushose.jda.commands.reflect;
-
-import com.github.kaktushose.jda.commands.annotations.interactions.Cooldown;
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
-
-import java.util.concurrent.TimeUnit;
-
-/**
- * Representation of a command cooldown.
- *
- * @see Cooldown
- * @since 2.0.0
- */
-public record CooldownDefinition(
- long delay,
- TimeUnit timeUnit
-) {
- /**
- * Builds a new CooldownDefinition.
- *
- * @param cooldown an instance of the corresponding {@link Cooldown} annotation
- * @return a new CooldownDefinition
- */
- @NotNull
- public static CooldownDefinition build(@Nullable Cooldown cooldown) {
- if (cooldown == null) {
- return new CooldownDefinition(0, TimeUnit.MILLISECONDS);
- }
- return new CooldownDefinition(cooldown.value(), cooldown.timeUnit());
- }
-}
diff --git a/src/main/java/com/github/kaktushose/jda/commands/reflect/InteractionControllerDefinition.java b/src/main/java/com/github/kaktushose/jda/commands/reflect/InteractionControllerDefinition.java
deleted file mode 100644
index 9f04d4f6b..000000000
--- a/src/main/java/com/github/kaktushose/jda/commands/reflect/InteractionControllerDefinition.java
+++ /dev/null
@@ -1,152 +0,0 @@
-package com.github.kaktushose.jda.commands.reflect;
-
-import com.github.kaktushose.jda.commands.annotations.Inject;
-import com.github.kaktushose.jda.commands.annotations.interactions.*;
-import com.github.kaktushose.jda.commands.dependency.DependencyInjector;
-import com.github.kaktushose.jda.commands.dispatching.validation.ValidatorRegistry;
-import com.github.kaktushose.jda.commands.reflect.interactions.AutoCompleteDefinition;
-import com.github.kaktushose.jda.commands.reflect.interactions.GenericInteractionDefinition;
-import com.github.kaktushose.jda.commands.reflect.interactions.ModalDefinition;
-import com.github.kaktushose.jda.commands.reflect.interactions.commands.ContextCommandDefinition;
-import com.github.kaktushose.jda.commands.reflect.interactions.commands.SlashCommandDefinition;
-import com.github.kaktushose.jda.commands.reflect.interactions.components.ButtonDefinition;
-import com.github.kaktushose.jda.commands.reflect.interactions.components.menus.EntitySelectMenuDefinition;
-import com.github.kaktushose.jda.commands.reflect.interactions.components.menus.StringSelectMenuDefinition;
-import net.dv8tion.jda.api.interactions.commands.localization.LocalizationFunction;
-import org.jetbrains.annotations.NotNull;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import java.lang.reflect.Field;
-import java.lang.reflect.Method;
-import java.util.Optional;
-import java.util.*;
-
-/**
- * Representation of an interaction controller.
- *
- * @since 2.0.0
- */
-public record InteractionControllerDefinition(
- Set definitions
-) {
-
- private static final Logger log = LoggerFactory.getLogger(InteractionControllerDefinition.class);
-
- /**
- * Builds a new ControllerDefinition.
- *
- * @param interactionClass the {@link Class} of the controller
- * @param validatorRegistry the corresponding {@link ValidatorRegistry}
- * @param dependencyInjector the corresponding {@link DependencyInjector}
- * @param localizationFunction the {@link LocalizationFunction} to use
- * @return an {@link Optional} holding the ControllerDefinition
- */
- public static InteractionControllerDefinition build(@NotNull Class> interactionClass,
- @NotNull ValidatorRegistry validatorRegistry,
- @NotNull DependencyInjector dependencyInjector,
- @NotNull LocalizationFunction localizationFunction) {
- Interaction interaction = interactionClass.getAnnotation(Interaction.class);
-
- List fields = Arrays.stream(interactionClass.getDeclaredFields())
- .filter(field -> field.isAnnotationPresent(Inject.class))
- .toList();
- dependencyInjector.registerDependencies(interactionClass, fields);
-
- Permissions permission = interactionClass.getAnnotation(Permissions.class);
- final Set permissions = permission != null
- ? Set.of(permission.value())
- : Set.of();
-
- // get controller level cooldown and use it if no command level cooldown is present
- Cooldown cooldownAnn = interactionClass.getAnnotation(Cooldown.class);
- CooldownDefinition cooldown = cooldownAnn != null
- ? CooldownDefinition.build(cooldownAnn)
- : null;
-
-
- Collection autoCompleteDefinitions = autoCompleteDefinitions(interactionClass);
-
- // index interactions
- Set interactionDefinitions = interactionDefinitions(
- interactionClass,
- validatorRegistry,
- localizationFunction,
- interaction,
- permissions,
- cooldown,
- autoCompleteDefinitions
- );
-
- // validate auto completes
- List commandDefinitions = interactionDefinitions.stream()
- .filter(SlashCommandDefinition.class::isInstance)
- .map(SlashCommandDefinition.class::cast)
- .toList();
-
- autoCompleteDefinitions.stream()
- .map(AutoCompleteDefinition::getCommandNames)
- .flatMap(Collection::stream)
- .filter(name -> commandDefinitions.stream().noneMatch(command -> command.getName().startsWith(name)))
- .forEach(s -> log.warn("No Command found for auto complete {}", s));
-
- return new InteractionControllerDefinition(interactionDefinitions);
- }
-
- private static Collection autoCompleteDefinitions(Class> interactionClass) {
- return Arrays.stream(interactionClass.getDeclaredMethods())
- .filter(method -> method.isAnnotationPresent(AutoComplete.class))
- .map(AutoCompleteDefinition::build)
- .flatMap(Optional::stream)
- .toList();
- }
-
- private static Set interactionDefinitions(Class> clazz,
- ValidatorRegistry validatorRegistry,
- LocalizationFunction localizationFunction,
- Interaction interaction,
- Set permissions,
- CooldownDefinition cooldown,
- Collection