diff --git a/build.gradle.kts b/build.gradle.kts index c821828..2cb87d1 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -8,7 +8,19 @@ allprojects { group = "net.tomatentum.Marinara" version = "1.0.0-RC1" + (if (!project.hasProperty("release")) ("-" + getGitHash()) else "") description = "A simple but powerful, library-agnostic Discord Interaction Wrapper." + plugins.withType { + tasks.withType().configureEach { + archiveBaseName.set("marinara-" + archiveBaseName.get()) + } + } + repositories { + // Use Maven Central for resolving dependencies. + mavenCentral() + maven { + url = uri("https://git.tomatentum.net/api/packages/tueem/maven") + } + } } subprojects { diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 5f2057a..4268ec0 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -8,11 +8,14 @@ javacord = "3.8.0" discord4j = "3.2.7" geantyref = "2.0.0" mockito = "5.15.2" +cutin = "0.2.0" [libraries] junit-jupiter = { module = "org.junit.jupiter:junit-jupiter", version.ref = "junit-jupiter" } slf4j = { module = "org.slf4j:slf4j-api", version.ref = "slf4j"} +slf4j-simple = { module = "org.slf4j:slf4j-simple", version.ref = "slf4j"} javacord = { module = "org.javacord:javacord", version.ref = "javacord"} discord4j = { module = "com.discord4j:discord4j-core", version.ref = "discord4j"} geantyref = { module = "io.leangen.geantyref:geantyref", version.ref = "geantyref"} mockito = {module = "org.mockito:mockito-core", version.ref = "mockito"} +cutin = {module = "net.tomatentum.cutin:lib", version.ref = "cutin"} diff --git a/lib/build.gradle.kts b/lib/build.gradle.kts index 19aca3b..5144454 100644 --- a/lib/build.gradle.kts +++ b/lib/build.gradle.kts @@ -10,11 +10,6 @@ plugins { `java-library` } -repositories { - // Use Maven Central for resolving dependencies. - mavenCentral() -} - dependencies { // Use JUnit Jupiter for testing. testImplementation(libs.junit.jupiter) @@ -22,6 +17,7 @@ dependencies { testRuntimeOnly("org.junit.platform:junit-platform-launcher") implementation(libs.slf4j) implementation(libs.geantyref) + api(libs.cutin) } // Apply a specific Java toolchain to ease working on different environments. diff --git a/lib/src/main/java/net/tomatentum/marinara/Marinara.java b/lib/src/main/java/net/tomatentum/marinara/Marinara.java index f53a7ae..8f65794 100644 --- a/lib/src/main/java/net/tomatentum/marinara/Marinara.java +++ b/lib/src/main/java/net/tomatentum/marinara/Marinara.java @@ -1,40 +1,85 @@ package net.tomatentum.marinara; -import org.slf4j.Logger; +import java.util.Arrays; +import java.util.List; -import net.tomatentum.marinara.registry.InteractionCheckRegistry; -import net.tomatentum.marinara.registry.InteractionRegistry; -import net.tomatentum.marinara.util.LoggerUtil; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import net.tomatentum.cutin.MethodExecutor; +import net.tomatentum.cutin.ProcessorMethodExecutor; +import net.tomatentum.cutin.container.MethodContainer; +import net.tomatentum.marinara.checks.CheckExecutionContext; +import net.tomatentum.marinara.checks.CheckMethodIdentifier; +import net.tomatentum.marinara.container.InteractionCheckContainer; +import net.tomatentum.marinara.container.InteractionMethodContainer; +import net.tomatentum.marinara.interaction.InteractionType; +import net.tomatentum.marinara.interaction.commands.SlashCommandDefinition; +import net.tomatentum.marinara.interaction.ident.InteractionIdentifier; +import net.tomatentum.marinara.interaction.ident.RootCommandIdentifier; +import net.tomatentum.marinara.interaction.processor.AutocompleteInteractionProcessor; +import net.tomatentum.marinara.interaction.processor.DirectInteractionProcessor; +import net.tomatentum.marinara.util.ObjectAggregator; +import net.tomatentum.marinara.wrapper.IdentifierProvider; import net.tomatentum.marinara.wrapper.LibraryWrapper; public class Marinara { - private Logger logger = LoggerUtil.getLogger(getClass()); + private Logger logger = LoggerFactory.getLogger(getClass()); - public static Marinara load(LibraryWrapper wrapper) { + public static Marinara load(LibraryWrapper wrapper) { return new Marinara(wrapper); } - private InteractionRegistry registry; - private InteractionCheckRegistry checkRegistry; private LibraryWrapper wrapper; + private MethodContainer checkContainer; + private MethodContainer interactionContainer; + private MethodExecutor interactionExecutor; private Marinara(LibraryWrapper wrapper) { this.wrapper = wrapper; - this.registry = new InteractionRegistry(this); - this.checkRegistry = new InteractionCheckRegistry(); + this.checkContainer = new InteractionCheckContainer(); + this.interactionContainer = new InteractionMethodContainer(getCheckContainer(), getWrapper().getContextObjectProvider()); + IdentifierProvider provider = wrapper.createIdentifierProvider(); + ProcessorMethodExecutor exec = new ProcessorMethodExecutor<>(getInteractionContainer()); + exec + .addProcessor(new DirectInteractionProcessor(provider, InteractionType.COMMAND, InteractionType.BUTTON)) + .addProcessor(new AutocompleteInteractionProcessor(getWrapper(), provider)); + this.interactionExecutor = exec; + wrapper.subscribeInteractions(this.interactionExecutor::handle); logger.info("Marinara loaded successfully!"); } - public InteractionRegistry getRegistry() { - return registry; - } + //TODO move to future interactionstructure module + public void registerCommands() { + List slashIdentifiers = getInteractionContainer().identifiers().stream() + .filter(i -> i.type().equals(InteractionType.COMMAND)) + .toList(); - public InteractionCheckRegistry getCheckRegistry() { - return checkRegistry; + SlashCommandDefinition[] defs = new ObjectAggregator( + i -> Arrays.asList((RootCommandIdentifier)i.rootNode()), + SlashCommandDefinition::addIdentifier, + SlashCommandDefinition::new) + .aggregate(slashIdentifiers) + .toArray(SlashCommandDefinition[]::new); + + wrapper.getRegisterer().register(defs); } public LibraryWrapper getWrapper() { - return wrapper; + return this.wrapper; } + + public MethodContainer getInteractionContainer() { + return this.interactionContainer; + } + + public MethodContainer getCheckContainer() { + return this.checkContainer; + } + + public MethodExecutor getInteractionExecutor() { + return interactionExecutor; + } + } diff --git a/lib/src/main/java/net/tomatentum/marinara/checks/AppliedCheck.java b/lib/src/main/java/net/tomatentum/marinara/checks/AppliedCheck.java index c20cf5a..5dac01f 100644 --- a/lib/src/main/java/net/tomatentum/marinara/checks/AppliedCheck.java +++ b/lib/src/main/java/net/tomatentum/marinara/checks/AppliedCheck.java @@ -1,50 +1,28 @@ package net.tomatentum.marinara.checks; import java.lang.annotation.Annotation; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.util.Arrays; import org.slf4j.Logger; +import org.slf4j.LoggerFactory; -import net.tomatentum.marinara.util.LoggerUtil; -import net.tomatentum.marinara.util.ReflectionUtil; +import net.tomatentum.cutin.method.ReflectedMethod; -public record AppliedCheck(InteractionCheck check, Annotation annotation) { +public record AppliedCheck( + Annotation annotation, + ReflectedMethod preExec, + ReflectedMethod postExec + ) { + + private static Logger logger = LoggerFactory.getLogger(AppliedCheck.class); - private static Logger logger = LoggerUtil.getLogger(AppliedCheck.class); - public boolean pre(Object context) { - Method[] methods = Arrays.stream(check.getClass().getMethods()) - .filter(x -> x.getName().equals("preExec")) - .filter(x -> !x.isBridge()) - .toArray(s -> new Method[s]); - Method method = ReflectionUtil.getMostSpecificMethod(methods, context.getClass(), annotation.annotationType()); - method.setAccessible(true); - try { - logger.debug("Executing pre check {} with context {}", check.getClass().getName(), context.toString()); - boolean result = (boolean) method.invoke(check, context, annotation); - logger.debug("Pre Check {} {} with context {}", check.getClass().getName(), result ? "succeeded" : "failed", context.toString()); - return result; - } catch (IllegalAccessException | InvocationTargetException | SecurityException e) { - logger.error("Failed executing pre-check", e); - return false; - } + logger.debug("Running InteractionCheck preExec {} with annotation {}", preExec(), annotation()); + return (boolean) preExec().run(new CheckExecutionContext(annotation, context)); } public void post(Object context) { - Method[] methods = Arrays.stream(check.getClass().getMethods()) - .filter(x -> x.getName().equals("postExec")) - .filter(x -> !x.isBridge()) - .toArray(s -> new Method[s]); - Method method = ReflectionUtil.getMostSpecificMethod(methods, context.getClass(), annotation.annotationType()); - method.setAccessible(true); - try { - logger.debug("Executing post check {} with context {}", check.getClass().getName(), context.toString()); - method.invoke(check, context, annotation); - } catch (IllegalAccessException | InvocationTargetException | SecurityException e) { - logger.error("Failed executing post-check", e); - } + logger.debug("Running InteractionCheck postExec {} with annotation {}", postExec(), annotation()); + postExec().run(new CheckExecutionContext(annotation, context)); } } diff --git a/lib/src/main/java/net/tomatentum/marinara/checks/CheckExecutionContext.java b/lib/src/main/java/net/tomatentum/marinara/checks/CheckExecutionContext.java new file mode 100644 index 0000000..4dfbdac --- /dev/null +++ b/lib/src/main/java/net/tomatentum/marinara/checks/CheckExecutionContext.java @@ -0,0 +1,7 @@ +package net.tomatentum.marinara.checks; + +import java.lang.annotation.Annotation; + +public record CheckExecutionContext(Annotation annotation, Object originalContext) { + +} diff --git a/lib/src/main/java/net/tomatentum/marinara/checks/CheckMethodIdentifier.java b/lib/src/main/java/net/tomatentum/marinara/checks/CheckMethodIdentifier.java new file mode 100644 index 0000000..af3ca01 --- /dev/null +++ b/lib/src/main/java/net/tomatentum/marinara/checks/CheckMethodIdentifier.java @@ -0,0 +1,27 @@ +package net.tomatentum.marinara.checks; + +import java.lang.reflect.Type; + +public record CheckMethodIdentifier(Type annotationType, CheckMethodType type) { + + public enum CheckMethodType { + PRE("preExec"), + POST("postExec"); + + private String methodName; + + private CheckMethodType(String methodName) { + this.methodName = methodName; + } + + public String methodName() { + return this.methodName; + } + } + + @Override + public final String toString() { + return "InteractionCheck(%s, %s)".formatted(annotationType, type); + } + +} diff --git a/lib/src/main/java/net/tomatentum/marinara/checks/InteractionCheckMethod.java b/lib/src/main/java/net/tomatentum/marinara/checks/InteractionCheckMethod.java new file mode 100644 index 0000000..56ce052 --- /dev/null +++ b/lib/src/main/java/net/tomatentum/marinara/checks/InteractionCheckMethod.java @@ -0,0 +1,74 @@ +package net.tomatentum.marinara.checks; + +import java.util.Optional; +import java.util.Set; + +import net.tomatentum.cutin.MethodParser; +import net.tomatentum.cutin.ReflectedMethodFactory.ParserResults; +import net.tomatentum.cutin.container.MethodContainer; +import net.tomatentum.cutin.method.BestCandidateMethod; +import net.tomatentum.marinara.checks.CheckMethodIdentifier.CheckMethodType; +import net.tomatentum.marinara.parser.InteractionCheckClassParser; + +public class InteractionCheckMethod extends BestCandidateMethod { + + private CheckMethodIdentifier identifier; + + public InteractionCheckMethod( + String methodName, + Object containingObject, + CheckMethodIdentifier identifier + ) { + super(methodName, containingObject); + this.identifier = identifier; + } + + @Override + public Object getParameter(CheckExecutionContext context, int index) { + switch (index) { + case 0: + return context.originalContext(); + case 1: + return context.annotation(); + default: + return null; + } + } + + @Override + public CheckMethodIdentifier identifier() { + return this.identifier; + } + + public static class InteractionCheckMethodFactory extends BestCandidateMethod.Factory { + + private CheckMethodType type; + + public InteractionCheckMethodFactory(MethodContainer methodContainer, CheckMethodType type) { + super(methodContainer, type.methodName()); + this.type = type; + } + + @Override + public void addParser(Set parsers) { + parsers.add( + new InteractionCheckClassParser() + ); + } + + @Override + protected Optional> bcProduce( + String methodName, + Object containingObject, + ParserResults parserResults + ) { + + CheckMethodIdentifier identifier = new CheckMethodIdentifier(parserResults.get(InteractionCheckClassParser.class), type); + if (identifier.annotationType() == null) + return null; + return Optional.of(new InteractionCheckMethod(methodName, containingObject, identifier)); + } + + } + +} diff --git a/lib/src/main/java/net/tomatentum/marinara/container/InteractionCheckContainer.java b/lib/src/main/java/net/tomatentum/marinara/container/InteractionCheckContainer.java new file mode 100644 index 0000000..11f8271 --- /dev/null +++ b/lib/src/main/java/net/tomatentum/marinara/container/InteractionCheckContainer.java @@ -0,0 +1,19 @@ +package net.tomatentum.marinara.container; + +import net.tomatentum.cutin.ReflectedMethodFactoryImpl; +import net.tomatentum.cutin.container.LoneMethodContainer; +import net.tomatentum.marinara.checks.CheckExecutionContext; +import net.tomatentum.marinara.checks.CheckMethodIdentifier; +import net.tomatentum.marinara.checks.CheckMethodIdentifier.CheckMethodType; +import net.tomatentum.marinara.checks.InteractionCheckMethod.InteractionCheckMethodFactory; + +public class InteractionCheckContainer extends LoneMethodContainer { + + public InteractionCheckContainer() { + super(new ReflectedMethodFactoryImpl<>()); + super.factory() + .addFactory(new InteractionCheckMethodFactory(this, CheckMethodType.PRE)) + .addFactory(new InteractionCheckMethodFactory(this, CheckMethodType.POST)); + } + +} diff --git a/lib/src/main/java/net/tomatentum/marinara/container/InteractionMethodContainer.java b/lib/src/main/java/net/tomatentum/marinara/container/InteractionMethodContainer.java new file mode 100644 index 0000000..0223c95 --- /dev/null +++ b/lib/src/main/java/net/tomatentum/marinara/container/InteractionMethodContainer.java @@ -0,0 +1,38 @@ +package net.tomatentum.marinara.container; + +import net.tomatentum.cutin.ReflectedMethodFactory; +import net.tomatentum.cutin.ReflectedMethodFactoryImpl; +import net.tomatentum.cutin.container.MethodContainer; +import net.tomatentum.cutin.container.MultiMethodContainer; +import net.tomatentum.cutin.method.ReflectedMethod; +import net.tomatentum.marinara.checks.CheckExecutionContext; +import net.tomatentum.marinara.checks.CheckMethodIdentifier; +import net.tomatentum.marinara.interaction.components.methods.ButtonInteractionMethod; +import net.tomatentum.marinara.interaction.ident.InteractionIdentifier; +import net.tomatentum.marinara.wrapper.ContextObjectProvider; +import net.tomatentum.marinara.interaction.methods.AutoCompleteInteractionMethod; +import net.tomatentum.marinara.interaction.methods.SlashCommandInteractionMethod; + +public class InteractionMethodContainer extends MultiMethodContainer { + + + private static ReflectedMethodFactory createFactory(MethodContainer checkRegistry, ContextObjectProvider cop) { + return new ReflectedMethodFactoryImpl() + .addFactory(new AutoCompleteInteractionMethod.Factory(checkRegistry, cop)) + .addFactory(new SlashCommandInteractionMethod.Factory(checkRegistry, cop)) + .addFactory(new ButtonInteractionMethod.Factory(checkRegistry, cop)); + } + + public InteractionMethodContainer(MethodContainer checkRegistry, ContextObjectProvider cop) { + super(createFactory(checkRegistry, cop)); + } + + @Override + public MethodContainer addMethod(ReflectedMethod method) { + super.identifiers().stream() + .filter(method.identifier()::equals) + .forEach(i -> InteractionIdentifier.tryAddDescriptions(i, method.identifier())); + return super.addMethod(method); + } + +} diff --git a/lib/src/main/java/net/tomatentum/marinara/interaction/annotation/AutoComplete.java b/lib/src/main/java/net/tomatentum/marinara/interaction/annotation/AutoComplete.java index 46aa6aa..01dc483 100644 --- a/lib/src/main/java/net/tomatentum/marinara/interaction/annotation/AutoComplete.java +++ b/lib/src/main/java/net/tomatentum/marinara/interaction/annotation/AutoComplete.java @@ -8,5 +8,5 @@ import java.lang.annotation.Target; @Target({ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) public @interface AutoComplete { - + public String value(); } diff --git a/lib/src/main/java/net/tomatentum/marinara/interaction/commands/SlashCommandDefinition.java b/lib/src/main/java/net/tomatentum/marinara/interaction/commands/SlashCommandDefinition.java index 0fc0f67..0c931c8 100644 --- a/lib/src/main/java/net/tomatentum/marinara/interaction/commands/SlashCommandDefinition.java +++ b/lib/src/main/java/net/tomatentum/marinara/interaction/commands/SlashCommandDefinition.java @@ -5,6 +5,7 @@ import java.util.List; import java.util.Set; import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import net.tomatentum.marinara.interaction.commands.annotation.CommandChoices; import net.tomatentum.marinara.interaction.commands.annotation.SlashCommandOption; @@ -14,7 +15,6 @@ import net.tomatentum.marinara.interaction.commands.choice.EnumChoices; import net.tomatentum.marinara.interaction.ident.InteractionIdentifier; import net.tomatentum.marinara.interaction.ident.RootCommandIdentifier; import net.tomatentum.marinara.interaction.ident.SlashCommandIdentifier; -import net.tomatentum.marinara.util.LoggerUtil; public class SlashCommandDefinition { @@ -30,7 +30,7 @@ public class SlashCommandDefinition { private RootCommandIdentifier rootIdentifier; private boolean isRootCommand; - private Logger logger = LoggerUtil.getLogger(getClass()); + private Logger logger = LoggerFactory.getLogger(getClass()); public SlashCommandDefinition(RootCommandIdentifier rootIdentifier) { this.entries = new HashSet<>(); diff --git a/lib/src/main/java/net/tomatentum/marinara/interaction/commands/annotation/SlashCommandOption.java b/lib/src/main/java/net/tomatentum/marinara/interaction/commands/annotation/SlashCommandOption.java index e29c361..e4aff31 100644 --- a/lib/src/main/java/net/tomatentum/marinara/interaction/commands/annotation/SlashCommandOption.java +++ b/lib/src/main/java/net/tomatentum/marinara/interaction/commands/annotation/SlashCommandOption.java @@ -5,6 +5,7 @@ import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; +import net.tomatentum.marinara.interaction.annotation.AutoComplete; import net.tomatentum.marinara.interaction.commands.option.SlashCommandOptionType; @Target({ElementType.ANNOTATION_TYPE}) @@ -14,11 +15,11 @@ public @interface SlashCommandOption { public String description() default ""; public SlashCommandOptionType type() default SlashCommandOptionType.STRING; public boolean required() default false; - public boolean autocomplete() default false; + public AutoComplete[] autocompletes() default {}; public Range range() default @Range; public CommandChoices choices() default @CommandChoices; - public static enum PlaceHolderEnum { + public enum PlaceHolderEnum { } } diff --git a/lib/src/main/java/net/tomatentum/marinara/interaction/commands/option/AutocompleteOptionData.java b/lib/src/main/java/net/tomatentum/marinara/interaction/commands/option/AutocompleteOptionData.java new file mode 100644 index 0000000..9f3afc6 --- /dev/null +++ b/lib/src/main/java/net/tomatentum/marinara/interaction/commands/option/AutocompleteOptionData.java @@ -0,0 +1,16 @@ +package net.tomatentum.marinara.interaction.commands.option; + +import java.util.Arrays; + +import net.tomatentum.marinara.interaction.commands.annotation.SlashCommandOption; + +public record AutocompleteOptionData(String name, Object input) { + + public String[] getAutocompleteRefs(SlashCommandOption[] options) { + return Arrays.stream(options) + .filter(o -> o.name().equals(this.name())) + .flatMap(o -> Arrays.stream(o.autocompletes())) + .map(a -> a.value()) + .toArray(String[]::new); + } +} diff --git a/lib/src/main/java/net/tomatentum/marinara/interaction/components/methods/ButtonInteractionMethod.java b/lib/src/main/java/net/tomatentum/marinara/interaction/components/methods/ButtonInteractionMethod.java new file mode 100644 index 0000000..164d666 --- /dev/null +++ b/lib/src/main/java/net/tomatentum/marinara/interaction/components/methods/ButtonInteractionMethod.java @@ -0,0 +1,93 @@ +package net.tomatentum.marinara.interaction.components.methods; + +import java.lang.reflect.Method; +import java.util.List; +import java.util.Optional; +import java.util.Set; + +import net.tomatentum.cutin.MethodParser; +import net.tomatentum.cutin.ReflectedMethodFactory.ParserResults; +import net.tomatentum.cutin.container.MethodContainer; +import net.tomatentum.cutin.method.ReflectedMethod; +import net.tomatentum.marinara.checks.AppliedCheck; +import net.tomatentum.marinara.checks.CheckExecutionContext; +import net.tomatentum.marinara.checks.CheckMethodIdentifier; +import net.tomatentum.marinara.interaction.InteractionHandler; +import net.tomatentum.marinara.interaction.InteractionType; +import net.tomatentum.marinara.interaction.ident.InteractionIdentifier; +import net.tomatentum.marinara.interaction.methods.InteractionMethod; +import net.tomatentum.marinara.parser.ButtonParser; +import net.tomatentum.marinara.parser.InteractionCheckParser; +import net.tomatentum.marinara.wrapper.ContextObjectProvider; + +public class ButtonInteractionMethod extends InteractionMethod { + + private String customId; + private ContextObjectProvider cop; + + private ButtonInteractionMethod( + Method method, + InteractionHandler handler, + List appliedChecks, + String customId, + ContextObjectProvider cop + ) { + super(method, handler, appliedChecks); + this.customId = customId; + this.cop = cop; + } + + @Override + public Object getParameter(Object context, int index) { + Class type = method().getParameterTypes()[index]; + Object superResult = super.getParameter(context, index); + if (superResult == null) + return this.cop.getComponentContextObject(context, type); + else + return superResult; + } + + @Override + public InteractionIdentifier identifier() { + return InteractionIdentifier.builder() + .name(customId) + .description("Button") + .type(InteractionType.BUTTON) + .build(); + } + + public static class Factory extends InteractionMethod.Factory { + + private ContextObjectProvider cop; + + public Factory(MethodContainer checkContainer, ContextObjectProvider cop) { + super(checkContainer); + this.cop = cop; + } + + @Override + public Optional> produce(Method method, Object containingObject, ParserResults parserResults) { + if (!(containingObject instanceof InteractionHandler)) return Optional.empty(); + String customId = parserResults.get(ButtonParser.class); + if (customId == null) return Optional.empty(); + return Optional.of(new ButtonInteractionMethod( + method, + (InteractionHandler) containingObject, + parserResults.get(InteractionCheckParser.class), + customId, + this.cop + )); + } + + @Override + public void addParser(Set parser) { + super.addParser(parser); + + parser.add( + new ButtonParser() + ); + } + + } + +} diff --git a/lib/src/main/java/net/tomatentum/marinara/interaction/ident/InteractionIdentifier.java b/lib/src/main/java/net/tomatentum/marinara/interaction/ident/InteractionIdentifier.java index 7207738..2fd6b42 100644 --- a/lib/src/main/java/net/tomatentum/marinara/interaction/ident/InteractionIdentifier.java +++ b/lib/src/main/java/net/tomatentum/marinara/interaction/ident/InteractionIdentifier.java @@ -80,14 +80,19 @@ public class InteractionIdentifier { return false; if (!name().equals(ident.name())) return false; - return Objects.equals(ident, obj); + return Objects.equals(parent(), ident.parent()); + } + + @Override + public int hashCode() { + return Objects.hash(type(), name(), parent()); } @Override public String toString() { if (parent() == null) - return name(); - return "{}.{}".formatted(name(), parent().toString()); + return name() + " - " + type(); + return "%s:%s".formatted(name(), parent().toString()); } public static class Builder { diff --git a/lib/src/main/java/net/tomatentum/marinara/interaction/ident/RootCommandIdentifier.java b/lib/src/main/java/net/tomatentum/marinara/interaction/ident/RootCommandIdentifier.java index ae0e6d4..af82d3c 100644 --- a/lib/src/main/java/net/tomatentum/marinara/interaction/ident/RootCommandIdentifier.java +++ b/lib/src/main/java/net/tomatentum/marinara/interaction/ident/RootCommandIdentifier.java @@ -28,7 +28,7 @@ public class RootCommandIdentifier extends SlashCommandIdentifier { private String description; private SlashCommandOption[] options; private long[] serverIds; - + private String[] autocompleteRef; public InteractionIdentifier parent() { return parent; @@ -75,12 +75,21 @@ public class RootCommandIdentifier extends SlashCommandIdentifier { return this; } - public SlashCommandIdentifier build(boolean autocomplete) { + public String[] autocompleteRef() { + return this.autocompleteRef; + } + + public Builder autocompleteRef(String[] autocompleteRef) { + this.autocompleteRef = autocompleteRef; + return this; + } + + public SlashCommandIdentifier build() { return new RootCommandIdentifier( parent, name, description, - autocomplete ? InteractionType.AUTOCOMPLETE : InteractionType.COMMAND, + InteractionType.COMMAND, options, serverIds); } diff --git a/lib/src/main/java/net/tomatentum/marinara/interaction/ident/SlashCommandIdentifier.java b/lib/src/main/java/net/tomatentum/marinara/interaction/ident/SlashCommandIdentifier.java index 7284a2a..1e6b54e 100644 --- a/lib/src/main/java/net/tomatentum/marinara/interaction/ident/SlashCommandIdentifier.java +++ b/lib/src/main/java/net/tomatentum/marinara/interaction/ident/SlashCommandIdentifier.java @@ -12,8 +12,7 @@ public class SlashCommandIdentifier extends InteractionIdentifier { String name, String description, InteractionType type, - SlashCommandOption[] options - ) { + SlashCommandOption[] options) { super(parent, name, description, type); this.options = options; } @@ -27,6 +26,7 @@ public class SlashCommandIdentifier extends InteractionIdentifier { private String name; private String description; private SlashCommandOption[] options; + private String[] autocompleteRef; public InteractionIdentifier parent() { return parent; @@ -64,12 +64,21 @@ public class SlashCommandIdentifier extends InteractionIdentifier { return this; } - public SlashCommandIdentifier build(boolean autocomplete) { + public String[] autocompleteRef() { + return this.autocompleteRef; + } + + public Builder autocompleteRef(String[] autocompleteRef) { + this.autocompleteRef = autocompleteRef; + return this; + } + + public SlashCommandIdentifier build() { return new SlashCommandIdentifier( parent, name, description, - autocomplete ? InteractionType.AUTOCOMPLETE : InteractionType.COMMAND, + InteractionType.COMMAND, options); } diff --git a/lib/src/main/java/net/tomatentum/marinara/interaction/methods/AutoCompleteInteractionMethod.java b/lib/src/main/java/net/tomatentum/marinara/interaction/methods/AutoCompleteInteractionMethod.java index a5d53b4..fb1d4d5 100644 --- a/lib/src/main/java/net/tomatentum/marinara/interaction/methods/AutoCompleteInteractionMethod.java +++ b/lib/src/main/java/net/tomatentum/marinara/interaction/methods/AutoCompleteInteractionMethod.java @@ -1,44 +1,98 @@ package net.tomatentum.marinara.interaction.methods; import java.lang.reflect.Method; +import java.util.List; +import java.util.Optional; +import java.util.Set; -import net.tomatentum.marinara.Marinara; +import net.tomatentum.cutin.MethodParser; +import net.tomatentum.cutin.ReflectedMethodFactory.ParserResults; +import net.tomatentum.cutin.container.MethodContainer; +import net.tomatentum.cutin.method.ReflectedMethod; +import net.tomatentum.marinara.checks.AppliedCheck; +import net.tomatentum.marinara.checks.CheckExecutionContext; +import net.tomatentum.marinara.checks.CheckMethodIdentifier; import net.tomatentum.marinara.interaction.InteractionHandler; +import net.tomatentum.marinara.interaction.InteractionType; import net.tomatentum.marinara.interaction.ident.InteractionIdentifier; -import net.tomatentum.marinara.parser.AnnotationParser; -import net.tomatentum.marinara.parser.SlashCommandParser; +import net.tomatentum.marinara.parser.AutocompleteParser; +import net.tomatentum.marinara.parser.InteractionCheckParser; +import net.tomatentum.marinara.wrapper.ContextObjectProvider; public class AutoCompleteInteractionMethod extends InteractionMethod { - private InteractionIdentifier interactionIdentifier; + private String autocompleteRef; + private ContextObjectProvider cop; - public AutoCompleteInteractionMethod(Method method, - InteractionHandler handler, - Marinara marinara + private AutoCompleteInteractionMethod( + Method method, + InteractionHandler handler, + List appliedChecks, + String autocompleteRef, + ContextObjectProvider cop ) { - super(method, handler, marinara); - } - - @Override - public AnnotationParser[] parsers() { - return new AnnotationParser[] { - new SlashCommandParser(method, true, (x) -> { this.interactionIdentifier = x; } ) - }; + super(method, handler, appliedChecks); + this.autocompleteRef = autocompleteRef; + this.cop = cop; } @Override public Object getParameter(Object context, int index) { - Class type = method().getParameterTypes()[index+1]; - Object autocompleteOptionValue = marinara.getWrapper().getContextObjectProvider().getAutocompleteFocusedOption(context); - if (autocompleteOptionValue != null) + Class type = method().getParameterTypes()[index]; + Object contextObject = this.cop.getInteractionContextObject(context, type); + if (contextObject != null) + return contextObject; + + Object autocompleteOptionValue = this.cop.getAutocompleteFocusedOption(context).input(); + if (type.isInstance(autocompleteOptionValue)) return autocompleteOptionValue; - return marinara.getWrapper().getContextObjectProvider().getInteractionContextObject(context, type); + return super.getParameter(context, index); } @Override public InteractionIdentifier identifier() { - return interactionIdentifier; + return InteractionIdentifier.builder() + .type(InteractionType.AUTOCOMPLETE) + .name(autocompleteRef) + .description("AUTOCOMPLETE") + .build(); + } + + public static class Factory extends InteractionMethod.Factory { + + private ContextObjectProvider cop; + + public Factory(MethodContainer checkContainer, ContextObjectProvider cop) { + super(checkContainer); + this.cop = cop; + } + + @Override + public Optional> produce(Method method, Object containingObject, ParserResults parserResults) { + if (!(containingObject instanceof InteractionHandler)) return Optional.empty(); + String[] autocompletes = parserResults.get(AutocompleteParser.class); + if (autocompletes.length <= 0) return Optional.empty(); + + return Optional.of(new AutoCompleteInteractionMethod( + method, + (InteractionHandler) containingObject, + parserResults.get(InteractionCheckParser.class), + autocompletes[0], + cop + )); + + } + + @Override + public void addParser(Set parser) { + super.addParser(parser); + + parser.add( + new AutocompleteParser() + ); + } + } } diff --git a/lib/src/main/java/net/tomatentum/marinara/interaction/methods/ButtonInteractionMethod.java b/lib/src/main/java/net/tomatentum/marinara/interaction/methods/ButtonInteractionMethod.java deleted file mode 100644 index ec011a4..0000000 --- a/lib/src/main/java/net/tomatentum/marinara/interaction/methods/ButtonInteractionMethod.java +++ /dev/null @@ -1,42 +0,0 @@ -package net.tomatentum.marinara.interaction.methods; - -import java.lang.reflect.Method; - -import net.tomatentum.marinara.Marinara; -import net.tomatentum.marinara.interaction.InteractionHandler; -import net.tomatentum.marinara.interaction.InteractionType; -import net.tomatentum.marinara.interaction.ident.InteractionIdentifier; -import net.tomatentum.marinara.parser.AnnotationParser; -import net.tomatentum.marinara.parser.ButtonParser; - -public class ButtonInteractionMethod extends InteractionMethod { - - private String customId; - - ButtonInteractionMethod(Method method, InteractionHandler handler, Marinara marinara) { - super(method, handler, marinara); - } - - @Override - public AnnotationParser[] parsers() { - return new AnnotationParser[] { - new ButtonParser(method, (x) -> { this.customId = x; } ) - }; - } - - @Override - public Object getParameter(Object context, int index) { - Class type = method().getParameterTypes()[index+1]; - return marinara.getWrapper().getContextObjectProvider().getComponentContextObject(context, type); - } - - @Override - public InteractionIdentifier identifier() { - return InteractionIdentifier.builder() - .name(customId) - .description("Button") - .type(InteractionType.BUTTON) - .build(); - } - -} diff --git a/lib/src/main/java/net/tomatentum/marinara/interaction/methods/InteractionMethod.java b/lib/src/main/java/net/tomatentum/marinara/interaction/methods/InteractionMethod.java index 9fdda56..12fbb53 100644 --- a/lib/src/main/java/net/tomatentum/marinara/interaction/methods/InteractionMethod.java +++ b/lib/src/main/java/net/tomatentum/marinara/interaction/methods/InteractionMethod.java @@ -1,105 +1,72 @@ package net.tomatentum.marinara.interaction.methods; -import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; -import java.security.InvalidParameterException; -import java.util.ArrayList; -import java.util.Arrays; import java.util.List; +import java.util.Set; -import org.slf4j.Logger; - -import net.tomatentum.marinara.Marinara; +import net.tomatentum.cutin.MethodParser; +import net.tomatentum.cutin.ReflectedMethodFactory; +import net.tomatentum.cutin.container.MethodContainer; +import net.tomatentum.cutin.method.ReflectedMethod; import net.tomatentum.marinara.checks.AppliedCheck; +import net.tomatentum.marinara.checks.CheckExecutionContext; +import net.tomatentum.marinara.checks.CheckMethodIdentifier; import net.tomatentum.marinara.interaction.InteractionHandler; -import net.tomatentum.marinara.interaction.annotation.AutoComplete; -import net.tomatentum.marinara.interaction.annotation.Button; -import net.tomatentum.marinara.interaction.commands.annotation.SlashCommand; -import net.tomatentum.marinara.interaction.commands.annotation.SubCommand; import net.tomatentum.marinara.interaction.ident.InteractionIdentifier; -import net.tomatentum.marinara.parser.AnnotationParser; import net.tomatentum.marinara.parser.InteractionCheckParser; -import net.tomatentum.marinara.util.LoggerUtil; -import net.tomatentum.marinara.util.ReflectionUtil; -public abstract class InteractionMethod { +public abstract class InteractionMethod extends ReflectedMethod { - public static InteractionMethod create(Method method, InteractionHandler handler, Marinara marinara) { - if (method.isAnnotationPresent(AutoComplete.class)) - return new AutoCompleteInteractionMethod(method, handler, marinara); - if (method.isAnnotationPresent(SlashCommand.class) || method.isAnnotationPresent(SubCommand.class)) - return new SlashCommandInteractionMethod(method, handler, marinara); - if (method.isAnnotationPresent(Button.class)) - return new ButtonInteractionMethod(method, handler, marinara); - return null; - } - - protected Method method; - protected InteractionHandler handler; - protected Marinara marinara; - protected List parsers; protected List appliedChecks; - private Logger logger = LoggerUtil.getLogger(getClass()); - protected InteractionMethod( Method method, - InteractionHandler handler, - Marinara marinara + InteractionHandler handler, + List appliedChecks ) { - if (!Arrays.asList(handler.getClass().getMethods()).contains(method)) - throw new InvalidParameterException("Method does not apply to specified handler"); - - this.method = method; - this.handler = handler; - this.marinara = marinara; - this.parsers = new ArrayList<>(Arrays.asList(parsers())); - this.appliedChecks = new ArrayList<>(); - - parsers.add(new InteractionCheckParser(method, appliedChecks::add, marinara.getCheckRegistry())); - - parsers.stream().forEach(AnnotationParser::parse); + super(method, handler); + this.appliedChecks = appliedChecks; } - public void run(Object context) { + @Override + public Object getParameter(Object context, int index) { + if (index == 0) + return context; + return null; + } + + @Override + public Object run(Object context) { + Object result = null; if (this.appliedChecks.stream().filter(x -> !x.pre(context)).count() > 0) - return; + return null; - method.setAccessible(true); - try { - method.invoke(handler, getParameters(context)); - }catch (IllegalAccessException | InvocationTargetException ex) { - logger.error("InteractionMethod failed to run", ex); - } + result = super.run(context); this.appliedChecks.forEach(x -> x.post(context)); + + return result; } - public abstract AnnotationParser[] parsers(); - - public abstract Object getParameter(Object context, int index); - - public abstract InteractionIdentifier identifier(); - - public Method method() { - return method; + public List appliedChecks() { + return this.appliedChecks; } - private Object[] getParameters(Object context) { - int parameterCount = method.getParameterCount(); - List parameters = new ArrayList<>(); - - for (int i = 0; i < parameterCount; i++) { - Object parameter; - if (i == 0) { - parameter = context; - }else - parameter = getParameter(context, i-1); + public abstract static class Factory implements ReflectedMethodFactory.Factory { - logger.trace("Found parameter {}={} for method {}", parameter != null ? parameter.getClass().toString() : " ", parameter, ReflectionUtil.getFullMethodName(method)); - parameters.add(parameter); + private MethodContainer checkContainer; + + protected Factory(MethodContainer checkContainer) { + this.checkContainer = checkContainer; } - return parameters.toArray(); + + @Override + public void addParser(Set parser) { + parser.add( + new InteractionCheckParser(this.checkContainer) + ); + } + } } diff --git a/lib/src/main/java/net/tomatentum/marinara/interaction/methods/SlashCommandInteractionMethod.java b/lib/src/main/java/net/tomatentum/marinara/interaction/methods/SlashCommandInteractionMethod.java index d89d709..87fe208 100644 --- a/lib/src/main/java/net/tomatentum/marinara/interaction/methods/SlashCommandInteractionMethod.java +++ b/lib/src/main/java/net/tomatentum/marinara/interaction/methods/SlashCommandInteractionMethod.java @@ -1,37 +1,87 @@ package net.tomatentum.marinara.interaction.methods; import java.lang.reflect.Method; +import java.util.List; +import java.util.Optional; +import java.util.Set; -import net.tomatentum.marinara.Marinara; +import net.tomatentum.cutin.MethodParser; +import net.tomatentum.cutin.ReflectedMethodFactory.ParserResults; +import net.tomatentum.cutin.container.MethodContainer; +import net.tomatentum.cutin.method.ReflectedMethod; +import net.tomatentum.marinara.checks.AppliedCheck; +import net.tomatentum.marinara.checks.CheckExecutionContext; +import net.tomatentum.marinara.checks.CheckMethodIdentifier; import net.tomatentum.marinara.interaction.InteractionHandler; import net.tomatentum.marinara.interaction.ident.InteractionIdentifier; import net.tomatentum.marinara.interaction.ident.SlashCommandIdentifier; -import net.tomatentum.marinara.parser.AnnotationParser; +import net.tomatentum.marinara.parser.InteractionCheckParser; import net.tomatentum.marinara.parser.SlashCommandParser; +import net.tomatentum.marinara.wrapper.ContextObjectProvider; public class SlashCommandInteractionMethod extends InteractionMethod { - private SlashCommandIdentifier interactionIdentifier; + private SlashCommandIdentifier identifier; + private ContextObjectProvider cop; - SlashCommandInteractionMethod(Method method, InteractionHandler handler, Marinara marinara) { - super(method, handler, marinara); - } - - @Override - public AnnotationParser[] parsers() { - return new AnnotationParser[] { - new SlashCommandParser(method, false, (x) -> { this.interactionIdentifier = x; } ) - }; + private SlashCommandInteractionMethod( + Method method, + InteractionHandler handler, + List appliedChecks, + SlashCommandIdentifier identifier, + ContextObjectProvider cop + ) { + super(method, handler, appliedChecks); + this.identifier = identifier; + this.cop = cop; } @Override public Object getParameter(Object context, int index) { - return marinara.getWrapper().getContextObjectProvider().convertCommandOption(context, interactionIdentifier.options()[index].name()); + Object superResult = super.getParameter(context, index); + if (superResult == null) + return this.cop.convertCommandOption(context, identifier.options()[index-1].name()); + else + return superResult; } @Override public InteractionIdentifier identifier() { - return interactionIdentifier; + return identifier; + } + + public static class Factory extends InteractionMethod.Factory { + + private ContextObjectProvider cop; + + public Factory(MethodContainer checkContainer, ContextObjectProvider cop) { + super(checkContainer); + this.cop = cop; + } + + @Override + public Optional> produce(Method method, Object containingObject, ParserResults parserResults) { + if (!(containingObject instanceof InteractionHandler)) return Optional.empty(); + SlashCommandIdentifier ident = parserResults.get(SlashCommandParser.class); + if (ident == null) return Optional.empty(); + return Optional.of(new SlashCommandInteractionMethod( + method, + (InteractionHandler) containingObject, + parserResults.get(InteractionCheckParser.class), + ident, + cop + )); + } + + @Override + public void addParser(Set parser) { + super.addParser(parser); + + parser.add( + new SlashCommandParser() + ); + } + } } diff --git a/lib/src/main/java/net/tomatentum/marinara/interaction/processor/AutocompleteInteractionProcessor.java b/lib/src/main/java/net/tomatentum/marinara/interaction/processor/AutocompleteInteractionProcessor.java new file mode 100644 index 0000000..1d02b92 --- /dev/null +++ b/lib/src/main/java/net/tomatentum/marinara/interaction/processor/AutocompleteInteractionProcessor.java @@ -0,0 +1,54 @@ +package net.tomatentum.marinara.interaction.processor; + +import java.util.Arrays; +import java.util.List; +import java.util.Objects; +import java.util.Optional; +import java.util.Set; + +import net.tomatentum.cutin.container.MethodContainer; +import net.tomatentum.marinara.interaction.InteractionType; +import net.tomatentum.marinara.interaction.ident.InteractionIdentifier; +import net.tomatentum.marinara.interaction.ident.SlashCommandIdentifier; +import net.tomatentum.marinara.wrapper.IdentifierProvider; +import net.tomatentum.marinara.wrapper.LibraryWrapper; + +public class AutocompleteInteractionProcessor extends InteractionMethodProcessor { + + private LibraryWrapper wrapper; + + public AutocompleteInteractionProcessor(LibraryWrapper wrapper, IdentifierProvider provider) { + super(provider, Set.of(InteractionType.AUTOCOMPLETE)); + this.wrapper = wrapper; + } + + @Override + public void processInteraction(Object context, MethodContainer container, InteractionIdentifier identifier) { + Optional oIdent = container.identifiers().stream() + .filter(i -> convertToCommandIdentifier(identifier).equals(i)) + .findFirst(); + if (oIdent.isPresent() && oIdent.get() instanceof SlashCommandIdentifier sIdent) { + List autocompleteRefs = Arrays.asList(this.wrapper.getContextObjectProvider() + .getAutocompleteFocusedOption(context).getAutocompleteRefs(sIdent.options())); + List results = container.methods().stream() + .filter(m -> m.identifier().type().equals(InteractionType.AUTOCOMPLETE)) + .filter(m -> autocompleteRefs.contains(m.identifier().name())) + .map(m -> m.run(context)) + .filter(Objects::nonNull) + .toList(); + if (!results.isEmpty()) + this.wrapper.respondAutocomplete(context, results); + } + } + + private InteractionIdentifier convertToCommandIdentifier(InteractionIdentifier identifier) { + if (Objects.isNull(identifier)) + return null; + return InteractionIdentifier.builder() + .type(InteractionType.COMMAND) + .name(identifier.name()) + .parent(convertToCommandIdentifier(identifier.parent())) + .build(); + } + +} diff --git a/lib/src/main/java/net/tomatentum/marinara/interaction/processor/DirectInteractionProcessor.java b/lib/src/main/java/net/tomatentum/marinara/interaction/processor/DirectInteractionProcessor.java new file mode 100644 index 0000000..6856d2f --- /dev/null +++ b/lib/src/main/java/net/tomatentum/marinara/interaction/processor/DirectInteractionProcessor.java @@ -0,0 +1,22 @@ +package net.tomatentum.marinara.interaction.processor; + +import java.util.Set; + +import net.tomatentum.cutin.container.MethodContainer; +import net.tomatentum.marinara.interaction.InteractionType; +import net.tomatentum.marinara.interaction.ident.InteractionIdentifier; +import net.tomatentum.marinara.wrapper.IdentifierProvider; + +public class DirectInteractionProcessor extends InteractionMethodProcessor { + + + public DirectInteractionProcessor(IdentifierProvider provider, InteractionType... types) { + super(provider, Set.of(types)); + } + + @Override + protected void processInteraction(Object context, MethodContainer container, InteractionIdentifier identifier) { + container.findFor(identifier).forEach(m -> m.run(context)); + } + +} diff --git a/lib/src/main/java/net/tomatentum/marinara/interaction/processor/InteractionMethodProcessor.java b/lib/src/main/java/net/tomatentum/marinara/interaction/processor/InteractionMethodProcessor.java new file mode 100644 index 0000000..273ff00 --- /dev/null +++ b/lib/src/main/java/net/tomatentum/marinara/interaction/processor/InteractionMethodProcessor.java @@ -0,0 +1,39 @@ +package net.tomatentum.marinara.interaction.processor; + +import java.util.Set; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import net.tomatentum.cutin.MethodProcessor; +import net.tomatentum.cutin.container.MethodContainer; +import net.tomatentum.marinara.interaction.InteractionType; +import net.tomatentum.marinara.interaction.ident.InteractionIdentifier; +import net.tomatentum.marinara.wrapper.IdentifierProvider; + +public abstract class InteractionMethodProcessor implements MethodProcessor { + + private Logger logger = LoggerFactory.getLogger(getClass()); + + private IdentifierProvider provider; + private Set types; + + protected InteractionMethodProcessor(IdentifierProvider provider, Set types) { + this.provider = provider; + this.types = types; + } + + @Override + public void process(Object context, MethodContainer container) { + InteractionIdentifier identifier = this.provider.provide(context); + if (!this.types.contains(identifier.type())) return; + logger.debug("Processing {} : {} with context {}", identifier, identifier.type(), context); + this.processInteraction(context, container, identifier); + } + + protected abstract void processInteraction( + Object context, + MethodContainer container, + InteractionIdentifier identifier); + +} diff --git a/lib/src/main/java/net/tomatentum/marinara/parser/AnnotationParser.java b/lib/src/main/java/net/tomatentum/marinara/parser/AnnotationParser.java deleted file mode 100644 index 187a4a4..0000000 --- a/lib/src/main/java/net/tomatentum/marinara/parser/AnnotationParser.java +++ /dev/null @@ -1,8 +0,0 @@ -package net.tomatentum.marinara.parser; - -import java.lang.reflect.Method; - -public interface AnnotationParser { - void parse(); - Method getMethod(); -} diff --git a/lib/src/main/java/net/tomatentum/marinara/parser/AutocompleteParser.java b/lib/src/main/java/net/tomatentum/marinara/parser/AutocompleteParser.java new file mode 100644 index 0000000..c325b6a --- /dev/null +++ b/lib/src/main/java/net/tomatentum/marinara/parser/AutocompleteParser.java @@ -0,0 +1,27 @@ +package net.tomatentum.marinara.parser; + +import java.lang.reflect.Method; +import java.util.Arrays; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import net.tomatentum.cutin.MethodParser; +import net.tomatentum.cutin.util.ReflectionUtil; +import net.tomatentum.marinara.interaction.annotation.AutoComplete; + +public class AutocompleteParser implements MethodParser { + + private Logger logger = LoggerFactory.getLogger(getClass()); + + @Override + public Object parse(Method method, Object containingObject) { + String[] autoCompletes = Arrays.stream(method.getAnnotationsByType(AutoComplete.class)) + .map(AutoComplete::value) + .toArray(String[]::new); + if (autoCompletes.length > 0) + logger.trace("Parsed AutoComplete annotations {} for method {}", autoCompletes, ReflectionUtil.getFullMethodName(method)); + return autoCompletes; + } + +} diff --git a/lib/src/main/java/net/tomatentum/marinara/parser/ButtonParser.java b/lib/src/main/java/net/tomatentum/marinara/parser/ButtonParser.java index ee8ab37..98f9aaa 100644 --- a/lib/src/main/java/net/tomatentum/marinara/parser/ButtonParser.java +++ b/lib/src/main/java/net/tomatentum/marinara/parser/ButtonParser.java @@ -1,36 +1,27 @@ package net.tomatentum.marinara.parser; import java.lang.reflect.Method; -import java.util.function.Consumer; import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import net.tomatentum.cutin.MethodParser; +import net.tomatentum.cutin.util.ReflectionUtil; import net.tomatentum.marinara.interaction.annotation.Button; -import net.tomatentum.marinara.util.LoggerUtil; -import net.tomatentum.marinara.util.ReflectionUtil; -public class ButtonParser implements AnnotationParser { +public class ButtonParser implements MethodParser { - private Method method; - private Consumer consumer; + private Logger logger = LoggerFactory.getLogger(getClass()); - private Logger logger = LoggerUtil.getLogger(getClass()); - - public ButtonParser(Method method, Consumer consumer) { - this.method = method; - this.consumer = consumer; + public ButtonParser() { } @Override - public void parse() { - Button button = getMethod().getAnnotation(Button.class); - logger.trace("Parsed Button annotation {} for method {}", button.toString(), ReflectionUtil.getFullMethodName(method)); - this.consumer.accept(button.value()); - } - - @Override - public Method getMethod() { - return this.method; + public Object parse(Method method, Object containingObject) { + Button button = method.getAnnotation(Button.class); + if (button == null) return null; + logger.trace("Parsed Button annotation {} for method {}", button, ReflectionUtil.getFullMethodName(method)); + return button.value(); } } diff --git a/lib/src/main/java/net/tomatentum/marinara/parser/InteractionCheckClassParser.java b/lib/src/main/java/net/tomatentum/marinara/parser/InteractionCheckClassParser.java new file mode 100644 index 0000000..db0457c --- /dev/null +++ b/lib/src/main/java/net/tomatentum/marinara/parser/InteractionCheckClassParser.java @@ -0,0 +1,28 @@ +package net.tomatentum.marinara.parser; + +import java.lang.reflect.Method; +import java.lang.reflect.ParameterizedType; +import java.lang.reflect.Type; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import io.leangen.geantyref.GenericTypeReflector; +import net.tomatentum.cutin.MethodParser; +import net.tomatentum.marinara.checks.InteractionCheck; + +public class InteractionCheckClassParser implements MethodParser { + + private Logger logger = LoggerFactory.getLogger(getClass()); + + @Override + public Object parse(Method method, Object containingObject) { + ParameterizedType type = (ParameterizedType) GenericTypeReflector.getExactSuperType(containingObject.getClass(), InteractionCheck.class); + if (type == null) return null; + Type typeParam = type.getActualTypeArguments().length == 1 ? type.getActualTypeArguments()[0] : null; + if (typeParam != null) + logger.trace("Parsed InteractionCheck Annotation {}", typeParam); + return typeParam; + } + +} diff --git a/lib/src/main/java/net/tomatentum/marinara/parser/InteractionCheckParser.java b/lib/src/main/java/net/tomatentum/marinara/parser/InteractionCheckParser.java index 7379141..7faa568 100644 --- a/lib/src/main/java/net/tomatentum/marinara/parser/InteractionCheckParser.java +++ b/lib/src/main/java/net/tomatentum/marinara/parser/InteractionCheckParser.java @@ -3,49 +3,47 @@ package net.tomatentum.marinara.parser; import java.lang.annotation.Annotation; import java.lang.reflect.Method; import java.util.Arrays; -import java.util.Optional; -import java.util.function.Consumer; +import java.util.Objects; import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import net.tomatentum.cutin.MethodParser; +import net.tomatentum.cutin.container.MethodContainer; +import net.tomatentum.cutin.util.ReflectionUtil; import net.tomatentum.marinara.checks.AppliedCheck; -import net.tomatentum.marinara.checks.InteractionCheck; -import net.tomatentum.marinara.registry.InteractionCheckRegistry; -import net.tomatentum.marinara.util.LoggerUtil; -import net.tomatentum.marinara.util.ReflectionUtil; +import net.tomatentum.marinara.checks.CheckExecutionContext; +import net.tomatentum.marinara.checks.CheckMethodIdentifier; +import net.tomatentum.marinara.checks.CheckMethodIdentifier.CheckMethodType; -public class InteractionCheckParser implements AnnotationParser { +public class InteractionCheckParser implements MethodParser { - private InteractionCheckRegistry checkRegistry; - private Method method; - private Consumer consumer; + private MethodContainer checkContainer; - private Logger logger = LoggerUtil.getLogger(getClass()); + private Logger logger = LoggerFactory.getLogger(getClass()); - public InteractionCheckParser(Method method, Consumer consumer, InteractionCheckRegistry checkRegistry) { - this.checkRegistry = checkRegistry; - this.method = method; - this.consumer = consumer; + public InteractionCheckParser(MethodContainer checkContainer) { + this.checkContainer = checkContainer; } @Override - public void parse() { + public Object parse(Method method, Object containingObject) { Annotation[] annotations = method.getAnnotations(); - Arrays.stream(annotations).forEach(this::convertAnnotation); + return Arrays.stream(annotations) + .map(a -> convertAnnotation(a, method)) + .filter(Objects::nonNull) + .toList(); } - private void convertAnnotation(Annotation annotation) { - Optional> check = this.checkRegistry.getCheckFromAnnotation(annotation.annotationType()); - if (check.isPresent()) { - AppliedCheck appliedCheck = new AppliedCheck(check.get(), annotation); - logger.trace("Parsed InteractionCheck {} for annotation {} for method {}", check.getClass().getName(), annotation.toString(), ReflectionUtil.getFullMethodName(method)); - consumer.accept(appliedCheck); + private AppliedCheck convertAnnotation(Annotation annotation, Method method) { + var preExec = this.checkContainer.findFirstFor(new CheckMethodIdentifier(annotation.annotationType(), CheckMethodType.PRE)); + var postExec = this.checkContainer.findFirstFor(new CheckMethodIdentifier(annotation.annotationType(), CheckMethodType.POST)); + if (preExec.isPresent() && postExec.isPresent()) { + AppliedCheck appliedCheck = new AppliedCheck(annotation, preExec.get(), postExec.get()); + logger.trace("Parsed InteractionCheck {} for annotation {} for method {}", preExec.get().containingObject(), annotation, ReflectionUtil.getFullMethodName(method)); + return appliedCheck; } - } - - @Override - public Method getMethod() { - return this.method; + return null; } } diff --git a/lib/src/main/java/net/tomatentum/marinara/parser/SlashCommandParser.java b/lib/src/main/java/net/tomatentum/marinara/parser/SlashCommandParser.java index c598761..ad75258 100644 --- a/lib/src/main/java/net/tomatentum/marinara/parser/SlashCommandParser.java +++ b/lib/src/main/java/net/tomatentum/marinara/parser/SlashCommandParser.java @@ -1,35 +1,28 @@ package net.tomatentum.marinara.parser; import java.lang.reflect.Method; -import java.util.function.Consumer; import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import net.tomatentum.cutin.MethodParser; +import net.tomatentum.cutin.util.ReflectionUtil; import net.tomatentum.marinara.interaction.InteractionType; import net.tomatentum.marinara.interaction.commands.annotation.SlashCommand; import net.tomatentum.marinara.interaction.commands.annotation.SubCommand; import net.tomatentum.marinara.interaction.commands.annotation.SubCommandGroup; import net.tomatentum.marinara.interaction.ident.InteractionIdentifier; -import net.tomatentum.marinara.interaction.ident.SlashCommandIdentifier; -import net.tomatentum.marinara.util.LoggerUtil; -import net.tomatentum.marinara.util.ReflectionUtil; -public class SlashCommandParser implements AnnotationParser { +public class SlashCommandParser implements MethodParser { - private Method method; - private boolean isAutoComplete; - private Consumer consumer; + private Logger logger = LoggerFactory.getLogger(getClass()); - private Logger logger = LoggerUtil.getLogger(getClass()); - - public SlashCommandParser(Method method, boolean isAutoComplete, Consumer consumer) { - this.method = method; - this.isAutoComplete = isAutoComplete; - this.consumer = consumer; + public SlashCommandParser() { } @Override - public void parse() { + public Object parse(Method method, Object containingObject) { + if (!method.isAnnotationPresent(SlashCommand.class) && !method.isAnnotationPresent(SubCommand.class)) return null; this.checkValidCommandMethod(method); SlashCommand cmd = ReflectionUtil.getAnnotation(method, SlashCommand.class); @@ -38,14 +31,14 @@ public class SlashCommandParser implements AnnotationParser { .description(cmd.description()) .options(cmd.options()) .serverIds(cmd.serverIds()) - .build(isAutoComplete); + .build(); if (ReflectionUtil.isAnnotationPresent(method, SubCommandGroup.class)) { SubCommandGroup cmdGroup = ReflectionUtil.getAnnotation(method, SubCommandGroup.class); lastIdentifier = InteractionIdentifier.builder() .name(cmdGroup.name()) .description(cmdGroup.description()) - .type(isAutoComplete ? InteractionType.AUTOCOMPLETE : InteractionType.COMMAND) + .type(InteractionType.COMMAND) .parent(lastIdentifier) .build(); } @@ -56,30 +49,25 @@ public class SlashCommandParser implements AnnotationParser { .name(subCmd.name()) .description(subCmd.description()) .options(subCmd.options()) - .build(isAutoComplete); + .build(); } - logger.trace("Parsed using SlashCommandParser for method {} with the result: {}", ReflectionUtil.getFullMethodName(method), lastIdentifier.toString()); - consumer.accept((SlashCommandIdentifier) lastIdentifier); - } - - @Override - public Method getMethod() { - return this.method; + logger.trace("Parsed using SlashCommandParser for method {} with the result: {}", ReflectionUtil.getFullMethodName(method), lastIdentifier); + return lastIdentifier; } private void checkValidCommandMethod(Method method) { if (method.isAnnotationPresent(SlashCommand.class) && method.getDeclaringClass().isAnnotationPresent(SlashCommand.class)) { - throw new RuntimeException(method.getName() + ": Can't have ApplicationCommand Annotation on Class and Method"); + throw new RuntimeException(method.getName() + ": Can't have SlashCommand Annotation on Class and Method"); } if (!ReflectionUtil.isAnnotationPresent(method, SlashCommand.class)) - throw new RuntimeException(method.getName() + ": Missing ApplicationCommand Annotation on either Class or Method"); + throw new RuntimeException(method.getName() + ": Missing SlashCommand Annotation on either Class or Method"); if ((method.isAnnotationPresent(SubCommand.class) && !ReflectionUtil.isAnnotationPresent(method, SlashCommand.class))) { - throw new RuntimeException(method.getName() + ": Missing ApplicationCommand Annotation on either Method or Class"); + throw new RuntimeException(method.getName() + ": Missing SlashCommand Annotation on either Method or Class"); } } diff --git a/lib/src/main/java/net/tomatentum/marinara/registry/InteractionCheckRegistry.java b/lib/src/main/java/net/tomatentum/marinara/registry/InteractionCheckRegistry.java deleted file mode 100644 index 1093adf..0000000 --- a/lib/src/main/java/net/tomatentum/marinara/registry/InteractionCheckRegistry.java +++ /dev/null @@ -1,40 +0,0 @@ -package net.tomatentum.marinara.registry; - -import java.lang.reflect.ParameterizedType; -import java.lang.reflect.Type; -import java.util.ArrayList; -import java.util.List; -import java.util.Optional; - -import org.slf4j.Logger; - -import io.leangen.geantyref.GenericTypeReflector; -import net.tomatentum.marinara.checks.InteractionCheck; -import net.tomatentum.marinara.util.LoggerUtil; - -public class InteractionCheckRegistry { - - private List> checks; - - private Logger logger = LoggerUtil.getLogger(getClass()); - - public InteractionCheckRegistry() { - this.checks = new ArrayList<>(); - } - - public void addCheck(InteractionCheck check) { - checks.add(check); - logger.info("Registered Check {}", check.getClass().getName()); - } - - public Optional> getCheckFromAnnotation(Type annotation) { - for (InteractionCheck interactionCheck : checks) { - ParameterizedType type = (ParameterizedType) GenericTypeReflector.getExactSuperType(interactionCheck.getClass(), InteractionCheck.class); - Type typeParam = type.getActualTypeArguments()[0]; - if (typeParam.equals(annotation)) - return Optional.of(interactionCheck); - } - return Optional.empty(); - } - -} diff --git a/lib/src/main/java/net/tomatentum/marinara/registry/InteractionEntry.java b/lib/src/main/java/net/tomatentum/marinara/registry/InteractionEntry.java deleted file mode 100644 index 2d2868a..0000000 --- a/lib/src/main/java/net/tomatentum/marinara/registry/InteractionEntry.java +++ /dev/null @@ -1,65 +0,0 @@ -package net.tomatentum.marinara.registry; - -import java.util.HashSet; -import java.util.Set; - -import org.slf4j.Logger; - -import net.tomatentum.marinara.interaction.InteractionType; -import net.tomatentum.marinara.interaction.ident.InteractionIdentifier; -import net.tomatentum.marinara.interaction.methods.InteractionMethod; -import net.tomatentum.marinara.util.LoggerUtil; - -public class InteractionEntry { - private InteractionIdentifier identifier; - private Set methods; - - private Logger logger = LoggerUtil.getLogger(getClass()); - - public InteractionEntry(InteractionIdentifier identifier) { - this.identifier = identifier; - this.methods = new HashSet<>(); - } - - public InteractionEntry addMethod(InteractionMethod method) { - if (!method.identifier().equals(this.identifier)) - throw new IllegalArgumentException("Method's identifier did not match the entry's identifier"); - - this.methods.add(method); - InteractionIdentifier.tryAddDescriptions(identifier, method.identifier()); - return this; - } - - public void runAll(Object context) { - this.methods.stream().forEach(x -> { - logger.debug("Running Method {} from {} with context {}", x.toString(), this.toString(), context.toString()); - x.run(context); - }); - } - - @Override - public boolean equals(Object obj) { - if (!(obj instanceof InteractionEntry)) - return false; - InteractionEntry other = (InteractionEntry) obj; - return other.identifier().equals(identifier()); - } - - @Override - public String toString() { - return "InteractionEntry(%s)".formatted(identifier().toString()); - } - - public InteractionType type() { - return identifier().type(); - } - - public InteractionIdentifier identifier() { - return identifier; - } - - public Set methods() { - return methods; - } - -} diff --git a/lib/src/main/java/net/tomatentum/marinara/registry/InteractionRegistry.java b/lib/src/main/java/net/tomatentum/marinara/registry/InteractionRegistry.java deleted file mode 100644 index be5678d..0000000 --- a/lib/src/main/java/net/tomatentum/marinara/registry/InteractionRegistry.java +++ /dev/null @@ -1,80 +0,0 @@ -package net.tomatentum.marinara.registry; - -import java.lang.reflect.Method; -import java.util.Arrays; -import java.util.HashSet; -import java.util.List; -import java.util.Optional; -import java.util.Set; - -import org.slf4j.Logger; - -import net.tomatentum.marinara.Marinara; -import net.tomatentum.marinara.interaction.InteractionHandler; -import net.tomatentum.marinara.interaction.InteractionType; -import net.tomatentum.marinara.interaction.commands.SlashCommandDefinition; -import net.tomatentum.marinara.interaction.ident.InteractionIdentifier; -import net.tomatentum.marinara.interaction.ident.RootCommandIdentifier; -import net.tomatentum.marinara.util.LoggerUtil; -import net.tomatentum.marinara.util.ObjectAggregator; -import net.tomatentum.marinara.wrapper.IdentifierProvider; -import net.tomatentum.marinara.interaction.methods.InteractionMethod; - -public class InteractionRegistry { - private Logger logger = LoggerUtil.getLogger(getClass()); - private Set interactions; - private Marinara marinara; - private IdentifierProvider identifierProvider; - - public InteractionRegistry(Marinara marinara) { - this.interactions = new HashSet<>(); - this.marinara = marinara; - this.identifierProvider = marinara.getWrapper().createIdentifierProvider(); - marinara.getWrapper().subscribeInteractions(this::handle); - } - - /* - * TODO: Maybe relocate InteractionEntry checking to another class with description merging. - */ - public void addInteractions(InteractionHandler interactionHandler) { - for (Method method : interactionHandler.getClass().getMethods()) { - InteractionMethod iMethod = InteractionMethod.create(method, interactionHandler, marinara); - if (iMethod != null) { - Optional oentry = this.interactions.stream() - .filter(i -> i.identifier().equals(iMethod.identifier())) - .findFirst(); - - InteractionEntry entry = oentry.orElse(new InteractionEntry(iMethod.identifier())).addMethod(iMethod); - if (oentry.isEmpty()) this.interactions.add(entry); - logger.debug("Added {} method from {}", iMethod.method().getName(), interactionHandler.getClass().getSimpleName()); - } - } - logger.info("Added all Interactions from {}", interactionHandler.getClass().getSimpleName()); - } - - public void registerCommands() { - List slashIdentifiers = interactions.stream() - .filter((x) -> x.type().equals(InteractionType.COMMAND)) - .map((x) -> x.identifier()) - .toList(); - - SlashCommandDefinition[] defs = new ObjectAggregator( - i -> Arrays.asList((RootCommandIdentifier)i.rootNode()), - SlashCommandDefinition::addIdentifier, - SlashCommandDefinition::new) - .aggregate(slashIdentifiers) - .toArray(SlashCommandDefinition[]::new); - - marinara.getWrapper().getRegisterer().register(defs); - } - - public void handle(Object context) { - logger.debug("Received {} interaction ", context); - interactions.forEach((e) -> { - if (this.identifierProvider.provide(context).equals(e.identifier())) { - logger.info("Running {} interaction using {}\ncontext: {}", e.type(), e.toString(), context.toString()); - e.runAll(context); - } - }); - } -} diff --git a/lib/src/main/java/net/tomatentum/marinara/util/LoggerUtil.java b/lib/src/main/java/net/tomatentum/marinara/util/LoggerUtil.java deleted file mode 100644 index 54eb77b..0000000 --- a/lib/src/main/java/net/tomatentum/marinara/util/LoggerUtil.java +++ /dev/null @@ -1,17 +0,0 @@ -package net.tomatentum.marinara.util; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.slf4j.helpers.NOPLoggerFactory; - -public class LoggerUtil { - public static Logger getLogger(String name) { - if (LoggerFactory.getILoggerFactory() instanceof NOPLoggerFactory) - return new SimpleLogger(name); - return LoggerFactory.getLogger(name); - } - - public static Logger getLogger(Class clazz) { - return getLogger(clazz.getName()); - } -} diff --git a/lib/src/main/java/net/tomatentum/marinara/util/ReflectionUtil.java b/lib/src/main/java/net/tomatentum/marinara/util/ReflectionUtil.java deleted file mode 100644 index 5bda90f..0000000 --- a/lib/src/main/java/net/tomatentum/marinara/util/ReflectionUtil.java +++ /dev/null @@ -1,107 +0,0 @@ -package net.tomatentum.marinara.util; - -import java.lang.annotation.Annotation; -import java.lang.reflect.Method; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import java.util.Objects; - -public final class ReflectionUtil { - - public static boolean isAnnotationPresent(Method method, Class annotationClass) { - if (method.isAnnotationPresent(annotationClass) || method.getDeclaringClass().isAnnotationPresent(annotationClass)) - return true; - - return false; - } - - public static T getAnnotation(Method method, Class annotationClass) { - return method.isAnnotationPresent(annotationClass) ? - method.getAnnotation(annotationClass) : - method.getDeclaringClass().getAnnotation(annotationClass); - } - - public static int getCastDepth(Class child, Class parent) { - - if (parent.equals(Object.class)) - return Integer.MAX_VALUE; - - if (!parent.isAssignableFrom(child)) { - throw new IllegalArgumentException("The specified class is not a child class of the specified parent."); - } - - int depth = 0; - Class curr = child; - List> parents = new ArrayList<>(); - - while (!curr.equals(parent)) { - depth++; - parents.add(curr.getSuperclass()); - parents.addAll(Arrays.asList(curr.getInterfaces())); - - for (Class currParent : parents) { - if (currParent != null && parent.isAssignableFrom(currParent)) { - curr = currParent; - break; - } - } - parents.clear(); - } - - return depth; - } - - public static Method getMostSpecificMethod(Method[] methods, Class... parameters) { - List compatibleMethods = Arrays.stream(methods) - .filter(x -> isMethodCallable(x, parameters)) - .toList(); - - if (compatibleMethods.size() == 0) - throw new IllegalArgumentException("There are no compatible Methods provided"); - - for (int i = 0; i < parameters.length; i++) { - final int currI = i; - Class[] parameterTypes = compatibleMethods.stream() - .map(x -> x.getParameterTypes()[currI]) - .toArray(x -> new Class[x]); - - Class mostSpecific = getMostSpecificClass(parameterTypes, parameters[i]); - - compatibleMethods = compatibleMethods.stream() - .filter(x -> Objects.equals(x.getParameterTypes()[currI], mostSpecific)) - .toList(); - } - - return compatibleMethods.getFirst(); - } - - public static Class getMostSpecificClass(Class[] classes, Class base) { - int min = Integer.MAX_VALUE; - Class currMostSpecific = null; - for (Class currClass : classes) { - int currCastDepth = getCastDepth(base, currClass); - if (currCastDepth <= min) { - min = currCastDepth; - currMostSpecific = currClass; - } - } - return currMostSpecific; - } - - public static boolean isMethodCallable(Method method, Class... parameters) { - if (!Objects.equals(method.getParameterCount(), parameters.length)) - return false; - - Class[] methodParams = method.getParameterTypes(); - for (int i = 0; i < parameters.length; i++) { - if (!methodParams[i].isAssignableFrom(parameters[i])) - return false; - } - return true; - } - - public static String getFullMethodName(Method method) { - return method.getDeclaringClass().getName() + "." + method.getName(); - } -} diff --git a/lib/src/main/java/net/tomatentum/marinara/util/SimpleLogger.java b/lib/src/main/java/net/tomatentum/marinara/util/SimpleLogger.java deleted file mode 100644 index db6a2a5..0000000 --- a/lib/src/main/java/net/tomatentum/marinara/util/SimpleLogger.java +++ /dev/null @@ -1,55 +0,0 @@ -package net.tomatentum.marinara.util; - -import org.slf4j.Marker; -import org.slf4j.event.Level; -import org.slf4j.helpers.LegacyAbstractLogger; -import org.slf4j.helpers.MessageFormatter; - -public class SimpleLogger extends LegacyAbstractLogger { - - private String name; - - public SimpleLogger(String name) { - this.name = name; - } - - @Override - public boolean isTraceEnabled() { - return true; - } - - @Override - public boolean isDebugEnabled() { - return true; - } - - @Override - public boolean isInfoEnabled() { - return true; - } - - @Override - public boolean isWarnEnabled() { - return true; - } - - @Override - public boolean isErrorEnabled() { - return true; - } - - @Override - protected String getFullyQualifiedCallerName() { - return this.name; - } - - @Override - protected void handleNormalizedLoggingCall(Level level, Marker marker, String messagePattern, Object[] arguments, - Throwable throwable) { - String formatted = MessageFormatter.basicArrayFormat(messagePattern, arguments); - System.out.println("[%s] %s => %s".formatted(level, this.name, formatted)); - } - - - -} diff --git a/lib/src/main/java/net/tomatentum/marinara/wrapper/CommandConverter.java b/lib/src/main/java/net/tomatentum/marinara/wrapper/CommandConverter.java index 0183de4..5624f2a 100644 --- a/lib/src/main/java/net/tomatentum/marinara/wrapper/CommandConverter.java +++ b/lib/src/main/java/net/tomatentum/marinara/wrapper/CommandConverter.java @@ -5,6 +5,7 @@ import java.util.Arrays; import java.util.List; import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import net.tomatentum.marinara.interaction.commands.SlashCommandDefinition; import net.tomatentum.marinara.interaction.commands.annotation.SlashCommandOption; @@ -12,7 +13,6 @@ import net.tomatentum.marinara.interaction.commands.annotation.SlashCommandOptio import net.tomatentum.marinara.interaction.ident.InteractionIdentifier; import net.tomatentum.marinara.interaction.ident.RootCommandIdentifier; import net.tomatentum.marinara.interaction.ident.SlashCommandIdentifier; -import net.tomatentum.marinara.util.LoggerUtil; public class CommandConverter { @@ -20,7 +20,7 @@ public class CommandConverter(spec); } - private Logger logger = LoggerUtil.getLogger(getClass()); + private Logger logger = LoggerFactory.getLogger(getClass()); private Spec spec; diff --git a/lib/src/main/java/net/tomatentum/marinara/wrapper/CommandRegisterer.java b/lib/src/main/java/net/tomatentum/marinara/wrapper/CommandRegisterer.java index 5cc8053..d178411 100644 --- a/lib/src/main/java/net/tomatentum/marinara/wrapper/CommandRegisterer.java +++ b/lib/src/main/java/net/tomatentum/marinara/wrapper/CommandRegisterer.java @@ -5,9 +5,9 @@ import java.util.Set; import java.util.stream.Collectors; import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import net.tomatentum.marinara.interaction.commands.SlashCommandDefinition; -import net.tomatentum.marinara.util.LoggerUtil; import net.tomatentum.marinara.util.ObjectAggregator; public class CommandRegisterer { @@ -16,7 +16,7 @@ public class CommandRegisterer { return new CommandRegisterer(strategy, converter); } - private Logger logger = LoggerUtil.getLogger(getClass()); + private Logger logger = LoggerFactory.getLogger(getClass()); private Strategy strategy; private CommandConverter converter; @@ -29,13 +29,17 @@ public class CommandRegisterer { public void register(SlashCommandDefinition[] slashDefs) { Set> serverCommands = new ObjectAggregator>( def -> Arrays.stream(def.serverIds()).boxed().toList(), - (l, o) -> l.add(converter.convert(o)), + (l, o) -> { + logger.debug("Added {} for server ({}) registration.", o.rootIdentifier(), l.serverId()); + l.add(converter.convert(o)); + }, ServerCommandList::new) .aggregate(Arrays.asList(slashDefs)).stream() .collect(Collectors.toSet()); Set globalCommands = Arrays.stream(slashDefs) .filter(x -> x.serverIds().length <= 0) + .peek(c -> logger.debug("Added {} for global registration.", c.rootIdentifier())) .map(converter::convert) .collect(Collectors.toSet()); diff --git a/lib/src/main/java/net/tomatentum/marinara/wrapper/ContextObjectProvider.java b/lib/src/main/java/net/tomatentum/marinara/wrapper/ContextObjectProvider.java index 27cbaa4..05afcc8 100644 --- a/lib/src/main/java/net/tomatentum/marinara/wrapper/ContextObjectProvider.java +++ b/lib/src/main/java/net/tomatentum/marinara/wrapper/ContextObjectProvider.java @@ -1,5 +1,7 @@ package net.tomatentum.marinara.wrapper; +import net.tomatentum.marinara.interaction.commands.option.AutocompleteOptionData; + public interface ContextObjectProvider { public Object convertCommandOption(Object context, String optionName); @@ -7,5 +9,5 @@ public interface ContextObjectProvider { public Object getComponentContextObject(Object context, Class type); public Object getInteractionContextObject(Object context, Class type); - public Object getAutocompleteFocusedOption(Object context); + public AutocompleteOptionData getAutocompleteFocusedOption(Object context); } diff --git a/lib/src/main/java/net/tomatentum/marinara/wrapper/IdentifierProvider.java b/lib/src/main/java/net/tomatentum/marinara/wrapper/IdentifierProvider.java index 1308222..28d23fc 100644 --- a/lib/src/main/java/net/tomatentum/marinara/wrapper/IdentifierProvider.java +++ b/lib/src/main/java/net/tomatentum/marinara/wrapper/IdentifierProvider.java @@ -8,11 +8,11 @@ import java.util.List; import java.util.Map; import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import io.leangen.geantyref.GenericTypeReflector; +import net.tomatentum.cutin.util.ReflectionUtil; import net.tomatentum.marinara.interaction.ident.InteractionIdentifier; -import net.tomatentum.marinara.util.LoggerUtil; -import net.tomatentum.marinara.util.ReflectionUtil; public class IdentifierProvider { @@ -20,8 +20,9 @@ public class IdentifierProvider { return new IdentifierProvider(Arrays.asList(converter)); } + private Logger logger = LoggerFactory.getLogger(getClass()); + private Map, Converter> converter; - private Logger logger = LoggerUtil.getLogger(getClass()); private IdentifierProvider(List> converter) { this.converter = new HashMap<>(); @@ -29,7 +30,7 @@ public class IdentifierProvider { if (conv.getClass().getName().contains("$$Lambda")) throw new IllegalArgumentException("Lambdas cannot be used for IdentifierConverter because of Type erasure."); Type type = GenericTypeReflector.getExactSuperType(conv.getClass(), Converter.class); - Type parameterType = (Class) ((ParameterizedType) type).getActualTypeArguments()[0]; + Type parameterType = ((ParameterizedType) type).getActualTypeArguments()[0]; if (!(parameterType instanceof Class)) throw new IllegalArgumentException("Only full Class types are supported by IdentiferConverters"); this.converter.put((Class) parameterType, conv); @@ -42,12 +43,14 @@ public class IdentifierProvider { context.getClass()); if (type == null) - logger.debug("No Identifier converter found for context {}", context.getClass().toString()); + logger.debug("No Identifier converter found for context {}", context.getClass()); @SuppressWarnings("unchecked") Converter conv = (Converter) converter.get(type); - return conv.convert(context); + InteractionIdentifier result = conv.convert(context); + logger.trace("Converted {} to {} using {}", context, result, conv); + return result; } @FunctionalInterface diff --git a/lib/src/main/java/net/tomatentum/marinara/wrapper/LibraryWrapper.java b/lib/src/main/java/net/tomatentum/marinara/wrapper/LibraryWrapper.java index 5b3ba04..f5459da 100644 --- a/lib/src/main/java/net/tomatentum/marinara/wrapper/LibraryWrapper.java +++ b/lib/src/main/java/net/tomatentum/marinara/wrapper/LibraryWrapper.java @@ -12,7 +12,7 @@ public abstract class LibraryWrapper { } public void handleInteraction(Object context) { - interactionSubscriber.forEach((o) -> o.accept(context)); + interactionSubscriber.forEach(o -> o.accept(context)); } public void subscribeInteractions(Consumer consumer) { @@ -25,5 +25,6 @@ public abstract class LibraryWrapper { public abstract CommandRegisterer getRegisterer(); public abstract IdentifierProvider createIdentifierProvider(); public abstract ContextObjectProvider getContextObjectProvider(); + public abstract void respondAutocomplete(Object context, List options); } \ No newline at end of file diff --git a/wrapper/discord4j/build.gradle.kts b/wrapper/discord4j/build.gradle.kts index 49f2259..b89d503 100644 --- a/wrapper/discord4j/build.gradle.kts +++ b/wrapper/discord4j/build.gradle.kts @@ -10,11 +10,6 @@ plugins { `java-library` } -repositories { - // Use Maven Central for resolving dependencies. - mavenCentral() -} - dependencies { // Use JUnit Jupiter for testing. testImplementation(libs.junit.jupiter) @@ -22,6 +17,8 @@ dependencies { testImplementation(libs.discord4j) testRuntimeOnly("org.junit.platform:junit-platform-launcher") + testImplementation(libs.slf4j.simple) + implementation(libs.slf4j) implementation(libs.discord4j) { exclude(module="discord4j-voice") diff --git a/wrapper/discord4j/src/main/java/net/tomatentum/marinara/wrapper/discord4j/Discord4JContextObjectProvider.java b/wrapper/discord4j/src/main/java/net/tomatentum/marinara/wrapper/discord4j/Discord4JContextObjectProvider.java index d16f789..081d1fa 100644 --- a/wrapper/discord4j/src/main/java/net/tomatentum/marinara/wrapper/discord4j/Discord4JContextObjectProvider.java +++ b/wrapper/discord4j/src/main/java/net/tomatentum/marinara/wrapper/discord4j/Discord4JContextObjectProvider.java @@ -5,7 +5,9 @@ import java.util.List; import discord4j.core.event.domain.interaction.ChatInputAutoCompleteEvent; import discord4j.core.event.domain.interaction.ChatInputInteractionEvent; import discord4j.core.event.domain.interaction.ComponentInteractionEvent; +import discord4j.core.event.domain.interaction.InteractionCreateEvent; import discord4j.core.object.command.ApplicationCommandInteractionOption; +import net.tomatentum.marinara.interaction.commands.option.AutocompleteOptionData; import net.tomatentum.marinara.interaction.commands.option.SlashCommandOptionType; import net.tomatentum.marinara.wrapper.ContextObjectProvider; @@ -79,24 +81,25 @@ public class Discord4JContextObjectProvider implements ContextObjectProvider { @Override public Object getInteractionContextObject(Object context, Class type) { - ComponentInteractionEvent componentInteractionEvent = (ComponentInteractionEvent) context; + InteractionCreateEvent interactionEvent = (InteractionCreateEvent) context; switch (type.getName()) { case "discord4j.core.object.entity.channel.MessageChannel": - return componentInteractionEvent.getInteraction().getChannel().block(); + return interactionEvent.getInteraction().getChannel().block(); case "discord4j.core.object.entity.Guild": - return componentInteractionEvent.getInteraction().getGuild().block(); + return interactionEvent.getInteraction().getGuild().block(); case "discord4j.core.object.entity.Member": - return componentInteractionEvent.getInteraction().getMember().orElse(null); + return interactionEvent.getInteraction().getMember().orElse(null); case "discord4j.core.object.entity.User": - return componentInteractionEvent.getInteraction().getUser(); + return interactionEvent.getInteraction().getUser(); + default: + return null; } - return null; } @Override - public Object getAutocompleteFocusedOption(Object context) { - ChatInputAutoCompleteEvent interaction = (ChatInputAutoCompleteEvent) context; - return getOptionValue(interaction.getFocusedOption()); + public AutocompleteOptionData getAutocompleteFocusedOption(Object context) { + ApplicationCommandInteractionOption option = ((ChatInputAutoCompleteEvent) context).getFocusedOption(); + return new AutocompleteOptionData(option.getName(), getOptionValue(option)); } } diff --git a/wrapper/discord4j/src/main/java/net/tomatentum/marinara/wrapper/discord4j/Discord4JConverterSpec.java b/wrapper/discord4j/src/main/java/net/tomatentum/marinara/wrapper/discord4j/Discord4JConverterSpec.java index 57a8d2e..33458e3 100644 --- a/wrapper/discord4j/src/main/java/net/tomatentum/marinara/wrapper/discord4j/Discord4JConverterSpec.java +++ b/wrapper/discord4j/src/main/java/net/tomatentum/marinara/wrapper/discord4j/Discord4JConverterSpec.java @@ -55,10 +55,10 @@ public class Discord4JConverterSpec implements CommandConverter.Spec 0) + .minLength((int) option.range().min()) .minValue(option.range().min()) - .maxLength(Double.valueOf(option.range().max()).intValue()) + .maxLength((int)option.range().max()) .maxValue(option.range().max()) .choices(choices) .build(); diff --git a/wrapper/discord4j/src/main/java/net/tomatentum/marinara/wrapper/discord4j/Discord4JRegistererStrategy.java b/wrapper/discord4j/src/main/java/net/tomatentum/marinara/wrapper/discord4j/Discord4JRegistererStrategy.java index fea6e5c..7f84f82 100644 --- a/wrapper/discord4j/src/main/java/net/tomatentum/marinara/wrapper/discord4j/Discord4JRegistererStrategy.java +++ b/wrapper/discord4j/src/main/java/net/tomatentum/marinara/wrapper/discord4j/Discord4JRegistererStrategy.java @@ -10,7 +10,7 @@ import net.tomatentum.marinara.wrapper.CommandRegisterer; import net.tomatentum.marinara.wrapper.ServerCommandList; public class Discord4JRegistererStrategy implements CommandRegisterer.Strategy { - + private ApplicationService appService; private long applicationId; diff --git a/wrapper/discord4j/src/main/java/net/tomatentum/marinara/wrapper/discord4j/Discord4JWrapper.java b/wrapper/discord4j/src/main/java/net/tomatentum/marinara/wrapper/discord4j/Discord4JWrapper.java index d77dc3e..74f710f 100644 --- a/wrapper/discord4j/src/main/java/net/tomatentum/marinara/wrapper/discord4j/Discord4JWrapper.java +++ b/wrapper/discord4j/src/main/java/net/tomatentum/marinara/wrapper/discord4j/Discord4JWrapper.java @@ -1,17 +1,19 @@ package net.tomatentum.marinara.wrapper.discord4j; import java.util.List; -import java.util.function.Function; +import java.util.function.UnaryOperator; import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import discord4j.core.GatewayDiscordClient; +import discord4j.core.event.domain.interaction.ChatInputAutoCompleteEvent; import discord4j.core.event.domain.interaction.InteractionCreateEvent; import discord4j.core.object.command.ApplicationCommandInteractionOption; import discord4j.core.object.command.ApplicationCommandOption.Type; +import discord4j.discordjson.json.ApplicationCommandOptionChoiceData; import discord4j.discordjson.json.ApplicationCommandRequest; -import net.tomatentum.marinara.util.LoggerUtil; import net.tomatentum.marinara.wrapper.CommandConverter; import net.tomatentum.marinara.wrapper.CommandRegisterer; import net.tomatentum.marinara.wrapper.ContextObjectProvider; @@ -22,13 +24,12 @@ import net.tomatentum.marinara.wrapper.discord4j.identifierconverter.ButtonIdent import net.tomatentum.marinara.wrapper.discord4j.identifierconverter.SlashCommandIdentifierConverter; public class Discord4JWrapper extends LibraryWrapper { - - public static final Function, List> SUB_FILTER = (i) -> + public static final UnaryOperator> SUB_FILTER = i -> i.stream() .filter(o -> o.getType().equals(Type.SUB_COMMAND) || o.getType().equals(Type.SUB_COMMAND_GROUP)) .toList(); - public static final Function, List> ARG_FILTER = (i) -> + public static final UnaryOperator> ARG_FILTER = i -> i.stream() .filter(o -> !o.getType().equals(Type.SUB_COMMAND) && !o.getType().equals(Type.SUB_COMMAND_GROUP)) .toList(); @@ -36,7 +37,7 @@ public class Discord4JWrapper extends LibraryWrapper { private Discord4JContextObjectProvider contextObjectProvider; private CommandRegisterer commandRegisterer; - private Logger logger = LoggerUtil.getLogger(getClass()); + private Logger logger = LoggerFactory.getLogger(getClass()); public Discord4JWrapper(GatewayDiscordClient api) { this.contextObjectProvider = new Discord4JContextObjectProvider(); @@ -71,4 +72,15 @@ public class Discord4JWrapper extends LibraryWrapper { return this.contextObjectProvider; } + @Override + public void respondAutocomplete(Object context, List options) { + if (context instanceof ChatInputAutoCompleteEvent event) { + List choices = options.stream() + .filter(ApplicationCommandOptionChoiceData.class::isInstance) + .map(o -> (ApplicationCommandOptionChoiceData)o) + .toList(); + event.respondWithSuggestions(choices); + } + } + } diff --git a/wrapper/discord4j/src/main/java/net/tomatentum/marinara/wrapper/discord4j/identifierconverter/AutocompleteIdentifierConverter.java b/wrapper/discord4j/src/main/java/net/tomatentum/marinara/wrapper/discord4j/identifierconverter/AutocompleteIdentifierConverter.java index 49761d9..34892a8 100644 --- a/wrapper/discord4j/src/main/java/net/tomatentum/marinara/wrapper/discord4j/identifierconverter/AutocompleteIdentifierConverter.java +++ b/wrapper/discord4j/src/main/java/net/tomatentum/marinara/wrapper/discord4j/identifierconverter/AutocompleteIdentifierConverter.java @@ -13,26 +13,28 @@ public class AutocompleteIdentifierConverter implements IdentifierProvider.Conve @Override public InteractionIdentifier convert(ChatInputAutoCompleteEvent context) { - List options = Discord4JWrapper.SUB_FILTER.apply(context.getOptions()); - String commandName = context.getCommandName(); + InteractionIdentifier last = InteractionIdentifier.builder() + .type(InteractionType.AUTOCOMPLETE) + .name(context.getCommandName()) + .build(); + List options = Discord4JWrapper.SUB_FILTER.apply(context.getOptions()); if (!options.isEmpty()) { - List sub_options = Discord4JWrapper.SUB_FILTER.apply(options.getFirst().getOptions()); - if (!sub_options.isEmpty()) - return InteractionIdentifier.createHierarchy( - InteractionType.AUTOCOMPLETE, - commandName, - options.getFirst().getName(), - sub_options.getFirst().getName()); - else - return InteractionIdentifier.createHierarchy( - InteractionType.AUTOCOMPLETE, - commandName, - options.getFirst().getName()); - }else - return InteractionIdentifier.createHierarchy( - InteractionType.AUTOCOMPLETE, - commandName); + last = InteractionIdentifier.builder() + .type(InteractionType.AUTOCOMPLETE) + .name(options.getFirst().getName()) + .parent(last) + .build(); + + List subOptions = Discord4JWrapper.SUB_FILTER.apply(options.getFirst().getOptions()); + if (!subOptions.isEmpty()) + last = InteractionIdentifier.builder() + .type(InteractionType.AUTOCOMPLETE) + .name(subOptions.getFirst().getName()) + .parent(last) + .build(); + } + return last; } } diff --git a/wrapper/discord4j/src/main/java/net/tomatentum/marinara/wrapper/discord4j/identifierconverter/SlashCommandIdentifierConverter.java b/wrapper/discord4j/src/main/java/net/tomatentum/marinara/wrapper/discord4j/identifierconverter/SlashCommandIdentifierConverter.java index 612cd0a..b3fc627 100644 --- a/wrapper/discord4j/src/main/java/net/tomatentum/marinara/wrapper/discord4j/identifierconverter/SlashCommandIdentifierConverter.java +++ b/wrapper/discord4j/src/main/java/net/tomatentum/marinara/wrapper/discord4j/identifierconverter/SlashCommandIdentifierConverter.java @@ -13,27 +13,28 @@ public class SlashCommandIdentifierConverter implements IdentifierProvider.Conve @Override public InteractionIdentifier convert(ChatInputInteractionEvent context) { + InteractionIdentifier last = InteractionIdentifier.builder() + .type(InteractionType.COMMAND) + .name(context.getCommandName()) + .build(); + List options = Discord4JWrapper.SUB_FILTER.apply(context.getOptions()); - String commandName = context.getCommandName(); - if (!options.isEmpty()) { - List sub_options = Discord4JWrapper.SUB_FILTER.apply(options.getFirst().getOptions()); - if (!sub_options.isEmpty()) - return InteractionIdentifier.createHierarchy( - InteractionType.COMMAND, - commandName, - options.getFirst().getName(), - sub_options.getFirst().getName()); - else - return InteractionIdentifier.createHierarchy( - InteractionType.COMMAND, - commandName, - options.getFirst().getName()); - }else - return InteractionIdentifier.createHierarchy( - InteractionType.COMMAND, - commandName); + last = InteractionIdentifier.builder() + .type(InteractionType.COMMAND) + .name(options.getFirst().getName()) + .parent(last) + .build(); + List subOptions = Discord4JWrapper.SUB_FILTER.apply(options.getFirst().getOptions()); + if (!subOptions.isEmpty()) + last = InteractionIdentifier.builder() + .type(InteractionType.COMMAND) + .name(subOptions.getFirst().getName()) + .parent(last) + .build(); + } + return last; } } diff --git a/wrapper/discord4j/src/test/java/net/tomatentum/marinara/test/discord4j/AutoCompleteTest.java b/wrapper/discord4j/src/test/java/net/tomatentum/marinara/test/discord4j/AutoCompleteTest.java index 62a9259..3f15b52 100644 --- a/wrapper/discord4j/src/test/java/net/tomatentum/marinara/test/discord4j/AutoCompleteTest.java +++ b/wrapper/discord4j/src/test/java/net/tomatentum/marinara/test/discord4j/AutoCompleteTest.java @@ -18,10 +18,10 @@ import net.tomatentum.marinara.Marinara; import net.tomatentum.marinara.wrapper.LibraryWrapper; import net.tomatentum.marinara.wrapper.discord4j.Discord4JWrapper; -public class AutoCompleteTest { +class AutoCompleteTest { @Test - public void testAutocomplete() { + void testAutocomplete() { ApplicationCommandInteractionOption optionMock = mock(); ChatInputAutoCompleteEvent autoCompleteEventMock = mock(); @@ -38,7 +38,7 @@ public class AutoCompleteTest { LibraryWrapper wrapper = new Discord4JWrapper(null); //null okay as we don't use the discord API in this test. Marinara marinara = Marinara.load(wrapper); - marinara.getRegistry().addInteractions(new TestAutocomplete()); + marinara.getInteractionContainer().addAllMethods(new TestAutocomplete()); wrapper.handleInteraction(autoCompleteEventMock); verify(autoCompleteEventMock).respondWithSuggestions(any()); } diff --git a/wrapper/discord4j/src/test/java/net/tomatentum/marinara/test/discord4j/ButtonTest.java b/wrapper/discord4j/src/test/java/net/tomatentum/marinara/test/discord4j/ButtonTest.java index bb0c70b..4e8ff2b 100644 --- a/wrapper/discord4j/src/test/java/net/tomatentum/marinara/test/discord4j/ButtonTest.java +++ b/wrapper/discord4j/src/test/java/net/tomatentum/marinara/test/discord4j/ButtonTest.java @@ -13,15 +13,15 @@ import net.tomatentum.marinara.wrapper.LibraryWrapper; import net.tomatentum.marinara.wrapper.discord4j.Discord4JWrapper; @TestInstance(Lifecycle.PER_CLASS) -public class ButtonTest { +class ButtonTest { @Test - public void testButtonExecution() { + void testButtonExecution() { ButtonInteractionEvent buttonEventMock = CommonMocks.getButtonEventMock("test"); LibraryWrapper wrapper = new Discord4JWrapper(null); //null okay as we don't use the discord API in this test. Marinara marinara = Marinara.load(wrapper); - marinara.getRegistry().addInteractions(new TestButton()); + marinara.getInteractionContainer().addAllMethods(new TestButton()); wrapper.handleInteraction(buttonEventMock); assertTrue(TestButton.didRun); } diff --git a/wrapper/discord4j/src/test/java/net/tomatentum/marinara/test/discord4j/InteractionCheckTest.java b/wrapper/discord4j/src/test/java/net/tomatentum/marinara/test/discord4j/InteractionCheckTest.java index 0e7874c..8e0a9b7 100644 --- a/wrapper/discord4j/src/test/java/net/tomatentum/marinara/test/discord4j/InteractionCheckTest.java +++ b/wrapper/discord4j/src/test/java/net/tomatentum/marinara/test/discord4j/InteractionCheckTest.java @@ -24,16 +24,16 @@ import net.tomatentum.marinara.wrapper.discord4j.checks.PermissionCheck; import reactor.core.publisher.Mono; @TestInstance(Lifecycle.PER_CLASS) -public class InteractionCheckTest { +class InteractionCheckTest { @Test - public void testInteractionCheck() { + void testInteractionCheck() { ButtonInteractionEvent buttonEventMock = CommonMocks.getButtonEventMock("test"); LibraryWrapper wrapper = new Discord4JWrapper(null); Marinara marinara = Marinara.load(wrapper); - marinara.getCheckRegistry().addCheck(new TestInteractionCheck()); - marinara.getRegistry().addInteractions(new TestButton()); + marinara.getCheckContainer().addAllMethods(new TestInteractionCheck()); + marinara.getInteractionContainer().addAllMethods(new TestButton()); wrapper.handleInteraction(buttonEventMock); assertTrue(TestInteractionCheck.preExecuted); @@ -42,7 +42,7 @@ public class InteractionCheckTest { } @Test - public void testPermissionCheck() { + void testPermissionCheck() { Member memberMock = mock(); Interaction interactionMock = mock(); @@ -54,8 +54,8 @@ public class InteractionCheckTest { LibraryWrapper wrapper = new Discord4JWrapper(null); Marinara marinara = Marinara.load(wrapper); - marinara.getCheckRegistry().addCheck(new PermissionCheck()); - marinara.getRegistry().addInteractions(new TestButton()); + marinara.getCheckContainer().addAllMethods(new PermissionCheck()); + marinara.getInteractionContainer().addAllMethods(new TestButton()); wrapper.handleInteraction(buttonEventMock); assertFalse(TestButton.didPermRun); diff --git a/wrapper/discord4j/src/test/java/net/tomatentum/marinara/test/discord4j/SlashCommandTest.java b/wrapper/discord4j/src/test/java/net/tomatentum/marinara/test/discord4j/SlashCommandTest.java index 377f123..17764f7 100644 --- a/wrapper/discord4j/src/test/java/net/tomatentum/marinara/test/discord4j/SlashCommandTest.java +++ b/wrapper/discord4j/src/test/java/net/tomatentum/marinara/test/discord4j/SlashCommandTest.java @@ -21,10 +21,11 @@ import discord4j.core.object.command.ApplicationCommandOption.Type; import net.tomatentum.marinara.Marinara; import net.tomatentum.marinara.wrapper.LibraryWrapper; import net.tomatentum.marinara.wrapper.discord4j.Discord4JWrapper; -@TestInstance(Lifecycle.PER_CLASS) -public class SlashCommandTest { - String DISCORD_TOKEN = System.getenv("DISCORD_TEST_TOKEN"); +@TestInstance(Lifecycle.PER_CLASS) +class SlashCommandTest { + + private static String DISCORD_TOKEN = System.getenv("DISCORD_TEST_TOKEN"); GatewayDiscordClient client; @BeforeAll @@ -41,8 +42,8 @@ public class SlashCommandTest { @Test void testSlashCommand() { Marinara marinara = Marinara.load(new Discord4JWrapper(client)); - marinara.getRegistry().addInteractions(new TestCommand()); - marinara.getRegistry().registerCommands(); + marinara.getInteractionContainer().addAllMethods(new TestCommand()); + marinara.registerCommands(); System.out.println("Success!"); } @@ -64,7 +65,7 @@ public class SlashCommandTest { LibraryWrapper wrapper = new Discord4JWrapper(client); Marinara marinara = Marinara.load(wrapper); - marinara.getRegistry().addInteractions(new TestCommand()); + marinara.getInteractionContainer().addAllMethods(new TestCommand()); wrapper.handleInteraction(eventMock); } diff --git a/wrapper/discord4j/src/test/java/net/tomatentum/marinara/test/discord4j/TestAutocomplete.java b/wrapper/discord4j/src/test/java/net/tomatentum/marinara/test/discord4j/TestAutocomplete.java index d216805..1c4517a 100644 --- a/wrapper/discord4j/src/test/java/net/tomatentum/marinara/test/discord4j/TestAutocomplete.java +++ b/wrapper/discord4j/src/test/java/net/tomatentum/marinara/test/discord4j/TestAutocomplete.java @@ -2,21 +2,36 @@ package net.tomatentum.marinara.test.discord4j; import static org.junit.jupiter.api.Assertions.assertEquals; -import java.util.Collections; - import discord4j.core.event.domain.interaction.ChatInputAutoCompleteEvent; +import discord4j.core.event.domain.interaction.ChatInputInteractionEvent; +import discord4j.discordjson.json.ApplicationCommandOptionChoiceData; import net.tomatentum.marinara.interaction.InteractionHandler; import net.tomatentum.marinara.interaction.annotation.AutoComplete; import net.tomatentum.marinara.interaction.commands.annotation.SlashCommand; +import net.tomatentum.marinara.interaction.commands.annotation.SlashCommandOption; +import net.tomatentum.marinara.interaction.commands.option.SlashCommandOptionType; public class TestAutocomplete implements InteractionHandler { + + @SlashCommand( + name = "test", + options = @SlashCommandOption( + name = "foo", + type = SlashCommandOptionType.STRING, + autocompletes = @AutoComplete("testAuto") + ) + ) + public void exec(ChatInputInteractionEvent context) { + // Not executed just there for autocomplete to work + } - @SlashCommand(name = "test") - @AutoComplete - public void autocomplete(ChatInputAutoCompleteEvent context, String value) { + @AutoComplete("testAuto") + public ApplicationCommandOptionChoiceData[] autocomplete(ChatInputAutoCompleteEvent context, String value) { System.out.println("Success!"); - assertEquals(value, "test"); - context.respondWithSuggestions(Collections.emptyList()); + assertEquals("test", value); + return new ApplicationCommandOptionChoiceData[]{ + ApplicationCommandOptionChoiceData.builder().name("TestValue").value("test").build() + }; } } diff --git a/wrapper/discord4j/src/test/java/net/tomatentum/marinara/test/discord4j/TestCommand.java b/wrapper/discord4j/src/test/java/net/tomatentum/marinara/test/discord4j/TestCommand.java index 9482748..3430155 100644 --- a/wrapper/discord4j/src/test/java/net/tomatentum/marinara/test/discord4j/TestCommand.java +++ b/wrapper/discord4j/src/test/java/net/tomatentum/marinara/test/discord4j/TestCommand.java @@ -26,7 +26,7 @@ public class TestCommand implements InteractionHandler { } ) public void exec(ChatInputInteractionEvent event, String test) { - assertEquals(test, "test"); + assertEquals("test", test); System.out.println("Success!"); } } diff --git a/wrapper/discord4j/src/test/resources/simplelogger.properties b/wrapper/discord4j/src/test/resources/simplelogger.properties new file mode 100644 index 0000000..a25b6c7 --- /dev/null +++ b/wrapper/discord4j/src/test/resources/simplelogger.properties @@ -0,0 +1,7 @@ +# SLF4J's SimpleLogger configuration file +# Simple implementation of Logger that sends all enabled log messages, for all defined loggers, to System.err. + +# Default logging detail level for all instances of SimpleLogger. +# Must be one of ("trace", "debug", "info", "warn", or "error"). +# If not specified, defaults to "info". +org.slf4j.simpleLogger.defaultLogLevel=trace \ No newline at end of file diff --git a/wrapper/javacord/build.gradle.kts b/wrapper/javacord/build.gradle.kts index 608bc3a..d5eb471 100644 --- a/wrapper/javacord/build.gradle.kts +++ b/wrapper/javacord/build.gradle.kts @@ -10,17 +10,14 @@ plugins { `java-library` } -repositories { - // Use Maven Central for resolving dependencies. - mavenCentral() -} - dependencies { // Use JUnit Jupiter for testing. testImplementation(libs.junit.jupiter) testImplementation(libs.mockito) testRuntimeOnly("org.junit.platform:junit-platform-launcher") + testImplementation(libs.slf4j.simple) + implementation(libs.slf4j) implementation(libs.javacord) implementation(libs.geantyref) diff --git a/wrapper/javacord/src/main/java/net/tomatentum/marinara/wrapper/javacord/JavacordContextObjectProvider.java b/wrapper/javacord/src/main/java/net/tomatentum/marinara/wrapper/javacord/JavacordContextObjectProvider.java index 0812f0c..c17a901 100644 --- a/wrapper/javacord/src/main/java/net/tomatentum/marinara/wrapper/javacord/JavacordContextObjectProvider.java +++ b/wrapper/javacord/src/main/java/net/tomatentum/marinara/wrapper/javacord/JavacordContextObjectProvider.java @@ -2,10 +2,12 @@ package net.tomatentum.marinara.wrapper.javacord; import org.javacord.api.interaction.AutocompleteInteraction; import org.javacord.api.interaction.ButtonInteraction; +import org.javacord.api.interaction.InteractionBase; import org.javacord.api.interaction.SlashCommandInteraction; import org.javacord.api.interaction.SlashCommandInteractionOption; import org.javacord.api.interaction.SlashCommandOptionType; +import net.tomatentum.marinara.interaction.commands.option.AutocompleteOptionData; import net.tomatentum.marinara.wrapper.ContextObjectProvider; public class JavacordContextObjectProvider implements ContextObjectProvider { @@ -16,14 +18,14 @@ public class JavacordContextObjectProvider implements ContextObjectProvider { return null; SlashCommandInteraction interaction = (SlashCommandInteraction) context; if (!interaction.getArguments().isEmpty()) - return getOptionValue(interaction.getOptionByName(optionName).get()); + return getOptionValue(interaction.getOptionByName(optionName).orElse(null)); SlashCommandInteractionOption subCommandOption = interaction.getOptions().getFirst(); if (!subCommandOption.getOptions().isEmpty()) subCommandOption = subCommandOption.getOptions().getFirst(); - return getOptionValue(subCommandOption.getOptionByName(optionName).get()); + return getOptionValue(subCommandOption.getOptionByName(optionName).orElse(null)); } private Object getOptionValue(SlashCommandInteractionOption option) { @@ -89,7 +91,7 @@ public class JavacordContextObjectProvider implements ContextObjectProvider { @Override public Object getInteractionContextObject(Object context, Class type) { - ButtonInteraction button = (ButtonInteraction) context; + InteractionBase button = (InteractionBase) context; switch (type.getName()) { case "org.javacord.api.entity.channel.TextChannel": return button.getChannel().orElse(null); @@ -102,9 +104,9 @@ public class JavacordContextObjectProvider implements ContextObjectProvider { } @Override - public Object getAutocompleteFocusedOption(Object context) { - AutocompleteInteraction interaction = (AutocompleteInteraction) context; - return getOptionValue(interaction.getFocusedOption()); + public AutocompleteOptionData getAutocompleteFocusedOption(Object context) { + SlashCommandInteractionOption option = ((AutocompleteInteraction) context).getFocusedOption(); + return new AutocompleteOptionData(option.getName(), getOptionValue(option)); } } diff --git a/wrapper/javacord/src/main/java/net/tomatentum/marinara/wrapper/javacord/JavacordConverterSpec.java b/wrapper/javacord/src/main/java/net/tomatentum/marinara/wrapper/javacord/JavacordConverterSpec.java index 0fe16f5..76f1d25 100644 --- a/wrapper/javacord/src/main/java/net/tomatentum/marinara/wrapper/javacord/JavacordConverterSpec.java +++ b/wrapper/javacord/src/main/java/net/tomatentum/marinara/wrapper/javacord/JavacordConverterSpec.java @@ -50,10 +50,10 @@ public class JavacordConverterSpec implements CommandConverter.Spec 0) + .setMinLength((long) option.range().min()) .setDecimalMinValue(option.range().min()) - .setMaxLength(Double.valueOf(option.range().max()).longValue()) + .setMaxLength((long) option.range().max()) .setDecimalMaxValue(option.range().max()) .setChoices(choices) .build(); diff --git a/wrapper/javacord/src/main/java/net/tomatentum/marinara/wrapper/javacord/JavacordWrapper.java b/wrapper/javacord/src/main/java/net/tomatentum/marinara/wrapper/javacord/JavacordWrapper.java index fa7a3f5..62a9cf1 100644 --- a/wrapper/javacord/src/main/java/net/tomatentum/marinara/wrapper/javacord/JavacordWrapper.java +++ b/wrapper/javacord/src/main/java/net/tomatentum/marinara/wrapper/javacord/JavacordWrapper.java @@ -1,14 +1,18 @@ package net.tomatentum.marinara.wrapper.javacord; +import java.util.List; + import org.javacord.api.DiscordApi; +import org.javacord.api.interaction.AutocompleteInteraction; import org.javacord.api.interaction.SlashCommandBuilder; +import org.javacord.api.interaction.SlashCommandOptionChoice; import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import net.tomatentum.marinara.wrapper.CommandConverter; import net.tomatentum.marinara.wrapper.CommandRegisterer; import net.tomatentum.marinara.wrapper.ContextObjectProvider; import net.tomatentum.marinara.wrapper.IdentifierProvider; -import net.tomatentum.marinara.util.LoggerUtil; import net.tomatentum.marinara.wrapper.LibraryWrapper; import net.tomatentum.marinara.wrapper.javacord.identifierconverter.AutocompleteIdentifierConverter; import net.tomatentum.marinara.wrapper.javacord.identifierconverter.ButtonIdentifierConverter; @@ -19,7 +23,7 @@ public class JavacordWrapper extends LibraryWrapper { private JavacordContextObjectProvider contextObjectProvider; private CommandRegisterer commandRegisterer; - private Logger logger = LoggerUtil.getLogger(getClass()); + private Logger logger = LoggerFactory.getLogger(getClass()); public JavacordWrapper(DiscordApi api) { this.contextObjectProvider = new JavacordContextObjectProvider(); @@ -27,7 +31,7 @@ public class JavacordWrapper extends LibraryWrapper { if (api != null) { this.commandRegisterer = CommandRegisterer.of(new JavacordRegistererStrategy(api), converter); - api.addInteractionCreateListener((e) -> handleInteraction(e.getInteraction())); + api.addInteractionCreateListener(e -> handleInteraction(e.getInteraction())); }else logger.warn("DiscordApi was null so no Events were subscribed to."); logger.info("Javacord wrapper loaded!"); @@ -52,4 +56,15 @@ public class JavacordWrapper extends LibraryWrapper { return contextObjectProvider; } + @Override + public void respondAutocomplete(Object context, List options) { + if (context instanceof AutocompleteInteraction interaction) { + List choices = options.stream() + .filter(SlashCommandOptionChoice.class::isInstance) + .map(o -> (SlashCommandOptionChoice)o) + .toList(); + interaction.respondWithChoices(choices); + } + } + } diff --git a/wrapper/javacord/src/main/java/net/tomatentum/marinara/wrapper/javacord/identifierconverter/AutocompleteIdentifierConverter.java b/wrapper/javacord/src/main/java/net/tomatentum/marinara/wrapper/javacord/identifierconverter/AutocompleteIdentifierConverter.java index 65fef44..4e6195e 100644 --- a/wrapper/javacord/src/main/java/net/tomatentum/marinara/wrapper/javacord/identifierconverter/AutocompleteIdentifierConverter.java +++ b/wrapper/javacord/src/main/java/net/tomatentum/marinara/wrapper/javacord/identifierconverter/AutocompleteIdentifierConverter.java @@ -13,25 +13,28 @@ public class AutocompleteIdentifierConverter implements IdentifierProvider.Conve @Override public InteractionIdentifier convert(AutocompleteInteraction context) { + InteractionIdentifier last = InteractionIdentifier.builder() + .type(InteractionType.AUTOCOMPLETE) + .name(context.getCommandName()) + .build(); + List options = context.getOptions(); - String commandName = context.getCommandName(); if (!options.isEmpty()) { - List sub_options = context.getOptions().getFirst().getOptions(); - if (!sub_options.isEmpty()) - return InteractionIdentifier.createHierarchy( - InteractionType.AUTOCOMPLETE, - commandName, - options.getFirst().getName(), - sub_options.getFirst().getName()); - else - return InteractionIdentifier.createHierarchy( - InteractionType.AUTOCOMPLETE, - commandName, - options.getFirst().getName()); - }else - return InteractionIdentifier.createHierarchy( - InteractionType.AUTOCOMPLETE, - commandName); + last = InteractionIdentifier.builder() + .type(InteractionType.AUTOCOMPLETE) + .name(options.getFirst().getName()) + .parent(last) + .build(); + + List subOptions = context.getOptions().getFirst().getOptions(); + if (!subOptions.isEmpty()) + last = InteractionIdentifier.builder() + .type(InteractionType.AUTOCOMPLETE) + .name(subOptions.getFirst().getName()) + .parent(last) + .build(); + } + return last; } } diff --git a/wrapper/javacord/src/main/java/net/tomatentum/marinara/wrapper/javacord/identifierconverter/SlashCommandIdentifierConverter.java b/wrapper/javacord/src/main/java/net/tomatentum/marinara/wrapper/javacord/identifierconverter/SlashCommandIdentifierConverter.java index 4b90bd1..a6f7d5b 100644 --- a/wrapper/javacord/src/main/java/net/tomatentum/marinara/wrapper/javacord/identifierconverter/SlashCommandIdentifierConverter.java +++ b/wrapper/javacord/src/main/java/net/tomatentum/marinara/wrapper/javacord/identifierconverter/SlashCommandIdentifierConverter.java @@ -13,26 +13,28 @@ public class SlashCommandIdentifierConverter implements IdentifierProvider.Conve @Override public InteractionIdentifier convert(SlashCommandInteraction context) { - List options = context.getOptions(); - String commandName = context.getCommandName(); - if (!options.isEmpty()) { - List sub_options = context.getOptions().getFirst().getOptions(); - if (!sub_options.isEmpty()) - return InteractionIdentifier.createHierarchy( - InteractionType.COMMAND, - commandName, - options.getFirst().getName(), - sub_options.getFirst().getName()); - else - return InteractionIdentifier.createHierarchy( - InteractionType.COMMAND, - commandName, - options.getFirst().getName()); - }else - return InteractionIdentifier.createHierarchy( - InteractionType.COMMAND, - commandName); + InteractionIdentifier last = InteractionIdentifier.builder() + .type(InteractionType.COMMAND) + .name(context.getCommandName()) + .build(); + List options = context.getOptions(); + if (!options.isEmpty()) { + last = InteractionIdentifier.builder() + .type(InteractionType.COMMAND) + .name(options.getFirst().getName()) + .parent(last) + .build(); + + List subOptions = context.getOptions().getFirst().getOptions(); + if (!subOptions.isEmpty()) + last = InteractionIdentifier.builder() + .type(InteractionType.COMMAND) + .name(subOptions.getFirst().getName()) + .parent(last) + .build(); + } + return last; } } diff --git a/wrapper/javacord/src/test/java/net/tomatentum/marinara/test/javacord/AutoCompleteTest.java b/wrapper/javacord/src/test/java/net/tomatentum/marinara/test/javacord/AutoCompleteTest.java index e10d19c..8724326 100644 --- a/wrapper/javacord/src/test/java/net/tomatentum/marinara/test/javacord/AutoCompleteTest.java +++ b/wrapper/javacord/src/test/java/net/tomatentum/marinara/test/javacord/AutoCompleteTest.java @@ -16,10 +16,10 @@ import net.tomatentum.marinara.Marinara; import net.tomatentum.marinara.wrapper.LibraryWrapper; import net.tomatentum.marinara.wrapper.javacord.JavacordWrapper; -public class AutoCompleteTest { +class AutoCompleteTest { @Test - public void testAutocomplete() { + void testAutocomplete() { SlashCommandInteractionOption optionMock = mock(); AutocompleteInteraction autocompleteInteractionMock = mock(); @@ -33,7 +33,7 @@ public class AutoCompleteTest { LibraryWrapper wrapper = new JavacordWrapper(null); //null okay as we don't use the discord API in this test. Marinara marinara = Marinara.load(wrapper); - marinara.getRegistry().addInteractions(new TestAutocomplete()); + marinara.getInteractionContainer().addAllMethods(new TestAutocomplete()); wrapper.handleInteraction(autocompleteInteractionMock); verify(autocompleteInteractionMock).respondWithChoices(any()); } diff --git a/wrapper/javacord/src/test/java/net/tomatentum/marinara/test/javacord/ButtonTest.java b/wrapper/javacord/src/test/java/net/tomatentum/marinara/test/javacord/ButtonTest.java index dc85d36..5e8a9b4 100644 --- a/wrapper/javacord/src/test/java/net/tomatentum/marinara/test/javacord/ButtonTest.java +++ b/wrapper/javacord/src/test/java/net/tomatentum/marinara/test/javacord/ButtonTest.java @@ -12,13 +12,13 @@ import net.tomatentum.marinara.wrapper.LibraryWrapper; import net.tomatentum.marinara.wrapper.javacord.JavacordWrapper; @TestInstance(Lifecycle.PER_CLASS) -public class ButtonTest { +class ButtonTest { @Test - public void testButtonExecution() { + void testButtonExecution() { LibraryWrapper wrapper = new JavacordWrapper(null); //null okay as we don't use the discord API in this test. Marinara marinara = Marinara.load(wrapper); - marinara.getRegistry().addInteractions(new TestButton()); + marinara.getInteractionContainer().addAllMethods(new TestButton()); wrapper.handleInteraction(CommonMocks.getButtonInteractionMock("test")); assertTrue(TestButton.didRun); } diff --git a/wrapper/javacord/src/test/java/net/tomatentum/marinara/test/javacord/InteractionCheckTest.java b/wrapper/javacord/src/test/java/net/tomatentum/marinara/test/javacord/InteractionCheckTest.java index 950c314..a522a27 100644 --- a/wrapper/javacord/src/test/java/net/tomatentum/marinara/test/javacord/InteractionCheckTest.java +++ b/wrapper/javacord/src/test/java/net/tomatentum/marinara/test/javacord/InteractionCheckTest.java @@ -19,25 +19,25 @@ import net.tomatentum.marinara.wrapper.javacord.JavacordWrapper; import net.tomatentum.marinara.wrapper.javacord.checks.PermissionCheck; @TestInstance(Lifecycle.PER_CLASS) -public class InteractionCheckTest { +class InteractionCheckTest { @Test - public void testInteractionCheck() { + void testInteractionCheck() { LibraryWrapper wrapper = new JavacordWrapper(null); Marinara marinara = Marinara.load(wrapper); - marinara.getCheckRegistry().addCheck(new TestInteractionCheck()); - marinara.getRegistry().addInteractions(new TestButton()); + marinara.getCheckContainer().addAllMethods(new TestInteractionCheck()); + marinara.getInteractionContainer().addAllMethods(new TestButton()); wrapper.handleInteraction(CommonMocks.getButtonInteractionMock("test")); assertTrue(TestInteractionCheck.preExecuted); assertTrue(TestInteractionCheck.postExecuted); } @Test - public void testPermissionCheck() { + void testPermissionCheck() { LibraryWrapper wrapper = new JavacordWrapper(null); Marinara marinara = Marinara.load(wrapper); - marinara.getCheckRegistry().addCheck(new PermissionCheck()); - marinara.getRegistry().addInteractions(new TestButton()); + marinara.getCheckContainer().addAllMethods(new PermissionCheck()); + marinara.getInteractionContainer().addAllMethods(new TestButton()); Server serverMock = mock(); ButtonInteraction buttonInteractionMock = CommonMocks.getButtonInteractionMock("permissionCheck", serverMock); diff --git a/wrapper/javacord/src/test/java/net/tomatentum/marinara/test/javacord/SlashCommandTest.java b/wrapper/javacord/src/test/java/net/tomatentum/marinara/test/javacord/SlashCommandTest.java index 8fd80d0..ce645a8 100644 --- a/wrapper/javacord/src/test/java/net/tomatentum/marinara/test/javacord/SlashCommandTest.java +++ b/wrapper/javacord/src/test/java/net/tomatentum/marinara/test/javacord/SlashCommandTest.java @@ -20,7 +20,7 @@ import net.tomatentum.marinara.Marinara; import net.tomatentum.marinara.wrapper.LibraryWrapper; import net.tomatentum.marinara.wrapper.javacord.JavacordWrapper; @TestInstance(Lifecycle.PER_CLASS) -public class SlashCommandTest { +class SlashCommandTest { String DISCORD_TOKEN = System.getenv("DISCORD_TEST_TOKEN"); DiscordApi api; @@ -41,8 +41,8 @@ public class SlashCommandTest { @Test void testSlashCommand() { Marinara marinara = Marinara.load(new JavacordWrapper(api)); - marinara.getRegistry().addInteractions(new TestCommand()); - marinara.getRegistry().registerCommands(); + marinara.getInteractionContainer().addAllMethods(new TestCommand()); + marinara.registerCommands(); System.out.println("Success!"); } @@ -50,7 +50,7 @@ public class SlashCommandTest { void testSlashCommandExecution() { LibraryWrapper wrapper = new JavacordWrapper(api); Marinara marinara = Marinara.load(wrapper); - marinara.getRegistry().addInteractions(new TestCommand()); + marinara.getInteractionContainer().addAllMethods(new TestCommand()); SlashCommandInteractionOption optionMock = mock(); SlashCommandInteraction interactionMock = mock(); diff --git a/wrapper/javacord/src/test/java/net/tomatentum/marinara/test/javacord/TestAutocomplete.java b/wrapper/javacord/src/test/java/net/tomatentum/marinara/test/javacord/TestAutocomplete.java index d9063bb..0285cff 100644 --- a/wrapper/javacord/src/test/java/net/tomatentum/marinara/test/javacord/TestAutocomplete.java +++ b/wrapper/javacord/src/test/java/net/tomatentum/marinara/test/javacord/TestAutocomplete.java @@ -5,18 +5,32 @@ import static org.junit.jupiter.api.Assertions.assertEquals; import java.util.Collections; import org.javacord.api.interaction.AutocompleteInteraction; +import org.javacord.api.interaction.SlashCommandInteraction; import net.tomatentum.marinara.interaction.InteractionHandler; import net.tomatentum.marinara.interaction.annotation.AutoComplete; import net.tomatentum.marinara.interaction.commands.annotation.SlashCommand; +import net.tomatentum.marinara.interaction.commands.annotation.SlashCommandOption; +import net.tomatentum.marinara.interaction.commands.option.SlashCommandOptionType; public class TestAutocomplete implements InteractionHandler { - @SlashCommand(name = "test") - @AutoComplete + @SlashCommand( + name = "test", + options = @SlashCommandOption( + name = "foo", + type = SlashCommandOptionType.STRING, + autocompletes = @AutoComplete("testAuto") + ) + ) + public void exec(SlashCommandInteraction context) { + //only here for command definition + } + + @AutoComplete("testAuto") public void autocomplete(AutocompleteInteraction context, String value) { System.out.println("Success!"); - assertEquals(value, "test"); + assertEquals("test", value); context.respondWithChoices(Collections.emptyList()); } diff --git a/wrapper/javacord/src/test/java/net/tomatentum/marinara/test/javacord/TestButton.java b/wrapper/javacord/src/test/java/net/tomatentum/marinara/test/javacord/TestButton.java index f838e5e..e1e65ac 100644 --- a/wrapper/javacord/src/test/java/net/tomatentum/marinara/test/javacord/TestButton.java +++ b/wrapper/javacord/src/test/java/net/tomatentum/marinara/test/javacord/TestButton.java @@ -16,8 +16,8 @@ import net.tomatentum.marinara.wrapper.javacord.checks.PermissionCheck.HasPermis public class TestButton implements InteractionHandler { - public static boolean didRun = false; + @Button("test") @TestCheck public void exec(ButtonInteraction interaction, TextChannel channel, Message message, User member, Server server) { diff --git a/wrapper/javacord/src/test/java/net/tomatentum/marinara/test/javacord/TestCommand.java b/wrapper/javacord/src/test/java/net/tomatentum/marinara/test/javacord/TestCommand.java index d6f371c..2a95ba7 100644 --- a/wrapper/javacord/src/test/java/net/tomatentum/marinara/test/javacord/TestCommand.java +++ b/wrapper/javacord/src/test/java/net/tomatentum/marinara/test/javacord/TestCommand.java @@ -11,6 +11,7 @@ import net.tomatentum.marinara.interaction.commands.annotation.SlashCommandOptio import net.tomatentum.marinara.interaction.commands.option.SlashCommandOptionType; public class TestCommand implements InteractionHandler { + @SlashCommand( name = "test", description = "testingen", @@ -27,7 +28,8 @@ public class TestCommand implements InteractionHandler { } ) public void exec(SlashCommandInteraction interaction, String test) { - assertEquals(test, "test"); + assertEquals("test", test); System.out.println("Success!"); } + } diff --git a/wrapper/javacord/src/test/resources/simplelogger.properties b/wrapper/javacord/src/test/resources/simplelogger.properties new file mode 100644 index 0000000..a25b6c7 --- /dev/null +++ b/wrapper/javacord/src/test/resources/simplelogger.properties @@ -0,0 +1,7 @@ +# SLF4J's SimpleLogger configuration file +# Simple implementation of Logger that sends all enabled log messages, for all defined loggers, to System.err. + +# Default logging detail level for all instances of SimpleLogger. +# Must be one of ("trace", "debug", "info", "warn", or "error"). +# If not specified, defaults to "info". +org.slf4j.simpleLogger.defaultLogLevel=trace \ No newline at end of file