Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Refactor/definition #149

Merged
merged 31 commits into from
Jan 5, 2025
Merged
Show file tree
Hide file tree
Changes from 30 commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
5ebb91d
first pass on new definition api
Kaktushose Dec 23, 2024
c48777a
make interaction interfaces records and first pass on new registry
Kaktushose Dec 25, 2024
54c75e8
update records
Kaktushose Dec 25, 2024
776ca02
fix invocation context
Kaktushose Dec 25, 2024
d87dc61
add missing parameter methods
Kaktushose Dec 25, 2024
fe4b191
rename
Kaktushose Dec 25, 2024
477597c
add reflection wrapper
Goldmensch Dec 25, 2024
e7f756e
add reflective descriptor
Goldmensch Dec 25, 2024
7953107
update definitions
Kaktushose Dec 25, 2024
ea5f6e8
update definitions
Kaktushose Dec 25, 2024
41cda31
fix shit ton of compile errors
Kaktushose Dec 26, 2024
821a477
cleanup
Kaktushose Dec 26, 2024
8e0ec84
formatting
Kaktushose Dec 26, 2024
28fa758
remove since tag
Kaktushose Dec 26, 2024
9534df8
update documentation
Kaktushose Dec 26, 2024
4524f9b
fix unit tests
Kaktushose Dec 26, 2024
5f81825
extract reflections out of InteractionRegistry
Kaktushose Dec 26, 2024
9b384b1
Use Iterable instead of List and introduce CustomId#independent
Goldmensch Dec 28, 2024
c2e5d4b
Restructure Definitions package and separate Context and SlashCommand
Goldmensch Dec 31, 2024
7d2438d
remove Permissions feature interface
Kaktushose Dec 31, 2024
05f588d
Forbid Definition#invoke by user and fix bug in CustomID
Goldmensch Dec 31, 2024
571aa8c
javadocs
Kaktushose Jan 3, 2025
f8822c3
Yeah..
Goldmensch Jan 3, 2025
d53982d
docs
Kaktushose Jan 4, 2025
e15f6d5
more javadoc
Kaktushose Jan 4, 2025
8c3f556
formatting
Kaktushose Jan 4, 2025
5397e8a
fix java tests
Kaktushose Jan 4, 2025
83c99f8
fix java tests
Kaktushose Jan 4, 2025
2b67173
fix wrong annotation
Kaktushose Jan 4, 2025
7b28c6f
fix codacy
Kaktushose Jan 5, 2025
d138ab4
small changes
Kaktushose Jan 5, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 17 additions & 0 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,23 @@
<link>https://javadoc.io/doc/net.dv8tion/JDA/5.0.2</link>
</links>
<docfilessubdirs>true</docfilessubdirs>
<tags>
<tag>
<name>apiNote</name>
<placement>a</placement>
<head>API Note:</head>
</tag>
<tag>
<name>implSpec</name>
<placement>a</placement>
<head>Implementation Requirements:</head>
</tag>
<tag>
<name>implNote</name>
<placement>a</placement>
<head>Implementation Note:</head>
</tag>
</tags>
</configuration>
</plugin>
<plugin>
Expand Down
52 changes: 19 additions & 33 deletions src/main/java/com/github/kaktushose/jda/commands/JDACommands.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,18 @@

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;
Expand All @@ -17,10 +23,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;
Expand All @@ -39,7 +41,7 @@ public record JDACommands(
TypeAdapterRegistry adapterRegistry,
ValidatorRegistry validatorRegistry,
DependencyInjector dependencyInjector,
InteractionRegistry interactionRegistry,
InteractionRegistry registry,
SlashCommandUpdater updater) {
private static final Logger log = LoggerFactory.getLogger(JDACommands.class);

Expand All @@ -53,7 +55,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));
Expand All @@ -62,7 +64,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();
Expand Down Expand Up @@ -188,38 +190,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 = registry.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].
///
/// 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 <S> the type of [SelectMenu]
/// @param menu the name of the select menu
/// @return the JDA [SelectMenu]
@SuppressWarnings("unchecked")
@NotNull
public <S extends SelectMenu> 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 = registry.find(SelectMenuDefinition.class, false, it -> it.definitionId().equals(id));
return (SelectMenu) definition.toJDAEntity(CustomId.independent(definition.definitionId()));
}
}
Original file line number Diff line number Diff line change
@@ -1,46 +1,38 @@
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.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 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 ImplementationRegistry
/// @see Middleware Middleware
/// @see 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
@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;

}
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
Original file line number Diff line number Diff line change
@@ -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.
*
* <p>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.
*
* <p>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)}
*
* <p>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;

}
Original file line number Diff line number Diff line change
Expand Up @@ -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();
}
Original file line number Diff line number Diff line change
Expand Up @@ -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 lower 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";
}
Original file line number Diff line number Diff line change
Expand Up @@ -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";
}
Loading
Loading