Compare commits
	
		
			17 Commits
		
	
	
		
			0ea330d48b
			...
			d8504a7cde
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| d8504a7cde | |||
| bef34ee548 | |||
| 29bb7e667e | |||
| 94da2a0e3c | |||
| 7f47130461 | |||
| 83a3efd4b8 | |||
| aefd8a51a0 | |||
| 4332592dfa | |||
| c363ab9744 | |||
| 33392b02fb | |||
| b7333c2e5e | |||
| 239e921e6f | |||
| 6eb7fb723f | |||
| 659218682e | |||
| 019ba8f552 | |||
| f89ae5e425 | |||
| 582e0f0bae | 
| @@ -21,13 +21,13 @@ dependencies { | |||||||
|  |  | ||||||
|     testRuntimeOnly("org.junit.platform:junit-platform-launcher") |     testRuntimeOnly("org.junit.platform:junit-platform-launcher") | ||||||
|     implementation(libs.log4j) |     implementation(libs.log4j) | ||||||
|  |     implementation(libs.geantyref) | ||||||
| } | } | ||||||
|  |  | ||||||
| // Apply a specific Java toolchain to ease working on different environments. | // Apply a specific Java toolchain to ease working on different environments. | ||||||
| java { | java { | ||||||
|     toolchain { |     toolchain { | ||||||
|         languageVersion = JavaLanguageVersion.of(21) |         languageVersion = JavaLanguageVersion.of(23) | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -1,22 +1,34 @@ | |||||||
| package net.tomatentum.marinara; | package net.tomatentum.marinara; | ||||||
|  |  | ||||||
|  | import net.tomatentum.marinara.registry.InteractionCheckRegistry; | ||||||
| import net.tomatentum.marinara.registry.InteractionRegistry; | import net.tomatentum.marinara.registry.InteractionRegistry; | ||||||
| import net.tomatentum.marinara.wrapper.LibraryWrapper; | import net.tomatentum.marinara.wrapper.LibraryWrapper; | ||||||
|  |  | ||||||
| public class Marinara { | public class Marinara { | ||||||
|      |      | ||||||
|     public static <T extends LibraryWrapper> Marinara load(LibraryWrapper wrapper) { |     public static <T extends LibraryWrapper> Marinara load(LibraryWrapper wrapper) { | ||||||
|         InteractionRegistry registry = new InteractionRegistry(wrapper); |         return new Marinara(wrapper); | ||||||
|         return new Marinara(registry); |  | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     private InteractionRegistry registry; |     private InteractionRegistry registry; | ||||||
|  |     private InteractionCheckRegistry checkRegistry; | ||||||
|  |     private LibraryWrapper wrapper; | ||||||
|  |  | ||||||
|     private Marinara(InteractionRegistry registry) { |     private Marinara(LibraryWrapper wrapper) { | ||||||
|         this.registry = registry; |         this.wrapper = wrapper; | ||||||
|  |         this.registry = new InteractionRegistry(this); | ||||||
|  |         this.checkRegistry = new InteractionCheckRegistry(); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     public InteractionRegistry getRegistry() { |     public InteractionRegistry getRegistry() { | ||||||
|         return registry; |         return registry; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     public InteractionCheckRegistry getCheckRegistry() { | ||||||
|  |         return checkRegistry; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     public LibraryWrapper getWrapper() { | ||||||
|  |         return wrapper; | ||||||
|  |     } | ||||||
| } | } | ||||||
|   | |||||||
| @@ -0,0 +1,41 @@ | |||||||
|  | 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 net.tomatentum.marinara.util.ReflectionUtil; | ||||||
|  |  | ||||||
|  | public record AppliedCheck(InteractionCheck<?> check, Annotation annotation) { | ||||||
|  |      | ||||||
|  |     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 { | ||||||
|  |             return (boolean) method.invoke(check, context, annotation); | ||||||
|  |         } catch (IllegalAccessException | InvocationTargetException | SecurityException e) { | ||||||
|  |             e.printStackTrace(); | ||||||
|  |             return false; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     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 { | ||||||
|  |             method.invoke(check, context, annotation); | ||||||
|  |         } catch (IllegalAccessException | InvocationTargetException | SecurityException e) { | ||||||
|  |             e.printStackTrace(); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  | } | ||||||
| @@ -0,0 +1,10 @@ | |||||||
|  | package net.tomatentum.marinara.checks; | ||||||
|  |  | ||||||
|  | import java.lang.annotation.Annotation; | ||||||
|  |  | ||||||
|  | public interface InteractionCheck<A extends Annotation> { | ||||||
|  |  | ||||||
|  |     public boolean preExec(Object context, A annotation); | ||||||
|  |     public void postExec(Object context, A annotation); | ||||||
|  |      | ||||||
|  | } | ||||||
| @@ -16,9 +16,18 @@ public record ExecutableSlashCommandDefinition( | |||||||
|         if (!(o instanceof ExecutableSlashCommandDefinition)) |         if (!(o instanceof ExecutableSlashCommandDefinition)) | ||||||
|             return false; |             return false; | ||||||
|         ExecutableSlashCommandDefinition other = (ExecutableSlashCommandDefinition) o; |         ExecutableSlashCommandDefinition other = (ExecutableSlashCommandDefinition) o; | ||||||
|         return other.applicationCommand.name().equals(this.applicationCommand.name()) &&  |         boolean equals = false; | ||||||
|             other.subCommandGroup.name().equals(this.subCommandGroup.name()) && |  | ||||||
|             other.subCommand.name().equals(this.subCommand.name()); |         if (this.applicationCommand() != null && other.subCommandGroup() != null) | ||||||
|  |             equals = this.applicationCommand.name().equals(other.applicationCommand().name()); | ||||||
|  |  | ||||||
|  |         if (this.subCommandGroup() != null && other.subCommandGroup() != null) | ||||||
|  |             equals = this.subCommandGroup().name().equals(other.subCommandGroup().name()); | ||||||
|  |          | ||||||
|  |         if (this.subCommand() != null && other.subCommand() != null) | ||||||
|  |             equals = this.subCommand().name().equals(other.subCommand().name()); | ||||||
|  |  | ||||||
|  |         return equals; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     @Override |     @Override | ||||||
|   | |||||||
| @@ -2,39 +2,40 @@ package net.tomatentum.marinara.interaction.methods; | |||||||
|  |  | ||||||
| import java.lang.reflect.Method; | import java.lang.reflect.Method; | ||||||
|  |  | ||||||
|  | import net.tomatentum.marinara.Marinara; | ||||||
| import net.tomatentum.marinara.interaction.InteractionHandler; | import net.tomatentum.marinara.interaction.InteractionHandler; | ||||||
| import net.tomatentum.marinara.interaction.InteractionType; | import net.tomatentum.marinara.interaction.InteractionType; | ||||||
| import net.tomatentum.marinara.interaction.annotation.Button; | import net.tomatentum.marinara.parser.AnnotationParser; | ||||||
| import net.tomatentum.marinara.wrapper.LibraryWrapper; | import net.tomatentum.marinara.parser.ButtonParser; | ||||||
|  |  | ||||||
| public class ButtonInteractionMethod extends InteractionMethod { | public class ButtonInteractionMethod extends InteractionMethod { | ||||||
|  |  | ||||||
|     private String customId; |     private String customId; | ||||||
|  |  | ||||||
|     ButtonInteractionMethod(Method method, InteractionHandler handler, LibraryWrapper wrapper) { |     ButtonInteractionMethod(Method method, InteractionHandler handler, Marinara marinara) { | ||||||
|         super(method, handler, wrapper); |         super(method, handler, marinara); | ||||||
|         parseMethod(); |     } | ||||||
|  |  | ||||||
|  |     @Override | ||||||
|  |     public AnnotationParser[] getParsers() { | ||||||
|  |         return new AnnotationParser[] { | ||||||
|  |             new ButtonParser(method, (x) -> { this.customId = x; } ) | ||||||
|  |         }; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     @Override |     @Override | ||||||
|     public Object getParameter(Object parameter, int index) { |     public Object getParameter(Object parameter, int index) { | ||||||
|         Class<?> type = getMethod().getParameterTypes()[index+1]; |         Class<?> type = getMethod().getParameterTypes()[index+1]; | ||||||
|         return wrapper.getComponentContextObject(parameter, type); |         return marinara.getWrapper().getComponentContextObject(parameter, type); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     @Override |     @Override | ||||||
|     public boolean canRun(Object context) { |     public boolean canRun(Object context) { | ||||||
|         return wrapper.getButtonId(context).equals(customId); |         return marinara.getWrapper().getButtonId(context).equals(customId); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     @Override |     @Override | ||||||
|     public InteractionType getType() { |     public InteractionType getType() { | ||||||
|         return InteractionType.BUTTON; |         return InteractionType.BUTTON; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     private void parseMethod() { |  | ||||||
|         Button button = getMethod().getAnnotation(Button.class); |  | ||||||
|         this.customId = button.value(); |  | ||||||
|     } |  | ||||||
|      |  | ||||||
| } | } | ||||||
|   | |||||||
| @@ -7,35 +7,52 @@ import java.util.ArrayList; | |||||||
| import java.util.Arrays; | import java.util.Arrays; | ||||||
| import java.util.List; | import java.util.List; | ||||||
|  |  | ||||||
|  | import net.tomatentum.marinara.Marinara; | ||||||
|  | import net.tomatentum.marinara.checks.AppliedCheck; | ||||||
| import net.tomatentum.marinara.interaction.InteractionHandler; | import net.tomatentum.marinara.interaction.InteractionHandler; | ||||||
| import net.tomatentum.marinara.interaction.InteractionType; | import net.tomatentum.marinara.interaction.InteractionType; | ||||||
| import net.tomatentum.marinara.interaction.annotation.Button; | import net.tomatentum.marinara.interaction.annotation.Button; | ||||||
| import net.tomatentum.marinara.interaction.commands.annotation.SlashCommand; | import net.tomatentum.marinara.interaction.commands.annotation.SlashCommand; | ||||||
| import net.tomatentum.marinara.interaction.commands.annotation.SubCommand; | import net.tomatentum.marinara.interaction.commands.annotation.SubCommand; | ||||||
| import net.tomatentum.marinara.wrapper.LibraryWrapper; | import net.tomatentum.marinara.parser.AnnotationParser; | ||||||
|  | import net.tomatentum.marinara.parser.InteractionCheckParser; | ||||||
|  |  | ||||||
| public abstract class InteractionMethod { | public abstract class InteractionMethod { | ||||||
|  |  | ||||||
|     public static InteractionMethod create(Method method, InteractionHandler handler, LibraryWrapper wrapper) { |     public static InteractionMethod create(Method method, InteractionHandler handler, Marinara marinara) { | ||||||
|         if (method.isAnnotationPresent(SlashCommand.class) || method.isAnnotationPresent(SubCommand.class)) |         if (method.isAnnotationPresent(SlashCommand.class) || method.isAnnotationPresent(SubCommand.class)) | ||||||
|             return new SlashCommandInteractionMethod(method, handler, wrapper); |             return new SlashCommandInteractionMethod(method, handler, marinara); | ||||||
|         if (method.isAnnotationPresent(Button.class)) |         if (method.isAnnotationPresent(Button.class)) | ||||||
|             return new ButtonInteractionMethod(method, handler, wrapper); |             return new ButtonInteractionMethod(method, handler, marinara); | ||||||
|         return null; |         return null; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     protected Method method; |     protected Method method; | ||||||
|     protected InteractionHandler handler; |     protected InteractionHandler handler; | ||||||
|     protected LibraryWrapper wrapper; |     protected Marinara marinara; | ||||||
|  |     protected List<AnnotationParser> parsers; | ||||||
|  |     protected List<AppliedCheck> appliedChecks; | ||||||
|  |  | ||||||
|     protected InteractionMethod(Method method, InteractionHandler handler, LibraryWrapper wrapper) { |     protected InteractionMethod(Method method,  | ||||||
|  |         InteractionHandler handler,  | ||||||
|  |         Marinara marinara | ||||||
|  |         ) { | ||||||
|         if (!Arrays.asList(handler.getClass().getMethods()).contains(method)) |         if (!Arrays.asList(handler.getClass().getMethods()).contains(method)) | ||||||
|             throw new InvalidParameterException("Method does not apply to specified handler"); |             throw new InvalidParameterException("Method does not apply to specified handler"); | ||||||
|  |  | ||||||
|         this.method = method; |         this.method = method; | ||||||
|         this.handler = handler; |         this.handler = handler; | ||||||
|         this.wrapper = wrapper; |         this.marinara = marinara; | ||||||
|  |         this.parsers = new ArrayList<>(Arrays.asList(getParsers())); | ||||||
|  |         this.appliedChecks = new ArrayList<>(); | ||||||
|  |  | ||||||
|  |         parsers.add(new InteractionCheckParser(method, appliedChecks::add, marinara.getCheckRegistry())); | ||||||
|  |  | ||||||
|  |         parsers.stream().forEach(AnnotationParser::parse); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     public abstract AnnotationParser[] getParsers(); | ||||||
|  |  | ||||||
|     public abstract Object getParameter(Object parameter, int index); |     public abstract Object getParameter(Object parameter, int index); | ||||||
|  |  | ||||||
|     public abstract boolean canRun(Object context); |     public abstract boolean canRun(Object context); | ||||||
| @@ -43,6 +60,24 @@ public abstract class InteractionMethod { | |||||||
|     public abstract InteractionType getType(); |     public abstract InteractionType getType(); | ||||||
|  |  | ||||||
|     public void run(Object context) { |     public void run(Object context) { | ||||||
|  |         if (this.appliedChecks.stream().filter(x -> !x.pre(context)).count() > 0) | ||||||
|  |             return; | ||||||
|  |  | ||||||
|  |         method.setAccessible(true); | ||||||
|  |         try { | ||||||
|  |             method.invoke(handler, getParameters(context)); | ||||||
|  |         }catch (IllegalAccessException | InvocationTargetException ex) { | ||||||
|  |             throw new RuntimeException(ex); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         this.appliedChecks.forEach(x -> x.post(context)); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     public Method getMethod() { | ||||||
|  |         return method; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     private Object[] getParameters(Object context) { | ||||||
|         int parameterCount = method.getParameterCount(); |         int parameterCount = method.getParameterCount(); | ||||||
|         List<Object> parameters = new ArrayList<>(); |         List<Object> parameters = new ArrayList<>(); | ||||||
|          |          | ||||||
| @@ -53,16 +88,7 @@ public abstract class InteractionMethod { | |||||||
|             } |             } | ||||||
|             parameters.add(getParameter(context, i-1)); |             parameters.add(getParameter(context, i-1)); | ||||||
|         } |         } | ||||||
|         method.setAccessible(true); |         return parameters.toArray(); | ||||||
|         try { |  | ||||||
|             method.invoke(handler, parameters.toArray()); |  | ||||||
|         }catch (IllegalAccessException | InvocationTargetException ex) { |  | ||||||
|             throw new RuntimeException(ex); |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     public Method getMethod() { |  | ||||||
|         return method; |  | ||||||
|     } |     } | ||||||
|  |  | ||||||
| } | } | ||||||
|   | |||||||
| @@ -2,32 +2,36 @@ package net.tomatentum.marinara.interaction.methods; | |||||||
|  |  | ||||||
| import java.lang.reflect.Method; | import java.lang.reflect.Method; | ||||||
|  |  | ||||||
|  | import net.tomatentum.marinara.Marinara; | ||||||
| import net.tomatentum.marinara.interaction.InteractionHandler; | import net.tomatentum.marinara.interaction.InteractionHandler; | ||||||
| import net.tomatentum.marinara.interaction.InteractionType; | import net.tomatentum.marinara.interaction.InteractionType; | ||||||
| import net.tomatentum.marinara.interaction.commands.ExecutableSlashCommandDefinition; | import net.tomatentum.marinara.interaction.commands.ExecutableSlashCommandDefinition; | ||||||
| import net.tomatentum.marinara.interaction.commands.annotation.SlashCommand; | import net.tomatentum.marinara.parser.AnnotationParser; | ||||||
| import net.tomatentum.marinara.interaction.commands.annotation.SubCommand; | import net.tomatentum.marinara.parser.SlashCommandParser; | ||||||
| import net.tomatentum.marinara.interaction.commands.annotation.SubCommandGroup; |  | ||||||
| import net.tomatentum.marinara.util.ReflectionUtil; |  | ||||||
| import net.tomatentum.marinara.wrapper.LibraryWrapper; |  | ||||||
|  |  | ||||||
| public class SlashCommandInteractionMethod extends InteractionMethod { | public class SlashCommandInteractionMethod extends InteractionMethod { | ||||||
|  |  | ||||||
|     private ExecutableSlashCommandDefinition commandDefinition; |     private ExecutableSlashCommandDefinition commandDefinition; | ||||||
|  |  | ||||||
|     SlashCommandInteractionMethod(Method method, InteractionHandler handler, LibraryWrapper wrapper) { |     SlashCommandInteractionMethod(Method method, InteractionHandler handler, Marinara marinara) { | ||||||
|         super(method, handler, wrapper); |         super(method, handler, marinara); | ||||||
|         parseMethod(); |     } | ||||||
|  |  | ||||||
|  |     @Override | ||||||
|  |     public AnnotationParser[] getParsers() { | ||||||
|  |         return new AnnotationParser[] {  | ||||||
|  |             new SlashCommandParser(method, (x) -> { this.commandDefinition = x; } )  | ||||||
|  |         }; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     @Override |     @Override | ||||||
|     public Object getParameter(Object context, int index) { |     public Object getParameter(Object context, int index) { | ||||||
|         return wrapper.convertCommandOption(context, commandDefinition.options()[index].type(), commandDefinition.options()[index].name()); |         return marinara.getWrapper().convertCommandOption(context, commandDefinition.options()[index].type(), commandDefinition.options()[index].name()); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     @Override |     @Override | ||||||
|     public boolean canRun(Object context) { |     public boolean canRun(Object context) { | ||||||
|         ExecutableSlashCommandDefinition other = wrapper.getCommandDefinition(context); |         ExecutableSlashCommandDefinition other = marinara.getWrapper().getCommandDefinition(context); | ||||||
|         return commandDefinition.equals(other); |         return commandDefinition.equals(other); | ||||||
|     } |     } | ||||||
|  |  | ||||||
| @@ -40,24 +44,8 @@ public class SlashCommandInteractionMethod extends InteractionMethod { | |||||||
|         return commandDefinition; |         return commandDefinition; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     private void parseMethod() { |     public void setCommandDefinition(ExecutableSlashCommandDefinition commandDefinition) { | ||||||
|         ReflectionUtil.checkValidCommandMethod(method); |         this.commandDefinition = commandDefinition; | ||||||
|  |  | ||||||
|         SlashCommand cmd = ReflectionUtil.getAnnotation(method, SlashCommand.class); |  | ||||||
|         ExecutableSlashCommandDefinition.Builder builder = new ExecutableSlashCommandDefinition.Builder(); |  | ||||||
|         builder.setApplicationCommand(cmd); |  | ||||||
|  |  | ||||||
|         if (ReflectionUtil.isAnnotationPresent(method, SubCommandGroup.class)) { |  | ||||||
|             SubCommandGroup cmdGroup = ReflectionUtil.getAnnotation(method, SubCommandGroup.class); |  | ||||||
|             builder.setSubCommandGroup(cmdGroup); |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         if (ReflectionUtil.isAnnotationPresent(method, SubCommand.class)) { |  | ||||||
|             SubCommand subCmd = ReflectionUtil.getAnnotation(method, SubCommand.class); |  | ||||||
|             builder.setSubCommand(subCmd); |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         this.commandDefinition = builder.build(); |  | ||||||
|     } |     } | ||||||
|  |  | ||||||
| } | } | ||||||
|   | |||||||
| @@ -0,0 +1,8 @@ | |||||||
|  | package net.tomatentum.marinara.parser; | ||||||
|  |  | ||||||
|  | import java.lang.reflect.Method; | ||||||
|  |  | ||||||
|  | public interface AnnotationParser { | ||||||
|  |     void parse(); | ||||||
|  |     Method getMethod(); | ||||||
|  | } | ||||||
| @@ -0,0 +1,29 @@ | |||||||
|  | package net.tomatentum.marinara.parser; | ||||||
|  |  | ||||||
|  | import java.lang.reflect.Method; | ||||||
|  | import java.util.function.Consumer; | ||||||
|  |  | ||||||
|  | import net.tomatentum.marinara.interaction.annotation.Button; | ||||||
|  |  | ||||||
|  | public class ButtonParser implements AnnotationParser { | ||||||
|  |      | ||||||
|  |     private Method method; | ||||||
|  |     private Consumer<String> consumer; | ||||||
|  |  | ||||||
|  |     public ButtonParser(Method method, Consumer<String> consumer) { | ||||||
|  |         this.method = method; | ||||||
|  |         this.consumer = consumer; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     @Override | ||||||
|  |     public void parse() { | ||||||
|  |         Button button = getMethod().getAnnotation(Button.class); | ||||||
|  |         this.consumer.accept(button.value()); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     @Override | ||||||
|  |     public Method getMethod() { | ||||||
|  |         return this.method; | ||||||
|  |     } | ||||||
|  |      | ||||||
|  | } | ||||||
| @@ -0,0 +1,42 @@ | |||||||
|  | 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 net.tomatentum.marinara.checks.AppliedCheck; | ||||||
|  | import net.tomatentum.marinara.checks.InteractionCheck; | ||||||
|  | import net.tomatentum.marinara.registry.InteractionCheckRegistry; | ||||||
|  |  | ||||||
|  | public class InteractionCheckParser implements AnnotationParser { | ||||||
|  |  | ||||||
|  |     private InteractionCheckRegistry checkRegistry; | ||||||
|  |     private Method method; | ||||||
|  |     private Consumer<AppliedCheck> consumer; | ||||||
|  |  | ||||||
|  |     public InteractionCheckParser(Method method, Consumer<AppliedCheck> consumer, InteractionCheckRegistry checkRegistry) { | ||||||
|  |         this.checkRegistry = checkRegistry; | ||||||
|  |         this.method = method; | ||||||
|  |         this.consumer = consumer; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     @Override | ||||||
|  |     public void parse() { | ||||||
|  |         Annotation[] annotations = method.getAnnotations(); | ||||||
|  |         Arrays.stream(annotations).forEach(this::convertAnnotation); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     private void convertAnnotation(Annotation annotation) { | ||||||
|  |             Optional<InteractionCheck<?>> check = this.checkRegistry.getCheckFromAnnotation(annotation.annotationType()); | ||||||
|  |             if (check.isPresent()) | ||||||
|  |                 consumer.accept(new AppliedCheck(check.get(), annotation)); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     @Override | ||||||
|  |     public Method getMethod() { | ||||||
|  |         return this.method; | ||||||
|  |     } | ||||||
|  |      | ||||||
|  | } | ||||||
| @@ -0,0 +1,63 @@ | |||||||
|  | package net.tomatentum.marinara.parser; | ||||||
|  |  | ||||||
|  | import java.lang.reflect.Method; | ||||||
|  | import java.util.function.Consumer; | ||||||
|  |  | ||||||
|  | import net.tomatentum.marinara.interaction.commands.ExecutableSlashCommandDefinition; | ||||||
|  | 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.util.ReflectionUtil; | ||||||
|  |  | ||||||
|  | public class SlashCommandParser implements AnnotationParser { | ||||||
|  |  | ||||||
|  |     private Method method; | ||||||
|  |     private Consumer<ExecutableSlashCommandDefinition> consumer; | ||||||
|  |  | ||||||
|  |     public SlashCommandParser(Method method, Consumer<ExecutableSlashCommandDefinition> consumer) { | ||||||
|  |         this.method = method; | ||||||
|  |         this.consumer = consumer; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     @Override | ||||||
|  |     public void parse() { | ||||||
|  |         this.checkValidCommandMethod(method); | ||||||
|  |  | ||||||
|  |         SlashCommand cmd = ReflectionUtil.getAnnotation(method, SlashCommand.class); | ||||||
|  |         ExecutableSlashCommandDefinition.Builder builder = new ExecutableSlashCommandDefinition.Builder(); | ||||||
|  |         builder.setApplicationCommand(cmd); | ||||||
|  |  | ||||||
|  |         if (ReflectionUtil.isAnnotationPresent(method, SubCommandGroup.class)) { | ||||||
|  |             SubCommandGroup cmdGroup = ReflectionUtil.getAnnotation(method, SubCommandGroup.class); | ||||||
|  |             builder.setSubCommandGroup(cmdGroup); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         if (ReflectionUtil.isAnnotationPresent(method, SubCommand.class)) { | ||||||
|  |             SubCommand subCmd = ReflectionUtil.getAnnotation(method, SubCommand.class); | ||||||
|  |             builder.setSubCommand(subCmd); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         consumer.accept(builder.build()); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     @Override | ||||||
|  |     public Method getMethod() { | ||||||
|  |        return this.method; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     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"); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         if (!ReflectionUtil.isAnnotationPresent(method, SlashCommand.class)) | ||||||
|  |             throw new RuntimeException(method.getName() + ": Missing ApplicationCommand 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"); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |      | ||||||
|  | } | ||||||
| @@ -0,0 +1,34 @@ | |||||||
|  | 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 io.leangen.geantyref.GenericTypeReflector; | ||||||
|  | import net.tomatentum.marinara.checks.InteractionCheck; | ||||||
|  |  | ||||||
|  | public class InteractionCheckRegistry { | ||||||
|  |      | ||||||
|  |     private List<InteractionCheck<?>> checks; | ||||||
|  |  | ||||||
|  |     public InteractionCheckRegistry() { | ||||||
|  |         this.checks = new ArrayList<>(); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     public void addCheck(InteractionCheck<?> check) { | ||||||
|  |         checks.add(check); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     public Optional<InteractionCheck<?>> 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(); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  | } | ||||||
| @@ -5,27 +5,27 @@ import java.util.ArrayList; | |||||||
| import java.util.List; | import java.util.List; | ||||||
| import java.util.Optional; | import java.util.Optional; | ||||||
|  |  | ||||||
|  | import net.tomatentum.marinara.Marinara; | ||||||
| import net.tomatentum.marinara.interaction.InteractionHandler; | import net.tomatentum.marinara.interaction.InteractionHandler; | ||||||
| import net.tomatentum.marinara.interaction.InteractionType; | import net.tomatentum.marinara.interaction.InteractionType; | ||||||
| import net.tomatentum.marinara.interaction.commands.SlashCommandDefinition; | import net.tomatentum.marinara.interaction.commands.SlashCommandDefinition; | ||||||
| import net.tomatentum.marinara.interaction.commands.ExecutableSlashCommandDefinition; | import net.tomatentum.marinara.interaction.commands.ExecutableSlashCommandDefinition; | ||||||
| import net.tomatentum.marinara.interaction.methods.SlashCommandInteractionMethod; | import net.tomatentum.marinara.interaction.methods.SlashCommandInteractionMethod; | ||||||
| import net.tomatentum.marinara.interaction.methods.InteractionMethod; | import net.tomatentum.marinara.interaction.methods.InteractionMethod; | ||||||
| import net.tomatentum.marinara.wrapper.LibraryWrapper; |  | ||||||
|  |  | ||||||
| public class InteractionRegistry { | public class InteractionRegistry { | ||||||
|     private List<InteractionMethod> interactionMethods; |     private List<InteractionMethod> interactionMethods; | ||||||
|     private LibraryWrapper wrapper; |     private Marinara marinara; | ||||||
|  |  | ||||||
|     public InteractionRegistry(LibraryWrapper wrapper) { |     public InteractionRegistry(Marinara marinara) { | ||||||
|         this.interactionMethods = new ArrayList<>(); |         this.interactionMethods = new ArrayList<>(); | ||||||
|         this.wrapper = wrapper; |         this.marinara = marinara; | ||||||
|         wrapper.subscribeInteractions(this::handle); |         marinara.getWrapper().subscribeInteractions(this::handle); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     public void addInteractions(InteractionHandler interactionHandler) { |     public void addInteractions(InteractionHandler interactionHandler) { | ||||||
|         for (Method method : interactionHandler.getClass().getMethods()) { |         for (Method method : interactionHandler.getClass().getMethods()) { | ||||||
|             InteractionMethod iMethod = InteractionMethod.create(method, interactionHandler, wrapper); |             InteractionMethod iMethod = InteractionMethod.create(method, interactionHandler, marinara); | ||||||
|             if (iMethod != null) |             if (iMethod != null) | ||||||
|                 this.interactionMethods.add(iMethod); |                 this.interactionMethods.add(iMethod); | ||||||
|         } |         } | ||||||
| @@ -48,13 +48,13 @@ public class InteractionRegistry { | |||||||
|                 defs.add(new SlashCommandDefinition(def.applicationCommand()).addExecutableCommand(def)); |                 defs.add(new SlashCommandDefinition(def.applicationCommand()).addExecutableCommand(def)); | ||||||
|         }); |         }); | ||||||
|  |  | ||||||
|         wrapper.registerSlashCommands(defs.toArray(new SlashCommandDefinition[0])); |         marinara.getWrapper().registerSlashCommands(defs.toArray(new SlashCommandDefinition[0])); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     public void handle(Object context) { |     public void handle(Object context) { | ||||||
|         interactionMethods.forEach((m) -> { |         interactionMethods.forEach((m) -> { | ||||||
|             InteractionType type = wrapper.getInteractionType(context.getClass()); |             InteractionType type = marinara.getWrapper().getInteractionType(context.getClass()); | ||||||
|             if (m.getType().equals(type)) |             if (m.getType().equals(type) && m.canRun(context)) | ||||||
|                 m.run(context); |                 m.run(context); | ||||||
|         }); |         }); | ||||||
|     } |     } | ||||||
|   | |||||||
| @@ -2,9 +2,10 @@ package net.tomatentum.marinara.util; | |||||||
|  |  | ||||||
| import java.lang.annotation.Annotation; | import java.lang.annotation.Annotation; | ||||||
| import java.lang.reflect.Method; | import java.lang.reflect.Method; | ||||||
|  | import java.util.ArrayList; | ||||||
| import net.tomatentum.marinara.interaction.commands.annotation.SlashCommand; | import java.util.Arrays; | ||||||
| import net.tomatentum.marinara.interaction.commands.annotation.SubCommand; | import java.util.List; | ||||||
|  | import java.util.Objects; | ||||||
|  |  | ||||||
| public final class ReflectionUtil { | public final class ReflectionUtil { | ||||||
|  |  | ||||||
| @@ -21,19 +22,82 @@ public final class ReflectionUtil { | |||||||
|             method.getDeclaringClass().getAnnotation(annotationClass); |             method.getDeclaringClass().getAnnotation(annotationClass); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     public static void checkValidCommandMethod(Method method) { |     public static int getCastDepth(Class<?> child, Class<?> parent) { | ||||||
|         if (method.isAnnotationPresent(SlashCommand.class) &&  |  | ||||||
|             method.getDeclaringClass().isAnnotationPresent(SlashCommand.class)) { |         if (parent.equals(Object.class)) | ||||||
|             throw new RuntimeException(method.getName() + ": Can't have ApplicationCommand Annotation on Class and Method"); |             return Integer.MAX_VALUE; | ||||||
|  |  | ||||||
|  |         if (!parent.isAssignableFrom(child)) { | ||||||
|  |             throw new IllegalArgumentException("The specified class is not a child class of the specified parent."); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         if (!isAnnotationPresent(method, SlashCommand.class)) |         int depth = 0; | ||||||
|             throw new RuntimeException(method.getName() + ": Missing ApplicationCommand Annotation on either Class or Method"); |         Class<?> curr = child; | ||||||
|  |         List<Class<?>> parents = new ArrayList<>(); | ||||||
|  |  | ||||||
|         if ((method.isAnnotationPresent(SubCommand.class) &&  |         while (!curr.equals(parent)) { | ||||||
|             !isAnnotationPresent(method, SlashCommand.class))) { |             depth++; | ||||||
|             throw new RuntimeException(method.getName() + ": Missing ApplicationCommand Annotation on either Method or Class"); |             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<Method> 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; | ||||||
|  |     } | ||||||
| } | } | ||||||
|   | |||||||
| @@ -29,7 +29,7 @@ dependencies { | |||||||
| // Apply a specific Java toolchain to ease working on different environments. | // Apply a specific Java toolchain to ease working on different environments. | ||||||
| java { | java { | ||||||
|     toolchain { |     toolchain { | ||||||
|         languageVersion = JavaLanguageVersion.of(21) |         languageVersion = JavaLanguageVersion.of(23) | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -0,0 +1,41 @@ | |||||||
|  | package net.tomatentum.marinara.wrapper.javacord.checks; | ||||||
|  |  | ||||||
|  | import java.lang.annotation.ElementType; | ||||||
|  | import java.lang.annotation.Retention; | ||||||
|  | import java.lang.annotation.RetentionPolicy; | ||||||
|  | import java.lang.annotation.Target; | ||||||
|  | import java.util.Optional; | ||||||
|  |  | ||||||
|  | import org.javacord.api.entity.permission.PermissionType; | ||||||
|  | import org.javacord.api.entity.server.Server; | ||||||
|  | import org.javacord.api.interaction.InteractionBase; | ||||||
|  |  | ||||||
|  | import net.tomatentum.marinara.checks.InteractionCheck; | ||||||
|  |  | ||||||
|  | public class PermissionCheck implements InteractionCheck<PermissionCheck.HasPermission> { | ||||||
|  |  | ||||||
|  |     @Retention(RetentionPolicy.RUNTIME) | ||||||
|  |     @Target(ElementType.METHOD) | ||||||
|  |     public static @interface HasPermission { | ||||||
|  |         public PermissionType[] value(); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     @Override | ||||||
|  |     public boolean preExec(Object context, HasPermission annotation) { | ||||||
|  |         throw new UnsupportedOperationException("Unimplemented method 'preExec'"); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     public boolean preExec(InteractionBase context, HasPermission annotation) { | ||||||
|  |         Optional<Server> server = context.getServer(); | ||||||
|  |         if (!server.isPresent()) | ||||||
|  |             return false; | ||||||
|  |  | ||||||
|  |        return server.get().hasPermissions(context.getUser(), annotation.value()); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     @Override | ||||||
|  |     public void postExec(Object context, HasPermission annotation) { | ||||||
|  |          | ||||||
|  |     } | ||||||
|  |      | ||||||
|  | } | ||||||
| @@ -20,7 +20,7 @@ public class ButtonTest { | |||||||
|         LibraryWrapper wrapper = new JavacordWrapper(new DiscordApiMock()); //null okay as we don't use the discord API in this test. |         LibraryWrapper wrapper = new JavacordWrapper(new DiscordApiMock()); //null okay as we don't use the discord API in this test. | ||||||
|         Marinara marinara = Marinara.load(wrapper); |         Marinara marinara = Marinara.load(wrapper); | ||||||
|         marinara.getRegistry().addInteractions(new TestButton()); |         marinara.getRegistry().addInteractions(new TestButton()); | ||||||
|         wrapper.handleInteraction(new ButtonInteractionMock()); |         wrapper.handleInteraction(new ButtonInteractionMock("test")); | ||||||
|         assertTrue(TestButton.didRun); |         assertTrue(TestButton.didRun); | ||||||
|     } |     } | ||||||
|      |      | ||||||
|   | |||||||
| @@ -0,0 +1,47 @@ | |||||||
|  | package net.tomatentum.marinara.test; | ||||||
|  |  | ||||||
|  | import static org.junit.jupiter.api.Assertions.assertFalse; | ||||||
|  | import static org.junit.jupiter.api.Assertions.assertTrue; | ||||||
|  |  | ||||||
|  | import org.javacord.api.entity.permission.PermissionType; | ||||||
|  | import org.junit.jupiter.api.Test; | ||||||
|  | import org.junit.jupiter.api.TestInstance; | ||||||
|  | import org.junit.jupiter.api.TestInstance.Lifecycle; | ||||||
|  |  | ||||||
|  | import net.tomatentum.marinara.Marinara; | ||||||
|  | import net.tomatentum.marinara.test.mocks.ButtonInteractionMock; | ||||||
|  | import net.tomatentum.marinara.test.mocks.DiscordApiMock; | ||||||
|  | import net.tomatentum.marinara.test.mocks.ServerMock; | ||||||
|  | import net.tomatentum.marinara.wrapper.LibraryWrapper; | ||||||
|  | import net.tomatentum.marinara.wrapper.javacord.JavacordWrapper; | ||||||
|  | import net.tomatentum.marinara.wrapper.javacord.checks.PermissionCheck; | ||||||
|  |  | ||||||
|  | @TestInstance(Lifecycle.PER_CLASS) | ||||||
|  | public class InteractionCheckTest { | ||||||
|  |      | ||||||
|  |     @Test | ||||||
|  |     public void testInteractionCheck() { | ||||||
|  |         LibraryWrapper wrapper = new JavacordWrapper(new DiscordApiMock()); | ||||||
|  |         Marinara marinara = Marinara.load(wrapper); | ||||||
|  |         marinara.getCheckRegistry().addCheck(new TestInteractionCheck()); | ||||||
|  |         marinara.getRegistry().addInteractions(new TestButton()); | ||||||
|  |         wrapper.handleInteraction(new ButtonInteractionMock("test")); | ||||||
|  |         assertTrue(TestInteractionCheck.preExecuted); | ||||||
|  |         assertTrue(TestInteractionCheck.postExecuted); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     @Test | ||||||
|  |     public void testPermissionCheck() { | ||||||
|  |         LibraryWrapper wrapper = new JavacordWrapper(new DiscordApiMock()); | ||||||
|  |         Marinara marinara = Marinara.load(wrapper); | ||||||
|  |         marinara.getCheckRegistry().addCheck(new PermissionCheck()); | ||||||
|  |         marinara.getRegistry().addInteractions(new TestButton()); | ||||||
|  |         wrapper.handleInteraction(new ButtonInteractionMock("permissionCheck")); | ||||||
|  |         assertTrue(TestButton.didPermRun); | ||||||
|  |         TestButton.didPermRun = false; | ||||||
|  |         ServerMock.TESTPERMISSION = PermissionType.ATTACH_FILE; | ||||||
|  |         wrapper.handleInteraction(new ButtonInteractionMock("permissionCheck")); | ||||||
|  |         assertFalse(TestButton.didPermRun); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  | } | ||||||
| @@ -4,18 +4,22 @@ import static org.junit.jupiter.api.Assertions.assertNotNull; | |||||||
|  |  | ||||||
| import org.javacord.api.entity.channel.TextChannel; | import org.javacord.api.entity.channel.TextChannel; | ||||||
| import org.javacord.api.entity.message.Message; | import org.javacord.api.entity.message.Message; | ||||||
|  | import org.javacord.api.entity.permission.PermissionType; | ||||||
| import org.javacord.api.entity.server.Server; | import org.javacord.api.entity.server.Server; | ||||||
| import org.javacord.api.entity.user.User; | import org.javacord.api.entity.user.User; | ||||||
| import org.javacord.api.interaction.ButtonInteraction; | import org.javacord.api.interaction.ButtonInteraction; | ||||||
|  |  | ||||||
| import net.tomatentum.marinara.interaction.InteractionHandler; | import net.tomatentum.marinara.interaction.InteractionHandler; | ||||||
| import net.tomatentum.marinara.interaction.annotation.Button; | import net.tomatentum.marinara.interaction.annotation.Button; | ||||||
|  | import net.tomatentum.marinara.test.TestInteractionCheck.TestCheck; | ||||||
|  | import net.tomatentum.marinara.wrapper.javacord.checks.PermissionCheck.HasPermission; | ||||||
|  |  | ||||||
| public class TestButton implements InteractionHandler { | public class TestButton implements InteractionHandler { | ||||||
|  |  | ||||||
|  |  | ||||||
|     public static boolean didRun = false; |     public static boolean didRun = false; | ||||||
|     @Button("test") |     @Button("test") | ||||||
|  |     @TestCheck | ||||||
|     public void exec(ButtonInteraction interaction, TextChannel channel, Message message, User member, Server server) { |     public void exec(ButtonInteraction interaction, TextChannel channel, Message message, User member, Server server) { | ||||||
|         assertNotNull(interaction); |         assertNotNull(interaction); | ||||||
|         assertNotNull(channel); |         assertNotNull(channel); | ||||||
| @@ -26,4 +30,13 @@ public class TestButton implements InteractionHandler { | |||||||
|         System.out.println("Success!"); |         System.out.println("Success!"); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     public static boolean didPermRun = false; | ||||||
|  |  | ||||||
|  |     @Button("permissionCheck") | ||||||
|  |     @HasPermission({PermissionType.ADMINISTRATOR}) | ||||||
|  |     public void exec(ButtonInteraction interaction) { | ||||||
|  |         didPermRun = true; | ||||||
|  |         System.out.println("It worked!"); | ||||||
|  |     } | ||||||
|  |      | ||||||
| } | } | ||||||
|   | |||||||
| @@ -0,0 +1,37 @@ | |||||||
|  | package net.tomatentum.marinara.test; | ||||||
|  |  | ||||||
|  | import static org.junit.jupiter.api.Assertions.assertNotNull; | ||||||
|  |  | ||||||
|  | import java.lang.annotation.ElementType; | ||||||
|  | import java.lang.annotation.Retention; | ||||||
|  | import java.lang.annotation.RetentionPolicy; | ||||||
|  | import java.lang.annotation.Target; | ||||||
|  |  | ||||||
|  | import net.tomatentum.marinara.checks.InteractionCheck; | ||||||
|  |  | ||||||
|  | public class TestInteractionCheck implements InteractionCheck<TestInteractionCheck.TestCheck> { | ||||||
|  |  | ||||||
|  |     public static boolean preExecuted = false; | ||||||
|  |     public static boolean postExecuted = false; | ||||||
|  |  | ||||||
|  |     @Target({ElementType.METHOD}) | ||||||
|  |     @Retention(RetentionPolicy.RUNTIME) | ||||||
|  |     public static @interface TestCheck { | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     @Override | ||||||
|  |     public boolean preExec(Object context, TestCheck annotation) { | ||||||
|  |         assertNotNull(annotation); | ||||||
|  |         assertNotNull(context); | ||||||
|  |         preExecuted = true; | ||||||
|  |         return true; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     @Override | ||||||
|  |     public void postExec(Object context, TestCheck annotation) { | ||||||
|  |         assertNotNull(annotation); | ||||||
|  |         assertNotNull(context); | ||||||
|  |         postExecuted = true; | ||||||
|  |     } | ||||||
|  |      | ||||||
|  | } | ||||||
| @@ -23,6 +23,12 @@ import org.javacord.api.interaction.callback.InteractionOriginalResponseUpdater; | |||||||
|  |  | ||||||
| public class ButtonInteractionMock implements ButtonInteraction { | public class ButtonInteractionMock implements ButtonInteraction { | ||||||
|  |  | ||||||
|  |     private String customId; | ||||||
|  |      | ||||||
|  |     public ButtonInteractionMock(String customId) { | ||||||
|  |         this.customId = customId; | ||||||
|  |     } | ||||||
|  |  | ||||||
|     @Override |     @Override | ||||||
|     public Message getMessage() { |     public Message getMessage() { | ||||||
|         return new MessageMock(); |         return new MessageMock(); | ||||||
| @@ -30,7 +36,7 @@ public class ButtonInteractionMock implements ButtonInteraction { | |||||||
|  |  | ||||||
|     @Override |     @Override | ||||||
|     public String getCustomId() { |     public String getCustomId() { | ||||||
|         return "test"; |         return this.customId; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     @Override |     @Override | ||||||
|   | |||||||
| @@ -1,5 +1,7 @@ | |||||||
| package net.tomatentum.marinara.test.mocks; | package net.tomatentum.marinara.test.mocks; | ||||||
|  |  | ||||||
|  | import static org.junit.jupiter.api.Assertions.assertNotNull; | ||||||
|  |  | ||||||
| import java.time.Instant; | import java.time.Instant; | ||||||
| import java.util.Collection; | import java.util.Collection; | ||||||
| import java.util.EnumSet; | import java.util.EnumSet; | ||||||
| @@ -27,6 +29,7 @@ import org.javacord.api.entity.channel.ServerTextChannel; | |||||||
| import org.javacord.api.entity.channel.ServerThreadChannel; | import org.javacord.api.entity.channel.ServerThreadChannel; | ||||||
| import org.javacord.api.entity.channel.ServerVoiceChannel; | import org.javacord.api.entity.channel.ServerVoiceChannel; | ||||||
| import org.javacord.api.entity.emoji.KnownCustomEmoji; | import org.javacord.api.entity.emoji.KnownCustomEmoji; | ||||||
|  | import org.javacord.api.entity.permission.PermissionType; | ||||||
| import org.javacord.api.entity.permission.Role; | import org.javacord.api.entity.permission.Role; | ||||||
| import org.javacord.api.entity.server.ActiveThreads; | import org.javacord.api.entity.server.ActiveThreads; | ||||||
| import org.javacord.api.entity.server.Ban; | import org.javacord.api.entity.server.Ban; | ||||||
| @@ -2259,5 +2262,12 @@ public class ServerMock implements Server { | |||||||
|         // TODO Auto-generated method stub |         // TODO Auto-generated method stub | ||||||
|         throw new UnsupportedOperationException("Unimplemented method 'getSystemChannelFlags'"); |         throw new UnsupportedOperationException("Unimplemented method 'getSystemChannelFlags'"); | ||||||
|     } |     } | ||||||
|  |     public static PermissionType TESTPERMISSION = PermissionType.ADMINISTRATOR; | ||||||
|  |     @Override | ||||||
|  |     public boolean hasPermissions(User user, PermissionType... type) { | ||||||
|  |         assertNotNull(user); | ||||||
|  |         assertNotNull(type); | ||||||
|  |         return TESTPERMISSION.equals(type[0]); | ||||||
|  |     } | ||||||
|      |      | ||||||
| } | } | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user