diff --git a/.gitea/workflows/gradle-build.yaml b/.gitea/workflows/gradle-build.yaml index 9f89304..d9a3eda 100644 --- a/.gitea/workflows/gradle-build.yaml +++ b/.gitea/workflows/gradle-build.yaml @@ -38,7 +38,10 @@ jobs: run: chmod +x gradlew; ./gradlew assemble - name: Move artifacts - run: mkdir artifacts; mv lib/build/libs/*.jar artifacts; mv wrapper/javacord/build/libs/*.jar artifacts; + run: | + mkdir artifacts; mv lib/build/libs/*.jar artifacts; + mv wrapper/javacord/build/libs/*.jar artifacts; + mv wrapper/discord4j/build/libs/*.jar artifacts; - name: Upload artifact uses: christopherhx/gitea-upload-artifact@v4 diff --git a/.gitea/workflows/gradle-test.yaml b/.gitea/workflows/gradle-test.yaml index 62fe064..af12cbc 100644 --- a/.gitea/workflows/gradle-test.yaml +++ b/.gitea/workflows/gradle-test.yaml @@ -44,6 +44,7 @@ jobs: mkdir test-results/; [ -d lib/build/test-results/test/ ] && mv lib/build/test-results/test/*.xml test-results/; [ -d wrapper/javacord/build/test-results/test/ ] && mv wrapper/javacord/build/test-results/test/*.xml test-results/; + [ -d wrapper/discord4j/build/test-results/test/ ] && mv wrapper/discord4j/build/test-results/test/*.xml test-results/; - name: Upload Test Result uses: christopherhx/gitea-upload-artifact@v4 diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index de79cc7..021ee38 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -5,10 +5,14 @@ junit-jupiter = "5.10.2" log4j = "2.24.1" javacord = "3.8.0" +discord4j = "3.2.7" geantyref = "2.0.0" +mockito = "5.15.2" [libraries] junit-jupiter = { module = "org.junit.jupiter:junit-jupiter", version.ref = "junit-jupiter" } log4j = { module = "org.apache.logging.log4j:log4j-api", version.ref = "log4j"} 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"} diff --git a/lib/src/main/java/net/tomatentum/marinara/interaction/commands/EnumChoices.java b/lib/src/main/java/net/tomatentum/marinara/interaction/commands/EnumChoices.java index 58d82d9..1001db3 100644 --- a/lib/src/main/java/net/tomatentum/marinara/interaction/commands/EnumChoices.java +++ b/lib/src/main/java/net/tomatentum/marinara/interaction/commands/EnumChoices.java @@ -67,7 +67,7 @@ public record EnumChoices(Class> enumClass, ChoiceType type, S return null; } } - return choices.toArray(new SlashCommandOptionChoice[0]); + return choices.toArray(SlashCommandOptionChoice[]::new); } public static enum ChoiceType { diff --git a/lib/src/main/java/net/tomatentum/marinara/interaction/commands/option/SlashCommandOptionType.java b/lib/src/main/java/net/tomatentum/marinara/interaction/commands/option/SlashCommandOptionType.java index ce80c6f..581bd30 100644 --- a/lib/src/main/java/net/tomatentum/marinara/interaction/commands/option/SlashCommandOptionType.java +++ b/lib/src/main/java/net/tomatentum/marinara/interaction/commands/option/SlashCommandOptionType.java @@ -23,4 +23,13 @@ public enum SlashCommandOptionType { public int getValue() { return value; } + + public static SlashCommandOptionType fromValue(int value) { + for (SlashCommandOptionType type : values()) { + if (type.getValue() == value) { + return type; + } + } + return UNKNOWN; + } } 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 fa383e3..ddc3618 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 @@ -97,7 +97,7 @@ public abstract class InteractionMethod { }else parameter = getParameter(context, i-1); - logger.trace("Found parameter {}={} for method {}", parameter.getClass().toString(), parameter, ReflectionUtil.getFullMethodName(method)); + logger.trace("Found parameter {}={} for method {}", parameter != null ? parameter.getClass().toString() : " ", parameter, ReflectionUtil.getFullMethodName(method)); parameters.add(parameter); } return parameters.toArray(); diff --git a/lib/src/main/java/net/tomatentum/marinara/registry/InteractionRegistry.java b/lib/src/main/java/net/tomatentum/marinara/registry/InteractionRegistry.java index c771761..27a2152 100644 --- a/lib/src/main/java/net/tomatentum/marinara/registry/InteractionRegistry.java +++ b/lib/src/main/java/net/tomatentum/marinara/registry/InteractionRegistry.java @@ -66,7 +66,7 @@ public class InteractionRegistry { } public void handle(Object context) { - InteractionType type = marinara.getWrapper().getInteractionType(context.getClass()); + InteractionType type = marinara.getWrapper().getInteractionType(context); logger.debug("Received {} interaction ", context); interactionMethods.forEach((m) -> { if (m.getType().equals(type) && m.canRun(context)) { 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 06e1661..7bf932a 100644 --- a/lib/src/main/java/net/tomatentum/marinara/wrapper/LibraryWrapper.java +++ b/lib/src/main/java/net/tomatentum/marinara/wrapper/LibraryWrapper.java @@ -27,7 +27,7 @@ public abstract class LibraryWrapper { interactionSubscriber.remove(consumer); } - public abstract InteractionType getInteractionType(Class clazz); + public abstract InteractionType getInteractionType(Object context); public abstract void registerSlashCommands(SlashCommandDefinition[] defs); public abstract ExecutableSlashCommandDefinition getCommandDefinition(Object context); diff --git a/settings.gradle.kts b/settings.gradle.kts index 06c8680..d885dc5 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -13,5 +13,9 @@ plugins { rootProject.name = "Marinara" include(":lib") include(":wrapper-javacord") +include(":wrapper-discord4j") + project(":wrapper-javacord").projectDir = file("wrapper/javacord") +project(":wrapper-discord4j").projectDir = file("wrapper/discord4j") + diff --git a/wrapper/discord4j/build.gradle.kts b/wrapper/discord4j/build.gradle.kts new file mode 100644 index 0000000..dbbc261 --- /dev/null +++ b/wrapper/discord4j/build.gradle.kts @@ -0,0 +1,42 @@ +/* + * This file was generated by the Gradle 'init' task. + * + * This generated file contains a sample Java library project to get you started. + * For more details on building Java & JVM projects, please refer to https://docs.gradle.org/8.8/userguide/building_java_projects.html in the Gradle documentation. + */ + +plugins { + // Apply the java-library plugin for API and implementation separation. + `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") + implementation(libs.log4j) + implementation(libs.discord4j) { +// exclude(module="discord4j-voice") + } + implementation(libs.geantyref) + implementation(project(":lib")) +} + +// Apply a specific Java toolchain to ease working on different environments. +java { + toolchain { + languageVersion = JavaLanguageVersion.of(23) + } +} + +tasks.named("test") { + // Use JUnit Platform for unit tests. + useJUnitPlatform() +} 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 new file mode 100644 index 0000000..d16f789 --- /dev/null +++ b/wrapper/discord4j/src/main/java/net/tomatentum/marinara/wrapper/discord4j/Discord4JContextObjectProvider.java @@ -0,0 +1,102 @@ +package net.tomatentum.marinara.wrapper.discord4j; + +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.object.command.ApplicationCommandInteractionOption; +import net.tomatentum.marinara.interaction.commands.option.SlashCommandOptionType; +import net.tomatentum.marinara.wrapper.ContextObjectProvider; + +public class Discord4JContextObjectProvider implements ContextObjectProvider { + + @Override + public Object convertCommandOption(Object context, String optionName) { + if (!(context instanceof ChatInputInteractionEvent)) + return null; + ChatInputInteractionEvent interactionEvent = (ChatInputInteractionEvent) context; + + List subOptions = Discord4JWrapper.SUB_FILTER.apply(interactionEvent.getOptions()); + + if (subOptions.isEmpty()) + return getOptionValue(interactionEvent.getOption(optionName).get()); + + + ApplicationCommandInteractionOption subCommandOption = interactionEvent.getOptions().getFirst(); + subOptions = Discord4JWrapper.SUB_FILTER.apply(subCommandOption.getOptions()); + + if (!subOptions.isEmpty()) + subCommandOption = subOptions.getFirst(); + + return getOptionValue(interactionEvent.getOption(optionName).get()); + + } + + private Object getOptionValue(ApplicationCommandInteractionOption option) { + if (!option.getValue().isPresent()) + return null; + SlashCommandOptionType type = getOptionType(option); + + switch (type) { + case ATTACHMENT: + return option.getValue().get().asAttachment(); + case BOOLEAN: + return option.getValue().get().asBoolean(); + case CHANNEL: + return option.getValue().get().asChannel(); + case DOUBLE: + return option.getValue().get().asDouble(); + case INTEGER: + return option.getValue().get().asLong(); + case MENTIONABLE: + return option.getValue().get().asSnowflake(); + case ROLE: + return option.getValue().get().asRole(); + case STRING: + return option.getValue().get().asString(); + case USER: + return option.getValue().get().asUser(); + default: + return null; + } + } + + private SlashCommandOptionType getOptionType(ApplicationCommandInteractionOption option) { + return SlashCommandOptionType.fromValue(option.getType().getValue()); + } + + @Override + public Object getComponentContextObject(Object context, Class type) { + ComponentInteractionEvent componentInteractionEvent = (ComponentInteractionEvent) context; + switch (type.getName()) { + case "discord4j.core.object.entity.Message": + return componentInteractionEvent.getMessage().orElse(null); + default: + return getInteractionContextObject(context, type); + } + } + + @Override + public Object getInteractionContextObject(Object context, Class type) { + ComponentInteractionEvent componentInteractionEvent = (ComponentInteractionEvent) context; + switch (type.getName()) { + case "discord4j.core.object.entity.channel.MessageChannel": + return componentInteractionEvent.getInteraction().getChannel().block(); + case "discord4j.core.object.entity.Guild": + return componentInteractionEvent.getInteraction().getGuild().block(); + case "discord4j.core.object.entity.Member": + return componentInteractionEvent.getInteraction().getMember().orElse(null); + case "discord4j.core.object.entity.User": + return componentInteractionEvent.getInteraction().getUser(); + } + return null; + } + + @Override + public Object getAutocompleteFocusedOption(Object context) { + ChatInputAutoCompleteEvent interaction = (ChatInputAutoCompleteEvent) context; + return getOptionValue(interaction.getFocusedOption()); + } + +} 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 new file mode 100644 index 0000000..66df289 --- /dev/null +++ b/wrapper/discord4j/src/main/java/net/tomatentum/marinara/wrapper/discord4j/Discord4JWrapper.java @@ -0,0 +1,209 @@ +package net.tomatentum.marinara.wrapper.discord4j; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.function.Function; + +import org.apache.logging.log4j.Logger; + +import discord4j.core.GatewayDiscordClient; +import discord4j.core.event.domain.interaction.ButtonInteractionEvent; +import discord4j.core.event.domain.interaction.ChatInputAutoCompleteEvent; +import discord4j.core.event.domain.interaction.ChatInputInteractionEvent; +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.ApplicationCommandOptionData; +import discord4j.discordjson.json.ApplicationCommandRequest; + +import io.leangen.geantyref.AnnotationFormatException; +import io.leangen.geantyref.TypeFactory; +import net.tomatentum.marinara.interaction.InteractionType; +import net.tomatentum.marinara.interaction.commands.ExecutableSlashCommandDefinition; +import net.tomatentum.marinara.interaction.commands.SlashCommandDefinition; +import net.tomatentum.marinara.interaction.commands.annotation.SlashCommand; +import net.tomatentum.marinara.interaction.commands.annotation.SlashCommandOption; +import net.tomatentum.marinara.interaction.commands.annotation.SlashCommandOptionChoice; +import net.tomatentum.marinara.interaction.commands.annotation.SubCommand; +import net.tomatentum.marinara.interaction.commands.annotation.SubCommandGroup; +import net.tomatentum.marinara.util.LoggerUtil; +import net.tomatentum.marinara.wrapper.ContextObjectProvider; +import net.tomatentum.marinara.wrapper.LibraryWrapper; + +public class Discord4JWrapper extends LibraryWrapper { + + public static final Function, List> 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) -> + i.stream() + .filter(o -> !o.getType().equals(Type.SUB_COMMAND) && !o.getType().equals(Type.SUB_COMMAND_GROUP)) + .toList(); + + private GatewayDiscordClient api; + private Discord4JContextObjectProvider contextObjectProvider; + + private Logger logger = LoggerUtil.getLogger(getClass()); + + public Discord4JWrapper(GatewayDiscordClient api) { + this.api = api; + this.contextObjectProvider = new Discord4JContextObjectProvider(); + if (api != null) + api.on(InteractionCreateEvent.class) + .subscribe(event -> handleInteraction(event)); + + logger.info("Discord4J wrapper loaded!"); + } + + @Override + public InteractionType getInteractionType(Object context) { + if (ChatInputAutoCompleteEvent.class.isAssignableFrom(context.getClass())) + return InteractionType.AUTOCOMPLETE; + if (ChatInputInteractionEvent.class.isAssignableFrom(context.getClass())) + return InteractionType.COMMAND; + if (ButtonInteractionEvent.class.isAssignableFrom(context.getClass())) + return InteractionType.BUTTON; + + return null; + } + + @Override + public void registerSlashCommands(SlashCommandDefinition[] defs) { + HashMap> serverCommands = new HashMap<>(); + List globalCommands = new ArrayList<>(); + long applicationId = api.getRestClient().getApplicationId().block(); + + for (SlashCommandDefinition slashCommandDefinition : defs) { + ApplicationCommandRequest request = convertSlashCommand(slashCommandDefinition); + if (slashCommandDefinition.getFullSlashCommand().serverIds().length > 0) { + for (long serverId : slashCommandDefinition.getFullSlashCommand().serverIds()) { + serverCommands.putIfAbsent(serverId, new ArrayList<>()); + serverCommands.get(serverId).add(request); + } + }else + globalCommands.add(request); + } + + for (long serverId : serverCommands.keySet()) { + api.getRestClient().getApplicationService().bulkOverwriteGuildApplicationCommand(applicationId, serverId, serverCommands.get(serverId)); + } + api.getRestClient().getApplicationService().bulkOverwriteGlobalApplicationCommand(applicationId, globalCommands); + } + + @Override + public ExecutableSlashCommandDefinition getCommandDefinition(Object context) { + List options; + String commandName; + + if (context instanceof ChatInputInteractionEvent) { + ChatInputInteractionEvent interaction = (ChatInputInteractionEvent) context; + options = SUB_FILTER.apply(interaction.getOptions()); + commandName = interaction.getCommandName(); + }else if (context instanceof ChatInputAutoCompleteEvent) { + ChatInputAutoCompleteEvent interaction = (ChatInputAutoCompleteEvent) context; + options = SUB_FILTER.apply(interaction.getOptions()); + commandName = interaction.getCommandName(); + }else + return null; + + ExecutableSlashCommandDefinition.Builder builder = new ExecutableSlashCommandDefinition.Builder(); + + try { + builder.setApplicationCommand(TypeFactory.annotation(SlashCommand.class, Map.of("name", commandName))); + if (!options.isEmpty()) { + if (!ARG_FILTER.apply(options.getFirst().getOptions()).isEmpty()) { + builder.setSubCommandGroup(TypeFactory.annotation(SubCommandGroup.class, Map.of("name", options.getFirst().getName()))); + builder.setSubCommand(TypeFactory.annotation(SubCommand.class, Map.of("name", SUB_FILTER.apply(options.getFirst().getOptions()).getFirst().getName()))); + }else + builder.setSubCommand(TypeFactory.annotation(SubCommand.class, Map.of("name", options.getFirst().getName()))); + } + } catch (AnnotationFormatException e) { + logger.fatal(e); + } + + return builder.build(); + } + + private ApplicationCommandRequest convertSlashCommand(SlashCommandDefinition def) { + List options = new ArrayList<>(); + SlashCommand cmd = def.getFullSlashCommand(); + if (!def.isRootCommand()) { + Arrays.stream(def.getSubCommands(null)).map(this::convertSubCommandDef).forEach(options::add); + Arrays.stream(def.getSubCommandGroups()).map((x) -> convertSubCommandGroupDef(def, x)).forEach(options::add); + }else { + Arrays.stream(cmd.options()).map(this::convertOptionDef).forEach(options::add); + } + + return ApplicationCommandRequest.builder() + .name(cmd.name()) + .description(cmd.description()) + .options(options) + .build(); + } + + private ApplicationCommandOptionData convertSubCommandGroupDef(SlashCommandDefinition def, SubCommandGroup subGroup) { + SubCommand[] subCommands = def.getSubCommands(subGroup.name()); + List convertedSubCommands = Arrays.stream(subCommands).map(this::convertSubCommandDef).toList(); + return ApplicationCommandOptionData.builder() + .type(Type.SUB_COMMAND_GROUP.getValue()) + .name(subGroup.name()) + .description(subGroup.description()) + .options(convertedSubCommands) + .build(); + } + + private ApplicationCommandOptionData convertSubCommandDef(SubCommand sub) { + List convertedOptions = Arrays.stream(sub.options()).map(this::convertOptionDef).toList(); + return ApplicationCommandOptionData.builder() + .type(Type.SUB_COMMAND_GROUP.getValue()) + .name(sub.name()) + .description(sub.description()) + .options(convertedOptions) + .build(); + } + + private ApplicationCommandOptionData convertOptionDef(SlashCommandOption option) { + Type type = Enum.valueOf(Type.class, option.type().toString()); + return ApplicationCommandOptionData.builder() + .type(type.getValue()) + .name(option.name()) + .description(option.description()) + .required(option.required()) + .autocomplete(option.autocomplete()) + .choices(convertChoices(option)) + .build(); + } + + private List convertChoices(SlashCommandOption option) { + List convertedChoices = new ArrayList<>(); + for (SlashCommandOptionChoice choice : ExecutableSlashCommandDefinition.getActualChoices(option)) { + var builder = ApplicationCommandOptionChoiceData.builder(); + builder.name(choice.name()); + if (choice.longValue() != Long.MAX_VALUE) + builder.value(choice.longValue()); + if (choice.doubleValue() != Double.MAX_VALUE) + builder.value(choice.doubleValue()); + if (!choice.stringValue().isEmpty()) + builder.value(choice.stringValue()); + } + return convertedChoices; + } + + @Override + public String getButtonId(Object context) { + ButtonInteractionEvent button = (ButtonInteractionEvent) context; + return button.getCustomId(); + } + + @Override + public ContextObjectProvider getContextObjectProvider() { + return this.contextObjectProvider; + } + +} diff --git a/wrapper/discord4j/src/main/java/net/tomatentum/marinara/wrapper/discord4j/checks/PermissionCheck.java b/wrapper/discord4j/src/main/java/net/tomatentum/marinara/wrapper/discord4j/checks/PermissionCheck.java new file mode 100644 index 0000000..7497c20 --- /dev/null +++ b/wrapper/discord4j/src/main/java/net/tomatentum/marinara/wrapper/discord4j/checks/PermissionCheck.java @@ -0,0 +1,42 @@ +package net.tomatentum.marinara.wrapper.discord4j.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 discord4j.core.event.domain.interaction.InteractionCreateEvent; +import discord4j.core.object.entity.Member; +import discord4j.rest.util.Permission; +import discord4j.rest.util.PermissionSet; +import net.tomatentum.marinara.checks.InteractionCheck; + +public class PermissionCheck implements InteractionCheck { + + @Retention(RetentionPolicy.RUNTIME) + @Target(ElementType.METHOD) + public static @interface HasPermission { + public Permission[] value(); + } + + @Override + public boolean preExec(Object context, HasPermission annotation) { + throw new UnsupportedOperationException("Unimplemented method 'preExec'"); + } + + public boolean preExec(InteractionCreateEvent context, HasPermission annotation) { + Optional member = context.getInteraction().getMember(); + if (member.isEmpty()) + return false; + PermissionSet ownPerms = PermissionSet.of(annotation.value()); + PermissionSet permSet = member.get().getBasePermissions().block(); + return permSet.containsAll(ownPerms); + } + + @Override + public void postExec(Object context, HasPermission annotation) { + + } + +} \ No newline at end of file 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 new file mode 100644 index 0000000..62a9259 --- /dev/null +++ b/wrapper/discord4j/src/test/java/net/tomatentum/marinara/test/discord4j/AutoCompleteTest.java @@ -0,0 +1,45 @@ +package net.tomatentum.marinara.test.discord4j; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import java.util.ArrayList; +import java.util.Optional; + +import org.junit.jupiter.api.Test; + +import discord4j.core.event.domain.interaction.ChatInputAutoCompleteEvent; +import discord4j.core.object.command.ApplicationCommandInteractionOption; +import discord4j.core.object.command.ApplicationCommandInteractionOptionValue; +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; + +public class AutoCompleteTest { + + @Test + public void testAutocomplete() { + ApplicationCommandInteractionOption optionMock = mock(); + ChatInputAutoCompleteEvent autoCompleteEventMock = mock(); + + when(optionMock.getName()).thenReturn("foo"); + when(optionMock.getType()).thenReturn(Type.STRING); + when(optionMock.getValue()).thenReturn( + Optional.of( + new ApplicationCommandInteractionOptionValue(null, null, Type.STRING.getValue(), "test", null) + )); + + when(autoCompleteEventMock.getCommandName()).thenReturn("test"); + when(autoCompleteEventMock.getOptions()).thenReturn(new ArrayList<>()); + when(autoCompleteEventMock.getFocusedOption()).thenReturn(optionMock); + + 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()); + 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 new file mode 100644 index 0000000..bb0c70b --- /dev/null +++ b/wrapper/discord4j/src/test/java/net/tomatentum/marinara/test/discord4j/ButtonTest.java @@ -0,0 +1,29 @@ +package net.tomatentum.marinara.test.discord4j; + +import static org.junit.jupiter.api.Assertions.assertTrue; + +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.TestInstance; +import org.junit.jupiter.api.TestInstance.Lifecycle; + +import discord4j.core.event.domain.interaction.ButtonInteractionEvent; +import net.tomatentum.marinara.Marinara; +import net.tomatentum.marinara.test.discord4j.mocks.CommonMocks; +import net.tomatentum.marinara.wrapper.LibraryWrapper; +import net.tomatentum.marinara.wrapper.discord4j.Discord4JWrapper; + +@TestInstance(Lifecycle.PER_CLASS) +public class ButtonTest { + + @Test + public 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()); + 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 new file mode 100644 index 0000000..0e7874c --- /dev/null +++ b/wrapper/discord4j/src/test/java/net/tomatentum/marinara/test/discord4j/InteractionCheckTest.java @@ -0,0 +1,70 @@ +package net.tomatentum.marinara.test.discord4j; + +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import java.util.Optional; + +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.TestInstance; +import org.junit.jupiter.api.TestInstance.Lifecycle; + +import discord4j.core.event.domain.interaction.ButtonInteractionEvent; +import discord4j.core.object.command.Interaction; +import discord4j.core.object.entity.Member; +import discord4j.rest.util.Permission; +import discord4j.rest.util.PermissionSet; +import net.tomatentum.marinara.Marinara; +import net.tomatentum.marinara.test.discord4j.mocks.CommonMocks; +import net.tomatentum.marinara.wrapper.LibraryWrapper; +import net.tomatentum.marinara.wrapper.discord4j.Discord4JWrapper; +import net.tomatentum.marinara.wrapper.discord4j.checks.PermissionCheck; +import reactor.core.publisher.Mono; + +@TestInstance(Lifecycle.PER_CLASS) +public class InteractionCheckTest { + + @Test + public 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()); + wrapper.handleInteraction(buttonEventMock); + + assertTrue(TestInteractionCheck.preExecuted); + assertTrue(TestInteractionCheck.postExecuted); + assertTrue(TestButton.didRun); + } + + @Test + public void testPermissionCheck() { + Member memberMock = mock(); + Interaction interactionMock = mock(); + + when(memberMock.getBasePermissions()).thenReturn(Mono.just(PermissionSet.none())); + + when(interactionMock.getMember()).thenReturn(Optional.of(memberMock)); + + ButtonInteractionEvent buttonEventMock = CommonMocks.getButtonEventMock("permissionCheck", interactionMock); + + LibraryWrapper wrapper = new Discord4JWrapper(null); + Marinara marinara = Marinara.load(wrapper); + marinara.getCheckRegistry().addCheck(new PermissionCheck()); + marinara.getRegistry().addInteractions(new TestButton()); + + wrapper.handleInteraction(buttonEventMock); + assertFalse(TestButton.didPermRun); + TestButton.didPermRun = false; + + when(memberMock.getBasePermissions()).thenReturn(Mono.just(PermissionSet.of(Permission.ATTACH_FILES))); + + wrapper.handleInteraction(buttonEventMock); + assertTrue(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 new file mode 100644 index 0000000..377f123 --- /dev/null +++ b/wrapper/discord4j/src/test/java/net/tomatentum/marinara/test/discord4j/SlashCommandTest.java @@ -0,0 +1,74 @@ +package net.tomatentum.marinara.test.discord4j; + +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import java.util.Arrays; +import java.util.Optional; + +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.TestInstance; +import org.junit.jupiter.api.TestInstance.Lifecycle; + +import discord4j.core.DiscordClient; +import discord4j.core.GatewayDiscordClient; +import discord4j.core.event.domain.interaction.ChatInputInteractionEvent; +import discord4j.core.object.command.ApplicationCommandInteractionOption; +import discord4j.core.object.command.ApplicationCommandInteractionOptionValue; +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"); + GatewayDiscordClient client; + + @BeforeAll + void setUp() { + client = DiscordClient.create(DISCORD_TOKEN).login().block(); + } + + @AfterAll + void tearDown() { + client.logout().block(); + client = null; + } + + @Test + void testSlashCommand() { + Marinara marinara = Marinara.load(new Discord4JWrapper(client)); + marinara.getRegistry().addInteractions(new TestCommand()); + marinara.getRegistry().registerCommands(); + System.out.println("Success!"); + } + + @Test + void testSlashCommandExecution() { + ApplicationCommandInteractionOption optionMock = mock(); + ChatInputInteractionEvent eventMock = mock(); + + when(optionMock.getName()).thenReturn("foo"); + when(optionMock.getType()).thenReturn(Type.STRING); + when(optionMock.getValue()).thenReturn( + Optional.of( + new ApplicationCommandInteractionOptionValue(null, null, Type.STRING.getValue(), "test", null) + )); + + when(eventMock.getCommandName()).thenReturn("test"); + when(eventMock.getOptions()).thenReturn(Arrays.asList(optionMock)); + when(eventMock.getOption("foo")).thenReturn(Optional.of(optionMock)); + + LibraryWrapper wrapper = new Discord4JWrapper(client); + Marinara marinara = Marinara.load(wrapper); + marinara.getRegistry().addInteractions(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 new file mode 100644 index 0000000..d216805 --- /dev/null +++ b/wrapper/discord4j/src/test/java/net/tomatentum/marinara/test/discord4j/TestAutocomplete.java @@ -0,0 +1,22 @@ +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 net.tomatentum.marinara.interaction.InteractionHandler; +import net.tomatentum.marinara.interaction.annotation.AutoComplete; +import net.tomatentum.marinara.interaction.commands.annotation.SlashCommand; + +public class TestAutocomplete implements InteractionHandler { + + @SlashCommand(name = "test") + @AutoComplete + public void autocomplete(ChatInputAutoCompleteEvent context, String value) { + System.out.println("Success!"); + assertEquals(value, "test"); + context.respondWithSuggestions(Collections.emptyList()); + } + +} diff --git a/wrapper/discord4j/src/test/java/net/tomatentum/marinara/test/discord4j/TestButton.java b/wrapper/discord4j/src/test/java/net/tomatentum/marinara/test/discord4j/TestButton.java new file mode 100644 index 0000000..25a1c91 --- /dev/null +++ b/wrapper/discord4j/src/test/java/net/tomatentum/marinara/test/discord4j/TestButton.java @@ -0,0 +1,43 @@ +package net.tomatentum.marinara.test.discord4j; + +import static org.junit.jupiter.api.Assertions.assertNotNull; + +import discord4j.core.event.domain.interaction.ButtonInteractionEvent; +import discord4j.core.object.entity.Guild; +import discord4j.core.object.entity.Member; +import discord4j.core.object.entity.Message; +import discord4j.core.object.entity.User; +import discord4j.core.object.entity.channel.MessageChannel; +import discord4j.rest.util.Permission; +import net.tomatentum.marinara.interaction.InteractionHandler; +import net.tomatentum.marinara.interaction.annotation.Button; +import net.tomatentum.marinara.test.discord4j.TestInteractionCheck.TestCheck; +import net.tomatentum.marinara.wrapper.discord4j.checks.PermissionCheck.HasPermission; + +public class TestButton implements InteractionHandler { + + + public static boolean didRun = false; + @Button("test") + @TestCheck + public void exec(ButtonInteractionEvent interaction, MessageChannel channel, Message message, Member member, User user, Guild server) { + assertNotNull(interaction); + assertNotNull(channel); + assertNotNull(message); + assertNotNull(member); + assertNotNull(user); + assertNotNull(server); + didRun = true; + System.out.println("Success!"); + } + + public static boolean didPermRun = false; + + @Button("permissionCheck") + @HasPermission({Permission.ATTACH_FILES}) + public void exec(ButtonInteractionEvent interaction) { + didPermRun = true; + System.out.println("It worked!"); + } + +} diff --git a/wrapper/discord4j/src/test/java/net/tomatentum/marinara/test/discord4j/TestChoiceEnum.java b/wrapper/discord4j/src/test/java/net/tomatentum/marinara/test/discord4j/TestChoiceEnum.java new file mode 100644 index 0000000..66ab699 --- /dev/null +++ b/wrapper/discord4j/src/test/java/net/tomatentum/marinara/test/discord4j/TestChoiceEnum.java @@ -0,0 +1,20 @@ +package net.tomatentum.marinara.test.discord4j; + +import net.tomatentum.marinara.interaction.commands.ChoiceValueProvider; + +public enum TestChoiceEnum implements ChoiceValueProvider { + TestValue("testValue"), + FooBar("fooBar"), + Spongebob("spongebob"); + + private String value; + + private TestChoiceEnum(String value) { + this.value = value; + } + @Override + public String getChoiceValue() { + return value; + } + +} 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 new file mode 100644 index 0000000..8a98424 --- /dev/null +++ b/wrapper/discord4j/src/test/java/net/tomatentum/marinara/test/discord4j/TestCommand.java @@ -0,0 +1,31 @@ +package net.tomatentum.marinara.test.discord4j; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import discord4j.core.event.domain.interaction.ChatInputInteractionEvent; +import net.tomatentum.marinara.interaction.InteractionHandler; +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 TestCommand implements InteractionHandler { + @SlashCommand( + name = "test", + description = "testingen", + serverIds = { + 1037753048602255440L + }, + options = { + @SlashCommandOption( + name = "foo", + description = "foo bar is very fooby", + type = SlashCommandOptionType.STRING, + choiceEnum = TestChoiceEnum.class + ) + } + ) + public void exec(ChatInputInteractionEvent event, String test) { + assertEquals(test, "test"); + System.out.println("Success!"); + } +} diff --git a/wrapper/discord4j/src/test/java/net/tomatentum/marinara/test/discord4j/TestInteractionCheck.java b/wrapper/discord4j/src/test/java/net/tomatentum/marinara/test/discord4j/TestInteractionCheck.java new file mode 100644 index 0000000..fcb794d --- /dev/null +++ b/wrapper/discord4j/src/test/java/net/tomatentum/marinara/test/discord4j/TestInteractionCheck.java @@ -0,0 +1,37 @@ +package net.tomatentum.marinara.test.discord4j; + +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 { + + 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; + } + +} diff --git a/wrapper/discord4j/src/test/java/net/tomatentum/marinara/test/discord4j/mocks/CommonMocks.java b/wrapper/discord4j/src/test/java/net/tomatentum/marinara/test/discord4j/mocks/CommonMocks.java new file mode 100644 index 0000000..f000365 --- /dev/null +++ b/wrapper/discord4j/src/test/java/net/tomatentum/marinara/test/discord4j/mocks/CommonMocks.java @@ -0,0 +1,55 @@ +package net.tomatentum.marinara.test.discord4j.mocks; + +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import java.util.Optional; + +import discord4j.core.event.domain.interaction.ButtonInteractionEvent; +import discord4j.core.object.command.Interaction; +import discord4j.core.object.entity.Guild; +import discord4j.core.object.entity.Member; +import discord4j.core.object.entity.Message; +import discord4j.core.object.entity.User; +import discord4j.core.object.entity.channel.MessageChannel; +import reactor.core.publisher.Mono; + +public class CommonMocks { + public static Interaction getInteractionMock() { + Interaction interaction = mock(Interaction.class); + Message message = mock(Message.class); + MessageChannel channel = mock(MessageChannel.class); + Guild guild = mock(Guild.class); + User user = mock(User.class); + Member member = mock(Member.class); + + + when(interaction.getMessage()).thenReturn(Optional.of(message)); + when(interaction.getChannel()).thenReturn(Mono.just(channel)); + when(interaction.getGuild()).thenReturn(Mono.just(guild)); + when(interaction.getUser()).thenReturn(user); + when(interaction.getMember()).thenReturn(Optional.of(member)); + + + return interaction; + } + + public static ButtonInteractionEvent getButtonEventMock(String customId) { + ButtonInteractionEvent buttonEventMock = mock(ButtonInteractionEvent.class); + + when(buttonEventMock.getCustomId()).thenReturn(customId); + Interaction interactionMock = getInteractionMock(); + when(buttonEventMock.getInteraction()).thenReturn(interactionMock); + Optional message = interactionMock.getMessage(); + when (buttonEventMock.getMessage()).thenReturn(message); + return buttonEventMock; + } + + public static ButtonInteractionEvent getButtonEventMock(String customId, Interaction interaction) { + ButtonInteractionEvent buttonEventMock = mock(ButtonInteractionEvent.class); + + when(buttonEventMock.getCustomId()).thenReturn(customId); + when(buttonEventMock.getInteraction()).thenReturn(interaction); + return buttonEventMock; + } +} 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 8972605..e8555bb 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 @@ -49,12 +49,12 @@ public class JavacordWrapper extends LibraryWrapper { } @Override - public InteractionType getInteractionType(Class clazz) { - if (AutocompleteInteraction.class.isAssignableFrom(clazz)) + public InteractionType getInteractionType(Object context) { + if (AutocompleteInteraction.class.isAssignableFrom(context.getClass())) return InteractionType.AUTOCOMPLETE; - if (ApplicationCommandInteraction.class.isAssignableFrom(clazz)) + if (ApplicationCommandInteraction.class.isAssignableFrom(context.getClass())) return InteractionType.COMMAND; - if (ButtonInteraction.class.isAssignableFrom(clazz)) + if (ButtonInteraction.class.isAssignableFrom(context.getClass())) return InteractionType.BUTTON; return null; } @@ -119,17 +119,16 @@ public class JavacordWrapper extends LibraryWrapper { private org.javacord.api.interaction.SlashCommandOption convertSubCommandGroupDef(SlashCommandDefinition def, SubCommandGroup subGroup) { SubCommand[] subCommands = def.getSubCommands(subGroup.name()); - org.javacord.api.interaction.SlashCommandOption[] convertedSubCommands = (org.javacord.api.interaction.SlashCommandOption[]) Arrays.stream(subCommands).map(this::convertSubCommandDef).toArray(); + List convertedSubCommands = Arrays.stream(subCommands).map(this::convertSubCommandDef).toList(); return org.javacord.api.interaction.SlashCommandOption.createWithOptions( org.javacord.api.interaction.SlashCommandOptionType.SUB_COMMAND_GROUP, subGroup.name(), subGroup.description(), - Arrays.asList(convertedSubCommands)); + convertedSubCommands); } private org.javacord.api.interaction.SlashCommandOption convertSubCommandDef(SubCommand sub) { - List convertedOptions = new ArrayList<>(); - Arrays.stream(sub.options()).map(this::convertOptionDef).forEach(convertedOptions::add); + List convertedOptions = Arrays.stream(sub.options()).map(this::convertOptionDef).toList(); return org.javacord.api.interaction.SlashCommandOption.createWithOptions( org.javacord.api.interaction.SlashCommandOptionType.SUB_COMMAND, sub.name(), diff --git a/wrapper/javacord/src/test/java/net/tomatentum/marinara/test/AutoCompleteTest.java b/wrapper/javacord/src/test/java/net/tomatentum/marinara/test/javacord/AutoCompleteTest.java similarity index 79% rename from wrapper/javacord/src/test/java/net/tomatentum/marinara/test/AutoCompleteTest.java rename to wrapper/javacord/src/test/java/net/tomatentum/marinara/test/javacord/AutoCompleteTest.java index 443c2b4..9c5fc32 100644 --- a/wrapper/javacord/src/test/java/net/tomatentum/marinara/test/AutoCompleteTest.java +++ b/wrapper/javacord/src/test/java/net/tomatentum/marinara/test/javacord/AutoCompleteTest.java @@ -1,12 +1,12 @@ -package net.tomatentum.marinara.test; +package net.tomatentum.marinara.test.javacord; import static org.junit.jupiter.api.Assertions.assertTrue; import org.junit.jupiter.api.Test; import net.tomatentum.marinara.Marinara; -import net.tomatentum.marinara.test.mocks.AutocompleteInteractionMock; -import net.tomatentum.marinara.test.mocks.DiscordApiMock; +import net.tomatentum.marinara.test.javacord.mocks.AutocompleteInteractionMock; +import net.tomatentum.marinara.test.javacord.mocks.DiscordApiMock; import net.tomatentum.marinara.wrapper.LibraryWrapper; import net.tomatentum.marinara.wrapper.javacord.JavacordWrapper; diff --git a/wrapper/javacord/src/test/java/net/tomatentum/marinara/test/ButtonTest.java b/wrapper/javacord/src/test/java/net/tomatentum/marinara/test/javacord/ButtonTest.java similarity index 81% rename from wrapper/javacord/src/test/java/net/tomatentum/marinara/test/ButtonTest.java rename to wrapper/javacord/src/test/java/net/tomatentum/marinara/test/javacord/ButtonTest.java index db08352..1040ceb 100644 --- a/wrapper/javacord/src/test/java/net/tomatentum/marinara/test/ButtonTest.java +++ b/wrapper/javacord/src/test/java/net/tomatentum/marinara/test/javacord/ButtonTest.java @@ -1,4 +1,4 @@ -package net.tomatentum.marinara.test; +package net.tomatentum.marinara.test.javacord; import static org.junit.jupiter.api.Assertions.assertTrue; @@ -7,8 +7,8 @@ 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.javacord.mocks.ButtonInteractionMock; +import net.tomatentum.marinara.test.javacord.mocks.DiscordApiMock; import net.tomatentum.marinara.wrapper.LibraryWrapper; import net.tomatentum.marinara.wrapper.javacord.JavacordWrapper; diff --git a/wrapper/javacord/src/test/java/net/tomatentum/marinara/test/InteractionCheckTest.java b/wrapper/javacord/src/test/java/net/tomatentum/marinara/test/javacord/InteractionCheckTest.java similarity index 87% rename from wrapper/javacord/src/test/java/net/tomatentum/marinara/test/InteractionCheckTest.java rename to wrapper/javacord/src/test/java/net/tomatentum/marinara/test/javacord/InteractionCheckTest.java index aed9f5a..be5d8e1 100644 --- a/wrapper/javacord/src/test/java/net/tomatentum/marinara/test/InteractionCheckTest.java +++ b/wrapper/javacord/src/test/java/net/tomatentum/marinara/test/javacord/InteractionCheckTest.java @@ -1,4 +1,4 @@ -package net.tomatentum.marinara.test; +package net.tomatentum.marinara.test.javacord; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; @@ -9,9 +9,9 @@ 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.test.javacord.mocks.ButtonInteractionMock; +import net.tomatentum.marinara.test.javacord.mocks.DiscordApiMock; +import net.tomatentum.marinara.test.javacord.mocks.ServerMock; import net.tomatentum.marinara.wrapper.LibraryWrapper; import net.tomatentum.marinara.wrapper.javacord.JavacordWrapper; import net.tomatentum.marinara.wrapper.javacord.checks.PermissionCheck; diff --git a/wrapper/javacord/src/test/java/net/tomatentum/marinara/test/SlashCommandTest.java b/wrapper/javacord/src/test/java/net/tomatentum/marinara/test/javacord/SlashCommandTest.java similarity index 91% rename from wrapper/javacord/src/test/java/net/tomatentum/marinara/test/SlashCommandTest.java rename to wrapper/javacord/src/test/java/net/tomatentum/marinara/test/javacord/SlashCommandTest.java index f7a2c49..fa077af 100644 --- a/wrapper/javacord/src/test/java/net/tomatentum/marinara/test/SlashCommandTest.java +++ b/wrapper/javacord/src/test/java/net/tomatentum/marinara/test/javacord/SlashCommandTest.java @@ -1,4 +1,4 @@ -package net.tomatentum.marinara.test; +package net.tomatentum.marinara.test.javacord; import org.javacord.api.DiscordApi; import org.javacord.api.DiscordApiBuilder; @@ -9,7 +9,7 @@ import org.junit.jupiter.api.TestInstance; import org.junit.jupiter.api.TestInstance.Lifecycle; import net.tomatentum.marinara.Marinara; -import net.tomatentum.marinara.test.mocks.SlashCommandInteractionMock; +import net.tomatentum.marinara.test.javacord.mocks.SlashCommandInteractionMock; import net.tomatentum.marinara.wrapper.LibraryWrapper; import net.tomatentum.marinara.wrapper.javacord.JavacordWrapper; @TestInstance(Lifecycle.PER_CLASS) diff --git a/wrapper/javacord/src/test/java/net/tomatentum/marinara/test/TestAutocomplete.java b/wrapper/javacord/src/test/java/net/tomatentum/marinara/test/javacord/TestAutocomplete.java similarity index 93% rename from wrapper/javacord/src/test/java/net/tomatentum/marinara/test/TestAutocomplete.java rename to wrapper/javacord/src/test/java/net/tomatentum/marinara/test/javacord/TestAutocomplete.java index c38f4a2..d9063bb 100644 --- a/wrapper/javacord/src/test/java/net/tomatentum/marinara/test/TestAutocomplete.java +++ b/wrapper/javacord/src/test/java/net/tomatentum/marinara/test/javacord/TestAutocomplete.java @@ -1,4 +1,4 @@ -package net.tomatentum.marinara.test; +package net.tomatentum.marinara.test.javacord; import static org.junit.jupiter.api.Assertions.assertEquals; diff --git a/wrapper/javacord/src/test/java/net/tomatentum/marinara/test/TestButton.java b/wrapper/javacord/src/test/java/net/tomatentum/marinara/test/javacord/TestButton.java similarity index 91% rename from wrapper/javacord/src/test/java/net/tomatentum/marinara/test/TestButton.java rename to wrapper/javacord/src/test/java/net/tomatentum/marinara/test/javacord/TestButton.java index 23a7dbf..f838e5e 100644 --- a/wrapper/javacord/src/test/java/net/tomatentum/marinara/test/TestButton.java +++ b/wrapper/javacord/src/test/java/net/tomatentum/marinara/test/javacord/TestButton.java @@ -1,4 +1,4 @@ -package net.tomatentum.marinara.test; +package net.tomatentum.marinara.test.javacord; import static org.junit.jupiter.api.Assertions.assertNotNull; @@ -11,7 +11,7 @@ import org.javacord.api.interaction.ButtonInteraction; import net.tomatentum.marinara.interaction.InteractionHandler; import net.tomatentum.marinara.interaction.annotation.Button; -import net.tomatentum.marinara.test.TestInteractionCheck.TestCheck; +import net.tomatentum.marinara.test.javacord.TestInteractionCheck.TestCheck; import net.tomatentum.marinara.wrapper.javacord.checks.PermissionCheck.HasPermission; public class TestButton implements InteractionHandler { diff --git a/wrapper/javacord/src/test/java/net/tomatentum/marinara/test/TestChoiceEnum.java b/wrapper/javacord/src/test/java/net/tomatentum/marinara/test/javacord/TestChoiceEnum.java similarity index 89% rename from wrapper/javacord/src/test/java/net/tomatentum/marinara/test/TestChoiceEnum.java rename to wrapper/javacord/src/test/java/net/tomatentum/marinara/test/javacord/TestChoiceEnum.java index 1c7fd0a..1423ef9 100644 --- a/wrapper/javacord/src/test/java/net/tomatentum/marinara/test/TestChoiceEnum.java +++ b/wrapper/javacord/src/test/java/net/tomatentum/marinara/test/javacord/TestChoiceEnum.java @@ -1,4 +1,4 @@ -package net.tomatentum.marinara.test; +package net.tomatentum.marinara.test.javacord; import net.tomatentum.marinara.interaction.commands.ChoiceValueProvider; diff --git a/wrapper/javacord/src/test/java/net/tomatentum/marinara/test/TestCommand.java b/wrapper/javacord/src/test/java/net/tomatentum/marinara/test/javacord/TestCommand.java similarity index 95% rename from wrapper/javacord/src/test/java/net/tomatentum/marinara/test/TestCommand.java rename to wrapper/javacord/src/test/java/net/tomatentum/marinara/test/javacord/TestCommand.java index 2716fea..e7aca90 100644 --- a/wrapper/javacord/src/test/java/net/tomatentum/marinara/test/TestCommand.java +++ b/wrapper/javacord/src/test/java/net/tomatentum/marinara/test/javacord/TestCommand.java @@ -1,4 +1,4 @@ -package net.tomatentum.marinara.test; +package net.tomatentum.marinara.test.javacord; import static org.junit.jupiter.api.Assertions.assertEquals; diff --git a/wrapper/javacord/src/test/java/net/tomatentum/marinara/test/TestInteractionCheck.java b/wrapper/javacord/src/test/java/net/tomatentum/marinara/test/javacord/TestInteractionCheck.java similarity index 95% rename from wrapper/javacord/src/test/java/net/tomatentum/marinara/test/TestInteractionCheck.java rename to wrapper/javacord/src/test/java/net/tomatentum/marinara/test/javacord/TestInteractionCheck.java index ed1339b..3e7ea48 100644 --- a/wrapper/javacord/src/test/java/net/tomatentum/marinara/test/TestInteractionCheck.java +++ b/wrapper/javacord/src/test/java/net/tomatentum/marinara/test/javacord/TestInteractionCheck.java @@ -1,4 +1,4 @@ -package net.tomatentum.marinara.test; +package net.tomatentum.marinara.test.javacord; import static org.junit.jupiter.api.Assertions.assertNotNull; diff --git a/wrapper/javacord/src/test/java/net/tomatentum/marinara/test/mocks/AutocompleteInteractionMock.java b/wrapper/javacord/src/test/java/net/tomatentum/marinara/test/javacord/mocks/AutocompleteInteractionMock.java similarity index 99% rename from wrapper/javacord/src/test/java/net/tomatentum/marinara/test/mocks/AutocompleteInteractionMock.java rename to wrapper/javacord/src/test/java/net/tomatentum/marinara/test/javacord/mocks/AutocompleteInteractionMock.java index 29d64b9..20460f6 100644 --- a/wrapper/javacord/src/test/java/net/tomatentum/marinara/test/mocks/AutocompleteInteractionMock.java +++ b/wrapper/javacord/src/test/java/net/tomatentum/marinara/test/javacord/mocks/AutocompleteInteractionMock.java @@ -1,4 +1,4 @@ -package net.tomatentum.marinara.test.mocks; +package net.tomatentum.marinara.test.javacord.mocks; import java.util.ArrayList; import java.util.EnumSet; diff --git a/wrapper/javacord/src/test/java/net/tomatentum/marinara/test/mocks/ButtonInteractionMock.java b/wrapper/javacord/src/test/java/net/tomatentum/marinara/test/javacord/mocks/ButtonInteractionMock.java similarity index 98% rename from wrapper/javacord/src/test/java/net/tomatentum/marinara/test/mocks/ButtonInteractionMock.java rename to wrapper/javacord/src/test/java/net/tomatentum/marinara/test/javacord/mocks/ButtonInteractionMock.java index 3e3e8fd..a80320e 100644 --- a/wrapper/javacord/src/test/java/net/tomatentum/marinara/test/mocks/ButtonInteractionMock.java +++ b/wrapper/javacord/src/test/java/net/tomatentum/marinara/test/javacord/mocks/ButtonInteractionMock.java @@ -1,4 +1,4 @@ -package net.tomatentum.marinara.test.mocks; +package net.tomatentum.marinara.test.javacord.mocks; import java.util.EnumSet; import java.util.List; diff --git a/wrapper/javacord/src/test/java/net/tomatentum/marinara/test/mocks/ChannelMock.java b/wrapper/javacord/src/test/java/net/tomatentum/marinara/test/javacord/mocks/ChannelMock.java similarity index 99% rename from wrapper/javacord/src/test/java/net/tomatentum/marinara/test/mocks/ChannelMock.java rename to wrapper/javacord/src/test/java/net/tomatentum/marinara/test/javacord/mocks/ChannelMock.java index 472751e..6048b0c 100644 --- a/wrapper/javacord/src/test/java/net/tomatentum/marinara/test/mocks/ChannelMock.java +++ b/wrapper/javacord/src/test/java/net/tomatentum/marinara/test/javacord/mocks/ChannelMock.java @@ -1,4 +1,4 @@ -package net.tomatentum.marinara.test.mocks; +package net.tomatentum.marinara.test.javacord.mocks; import java.util.Collection; import java.util.List; diff --git a/wrapper/javacord/src/test/java/net/tomatentum/marinara/test/mocks/DiscordApiMock.java b/wrapper/javacord/src/test/java/net/tomatentum/marinara/test/javacord/mocks/DiscordApiMock.java similarity index 99% rename from wrapper/javacord/src/test/java/net/tomatentum/marinara/test/mocks/DiscordApiMock.java rename to wrapper/javacord/src/test/java/net/tomatentum/marinara/test/javacord/mocks/DiscordApiMock.java index d0e952f..ccc26b0 100644 --- a/wrapper/javacord/src/test/java/net/tomatentum/marinara/test/mocks/DiscordApiMock.java +++ b/wrapper/javacord/src/test/java/net/tomatentum/marinara/test/javacord/mocks/DiscordApiMock.java @@ -1,4 +1,4 @@ -package net.tomatentum.marinara.test.mocks; +package net.tomatentum.marinara.test.javacord.mocks; import java.time.Duration; import java.util.Collection; diff --git a/wrapper/javacord/src/test/java/net/tomatentum/marinara/test/mocks/MessageMock.java b/wrapper/javacord/src/test/java/net/tomatentum/marinara/test/javacord/mocks/MessageMock.java similarity index 99% rename from wrapper/javacord/src/test/java/net/tomatentum/marinara/test/mocks/MessageMock.java rename to wrapper/javacord/src/test/java/net/tomatentum/marinara/test/javacord/mocks/MessageMock.java index 248fffd..186bce2 100644 --- a/wrapper/javacord/src/test/java/net/tomatentum/marinara/test/mocks/MessageMock.java +++ b/wrapper/javacord/src/test/java/net/tomatentum/marinara/test/javacord/mocks/MessageMock.java @@ -1,4 +1,4 @@ -package net.tomatentum.marinara.test.mocks; +package net.tomatentum.marinara.test.javacord.mocks; import java.time.Instant; import java.util.Collection; diff --git a/wrapper/javacord/src/test/java/net/tomatentum/marinara/test/mocks/ServerMock.java b/wrapper/javacord/src/test/java/net/tomatentum/marinara/test/javacord/mocks/ServerMock.java similarity index 99% rename from wrapper/javacord/src/test/java/net/tomatentum/marinara/test/mocks/ServerMock.java rename to wrapper/javacord/src/test/java/net/tomatentum/marinara/test/javacord/mocks/ServerMock.java index 275c8ab..f07f85a 100644 --- a/wrapper/javacord/src/test/java/net/tomatentum/marinara/test/mocks/ServerMock.java +++ b/wrapper/javacord/src/test/java/net/tomatentum/marinara/test/javacord/mocks/ServerMock.java @@ -1,4 +1,4 @@ -package net.tomatentum.marinara.test.mocks; +package net.tomatentum.marinara.test.javacord.mocks; import static org.junit.jupiter.api.Assertions.assertNotNull; diff --git a/wrapper/javacord/src/test/java/net/tomatentum/marinara/test/mocks/SlashCommandInteractionMock.java b/wrapper/javacord/src/test/java/net/tomatentum/marinara/test/javacord/mocks/SlashCommandInteractionMock.java similarity index 98% rename from wrapper/javacord/src/test/java/net/tomatentum/marinara/test/mocks/SlashCommandInteractionMock.java rename to wrapper/javacord/src/test/java/net/tomatentum/marinara/test/javacord/mocks/SlashCommandInteractionMock.java index 1f04e89..8a66a77 100644 --- a/wrapper/javacord/src/test/java/net/tomatentum/marinara/test/mocks/SlashCommandInteractionMock.java +++ b/wrapper/javacord/src/test/java/net/tomatentum/marinara/test/javacord/mocks/SlashCommandInteractionMock.java @@ -1,4 +1,4 @@ -package net.tomatentum.marinara.test.mocks; +package net.tomatentum.marinara.test.javacord.mocks; import java.util.Arrays; import java.util.EnumSet; diff --git a/wrapper/javacord/src/test/java/net/tomatentum/marinara/test/mocks/SlashCommandInteractionOptionMock.java b/wrapper/javacord/src/test/java/net/tomatentum/marinara/test/javacord/mocks/SlashCommandInteractionOptionMock.java similarity index 97% rename from wrapper/javacord/src/test/java/net/tomatentum/marinara/test/mocks/SlashCommandInteractionOptionMock.java rename to wrapper/javacord/src/test/java/net/tomatentum/marinara/test/javacord/mocks/SlashCommandInteractionOptionMock.java index b102a21..478427b 100644 --- a/wrapper/javacord/src/test/java/net/tomatentum/marinara/test/mocks/SlashCommandInteractionOptionMock.java +++ b/wrapper/javacord/src/test/java/net/tomatentum/marinara/test/javacord/mocks/SlashCommandInteractionOptionMock.java @@ -1,4 +1,4 @@ -package net.tomatentum.marinara.test.mocks; +package net.tomatentum.marinara.test.javacord.mocks; import java.util.Collections; import java.util.List; diff --git a/wrapper/javacord/src/test/java/net/tomatentum/marinara/test/mocks/UserMock.java b/wrapper/javacord/src/test/java/net/tomatentum/marinara/test/javacord/mocks/UserMock.java similarity index 99% rename from wrapper/javacord/src/test/java/net/tomatentum/marinara/test/mocks/UserMock.java rename to wrapper/javacord/src/test/java/net/tomatentum/marinara/test/javacord/mocks/UserMock.java index 7258b04..6511209 100644 --- a/wrapper/javacord/src/test/java/net/tomatentum/marinara/test/mocks/UserMock.java +++ b/wrapper/javacord/src/test/java/net/tomatentum/marinara/test/javacord/mocks/UserMock.java @@ -1,4 +1,4 @@ -package net.tomatentum.marinara.test.mocks; +package net.tomatentum.marinara.test.javacord.mocks; import java.awt.Color; import java.time.Instant;